mirror of
https://github.com/EQEmu/Server.git
synced 2026-01-02 17:53:51 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
53fd5e0a5c
@ -229,7 +229,7 @@ ENDIF(EQEMU_ENABLE_BOTS)
|
||||
#What to build
|
||||
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
|
||||
OPTION(EQEMU_BUILD_LOGIN "Build the login server." OFF)
|
||||
OPTION(EQEMU_BUILD_AZONE "Build azone utility." OFF)
|
||||
OPTION(EQEMU_BUILD_SOCKET_SERVER "Build the socket server." OFF)
|
||||
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
|
||||
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
|
||||
OPTION(EQEMU_BUILD_LUA "Build Lua parser." OFF)
|
||||
@ -298,6 +298,13 @@ IF(EQEMU_BUILD_LUA)
|
||||
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
IF(EQEMU_BUILD_SOCKET_SERVER)
|
||||
FIND_PACKAGE(Boost COMPONENTS system filesystem thread REQUIRED)
|
||||
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/dependencies/websocketpp")
|
||||
ADD_DEFINITIONS(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
|
||||
ENDIF(EQEMU_BUILD_SOCKET_SERVER)
|
||||
|
||||
INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm")
|
||||
|
||||
IF(EQEMU_BUILD_LUA)
|
||||
@ -313,16 +320,13 @@ IF(EQEMU_BUILD_SERVER)
|
||||
ADD_SUBDIRECTORY(zone)
|
||||
ADD_SUBDIRECTORY(ucs)
|
||||
ADD_SUBDIRECTORY(queryserv)
|
||||
ADD_SUBDIRECTORY(socket_server)
|
||||
ADD_SUBDIRECTORY(eqlaunch)
|
||||
ENDIF(EQEMU_BUILD_SERVER)
|
||||
IF(EQEMU_BUILD_LOGIN)
|
||||
ADD_SUBDIRECTORY(loginserver)
|
||||
ENDIF(EQEMU_BUILD_LOGIN)
|
||||
|
||||
IF(EQEMU_BUILD_AZONE)
|
||||
ADD_SUBDIRECTORY(utils)
|
||||
ENDIF(EQEMU_BUILD_AZONE)
|
||||
|
||||
IF(EQEMU_BUILD_TESTS)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
ENDIF(EQEMU_BUILD_TESTS)
|
||||
|
||||
@ -1,5 +1,47 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
|
||||
== 06/25/2014 ==
|
||||
Kayen: Updated SE_Hate (Renamed from SE_Hate2) to now properly work for instant +/- hate spells.
|
||||
Kayen: Updated SE_FadingMemories - Base value will be properly utilized to set % chance for fade effect to work.
|
||||
Kayen: Implemented SE_StrikeThough (Was incorrectly defined as implemented previously) - Works same as item bonus.
|
||||
Kayen: Update SE_Taunt - Limit value if present will now add instant hate.
|
||||
Kayen: Implemented SE_MassGroupBuff - Allows next group buff cast to be a MGB (AA now uses this)
|
||||
Kayen: Implemented SE_IllusionOther - Allows next Illusion buff (self only) cast to be cast on target. (AA now uses this)
|
||||
Kayen: Update SE_AETaunt - Base value will now determine AE taunt range (This will not result in any change to currently used spells).
|
||||
Kayen: Udpated SE_ReclaimPet - Correct forumla for mana returned to properly return 75% of actual pet spell mana cost.
|
||||
Kayen: Implemented SE_ImprovedReclaimEnergy - Modifies % mana returned from SE_ReclaimPet.
|
||||
Kayen: Implemented SE_HeadShot, SE_HeadShotLevel - Defines headshot damage and level requirements.
|
||||
Revised HeadShot mechanic so damage now receives all archery bonuses, proc chance can be set to either (lives new Proc Per minute
|
||||
system, or flat chance based on dex (formula updated).
|
||||
Kayen: Implemented SE_Assassinate, SE_AssassinateLevel - Defines assassinate damage and level requirements.
|
||||
Revised Assassinate mechanic so damage now receives all backstab bonuses, proc chance can be set to either (lives new Proc Per minute
|
||||
system, or flat chance based on dex (formula updated). Assassinate can now proc from THROW if behind target, various other adjustments.
|
||||
Kayen: Fix to AA Finishing Blow missing aa_effects data, update required SQL.
|
||||
Revised Finishing blow so that damage now receives all melee bonus. Support also for this effect if placed on items or spells.
|
||||
Kayen: Implemented SE_PetMeleeMitigation - Bonus applied to pet owner. Gives AC to owner's pet.
|
||||
|
||||
Required SQL: utils/sql/git/required/2014_06_25_AA_Update.sql
|
||||
Optional SQL: utils/sql/git/optiional/2014_06_29_HeadShotRules.sql
|
||||
|
||||
|
||||
== 06/17/2014 ==
|
||||
Kayen: Implemented SE_AStacker, SE_BStacker, SE_CStacker, SE_DStacker.
|
||||
These effects when present in buffs prevent each other from stacking,
|
||||
Any effect with B prevents A, C prevents B, D prevents C.
|
||||
Kayen: Implemented SE_DamageModifier2 (Stacks with SE_DamageModifier, mods damage by skill type)
|
||||
Kayen: Implemented SE_AddHatePct (Modifies +/- your total hate on NPC by percent)
|
||||
Kayen: Implemented SE_AddHateOverTimePct (Modifies +/- your total hate on NPC by percent over time)
|
||||
Kayen: Implemented SE_DoubleRiposte (Modifies +/- your double riposte chance) *Not used in any live effects
|
||||
Kayen: Implemented SE_Berserk (Sets client as 'Berserk' giving chance to crippling blow) *Not used in any live effects
|
||||
Kayen: Implemented SE_Vampirsm (Stackable lifetap from melee effect) *Not used in any live effects
|
||||
Kayen: Minor fixes to how lifetap from melee effects are calced. Removed arbitrary hard cap of 100%, Negative value will now dmg client.
|
||||
Kayen: Fix to issue that prevented NPC's from receiving HP Regeneration derived from spell buffs.
|
||||
Kayen: Fixes and Updates for melee and spell mitigation runes.
|
||||
Kayen: Update to SE_NegateAttack, 'max' value can now set upper limit of damage absorbed. DOT ticks will no longer be absorbed.
|
||||
Kayen: Implemented SE_Metabolism - Modifies food/drink consumption rates. [Data for AA is already in database]
|
||||
Kayen: Update to SE_BalanaceMana, SE_BalanceHP to support limit value which caps max mana/hp that can be taken per player.
|
||||
|
||||
== 06/13/2014 ==
|
||||
Kayen: For table 'npc_spell_effects_entries' setting se_max for damage shield effects (59) will now determine the DS Type (ie burning)
|
||||
Setting se_max to 1 for SkillDamageTaken effects (127) will allow for stackable mitigation/weakness same as quest function ModSkillDmgTaken.
|
||||
|
||||
@ -366,7 +366,22 @@ bool EmuTCPConnection::LineOutQueuePush(char* line) {
|
||||
safe_delete_array(line);
|
||||
return(true);
|
||||
}
|
||||
|
||||
if (strcmp(line, "**PACKETMODESS**") == 0) {
|
||||
MSendQueue.lock();
|
||||
safe_delete_array(sendbuf);
|
||||
if (TCPMode == modeConsole)
|
||||
Send((const uchar*) "\0**PACKETMODESS**\r", 18);
|
||||
TCPMode = modePacket;
|
||||
PacketMode = packetModeSocket_Server;
|
||||
EmuTCPNetPacket_Struct* tnps = 0;
|
||||
while ((tnps = InModeQueue.pop())) {
|
||||
SendPacket(tnps);
|
||||
safe_delete_array(tnps);
|
||||
}
|
||||
MSendQueue.unlock();
|
||||
safe_delete_array(line);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
|
||||
return(TCPConnection::LineOutQueuePush(line));
|
||||
@ -419,7 +434,15 @@ bool EmuTCPConnection::ConnectIP(uint32 irIP, uint16 irPort, char* errbuf) {
|
||||
sendbuf_used = sendbuf_size;
|
||||
sendbuf = new uchar[sendbuf_size];
|
||||
memcpy(sendbuf, "\0**PACKETMODEQS**\r", sendbuf_size);
|
||||
} else {
|
||||
}
|
||||
else if (PacketMode == packetModeSocket_Server) {
|
||||
safe_delete_array(sendbuf);
|
||||
sendbuf_size = 18;
|
||||
sendbuf_used = sendbuf_size;
|
||||
sendbuf = new uchar[sendbuf_size];
|
||||
memcpy(sendbuf, "\0**PACKETMODESS**\r", sendbuf_size);
|
||||
}
|
||||
else {
|
||||
//default: packetModeZone
|
||||
safe_delete_array(sendbuf);
|
||||
sendbuf_size = 20;
|
||||
|
||||
@ -30,7 +30,7 @@ class EmuTCPServer;
|
||||
class EmuTCPConnection : public TCPConnection {
|
||||
public:
|
||||
enum eTCPMode { modeConsole, modeTransition, modePacket };
|
||||
enum ePacketMode { packetModeZone, packetModeLauncher, packetModeLogin, packetModeUCS, packetModeQueryServ };
|
||||
enum ePacketMode { packetModeZone, packetModeLauncher, packetModeLogin, packetModeUCS, packetModeQueryServ, packetModeSocket_Server };
|
||||
|
||||
EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, SOCKET iSock, uint32 irIP, uint16 irPort, bool iOldFormat = false);
|
||||
EmuTCPConnection(bool iOldFormat = false, EmuTCPServer* iRelayServer = 0, eTCPMode iMode = modePacket); // for outgoing connections
|
||||
|
||||
@ -65,6 +65,13 @@ LOG_TYPE( QUERYSERV, CLIENT, DISABLED )
|
||||
LOG_TYPE( QUERYSERV, TRACE, DISABLED )
|
||||
LOG_TYPE( QUERYSERV, PACKETS, DISABLED)
|
||||
|
||||
LOG_CATEGORY(SOCKET_SERVER)
|
||||
LOG_TYPE(SOCKET_SERVER, INIT, ENABLED)
|
||||
LOG_TYPE(SOCKET_SERVER, ERROR, ENABLED)
|
||||
LOG_TYPE(SOCKET_SERVER, CLIENT, DISABLED)
|
||||
LOG_TYPE(SOCKET_SERVER, TRACE, DISABLED)
|
||||
LOG_TYPE(SOCKET_SERVER, PACKETS, DISABLED)
|
||||
|
||||
LOG_CATEGORY( SPAWNS )
|
||||
LOG_TYPE( SPAWNS, MAIN, DISABLED )
|
||||
LOG_TYPE( SPAWNS, CONDITIONS, DISABLED )
|
||||
|
||||
@ -8,6 +8,7 @@ enum EQEmuExePlatform
|
||||
ExePlatformWorld,
|
||||
ExePlatformLogin,
|
||||
ExePlatformQueryServ,
|
||||
ExePlatformSocket_Server,
|
||||
ExePlatformUCS,
|
||||
ExePlatformLaunch,
|
||||
ExePlatformSharedMemory,
|
||||
|
||||
@ -333,6 +333,8 @@ RULE_REAL ( Combat, AvgProcsPerMinute, 2.0)
|
||||
RULE_REAL ( Combat, ProcPerMinDexContrib, 0.075)
|
||||
RULE_REAL ( Combat, BaseProcChance, 0.035)
|
||||
RULE_REAL ( Combat, ProcDexDivideBy, 11000)
|
||||
RULE_BOOL ( Combat, AdjustSpecialProcPerMinute, true) //Set PPM for special abilities like HeadShot (Live does this as of 4-14)
|
||||
RULE_REAL ( Combat, AvgSpecialProcsPerMinute, 2.0) //Unclear what best value is atm.
|
||||
RULE_REAL ( Combat, BaseHitChance, 69.0)
|
||||
RULE_REAL ( Combat, NPCBonusHitChance, 26.0)
|
||||
RULE_REAL ( Combat, HitFalloffMinor, 5.0) //hit will fall off up to 5% over the initial level range
|
||||
|
||||
@ -1009,6 +1009,19 @@ uint32 GetMorphTrigger(uint32 spell_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IsCastonFadeDurationSpell(uint16 spell_id)
|
||||
{
|
||||
for (int i = 0; i < EFFECT_COUNT; ++i) {
|
||||
if (spells[spell_id].effectid[i] == SE_ImprovedSpellEffect
|
||||
|| spells[spell_id].effectid[i] == SE_BossSpellTrigger
|
||||
|| spells[spell_id].effectid[i] == SE_CastOnWearoff){
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetPartialMeleeRuneReduction(uint32 spell_id)
|
||||
{
|
||||
for (int i = 0; i < EFFECT_COUNT; ++i)
|
||||
|
||||
@ -190,9 +190,9 @@ typedef enum {
|
||||
#define SE_DivineAura 40 // implemented
|
||||
#define SE_Destroy 41 // implemented - Disintegrate, Banishment of Shadows
|
||||
#define SE_ShadowStep 42 // implemented
|
||||
//#define SE_Berserk 43 // not used
|
||||
#define SE_Lycanthropy 44 // implemented
|
||||
//#define SE_Vampirism 45 // not used
|
||||
#define SE_Berserk 43 // implemented (*not used in any known live spell) Makes client 'Berserk' giving crip blow chance.
|
||||
#define SE_Lycanthropy 44 // implemented
|
||||
#define SE_Vampirism 45 // implemented (*not used in any known live spell) Stackable lifetap from melee.
|
||||
#define SE_ResistFire 46 // implemented
|
||||
#define SE_ResistCold 47 // implemented
|
||||
#define SE_ResistPoison 48 // implemented
|
||||
@ -237,7 +237,7 @@ typedef enum {
|
||||
#define SE_MagnifyVision 87 // implemented - Telescope
|
||||
#define SE_Succor 88 // implemented - Evacuate/Succor lines
|
||||
#define SE_ModelSize 89 // implemented - Shrink, Growth
|
||||
#define SE_Cloak 90 // *not implemented - Used in only 2 spells
|
||||
//#define SE_Cloak 90 // *not implemented - Used in only 2 spells
|
||||
#define SE_SummonCorpse 91 // implemented
|
||||
#define SE_InstantHate 92 // implemented - add hate
|
||||
#define SE_StopRain 93 // implemented - Wake of Karana
|
||||
@ -307,7 +307,7 @@ typedef enum {
|
||||
#define SE_SpellDamageShield 157 // implemented - Petrad's Protection
|
||||
#define SE_Reflect 158 // implemented
|
||||
#define SE_AllStats 159 // implemented
|
||||
#define SE_MakeDrunk 160 // implemented - poorly though, should check against tolerance
|
||||
//#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance)
|
||||
#define SE_MitigateSpellDamage 161 // implemented - rune with max value
|
||||
#define SE_MitigateMeleeDamage 162 // implemented - rune with max value
|
||||
#define SE_NegateAttacks 163 // implemented
|
||||
@ -339,48 +339,48 @@ typedef enum {
|
||||
#define SE_CurrentEndurance 189 // implemented
|
||||
#define SE_EndurancePool 190 // implemented
|
||||
#define SE_Amnesia 191 // implemented - Silence vs Melee Effect
|
||||
#define SE_Hate2 192 // implemented
|
||||
#define SE_Hate 192 // implemented - Instant and hate over time.
|
||||
#define SE_SkillAttack 193 // implemented
|
||||
#define SE_FadingMemories 194 // implemented
|
||||
#define SE_StunResist 195 // implemented
|
||||
#define SE_Strikethrough 196 // implemented
|
||||
#define SE_StrikeThrough 196 // implemented
|
||||
#define SE_SkillDamageTaken 197 // implemented
|
||||
#define SE_CurrentEnduranceOnce 198 // implemented
|
||||
#define SE_Taunt 199 // implemented - % chance to taunt the target
|
||||
#define SE_ProcChance 200 // implemented
|
||||
#define SE_RangedProc 201 // implemented
|
||||
//#define SE_IllusionOther 202 // *not implemented as bonus(Project Illusion)
|
||||
//#define SE_MassGroupBuff 203 // *not implemented as bonus
|
||||
#define SE_GroupFearImmunity 204 // *not implemented as bonus
|
||||
#define SE_IllusionOther 202 // implemented - Project Illusion
|
||||
#define SE_MassGroupBuff 203 // implemented
|
||||
#define SE_GroupFearImmunity 204 // implemented - (Does not use bonus)
|
||||
#define SE_Rampage 205 // implemented
|
||||
#define SE_AETaunt 206 // implemented
|
||||
#define SE_FleshToBone 207 // implemented
|
||||
//#define SE_PurgePoison 208 // not used
|
||||
#define SE_DispelBeneficial 209 // implemented
|
||||
//#define SE_PetShield 210 // *not implemented
|
||||
#define SE_AEMelee 211 // implemented
|
||||
#define SE_AEMelee 211 // implemented TO DO: Implement to allow NPC use (client only atm).
|
||||
#define SE_FrenziedDevastation 212 // implemented - increase spell criticals + all DD spells cast 2x mana.
|
||||
#define SE_PetMaxHP 213 // implemented[AA] - increases the maximum hit points of your pet
|
||||
#define SE_MaxHPChange 214 // implemented
|
||||
#define SE_PetAvoidance 215 // implemented[AA] - increases pet ability to avoid melee damage
|
||||
#define SE_Accuracy 216 // implemented
|
||||
//#define SE_HeadShot 217 // not implemented as bonus - ability to head shot (base2 = damage)
|
||||
#define SE_HeadShot 217 // implemented - ability to head shot (base2 = damage)
|
||||
#define SE_PetCriticalHit 218 // implemented[AA] - gives pets a baseline critical hit chance
|
||||
#define SE_SlayUndead 219 // implemented - Allow extra damage against undead (base1 = rate, base2 = damage mod).
|
||||
#define SE_SkillDamageAmount 220 // implemented
|
||||
#define SE_Packrat 221 // implemented as bonus
|
||||
#define SE_BlockBehind 222 // implemented - Chance to block from behind (with our without Shield)
|
||||
//#define SE_DoubleRiposte 223 // not used
|
||||
#define SE_DoubleRiposte 223 // implemented - Chance to double riposte [not used on live]
|
||||
#define SE_GiveDoubleRiposte 224 // implemented[AA]
|
||||
#define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance.
|
||||
#define SE_TwoHandBash 226 // *not implemented as bonus
|
||||
#define SE_ReduceSkillTimer 227 // implemented
|
||||
#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling
|
||||
//#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling
|
||||
#define SE_PersistantCasting 229 // implemented
|
||||
//#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
|
||||
#define SE_StunBashChance 231 // implemented - increase chance to stun from bash.
|
||||
#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save)
|
||||
//#define SE_Metabolism 233 // *not implemented - (Crown of Feathers) Increase metabolism?
|
||||
#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates.
|
||||
//#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
|
||||
#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live.
|
||||
//#define SE_FreePet 236 // not used
|
||||
@ -388,7 +388,7 @@ typedef enum {
|
||||
//#define SE_IllusionPersistence 238 // *not implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed.
|
||||
//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
|
||||
//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.]
|
||||
#define SE_ImprovedReclaimEnergy 241 // not implemented as bonus - increase the amount of mana returned to you when reclaiming your pet.
|
||||
#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet.
|
||||
#define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr
|
||||
#define SE_CharmBreakChance 243 // implemented - Total Domination
|
||||
#define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break.
|
||||
@ -410,7 +410,7 @@ typedef enum {
|
||||
#define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType
|
||||
#define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live)
|
||||
#define SE_RaiseStatCap 262 // implemented
|
||||
#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master.
|
||||
//#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master.
|
||||
//#define SE_HastenedAASkill 264 // not implemented as bonus - Use redux field in aa_actions table for this effect
|
||||
#define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled
|
||||
#define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon.
|
||||
@ -492,8 +492,8 @@ typedef enum {
|
||||
#define SE_ImmuneFleeing 342 // implemented - stop mob from fleeing
|
||||
#define SE_InterruptCasting 343 // implemented - % chance to interrupt spells being cast every tic. Cacophony (8272)
|
||||
#define SE_ChannelChanceItems 344 // implemented[AA] - chance to not have ITEM effects interrupted when you take damage.
|
||||
//#define SE_AssassinationLevel 345 // not implemented as bonus - AA Assisination max level to kill
|
||||
//#define SE_HeadShotLevel 346 // not implemented as bonus - AA HeadShot max level to kill
|
||||
#define SE_AssassinateLevel 345 // implemented as bonus - AA Assisination max level to kill
|
||||
#define SE_HeadShotLevel 346 // implemented[AA] - HeadShot max level to kill
|
||||
#define SE_DoubleRangedAttack 347 // implemented - chance at an additional archery attack (consumes arrow)
|
||||
#define SE_LimitManaMin 348 // implemented
|
||||
#define SE_ShieldEquipHateMod 349 // implemented[AA] Increase melee hate when wearing a shield.
|
||||
@ -506,13 +506,13 @@ typedef enum {
|
||||
//#define SE_ChangeTriggerType 356 // not used
|
||||
#define SE_FcMute 357 // implemented - silences casting of spells that contain specific spell effects (focus limited)
|
||||
#define SE_CurrentManaOnce 358 // implemented
|
||||
#define SE_Invulnerabilty 359 // *not implemented - Invulnerability (Brell's Blessing)
|
||||
#define SE_SpellOnKill 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level
|
||||
//#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing)
|
||||
#define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level
|
||||
#define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed
|
||||
//#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
|
||||
//#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
|
||||
#define SE_TripleAttackChance 364 // implemented
|
||||
#define SE_SpellOnKill2 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin)
|
||||
#define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin)
|
||||
#define SE_ShieldEquipDmgMod 366 // implemented[AA] Damage modifier to melee if shield equiped. (base1 = dmg mod , base2 = ?) ie Shield Specialist AA
|
||||
#define SE_SetBodyType 367 // implemented - set body type of base1 so it can be affected by spells that are limited to that type (Plant, Animal, Undead, etc)
|
||||
//#define SE_FactionMod 368 // *not implemented - increases faction with base1 (faction id, live won't match up w/ ours) by base2
|
||||
@ -544,7 +544,7 @@ typedef enum {
|
||||
#define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions.
|
||||
#define SE_FcHealPctCritIncoming 395 // implemented[AA] - Increases chance of having a heal crit when cast on you. [focus limited]
|
||||
#define SE_FcHealAmtCrit 396 // implemented - Adds a direct healing amount to spells
|
||||
//#define SE_PetMeleeMitigation 397 // *not implemented[AA] - additional mitigation to your pets.
|
||||
#define SE_PetMeleeMitigation 397 // implemented[AA] - additional mitigation to your pets. Adds AC.
|
||||
#define SE_SwarmPetDuration 398 // implemented - Affects the duration of swarm pets
|
||||
#define SE_FcTwincast 399 // implemented - cast 2 spells for every 1
|
||||
#define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained
|
||||
@ -586,27 +586,27 @@ typedef enum {
|
||||
//#define SE_BeneficialCountDownHold 436 // not used ( 23491 | ABTest Buff Hold)
|
||||
//#define SE_TeleporttoAnchor 437 // *not implemented - Teleport Guild Hall Anchor(33099)
|
||||
//#define SE_TranslocatetoAnchor 438 // *not implemented - Translocate Primary Anchor (27750)
|
||||
//#define SE_IncreaseAssassinationLvl 439 // *not implemented[AA] - increases the maximum level of humanoid that can be affected by assassination
|
||||
#define SE_Assassinate 439 // implemented[AA] - Assassinate damage
|
||||
#define SE_FinishingBlowLvl 440 // implemented[AA] - Sets the level Finishing blow can be triggered on an NPC
|
||||
#define SE_DistanceRemoval 441 // implemented - Buff is removed from target when target moves X amount of distance away from where initially hit.
|
||||
#define SE_TriggerOnReqTarget 442 // implemented - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist)
|
||||
#define SE_TriggerOnReqCaster 443 // implemented - triggers a spell which a certain criteria are met (below X amount of hp,mana,end, number of pets on hatelist)
|
||||
#define SE_ImprovedTaunt 444 // implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y
|
||||
//#define SE_AddMercSlot 445 // *not implemented[AA] - [Hero's Barracks] Allows you to conscript additional mercs.
|
||||
//#define SE_AStacker 446 // *not implementet - bufff stacking blocker ? (26219 | Qirik's Watch)
|
||||
//#define SE_BStacker 447 // *not implemented
|
||||
//#define SE_CStacker 448 // *not implemented
|
||||
//#define SE_DStacker 449 // *not implemented
|
||||
#define SE_AStacker 446 // implementet - bufff stacking blocker (26219 | Qirik's Watch)
|
||||
#define SE_BStacker 447 // implemented
|
||||
#define SE_CStacker 448 // implemented
|
||||
#define SE_DStacker 449 // implemented
|
||||
#define SE_MitigateDotDamage 450 // implemented DOT spell mitigation rune with max value
|
||||
#define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage
|
||||
#define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage
|
||||
#define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken
|
||||
#define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken
|
||||
//#define SE_AddHatePct 455 // not used
|
||||
//#define SE_AddHateOverTimePct 456 // not used
|
||||
#define SE_AddHatePct 455 // implemented Modify total hate by %
|
||||
#define SE_AddHateOverTimePct 456 // implemented Modify total hate by % over time.
|
||||
//#define SE_ResourceTap 457 // not used
|
||||
//#define SE_FactionModPct 458 // not used
|
||||
//#define SE_DamageModifier2 459 // *not implemented - Modifies melee damage by skill type
|
||||
#define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type
|
||||
|
||||
// LAST
|
||||
|
||||
@ -833,6 +833,7 @@ 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);
|
||||
uint32 GetPartialMeleeRuneReduction(uint32 spell_id);
|
||||
uint32 GetPartialMagicRuneReduction(uint32 spell_id);
|
||||
uint32 GetPartialMeleeRuneAmount(uint32 spell_id);
|
||||
|
||||
@ -13,12 +13,17 @@
|
||||
# include <boost/mpl/next.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
|
||||
namespace luabind {
|
||||
namespace luabind { namespace adl {
|
||||
|
||||
class object;
|
||||
class argument;
|
||||
template <class Base>
|
||||
struct table;
|
||||
class object;
|
||||
class argument;
|
||||
template <class Base>
|
||||
struct table;
|
||||
} // namespace adl
|
||||
|
||||
using adl::object;
|
||||
using adl::argument;
|
||||
using adl::table;
|
||||
|
||||
} // namespace luabind
|
||||
|
||||
|
||||
44
socket_server/CMakeLists.txt
Normal file
44
socket_server/CMakeLists.txt
Normal file
@ -0,0 +1,44 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
SET(socket_server_sources
|
||||
database.cpp
|
||||
socket_server.cpp
|
||||
socket_server_config.cpp
|
||||
worldserver.cpp
|
||||
)
|
||||
|
||||
SET(socket_server_headers
|
||||
database.h
|
||||
socket_server_config.h
|
||||
worldserver.h
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(socket_server ${socket_server_sources} ${socket_server_headers})
|
||||
|
||||
INSTALL(TARGETS socket_server RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
ADD_DEFINITIONS(-DQSERV)
|
||||
|
||||
TARGET_LINK_LIBRARIES(socket_server Common ${Boost_LIBRARIES} debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
||||
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(socket_server PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
TARGET_LINK_LIBRARIES(socket_server "Ws2_32.lib")
|
||||
ENDIF(MSVC)
|
||||
|
||||
IF(MINGW)
|
||||
TARGET_LINK_LIBRARIES(socket_server "WS2_32")
|
||||
ENDIF(MINGW)
|
||||
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(socket_server "${CMAKE_DL_LIBS}")
|
||||
TARGET_LINK_LIBRARIES(socket_server "z")
|
||||
TARGET_LINK_LIBRARIES(socket_server "m")
|
||||
IF(NOT DARWIN)
|
||||
TARGET_LINK_LIBRARIES(socket_server "rt")
|
||||
ENDIF(NOT DARWIN)
|
||||
TARGET_LINK_LIBRARIES(socket_server "pthread")
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/Bin)
|
||||
131
socket_server/database.cpp
Normal file
131
socket_server/database.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
|
||||
// Disgrace: for windows compile
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#define snprintf _snprintf
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#else
|
||||
#include "../common/unix.h"
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "database.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
#include "../common/StringUtil.h"
|
||||
#include "../common/servertalk.h"
|
||||
|
||||
Database::Database ()
|
||||
{
|
||||
DBInitVars();
|
||||
}
|
||||
|
||||
/*
|
||||
Establish a connection to a mysql database with the supplied parameters
|
||||
*/
|
||||
|
||||
Database::Database(const char* host, const char* user, const char* passwd, const char* database, uint32 port)
|
||||
{
|
||||
DBInitVars();
|
||||
Connect(host, user, passwd, database, port);
|
||||
}
|
||||
|
||||
bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port)
|
||||
{
|
||||
uint32 errnum= 0;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
if (!Open(host, user, passwd, database, port, &errnum, errbuf))
|
||||
{
|
||||
LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf);
|
||||
HandleMysqlError(errnum);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile->write(EQEMuLog::Status, "Using database '%s' at %s:%d",database,host,port);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Database::DBInitVars() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Database::HandleMysqlError(uint32 errnum) {
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Close the connection to the database
|
||||
*/
|
||||
Database::~Database()
|
||||
{
|
||||
}
|
||||
|
||||
bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_len) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `value` from `variables` where `varname`='%s'", varname), errbuf, &result)) {
|
||||
|
||||
_log(UCS__ERROR, "Unable to get message count from database. %s %s", query, errbuf);
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
if (mysql_num_rows(result) != 1) {
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
snprintf(varvalue, varvalue_len, "%s", row[0]);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
54
socket_server/database.h
Normal file
54
socket_server/database.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CHATSERVER_DATABASE_H
|
||||
#define CHATSERVER_DATABASE_H
|
||||
|
||||
#define AUTHENTICATION_TIMEOUT 60
|
||||
#define INVALID_ID 0xFFFFFFFF
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "../common/types.h"
|
||||
#include "../common/dbcore.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
//atoi is not uint32 or uint32 safe!!!!
|
||||
#define atoul(str) strtoul(str, nullptr, 10)
|
||||
|
||||
class Database : public DBcore {
|
||||
public:
|
||||
Database();
|
||||
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
~Database();
|
||||
|
||||
bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len);
|
||||
protected:
|
||||
void HandleMysqlError(uint32 errnum);
|
||||
private:
|
||||
void DBInitVars();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
281
socket_server/socket_server.cpp
Normal file
281
socket_server/socket_server.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
#include <iostream>
|
||||
/*#include <boost/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>*/
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
using websocketpp::lib::thread;
|
||||
using websocketpp::lib::mutex;
|
||||
using websocketpp::lib::unique_lock;
|
||||
using websocketpp::lib::condition_variable;
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "../common/opcodemgr.h"
|
||||
#include "../common/EQStreamFactory.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/platform.h"
|
||||
#include "../common/crash.h"
|
||||
#include "database.h"
|
||||
#include "socket_server_config.h"
|
||||
#include "worldserver.h"
|
||||
#include <list>
|
||||
|
||||
#include <signal.h>
|
||||
volatile bool RunLoops = true;
|
||||
TimeoutManager timeout_manager;
|
||||
Database database;
|
||||
std::string WorldShortName;
|
||||
|
||||
const socket_server_config *Config;
|
||||
WorldServer *worldserver = 0;
|
||||
|
||||
void CatchSignal(int sig_num) {
|
||||
RunLoops = false;
|
||||
if(worldserver)
|
||||
worldserver->Disconnect();
|
||||
}
|
||||
|
||||
/* Web Sockets Start Shit */
|
||||
|
||||
enum action_type {
|
||||
SUBSCRIBE,
|
||||
UNSUBSCRIBE,
|
||||
MESSAGE
|
||||
};
|
||||
|
||||
struct action {
|
||||
action(action_type t, connection_hdl h) : type(t), hdl(h) {}
|
||||
action(action_type t, connection_hdl h, server::message_ptr m)
|
||||
: type(t), hdl(h), msg(m) {}
|
||||
|
||||
action_type type;
|
||||
websocketpp::connection_hdl hdl;
|
||||
server::message_ptr msg;
|
||||
};
|
||||
|
||||
class broadcast_server {
|
||||
public:
|
||||
broadcast_server() {
|
||||
// Initialize Asio Transport
|
||||
m_server.init_asio();
|
||||
|
||||
// Register handler callbacks
|
||||
m_server.set_open_handler(bind(&broadcast_server::on_open, this, ::_1));
|
||||
m_server.set_close_handler(bind(&broadcast_server::on_close, this, ::_1));
|
||||
m_server.set_message_handler(bind(&broadcast_server::on_message, this, ::_1, ::_2));
|
||||
}
|
||||
|
||||
void run(uint16_t port) {
|
||||
// listen on specified port
|
||||
m_server.listen(port);
|
||||
|
||||
// Start the server accept loop
|
||||
m_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
try {
|
||||
m_server.run();
|
||||
}
|
||||
catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
}
|
||||
catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
//std::cout << "on_open" << std::endl;
|
||||
m_actions.push(action(SUBSCRIBE, hdl));
|
||||
lock.unlock();
|
||||
m_action_cond.notify_one();
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
//std::cout << "on_close" << std::endl;
|
||||
m_actions.push(action(UNSUBSCRIBE, hdl));
|
||||
lock.unlock();
|
||||
m_action_cond.notify_one();
|
||||
}
|
||||
|
||||
void on_message(connection_hdl hdl, server::message_ptr msg) {
|
||||
// queue message up for sending by processing thread
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
msg->set_payload("Niggers");
|
||||
// std::cout << "on_message" << std::endl;
|
||||
m_actions.push(action(MESSAGE, hdl, msg));
|
||||
lock.unlock();
|
||||
m_action_cond.notify_one();
|
||||
}
|
||||
|
||||
void process_messages() {
|
||||
while (1) {
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
|
||||
while (m_actions.empty()) {
|
||||
m_action_cond.wait(lock);
|
||||
}
|
||||
|
||||
action a = m_actions.front();
|
||||
m_actions.pop();
|
||||
|
||||
lock.unlock();
|
||||
|
||||
if (a.type == SUBSCRIBE) {
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
m_connections.insert(a.hdl);
|
||||
}
|
||||
else if (a.type == UNSUBSCRIBE) {
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
m_connections.erase(a.hdl);
|
||||
}
|
||||
else if (a.type == MESSAGE) {
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
|
||||
con_list::iterator it;
|
||||
for (it = m_connections.begin(); it != m_connections.end(); ++it) {
|
||||
m_server.send(*it, a.msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// undefined.
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
typedef std::set<connection_hdl, std::owner_less<connection_hdl>> con_list;
|
||||
|
||||
server m_server;
|
||||
con_list m_connections;
|
||||
std::queue<action> m_actions;
|
||||
|
||||
mutex m_action_lock;
|
||||
mutex m_connection_lock;
|
||||
condition_variable m_action_cond;
|
||||
};
|
||||
|
||||
/* Web Sockets Shit End*/
|
||||
|
||||
int main() {
|
||||
|
||||
try {
|
||||
broadcast_server server_instance;
|
||||
|
||||
// Start a thread to run the processing loop
|
||||
thread t(bind(&broadcast_server::process_messages, &server_instance));
|
||||
|
||||
// Run the asio loop with the main thread
|
||||
server_instance.run(9002);
|
||||
|
||||
t.join();
|
||||
|
||||
}
|
||||
catch (std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
RegisterExecutablePlatform(ExePlatformSocket_Server);
|
||||
set_exception_handler();
|
||||
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
|
||||
_log(SOCKET_SERVER__INIT, "Starting EQEmu Socket Server.");
|
||||
if (!socket_server_config::LoadConfig()) {
|
||||
_log(SOCKET_SERVER__INIT, "Loading server configuration failed.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Config = socket_server_config::get();
|
||||
|
||||
if(!load_log_settings(Config->LogSettingsFile.c_str()))
|
||||
_log(SOCKET_SERVER__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
|
||||
else
|
||||
_log(SOCKET_SERVER__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());
|
||||
|
||||
WorldShortName = Config->ShortName;
|
||||
|
||||
/*
|
||||
_log(SOCKET_SERVER__INIT, "Connecting to MySQL...");
|
||||
|
||||
if (!database.Connect(
|
||||
Config->QSDatabaseHost.c_str(),
|
||||
Config->QSDatabaseUsername.c_str(),
|
||||
Config->QSDatabasePassword.c_str(),
|
||||
Config->QSDatabaseDB.c_str(),
|
||||
Config->QSDatabasePort)) {
|
||||
_log(WORLD__INIT_ERR, "Cannot continue without a database connection.");
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
if (signal(SIGINT, CatchSignal) == SIG_ERR) {
|
||||
_log(SOCKET_SERVER__ERROR, "Could not set signal handler");
|
||||
return 1;
|
||||
}
|
||||
if (signal(SIGTERM, CatchSignal) == SIG_ERR) {
|
||||
_log(SOCKET_SERVER__ERROR, "Could not set signal handler");
|
||||
return 1;
|
||||
}
|
||||
|
||||
worldserver = new WorldServer;
|
||||
worldserver->Connect();
|
||||
|
||||
while(RunLoops) {
|
||||
Timer::SetCurrentTime();
|
||||
if (InterserverTimer.Check()) {
|
||||
if (worldserver->TryReconnect() && (!worldserver->Connected()))
|
||||
worldserver->AsyncConnect();
|
||||
}
|
||||
worldserver->Process();
|
||||
timeout_manager.CheckTimeouts();
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UpdateWindowTitle(char* iNewTitle) {
|
||||
#ifdef _WINDOWS
|
||||
char tmp[500];
|
||||
if (iNewTitle) {
|
||||
snprintf(tmp, sizeof(tmp), "SOCKET_SERVER: %s", iNewTitle);
|
||||
}
|
||||
else {
|
||||
snprintf(tmp, sizeof(tmp), "SOCKET_SERVER");
|
||||
}
|
||||
SetConsoleTitle(tmp);
|
||||
#endif
|
||||
}
|
||||
28
socket_server/socket_server_config.cpp
Normal file
28
socket_server/socket_server_config.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "socket_server_config.h"
|
||||
|
||||
socket_server_config *socket_server_config::_chat_config = nullptr;
|
||||
|
||||
std::string socket_server_config::GetByName(const std::string &var_name) const {
|
||||
return(EQEmuConfig::GetByName(var_name));
|
||||
}
|
||||
|
||||
55
socket_server/socket_server_config.h
Normal file
55
socket_server/socket_server_config.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __socket_server_config_H
|
||||
#define __socket_server_config_H
|
||||
|
||||
#include "../common/EQEmuConfig.h"
|
||||
|
||||
class socket_server_config : public EQEmuConfig {
|
||||
public:
|
||||
virtual std::string GetByName(const std::string &var_name) const;
|
||||
|
||||
private:
|
||||
|
||||
static socket_server_config *_chat_config;
|
||||
|
||||
public:
|
||||
|
||||
// Produce a const singleton
|
||||
static const socket_server_config *get() {
|
||||
if (_chat_config == nullptr)
|
||||
LoadConfig();
|
||||
return(_chat_config);
|
||||
}
|
||||
|
||||
// Load the config
|
||||
static bool LoadConfig() {
|
||||
if (_chat_config != nullptr)
|
||||
delete _chat_config;
|
||||
_chat_config=new socket_server_config;
|
||||
_config=_chat_config;
|
||||
|
||||
return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
68
socket_server/worldserver.cpp
Normal file
68
socket_server/worldserver.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "../common/servertalk.h"
|
||||
#include "worldserver.h"
|
||||
#include "socket_server_config.h"
|
||||
#include "database.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "../common/md5.h"
|
||||
#include "../common/packet_dump.h"
|
||||
|
||||
extern WorldServer worldserver;
|
||||
extern const socket_server_config *Config;
|
||||
extern Database database;
|
||||
|
||||
WorldServer::WorldServer()
|
||||
: WorldConnection(EmuTCPConnection::packetModeSocket_Server, Config->SharedKey.c_str()){
|
||||
pTryReconnect = true;
|
||||
}
|
||||
|
||||
WorldServer::~WorldServer(){
|
||||
}
|
||||
|
||||
void WorldServer::OnConnected(){
|
||||
_log(SOCKET_SERVER__INIT, "Connected to World.");
|
||||
WorldConnection::OnConnected();
|
||||
}
|
||||
|
||||
void WorldServer::Process(){
|
||||
WorldConnection::Process();
|
||||
if (!Connected())
|
||||
return;
|
||||
|
||||
ServerPacket *pack = 0;
|
||||
while((pack = tcpc.PopPacket())){
|
||||
_log(SOCKET_SERVER__TRACE, "Received Opcode: %4X", pack->opcode);
|
||||
switch(pack->opcode) {
|
||||
case 0: { break; }
|
||||
case ServerOP_KeepAlive: { break; }
|
||||
}
|
||||
}
|
||||
|
||||
safe_delete(pack);
|
||||
return;
|
||||
}
|
||||
35
socket_server/worldserver.h
Normal file
35
socket_server/worldserver.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef WORLDSERVER_H
|
||||
#define WORLDSERVER_H
|
||||
|
||||
#include "../common/worldconn.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
|
||||
class WorldServer : public WorldConnection
|
||||
{
|
||||
public:
|
||||
WorldServer();
|
||||
virtual ~WorldServer();
|
||||
virtual void Process();
|
||||
|
||||
private:
|
||||
virtual void OnConnected();
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
IF(UNIX)
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
ADD_SUBDIRECTORY(azone2)
|
||||
@ -1,119 +0,0 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
IF(NOT MSVC)
|
||||
ADD_DEFINITIONS(-fpermissive)
|
||||
ENDIF(NOT MSVC)
|
||||
|
||||
#azone common
|
||||
SET(azone_common_sources
|
||||
dat.cpp
|
||||
file.cpp
|
||||
global.cpp
|
||||
pfs.cpp
|
||||
ter.cpp
|
||||
wld.cpp
|
||||
zon.cpp
|
||||
zonv4.cpp
|
||||
)
|
||||
|
||||
SET(azone_common_headers
|
||||
3d.hpp
|
||||
3d_base.hpp
|
||||
archive.hpp
|
||||
dat.hpp
|
||||
file.hpp
|
||||
file_loader.hpp
|
||||
global.hpp
|
||||
octree.hpp
|
||||
pfs.hpp
|
||||
s3d.h
|
||||
ter.hpp
|
||||
types.h
|
||||
wld.hpp
|
||||
wld_structs.hpp
|
||||
zon.hpp
|
||||
zonv4.hpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(azone_common ${azone_common_sources} ${azone_common_headers})
|
||||
SET(LIBRARY_OUTPUT_PATH ../../Bin)
|
||||
|
||||
#azone
|
||||
SET(azone_sources
|
||||
azone.cpp
|
||||
)
|
||||
|
||||
SET(azone_headers
|
||||
azone.h
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(azone ${azone_sources} ${azone_headers})
|
||||
TARGET_LINK_LIBRARIES(azone azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(azone PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
TARGET_LINK_LIBRARIES(azone "Ws2_32.lib")
|
||||
ENDIF(MSVC)
|
||||
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(azone "z")
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ../../Bin)
|
||||
|
||||
#awater
|
||||
SET(awater_sources
|
||||
awater.cpp
|
||||
)
|
||||
|
||||
SET(awater_headers
|
||||
awater.h
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(awater ${awater_sources} ${awater_headers})
|
||||
TARGET_LINK_LIBRARIES(awater azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(awater PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
TARGET_LINK_LIBRARIES(awater "Ws2_32.lib")
|
||||
ENDIF(MSVC)
|
||||
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(awater "z")
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ../../Bin)
|
||||
|
||||
#listobj
|
||||
SET(listobj_sources
|
||||
listobj.cpp
|
||||
)
|
||||
|
||||
SET(listobj_headers
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(listobj ${listobj_sources} ${listobj_headers})
|
||||
TARGET_LINK_LIBRARIES(listobj azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(listobj PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
TARGET_LINK_LIBRARIES(listobj "Ws2_32.lib")
|
||||
ENDIF(MSVC)
|
||||
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(listobj "z")
|
||||
ENDIF(UNIX)
|
||||
|
||||
#on windows: glmodelviewer
|
||||
IF(MSVC)
|
||||
SET(glmodelviewer_sources
|
||||
GLModelViewer.cpp
|
||||
)
|
||||
|
||||
SET(glmodelviewer_headers
|
||||
GLModelViewer.h
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(glmodelviewer WIN32 ${glmodelviewer_sources} ${glmodelviewer_headers})
|
||||
TARGET_LINK_LIBRARIES(glmodelviewer azone_common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} "opengl32.lib" "GLU32.lib" "Ws2_32.lib")
|
||||
SET_TARGET_PROPERTIES(glmodelviewer PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ../../Bin)
|
||||
ENDIF(MSVC)
|
||||
2
utils/sql/git/optional/2014_06_29_HeadShotRules.sql
Normal file
2
utils/sql/git/optional/2014_06_29_HeadShotRules.sql
Normal file
@ -0,0 +1,2 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:AdjustSpecialProcPerMinute', 'false', 'Allow PPM for special abilities HeadShot, Assassinate, Decap ect.');
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:AvgSpecialProcsPerMinute', '2.0', 'Set PPM for special abilities HeadShot, Assassinate, Decap ect. (Unknown what value live uses) .');
|
||||
34
utils/sql/git/required/2014_06_25_AA_Updates..sql
Normal file
34
utils/sql/git/required/2014_06_25_AA_Updates..sql
Normal file
@ -0,0 +1,34 @@
|
||||
-- AA MGB update
|
||||
UPDATE altadv_vars SET spellid = 5228 WHERE skill_id = 128;
|
||||
UPDATE aa_actions SET spell_id = 5228, nonspell_action = 0 WHERE aaid = 128;
|
||||
|
||||
-- AA Project Illusion update
|
||||
UPDATE altadv_vars SET spellid = 5227 WHERE skill_id = 643;
|
||||
UPDATE aa_actions SET spell_id = 5227, nonspell_action = 0 WHERE aaid = 643;
|
||||
|
||||
-- AA Improved Reclaim Energy
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('180', '1', '241', '95', '0');
|
||||
|
||||
-- AA Headshot
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '1', '217', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '2', '346', '46', '0');
|
||||
|
||||
-- AA Anatomy (Rogue Assassinate)
|
||||
INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`, `sof_current_level`,`sof_next_id`,`level_inc`) VALUES ('1604', 'Anatomy', '5', '3', '4294967295', '4294967295', '1604', '1604', '1', '4294967295', '0', '0', '0', '0', '512', '0', '60', '1', '10', '4294967295', '3', '0', '3', '1604', '1', '0', '0', '0', '0');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '1', '439', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '2', '345', '48', '0');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '1', '439', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '2', '345', '51', '0');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '1', '439', '0', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '2', '345', '53', '0');
|
||||
|
||||
-- AA Finishing Blow Fix
|
||||
DELETE FROM aa_effects WHERE aaid = 199 AND slot = 2;
|
||||
DELETE FROM aa_effects WHERE aaid = 200 AND slot = 2;
|
||||
DELETE FROM aa_effects WHERE aaid = 201 AND slot = 2;
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '1', '278', '500', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '2', '440', '50', '200');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '1', '278', '500', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '2', '440', '52', '200');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '1', '278', '500', '32000');
|
||||
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '2', '440', '54', '200');
|
||||
@ -23,6 +23,7 @@ SET(world_sources
|
||||
perl_EQW.cpp
|
||||
perl_HTTPRequest.cpp
|
||||
queryserv.cpp
|
||||
socket_server.cpp
|
||||
ucs.cpp
|
||||
wguild_mgr.cpp
|
||||
world_logsys.cpp
|
||||
@ -53,6 +54,7 @@ SET(world_headers
|
||||
LoginServerList.h
|
||||
net.h
|
||||
queryserv.h
|
||||
socket_server.h
|
||||
SoFCharCreateData.h
|
||||
ucs.h
|
||||
wguild_mgr.h
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
#include "LauncherList.h"
|
||||
#include "ucs.h"
|
||||
#include "queryserv.h"
|
||||
#include "socket_server.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
@ -60,6 +61,7 @@ extern ClientList client_list;
|
||||
extern LauncherList launcher_list;
|
||||
extern UCSConnection UCSLink;
|
||||
extern QueryServConnection QSLink;
|
||||
extern Socket_Server_Connection SSLink;
|
||||
extern volatile bool RunLoops;
|
||||
|
||||
ConsoleList console_list;
|
||||
@ -250,18 +252,26 @@ bool Console::Process() {
|
||||
_log(WORLD__CONSOLE,"New launcher from %s:%d", inet_ntoa(in), GetPort());
|
||||
launcher_list.Add(tcpc);
|
||||
tcpc = 0;
|
||||
} else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS)
|
||||
}
|
||||
else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS)
|
||||
{
|
||||
_log(WORLD__CONSOLE,"New UCS Connection from %s:%d", inet_ntoa(in), GetPort());
|
||||
UCSLink.SetConnection(tcpc);
|
||||
tcpc = 0;
|
||||
}
|
||||
else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ)
|
||||
else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ)
|
||||
{
|
||||
_log(WORLD__CONSOLE,"New QS Connection from %s:%d", inet_ntoa(in), GetPort());
|
||||
QSLink.SetConnection(tcpc);
|
||||
tcpc = 0;
|
||||
} else {
|
||||
}
|
||||
else if (tcpc->GetPacketMode() == EmuTCPConnection::packetModeSocket_Server)
|
||||
{
|
||||
_log(WORLD__CONSOLE, "New Socket Server Connection from %s:%d", inet_ntoa(in), GetPort());
|
||||
SSLink.SetConnection(tcpc);
|
||||
tcpc = 0;
|
||||
}
|
||||
else {
|
||||
_log(WORLD__CONSOLE,"Unsupported packet mode from %s:%d", inet_ntoa(in), GetPort());
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -86,6 +86,7 @@
|
||||
#include "AdventureManager.h"
|
||||
#include "ucs.h"
|
||||
#include "queryserv.h"
|
||||
#include "socket_server.h"
|
||||
|
||||
TimeoutManager timeout_manager;
|
||||
EQStreamFactory eqsf(WorldStream,9000);
|
||||
@ -97,6 +98,7 @@ LoginServerList loginserverlist;
|
||||
EQWHTTPServer http_server;
|
||||
UCSConnection UCSLink;
|
||||
QueryServConnection QSLink;
|
||||
Socket_Server_Connection SSLink;
|
||||
LauncherList launcher_list;
|
||||
AdventureManager adventure_manager;
|
||||
DBAsync *dbasync = nullptr;
|
||||
@ -454,6 +456,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
QSLink.Process();
|
||||
|
||||
SSLink.Process();
|
||||
|
||||
LFPGroupList.Process();
|
||||
|
||||
adventure_manager.Process();
|
||||
|
||||
127
world/socket_server.cpp
Normal file
127
world/socket_server.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include "../common/debug.h"
|
||||
#include "Socket_Server.h"
|
||||
#include "WorldConfig.h"
|
||||
#include "clientlist.h"
|
||||
#include "zonelist.h"
|
||||
#include "../common/logsys.h"
|
||||
#include "../common/logtypes.h"
|
||||
#include "../common/md5.h"
|
||||
#include "../common/EmuTCPConnection.h"
|
||||
#include "../common/packet_dump.h"
|
||||
|
||||
extern ClientList client_list;
|
||||
extern ZSList zoneserver_list;
|
||||
|
||||
Socket_Server_Connection::Socket_Server_Connection()
|
||||
{
|
||||
Stream = 0;
|
||||
authenticated = false;
|
||||
}
|
||||
|
||||
void Socket_Server_Connection::SetConnection(EmuTCPConnection *inStream)
|
||||
{
|
||||
if(Stream)
|
||||
{
|
||||
_log(SOCKET_SERVER__ERROR, "Incoming Socket_Server Connection while we were already connected to a Socket_Server.");
|
||||
Stream->Disconnect();
|
||||
}
|
||||
|
||||
Stream = inStream;
|
||||
|
||||
authenticated = false;
|
||||
}
|
||||
|
||||
bool Socket_Server_Connection::Process()
|
||||
{
|
||||
if (!Stream || !Stream->Connected())
|
||||
return false;
|
||||
|
||||
ServerPacket *pack = 0;
|
||||
|
||||
while((pack = Stream->PopPacket()))
|
||||
{
|
||||
if (!authenticated)
|
||||
{
|
||||
if (WorldConfig::get()->SharedKey.length() > 0)
|
||||
{
|
||||
if (pack->opcode == ServerOP_ZAAuth && pack->size == 16)
|
||||
{
|
||||
uint8 tmppass[16];
|
||||
|
||||
MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass);
|
||||
|
||||
if (memcmp(pack->pBuffer, tmppass, 16) == 0)
|
||||
authenticated = true;
|
||||
else
|
||||
{
|
||||
struct in_addr in;
|
||||
in.s_addr = GetIP();
|
||||
_log(SOCKET_SERVER__ERROR, "Socket_Server authorization failed.");
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
|
||||
SendPacket(pack);
|
||||
delete pack;
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct in_addr in;
|
||||
in.s_addr = GetIP();
|
||||
_log(SOCKET_SERVER__ERROR, "Socket_Server_ authorization failed.");
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
|
||||
SendPacket(pack);
|
||||
delete pack;
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log(SOCKET_SERVER__ERROR,"**WARNING** You have not configured a world shared key in your config file. You should add a <key>STRING</key> element to your <world> element to prevent unauthorized zone access.");
|
||||
authenticated = true;
|
||||
}
|
||||
delete pack;
|
||||
continue;
|
||||
}
|
||||
switch(pack->opcode)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case ServerOP_KeepAlive:
|
||||
{
|
||||
// ignore this
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZAAuth:
|
||||
{
|
||||
_log(SOCKET_SERVER__ERROR, "Got authentication from Socket_Server_ when they are already authenticated.");
|
||||
break;
|
||||
}
|
||||
case ServerOP_LFGuildUpdate:
|
||||
{
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
_log(SOCKET_SERVER__ERROR, "Unknown ServerOPcode from Socket_Server_ 0x%04x, size %d", pack->opcode, pack->size);
|
||||
DumpPacket(pack->pBuffer, pack->size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete pack;
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool Socket_Server_Connection::SendPacket(ServerPacket* pack)
|
||||
{
|
||||
if(!Stream)
|
||||
return false;
|
||||
|
||||
return Stream->SendPacket(pack);
|
||||
}
|
||||
|
||||
23
world/socket_server.h
Normal file
23
world/socket_server.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef Socket_Server__H
|
||||
#define Socket_Server__H
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/EmuTCPConnection.h"
|
||||
#include "../common/servertalk.h"
|
||||
|
||||
class Socket_Server_Connection
|
||||
{
|
||||
public:
|
||||
Socket_Server_Connection();
|
||||
void SetConnection(EmuTCPConnection *inStream);
|
||||
bool Process();
|
||||
bool SendPacket(ServerPacket* pack);
|
||||
void Disconnect() { if(Stream) Stream->Disconnect(); }
|
||||
void SendMessage(const char *From, const char *Message);
|
||||
private:
|
||||
inline uint32 GetIP() const { return Stream ? Stream->GetrIP() : 0; }
|
||||
EmuTCPConnection *Stream;
|
||||
bool authenticated;
|
||||
};
|
||||
|
||||
#endif /*Socket_Server__H_*/
|
||||
11
zone/AA.cpp
11
zone/AA.cpp
@ -352,11 +352,6 @@ void Client::HandleAAAction(aaID activate) {
|
||||
entity_list.AETaunt(this);
|
||||
break;
|
||||
|
||||
case aaActionMassBuff:
|
||||
EnableAAEffect(aaEffectMassGroupBuff, 3600);
|
||||
Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range.
|
||||
break;
|
||||
|
||||
case aaActionFlamingArrows:
|
||||
//toggle it
|
||||
if(CheckAAEffect(aaEffectFlamingArrows))
|
||||
@ -459,12 +454,6 @@ void Client::HandleAAAction(aaID activate) {
|
||||
}
|
||||
break;
|
||||
|
||||
case aaActionProjectIllusion:
|
||||
EnableAAEffect(aaEffectProjectIllusion, 3600);
|
||||
Message(10, "The power of your next illusion spell will flow to your grouped target in your place.");
|
||||
break;
|
||||
|
||||
|
||||
case aaActionEscape:
|
||||
Escape();
|
||||
break;
|
||||
|
||||
@ -43,14 +43,14 @@ typedef enum {
|
||||
//use these for AAs which dont cast spells, yet need effects
|
||||
//if this list grows beyond 32, more work is needed in *AAEffect
|
||||
typedef enum { //AA Effect IDs
|
||||
aaEffectMassGroupBuff = 1,
|
||||
aaEffectMassGroupBuff = 1, //unused - Handled via spell effect.
|
||||
aaEffectRampage,
|
||||
aaEffectSharedHealth,
|
||||
aaEffectFlamingArrows,
|
||||
aaEffectFrostArrows,
|
||||
aaEffectWarcry,
|
||||
aaEffectLeechTouch,
|
||||
aaEffectProjectIllusion // seveian 2008-09-23
|
||||
aaEffectProjectIllusion // unused - Handled via spell effect
|
||||
} aaEffectType;
|
||||
|
||||
|
||||
|
||||
144
zone/attack.cpp
144
zone/attack.cpp
@ -560,11 +560,21 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
|
||||
weight = (CastToClient()->CalcCurrentWeight() / 10.0);
|
||||
} else if (IsNPC()) {
|
||||
armor = CastToNPC()->GetRawAC();
|
||||
int PetACBonus = 0;
|
||||
|
||||
if (!IsPet())
|
||||
armor = (armor / RuleR(Combat, NPCACFactor));
|
||||
else{
|
||||
Mob *owner = nullptr;
|
||||
owner = GetOwner();
|
||||
if (owner){
|
||||
PetACBonus = owner->aabonuses.PetMeleeMitigation
|
||||
+ owner->itembonuses.PetMeleeMitigation +
|
||||
owner->spellbonuses.PetMeleeMitigation;
|
||||
}
|
||||
}
|
||||
|
||||
armor += spellbonuses.AC + itembonuses.AC + 1;
|
||||
armor += spellbonuses.AC + itembonuses.AC + PetACBonus + 1;
|
||||
}
|
||||
|
||||
if (opts) {
|
||||
@ -1350,7 +1360,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
MeleeLifeTap(damage);
|
||||
|
||||
if (damage > 0)
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
//break invis when you attack
|
||||
if(invisible) {
|
||||
@ -1965,7 +1975,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
MeleeLifeTap(damage);
|
||||
|
||||
if (damage > 0)
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
//break invis when you attack
|
||||
if(invisible) {
|
||||
@ -3176,7 +3186,11 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot , true);
|
||||
}
|
||||
return -6;
|
||||
|
||||
if (spellbonuses.NegateAttacks[2] && (damage > spellbonuses.NegateAttacks[2]))
|
||||
damage -= spellbonuses.NegateAttacks[2];
|
||||
else
|
||||
return -6;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3188,11 +3202,11 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
{
|
||||
DisableMeleeRune = true;
|
||||
int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100;
|
||||
if(damage_to_reduce > buffs[slot].melee_rune)
|
||||
if(damage_to_reduce >= buffs[slot].melee_rune)
|
||||
{
|
||||
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d"
|
||||
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune);
|
||||
damage -= damage_to_reduce;
|
||||
damage -= buffs[slot].melee_rune;
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
@ -3212,11 +3226,15 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
if(slot >= 0)
|
||||
{
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateMeleeRune[0] / 100;
|
||||
if(damage_to_reduce > buffs[slot].melee_rune)
|
||||
|
||||
if (spellbonuses.MitigateMeleeRune[2] && (damage_to_reduce > spellbonuses.MitigateMeleeRune[2]))
|
||||
damage_to_reduce = spellbonuses.MitigateMeleeRune[2];
|
||||
|
||||
if(spellbonuses.MitigateMeleeRune[3] && (damage_to_reduce >= buffs[slot].melee_rune))
|
||||
{
|
||||
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
|
||||
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune);
|
||||
damage -= damage_to_reduce;
|
||||
damage -= buffs[slot].melee_rune;
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
@ -3224,7 +3242,10 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
{
|
||||
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
|
||||
" damage remaining.", damage_to_reduce, buffs[slot].melee_rune);
|
||||
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
|
||||
|
||||
if (spellbonuses.MitigateMeleeRune[3])
|
||||
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
|
||||
|
||||
damage -= damage_to_reduce;
|
||||
}
|
||||
}
|
||||
@ -3265,7 +3286,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
int32 slot = -1;
|
||||
|
||||
// See if we block the spell outright first
|
||||
if (spellbonuses.NegateAttacks[0]){
|
||||
if (!iBuffTic && spellbonuses.NegateAttacks[0]){
|
||||
slot = spellbonuses.NegateAttacks[1];
|
||||
if(slot >= 0) {
|
||||
if(--buffs[slot].numhits == 0) {
|
||||
@ -3273,7 +3294,11 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot , true);
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (spellbonuses.NegateAttacks[2] && (damage > spellbonuses.NegateAttacks[2]))
|
||||
damage -= spellbonuses.NegateAttacks[2];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3286,15 +3311,21 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
if(slot >= 0)
|
||||
{
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateDotRune[0] / 100;
|
||||
if(damage_to_reduce > buffs[slot].dot_rune)
|
||||
|
||||
if (spellbonuses.MitigateDotRune[2] && (damage_to_reduce > spellbonuses.MitigateDotRune[2]))
|
||||
damage_to_reduce = spellbonuses.MitigateDotRune[2];
|
||||
|
||||
if(spellbonuses.MitigateDotRune[3] && (damage_to_reduce >= buffs[slot].dot_rune))
|
||||
{
|
||||
damage -= damage_to_reduce;
|
||||
damage -= buffs[slot].dot_rune;
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce);
|
||||
if (spellbonuses.MitigateDotRune[3])
|
||||
buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce);
|
||||
|
||||
damage -= damage_to_reduce;
|
||||
}
|
||||
}
|
||||
@ -3316,9 +3347,9 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
{
|
||||
DisableSpellRune = true;
|
||||
int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100;
|
||||
if(damage_to_reduce > buffs[slot].magic_rune)
|
||||
if(damage_to_reduce >= buffs[slot].magic_rune)
|
||||
{
|
||||
damage -= damage_to_reduce;
|
||||
damage -= buffs[slot].magic_rune;
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
@ -3337,11 +3368,15 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
if(slot >= 0)
|
||||
{
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateSpellRune[0] / 100;
|
||||
if(damage_to_reduce > buffs[slot].magic_rune)
|
||||
|
||||
if (spellbonuses.MitigateSpellRune[2] && (damage_to_reduce > spellbonuses.MitigateSpellRune[2]))
|
||||
damage_to_reduce = spellbonuses.MitigateSpellRune[2];
|
||||
|
||||
if(spellbonuses.MitigateSpellRune[3] && (damage_to_reduce >= buffs[slot].magic_rune))
|
||||
{
|
||||
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
|
||||
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
|
||||
damage -= damage_to_reduce;
|
||||
damage -= buffs[slot].magic_rune;
|
||||
if(!TryFadeEffect(slot))
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
@ -3349,7 +3384,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
{
|
||||
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
|
||||
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
|
||||
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
|
||||
|
||||
if (spellbonuses.MitigateSpellRune[3])
|
||||
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
|
||||
|
||||
damage -= damage_to_reduce;
|
||||
}
|
||||
}
|
||||
@ -3393,7 +3431,7 @@ int32 Mob::ReduceAllDamage(int32 damage)
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
}
|
||||
|
||||
CheckNumHitsRemaining(8);
|
||||
CheckNumHitsRemaining(NUMHIT_IncomingDamage);
|
||||
|
||||
return(damage);
|
||||
}
|
||||
@ -3499,10 +3537,10 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
}
|
||||
|
||||
if (spell_id == SPELL_UNKNOWN && skill_used) {
|
||||
CheckNumHitsRemaining(1); //Incoming Hit Attempts
|
||||
CheckNumHitsRemaining(NUMHIT_IncomingHitAttempts);
|
||||
|
||||
if (attacker)
|
||||
attacker->CheckNumHitsRemaining(2); //Outgoing Hit Attempts
|
||||
attacker->CheckNumHitsRemaining(NUMHIT_OutgoingHitAttempts);
|
||||
}
|
||||
|
||||
if(attacker){
|
||||
@ -3576,7 +3614,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
|
||||
}
|
||||
|
||||
if (skill_used)
|
||||
CheckNumHitsRemaining(6); //Incomming Hit Success on Defender
|
||||
CheckNumHitsRemaining(NUMHIT_IncomingHitSuccess);
|
||||
|
||||
ReduceAllDamage(damage);
|
||||
|
||||
@ -3993,7 +4031,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int dam
|
||||
int chance = ProcChance * (DefensiveProcs[i].chance);
|
||||
if ((MakeRandomInt(0, 100) < chance)) {
|
||||
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(10,0,DefensiveProcs[i].base_spellID);
|
||||
CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4180,7 +4218,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
"Spell proc %d procing spell %d (%.2f percent chance)",
|
||||
i, SpellProcs[i].spellID, chance);
|
||||
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(11, 0, SpellProcs[i].base_spellID);
|
||||
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs, 0, SpellProcs[i].base_spellID);
|
||||
} else {
|
||||
mlog(COMBAT__PROCS,
|
||||
"Spell proc %d failed to proc %d (%.2f percent chance)",
|
||||
@ -4196,7 +4234,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
||||
"Ranged proc %d procing spell %d (%.2f percent chance)",
|
||||
i, RangedProcs[i].spellID, chance);
|
||||
ExecWeaponProc(nullptr, RangedProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(11, 0, RangedProcs[i].base_spellID);
|
||||
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs, 0, RangedProcs[i].base_spellID);
|
||||
} else {
|
||||
mlog(COMBAT__PROCS,
|
||||
"Ranged proc %d failed to proc %d (%.2f percent chance)",
|
||||
@ -4283,6 +4321,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
|
||||
|
||||
|
||||
float critChance = 0.0f;
|
||||
bool IsBerskerSPA = false;
|
||||
|
||||
//1: Try Slay Undead
|
||||
if(defender && defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire){
|
||||
@ -4310,12 +4349,15 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
|
||||
//are defined you will have an innate chance to hit at Level 1 regardless of bonuses.
|
||||
//Warning: Do not define these rules if you want live like critical hits.
|
||||
critChance += RuleI(Combat, MeleeBaseCritChance);
|
||||
|
||||
|
||||
if (IsClient()) {
|
||||
critChance += RuleI(Combat, ClientBaseCritChance);
|
||||
critChance += RuleI(Combat, ClientBaseCritChance);
|
||||
|
||||
if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) {
|
||||
if (IsBerserk())
|
||||
if (spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA)
|
||||
IsBerskerSPA = true;
|
||||
|
||||
if (((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) || IsBerskerSPA) {
|
||||
if (IsBerserk() || IsBerskerSPA)
|
||||
critChance += RuleI(Combat, BerserkBaseCritChance);
|
||||
else
|
||||
critChance += RuleI(Combat, WarBerBaseCritChance);
|
||||
@ -4360,15 +4402,15 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
|
||||
uint16 critMod = 200;
|
||||
bool crip_success = false;
|
||||
int16 CripplingBlowChance = GetCrippBlowChance();
|
||||
|
||||
|
||||
//Crippling Blow Chance: The percent value of the effect is applied
|
||||
//to the your Chance to Critical. (ie You have 10% chance to critical and you
|
||||
//have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow.
|
||||
if (CripplingBlowChance || IsBerserk()) {
|
||||
if (!IsBerserk())
|
||||
if (CripplingBlowChance || (IsBerserk() || IsBerskerSPA)) {
|
||||
if (!IsBerserk() && !IsBerskerSPA)
|
||||
critChance *= float(CripplingBlowChance)/100.0f;
|
||||
|
||||
if (IsBerserk() || MakeRandomFloat(0, 1) < critChance) {
|
||||
if ((IsBerserk() || IsBerskerSPA) || MakeRandomFloat(0, 1) < critChance) {
|
||||
critMod = 400;
|
||||
crip_success = true;
|
||||
}
|
||||
@ -4411,27 +4453,25 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
|
||||
|
||||
bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
|
||||
{
|
||||
if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){
|
||||
|
||||
if (!defender)
|
||||
return false;
|
||||
uint32 FB_Dmg = aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1];
|
||||
|
||||
uint16 FB_Level = 0;
|
||||
FB_Level = aabonuses.FinishingBlowLvl[0];
|
||||
if (FB_Level < spellbonuses.FinishingBlowLvl[0])
|
||||
FB_Level = spellbonuses.FinishingBlowLvl[0];
|
||||
else if (FB_Level < itembonuses.FinishingBlowLvl[0])
|
||||
FB_Level = itembonuses.FinishingBlowLvl[0];
|
||||
|
||||
if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10){
|
||||
//Proc Chance value of 500 = 5%
|
||||
uint32 ProcChance = (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0])/10;
|
||||
|
||||
uint32 chance = aabonuses.FinishingBlow[0]/10; //500 = 5% chance.
|
||||
uint32 damage = aabonuses.FinishingBlow[1];
|
||||
uint16 levelreq = aabonuses.FinishingBlowLvl[0];
|
||||
|
||||
if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){
|
||||
mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
|
||||
if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= MakeRandomInt(0, 1000))){
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
|
||||
defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
|
||||
DoSpecialAttackDamage(defender, skillinuse, FB_Dmg, 1, -1, 10, false, false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mlog(COMBAT__ATTACKS, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -4449,6 +4489,10 @@ void Mob::DoRiposte(Mob* defender) {
|
||||
defender->spellbonuses.GiveDoubleRiposte[0] +
|
||||
defender->itembonuses.GiveDoubleRiposte[0];
|
||||
|
||||
DoubleRipChance = defender->aabonuses.DoubleRiposte +
|
||||
defender->spellbonuses.DoubleRiposte +
|
||||
defender->itembonuses.DoubleRiposte;
|
||||
|
||||
//Live AA - Double Riposte
|
||||
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
|
||||
mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance);
|
||||
@ -4558,7 +4602,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, float chance)
|
||||
int ProcChance = chance * (float)SkillProcs[i].chance;
|
||||
if ((MakeRandomInt(0, 100) < ProcChance)) {
|
||||
ExecWeaponProc(nullptr, SkillProcs[i].spellID, on);
|
||||
CheckNumHitsRemaining(11,0, SkillProcs[i].base_spellID);
|
||||
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, SkillProcs[i].base_spellID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
310
zone/bonuses.cpp
310
zone/bonuses.cpp
@ -637,7 +637,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
continue;
|
||||
|
||||
_log(AA__BONUSES, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName());
|
||||
|
||||
|
||||
uint8 focus = IsFocusEffect(0, 0, true,effect);
|
||||
if (focus)
|
||||
{
|
||||
@ -953,6 +953,8 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
case SE_BlockBehind:
|
||||
newbon->BlockBehind += base1;
|
||||
break;
|
||||
|
||||
case SE_StrikeThrough:
|
||||
case SE_StrikeThrough2:
|
||||
newbon->StrikeThrough += base1;
|
||||
break;
|
||||
@ -987,7 +989,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
newbon->CrippBlowChance += base1;
|
||||
break;
|
||||
|
||||
case SE_SpellOnKill:
|
||||
case SE_ProcOnKillShot:
|
||||
for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3)
|
||||
{
|
||||
if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1)))
|
||||
@ -1099,6 +1101,15 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_DamageModifier2:
|
||||
{
|
||||
if(base2 == -1)
|
||||
newbon->DamageModifier2[HIGHEST_SKILL+1] += base1;
|
||||
else
|
||||
newbon->DamageModifier2[base2] += base1;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_SlayUndead:
|
||||
{
|
||||
if(newbon->SlayUndead[1] < base1)
|
||||
@ -1107,6 +1118,11 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_DoubleRiposte:
|
||||
{
|
||||
newbon->DoubleRiposte += base1;
|
||||
}
|
||||
|
||||
case SE_GiveDoubleRiposte:
|
||||
{
|
||||
//0=Regular Riposte 1=Skill Attack Riposte 2=Skill
|
||||
@ -1188,7 +1204,6 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
|
||||
case SE_FinishingBlow:
|
||||
{
|
||||
|
||||
//base1 = chance, base2 = damage
|
||||
if (newbon->FinishingBlow[1] < base2){
|
||||
newbon->FinishingBlow[0] = base1;
|
||||
@ -1234,6 +1249,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Vampirism:
|
||||
newbon->Vampirism += base1;
|
||||
break;
|
||||
|
||||
case SE_FrenziedDevastation:
|
||||
newbon->FrenziedDevastation += base2;
|
||||
break;
|
||||
@ -1242,6 +1261,60 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
newbon->SpellProcChance += base1;
|
||||
break;
|
||||
|
||||
case SE_Berserk:
|
||||
newbon->BerserkSPA = true;
|
||||
break;
|
||||
|
||||
case SE_Metabolism:
|
||||
newbon->Metabolism += base1;
|
||||
break;
|
||||
|
||||
case SE_ImprovedReclaimEnergy:
|
||||
{
|
||||
if((base1 < 0) && (newbon->ImprovedReclaimEnergy > base1))
|
||||
newbon->ImprovedReclaimEnergy = base1;
|
||||
|
||||
else if(newbon->ImprovedReclaimEnergy < base1)
|
||||
newbon->ImprovedReclaimEnergy = base1;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_HeadShot:
|
||||
{
|
||||
if(newbon->HeadShot[1] < base2){
|
||||
newbon->HeadShot[0] = base1;
|
||||
newbon->HeadShot[1] = base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_HeadShotLevel:
|
||||
{
|
||||
if(newbon->HSLevel < base1)
|
||||
newbon->HSLevel = base1;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Assassinate:
|
||||
{
|
||||
if(newbon->Assassinate[1] < base2){
|
||||
newbon->Assassinate[0] = base1;
|
||||
newbon->Assassinate[1] = base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_AssassinateLevel:
|
||||
{
|
||||
if(newbon->AssassinateLevel < base1)
|
||||
newbon->AssassinateLevel = base1;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_PetMeleeMitigation:
|
||||
newbon->PetMeleeMitigation += base1;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1813,6 +1886,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Vampirism:
|
||||
newbon->Vampirism += effect_value;
|
||||
break;
|
||||
|
||||
case SE_AllInstrumentMod:
|
||||
{
|
||||
if(effect_value > newbon->singingMod)
|
||||
@ -1909,6 +1986,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_DamageModifier2:
|
||||
{
|
||||
if(base2 == -1)
|
||||
newbon->DamageModifier2[HIGHEST_SKILL+1] += effect_value;
|
||||
else
|
||||
newbon->DamageModifier2[base2] += effect_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_MinDamageModifier:
|
||||
{
|
||||
if(base2 == -1)
|
||||
@ -2093,7 +2179,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
newbon->CriticalDoTChance += effect_value;
|
||||
break;
|
||||
|
||||
case SE_SpellOnKill:
|
||||
case SE_ProcOnKillShot:
|
||||
{
|
||||
for(int e = 0; e < MAX_SPELL_TRIGGER*3; e+=3)
|
||||
{
|
||||
@ -2256,9 +2342,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
|
||||
case SE_NegateAttacks:
|
||||
{
|
||||
if (!newbon->NegateAttacks[0]){
|
||||
if (!newbon->NegateAttacks[0] ||
|
||||
((newbon->NegateAttacks[0] && newbon->NegateAttacks[2]) && (newbon->NegateAttacks[2] < max))){
|
||||
newbon->NegateAttacks[0] = 1;
|
||||
newbon->NegateAttacks[1] = buffslot;
|
||||
newbon->NegateAttacks[2] = max;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2268,6 +2356,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
if (newbon->MitigateMeleeRune[0] < effect_value){
|
||||
newbon->MitigateMeleeRune[0] = effect_value;
|
||||
newbon->MitigateMeleeRune[1] = buffslot;
|
||||
newbon->MitigateMeleeRune[2] = base2;
|
||||
newbon->MitigateMeleeRune[3] = max;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2298,6 +2388,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
if (newbon->MitigateSpellRune[0] < effect_value){
|
||||
newbon->MitigateSpellRune[0] = effect_value;
|
||||
newbon->MitigateSpellRune[1] = buffslot;
|
||||
newbon->MitigateSpellRune[2] = base2;
|
||||
newbon->MitigateSpellRune[3] = max;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2307,6 +2399,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
if (newbon->MitigateDotRune[0] < effect_value){
|
||||
newbon->MitigateDotRune[0] = effect_value;
|
||||
newbon->MitigateDotRune[1] = buffslot;
|
||||
newbon->MitigateDotRune[2] = base2;
|
||||
newbon->MitigateDotRune[3] = max;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2422,6 +2516,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
newbon->SecondaryDmgInc = true;
|
||||
break;
|
||||
|
||||
case SE_StrikeThrough:
|
||||
case SE_StrikeThrough2:
|
||||
newbon->StrikeThrough += effect_value;
|
||||
break;
|
||||
@ -2553,6 +2648,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_DoubleRiposte:
|
||||
{
|
||||
newbon->DoubleRiposte += effect_value;
|
||||
}
|
||||
|
||||
case SE_GiveDoubleRiposte:
|
||||
{
|
||||
//Only allow for regular double riposte chance.
|
||||
@ -2661,6 +2761,101 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_AStacker:
|
||||
newbon->AStacker[0] = 1;
|
||||
newbon->AStacker[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_BStacker:
|
||||
newbon->BStacker[0] = 1;
|
||||
newbon->BStacker[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_CStacker:
|
||||
newbon->CStacker[0] = 1;
|
||||
newbon->CStacker[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_DStacker:
|
||||
newbon->DStacker[0] = 1;
|
||||
newbon->DStacker[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_Berserk:
|
||||
newbon->BerserkSPA = true;
|
||||
break;
|
||||
|
||||
|
||||
case SE_Metabolism:
|
||||
newbon->Metabolism += effect_value;
|
||||
break;
|
||||
|
||||
case SE_ImprovedReclaimEnergy:
|
||||
{
|
||||
if((effect_value < 0) && (newbon->ImprovedReclaimEnergy > effect_value))
|
||||
newbon->ImprovedReclaimEnergy = effect_value;
|
||||
|
||||
else if(newbon->ImprovedReclaimEnergy < effect_value)
|
||||
newbon->ImprovedReclaimEnergy = effect_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_HeadShot:
|
||||
{
|
||||
if(newbon->HeadShot[1] < base2){
|
||||
newbon->HeadShot[0] = effect_value;
|
||||
newbon->HeadShot[1] = base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_HeadShotLevel:
|
||||
{
|
||||
if(newbon->HSLevel < effect_value)
|
||||
newbon->HSLevel = effect_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Assassinate:
|
||||
{
|
||||
if(newbon->Assassinate[1] < base2){
|
||||
newbon->Assassinate[0] = effect_value;
|
||||
newbon->Assassinate[1] = base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_AssassinateLevel:
|
||||
{
|
||||
if(newbon->AssassinateLevel < effect_value)
|
||||
newbon->AssassinateLevel = effect_value;
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_FinishingBlow:
|
||||
{
|
||||
//base1 = chance, base2 = damage
|
||||
if (newbon->FinishingBlow[1] < base2){
|
||||
newbon->FinishingBlow[0] = effect_value;
|
||||
newbon->FinishingBlow[1] = base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_FinishingBlowLvl:
|
||||
{
|
||||
//base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?)
|
||||
if (newbon->FinishingBlowLvl[0] < effect_value){
|
||||
newbon->FinishingBlowLvl[0] = effect_value;
|
||||
newbon->FinishingBlowLvl[1] = base2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_PetMeleeMitigation:
|
||||
newbon->PetMeleeMitigation += effect_value;
|
||||
break;
|
||||
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
@ -3438,6 +3633,17 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_DamageModifier2:
|
||||
{
|
||||
for(int e = 0; e < HIGHEST_SKILL+1; e++)
|
||||
{
|
||||
spellbonuses.DamageModifier2[e] = effect_value;
|
||||
aabonuses.DamageModifier2[e] = effect_value;
|
||||
itembonuses.DamageModifier2[e] = effect_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_MinDamageModifier:
|
||||
{
|
||||
for(int e = 0; e < HIGHEST_SKILL+1; e++)
|
||||
@ -3583,7 +3789,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
itembonuses.CriticalDoTChance = effect_value;
|
||||
break;
|
||||
|
||||
case SE_SpellOnKill:
|
||||
case SE_ProcOnKillShot:
|
||||
{
|
||||
for(int e = 0; e < MAX_SPELL_TRIGGER*3; e=3)
|
||||
{
|
||||
@ -3821,6 +4027,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
itembonuses.SecondaryDmgInc = false;
|
||||
break;
|
||||
|
||||
case SE_StrikeThrough:
|
||||
spellbonuses.StrikeThrough = effect_value;
|
||||
aabonuses.StrikeThrough = effect_value;
|
||||
itembonuses.StrikeThrough = effect_value;
|
||||
break;
|
||||
|
||||
case SE_StrikeThrough2:
|
||||
spellbonuses.StrikeThrough = effect_value;
|
||||
aabonuses.StrikeThrough = effect_value;
|
||||
@ -3875,6 +4087,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
itembonuses.GivePetGroupTarget = false;
|
||||
break;
|
||||
|
||||
case SE_PetMeleeMitigation:
|
||||
spellbonuses.PetMeleeMitigation = effect_value;
|
||||
itembonuses.PetMeleeMitigation = effect_value;
|
||||
aabonuses.PetMeleeMitigation = effect_value;
|
||||
break;
|
||||
|
||||
case SE_RootBreakChance:
|
||||
spellbonuses.RootBreakChance = effect_value;
|
||||
aabonuses.RootBreakChance = effect_value;
|
||||
@ -3933,6 +4151,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
itembonuses.MasteryofPast = effect_value;
|
||||
break;
|
||||
|
||||
case SE_DoubleRiposte:
|
||||
spellbonuses.DoubleRiposte = effect_value;
|
||||
itembonuses.DoubleRiposte = effect_value;
|
||||
aabonuses.DoubleRiposte = effect_value;
|
||||
break;
|
||||
|
||||
case SE_GiveDoubleRiposte:
|
||||
spellbonuses.GiveDoubleRiposte[0] = effect_value;
|
||||
itembonuses.GiveDoubleRiposte[0] = effect_value;
|
||||
@ -4033,7 +4257,79 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
||||
spellbonuses.AbsorbMagicAtt[0] = effect_value;
|
||||
spellbonuses.AbsorbMagicAtt[1] = -1;
|
||||
break;
|
||||
|
||||
|
||||
case SE_Berserk:
|
||||
spellbonuses.BerserkSPA = false;
|
||||
aabonuses.BerserkSPA = false;
|
||||
itembonuses.BerserkSPA = false;
|
||||
break;
|
||||
|
||||
case SE_Vampirism:
|
||||
spellbonuses.Vampirism = effect_value;
|
||||
aabonuses.Vampirism = effect_value;
|
||||
itembonuses.Vampirism = effect_value;
|
||||
break;
|
||||
|
||||
case SE_Metabolism:
|
||||
spellbonuses.Metabolism = effect_value;
|
||||
aabonuses.Metabolism = effect_value;
|
||||
itembonuses.Metabolism = effect_value;
|
||||
break;
|
||||
|
||||
case SE_ImprovedReclaimEnergy:
|
||||
spellbonuses.ImprovedReclaimEnergy = effect_value;
|
||||
aabonuses.ImprovedReclaimEnergy = effect_value;
|
||||
itembonuses.ImprovedReclaimEnergy = effect_value;
|
||||
break;
|
||||
|
||||
case SE_HeadShot:
|
||||
spellbonuses.HeadShot[0] = effect_value;
|
||||
aabonuses.HeadShot[0] = effect_value;
|
||||
itembonuses.HeadShot[0] = effect_value;
|
||||
spellbonuses.HeadShot[1] = effect_value;
|
||||
aabonuses.HeadShot[1] = effect_value;
|
||||
itembonuses.HeadShot[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_HeadShotLevel:
|
||||
spellbonuses.HSLevel = effect_value;
|
||||
aabonuses.HSLevel = effect_value;
|
||||
itembonuses.HSLevel = effect_value;
|
||||
break;
|
||||
|
||||
case SE_Assassinate:
|
||||
spellbonuses.Assassinate[0] = effect_value;
|
||||
aabonuses.Assassinate[0] = effect_value;
|
||||
itembonuses.Assassinate[0] = effect_value;
|
||||
spellbonuses.Assassinate[1] = effect_value;
|
||||
aabonuses.Assassinate[1] = effect_value;
|
||||
itembonuses.Assassinate[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_AssassinateLevel:
|
||||
spellbonuses.AssassinateLevel = effect_value;
|
||||
aabonuses.AssassinateLevel = effect_value;
|
||||
itembonuses.AssassinateLevel = effect_value;
|
||||
break;
|
||||
|
||||
case SE_FinishingBlow:
|
||||
spellbonuses.FinishingBlow[0] = effect_value;
|
||||
aabonuses.FinishingBlow[0] = effect_value;
|
||||
itembonuses.FinishingBlow[0] = effect_value;
|
||||
spellbonuses.FinishingBlow[1] = effect_value;
|
||||
aabonuses.FinishingBlow[1] = effect_value;
|
||||
itembonuses.FinishingBlow[1] = effect_value;
|
||||
break;
|
||||
|
||||
case SE_FinishingBlowLvl:
|
||||
spellbonuses.FinishingBlowLvl[0] = effect_value;
|
||||
aabonuses.FinishingBlowLvl[0] = effect_value;
|
||||
itembonuses.FinishingBlowLvl[0] = effect_value;
|
||||
spellbonuses.FinishingBlowLvl[1] = effect_value;
|
||||
aabonuses.FinishingBlowLvl[1] = effect_value;
|
||||
itembonuses.FinishingBlowLvl[1] = effect_value;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1900,7 +1900,7 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
||||
newbon->UnfailingDivinity += base1;
|
||||
break;
|
||||
|
||||
case SE_SpellOnKill:
|
||||
case SE_ProcOnKillShot:
|
||||
for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3)
|
||||
{
|
||||
if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1)))
|
||||
@ -3389,7 +3389,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
return;
|
||||
|
||||
if (damage > 0)
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && MakeRandomInt(0, 99) < 25){
|
||||
SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff);
|
||||
@ -6632,7 +6632,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
|
||||
MeleeLifeTap(damage);
|
||||
|
||||
if (damage > 0)
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
//break invis when you attack
|
||||
if(invisible) {
|
||||
@ -8092,7 +8092,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
if (HasDied()) return;
|
||||
|
||||
if (max_damage > 0)
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
//[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill
|
||||
if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){
|
||||
|
||||
@ -8134,20 +8134,12 @@ void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_
|
||||
|
||||
uint16 cons_mod = 180;
|
||||
|
||||
switch(GetAA(aaInnateMetabolism)){
|
||||
case 1:
|
||||
cons_mod = cons_mod * 110 * RuleI(Character, ConsumptionMultiplier) / 10000;
|
||||
break;
|
||||
case 2:
|
||||
cons_mod = cons_mod * 125 * RuleI(Character, ConsumptionMultiplier) / 10000;
|
||||
break;
|
||||
case 3:
|
||||
cons_mod = cons_mod * 150 * RuleI(Character, ConsumptionMultiplier) / 10000;
|
||||
break;
|
||||
default:
|
||||
cons_mod = cons_mod * RuleI(Character, ConsumptionMultiplier) / 100;
|
||||
break;
|
||||
}
|
||||
int16 metabolism_bonus = spellbonuses.Metabolism + itembonuses.Metabolism + aabonuses.Metabolism;
|
||||
|
||||
if (metabolism_bonus)
|
||||
cons_mod = cons_mod * metabolism_bonus * RuleI(Character, ConsumptionMultiplier) / 10000;
|
||||
else
|
||||
cons_mod = cons_mod * RuleI(Character, ConsumptionMultiplier) / 100;
|
||||
|
||||
if(type == ItemTypeFood)
|
||||
{
|
||||
|
||||
@ -1177,7 +1177,7 @@ uint32 Client::CalcCurrentWeight() {
|
||||
Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4;
|
||||
}
|
||||
|
||||
float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat;
|
||||
float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat;
|
||||
if (Packrat > 0)
|
||||
Total = (uint32)((float)Total * (1.0f - ((Packrat * 1.0f) / 100.0f))); //AndMetal: 1% per level, up to 5% (calculated from Titanium client). verified thru client that it reduces coin weight by the same %
|
||||
//without casting to float & back to uint32, this didn't work right
|
||||
@ -1864,7 +1864,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const
|
||||
break;
|
||||
}
|
||||
|
||||
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap;
|
||||
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap;
|
||||
|
||||
if (effectmod < 10)
|
||||
effectmod = 10;
|
||||
|
||||
@ -150,6 +150,20 @@ enum TradeState {
|
||||
TradeCompleting
|
||||
};
|
||||
|
||||
enum { //Numhits type
|
||||
NUMHIT_IncomingHitAttempts = 1, //Attempted incoming melee attacks (hit or miss) on YOU.
|
||||
NUMHIT_OutgoingHitAttempts = 2, //Attempted outgoing melee attacks (hit or miss) on YOUR TARGET.
|
||||
NUMHIT_IncomingSpells = 3, //Incoming detrimental spells
|
||||
NUMHIT_OutgoingSpells = 4, //Outgoing deterimental spells
|
||||
NUMHIT_OutgoingHitSuccess = 5, //Successful outgoing melee attack HIT on YOUR TARGET.
|
||||
NUMHIT_IncomingHitSuccess = 6, //Successful incoming melee attack HIT on YOU.
|
||||
NUMHIT_MatchingSpells = 7, //Any casted spell matching/triggering a focus effect.
|
||||
NUMHIT_IncomingDamage = 8, //Successful incoming spell or melee dmg attack on YOU
|
||||
NUMHIT_ReflectSpell = 9, //Incoming Reflected spells.
|
||||
NUMHIT_DefensiveSpellProcs = 10, //Defensive buff procs
|
||||
NUMHIT_OffensiveSpellProcs = 11 //Offensive buff procs
|
||||
};
|
||||
|
||||
//this is our internal representation of the BUFF struct, can put whatever we want in it
|
||||
struct Buffs_Struct {
|
||||
uint16 spellid;
|
||||
@ -279,6 +293,7 @@ struct StatBonuses {
|
||||
int16 HitChance; //HitChance/15 == % increase i = Accuracy (Item: Accuracy)
|
||||
int16 HitChanceEffect[HIGHEST_SKILL+2]; //Spell effect Chance to Hit, straight percent increase
|
||||
int16 DamageModifier[HIGHEST_SKILL+2]; //i
|
||||
int16 DamageModifier2[HIGHEST_SKILL+2]; //i
|
||||
int16 MinDamageModifier[HIGHEST_SKILL+2]; //i
|
||||
int16 ProcChance; // ProcChance/10 == % increase i = CombatEffects
|
||||
int16 ProcChanceSPA; // ProcChance from spell effects
|
||||
@ -289,7 +304,8 @@ struct StatBonuses {
|
||||
int16 FlurryChance;
|
||||
int16 Accuracy[HIGHEST_SKILL+2]; //Accuracy/15 == % increase [Spell Effect: Accuracy)
|
||||
int16 HundredHands; //extra haste, stacks with all other haste i
|
||||
int8 MeleeLifetap; //i
|
||||
int16 MeleeLifetap; //i
|
||||
int16 Vampirism; //i
|
||||
int16 HealRate; // Spell effect that influences effectiveness of heals
|
||||
int32 MaxHPChange; // Spell Effect
|
||||
int16 SkillDmgTaken[HIGHEST_SKILL+2]; // All Skills + -1
|
||||
@ -326,12 +342,12 @@ struct StatBonuses {
|
||||
uint16 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
|
||||
bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses)
|
||||
int16 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage
|
||||
uint16 NegateAttacks[2]; // 0 = bool HasEffect 1 = Buff Slot
|
||||
uint16 MitigateMeleeRune[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
uint16 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit
|
||||
uint16 MitigateMeleeRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per hit 3 = Rune Amt
|
||||
uint16 MeleeThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger.
|
||||
uint16 SpellThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger.
|
||||
uint16 MitigateSpellRune[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
uint16 MitigateDotRune[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
uint16 MitigateSpellRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per spell 3 = Rune Amt
|
||||
uint16 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt
|
||||
uint32 TriggerMeleeThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger
|
||||
uint32 TriggerSpellThreshold[3]; // 0 = Spell Effect ID 1 = Buff slot 2 = Damage Amount to Trigger
|
||||
uint16 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot
|
||||
@ -350,6 +366,12 @@ struct StatBonuses {
|
||||
bool NegateIfCombat; // Bool Drop buff if cast or melee
|
||||
int8 Screech; // -1 = Will be blocked if another Screech is +(1)
|
||||
int16 AlterNPCLevel; // amount of lvls +/-
|
||||
int16 AStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value
|
||||
int16 BStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value
|
||||
int16 CStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value
|
||||
int16 DStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value
|
||||
bool BerserkSPA; // berserk effect
|
||||
int16 Metabolism; // Food/drink consumption rates.
|
||||
|
||||
// AAs
|
||||
int8 Packrat; //weight reduction for items, 1 point = 10%
|
||||
@ -378,6 +400,7 @@ struct StatBonuses {
|
||||
int16 PetCriticalHit; // Allow pets to critical hit with % value.
|
||||
int16 PetAvoidance; // Pet avoidance chance.
|
||||
int16 CombatStability; // Melee damage mitigation.
|
||||
int16 DoubleRiposte; // Chance to double riposte
|
||||
int16 GiveDoubleRiposte[3]; // 0=Regular Chance, 1=Skill Attack Chance, 2=Skill
|
||||
uint16 RaiseSkillCap[2]; // Raise a specific skill cap (1 = value, 2=skill)
|
||||
int16 Ambidexterity; // Increase chance to duel wield by adding bonus 'skill'.
|
||||
@ -399,6 +422,13 @@ struct StatBonuses {
|
||||
int8 StunBashChance; // chance to stun with bash.
|
||||
int8 IncreaseChanceMemwipe; // increases chance to memory wipe
|
||||
int8 CriticalMend; // chance critical monk mend
|
||||
int16 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy
|
||||
uint32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg
|
||||
uint8 HSLevel; // Max Level Headshot will be effective at.
|
||||
uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg
|
||||
uint8 AssassinateLevel; // Max Level Assassinate will be effective at.
|
||||
int32 PetMeleeMitigation; // Add AC to owner's pet.
|
||||
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
||||
@ -447,7 +447,7 @@ bool Group::UpdatePlayer(Mob* update){
|
||||
//update their player profile
|
||||
PlayerProfile_Struct &pp = update->CastToClient()->GetPP();
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||
if(membername[0] == '\0')
|
||||
if(membername[i][0] == '\0')
|
||||
memset(pp.groupMembers[i], 0, 64);
|
||||
else
|
||||
strn0cpy(pp.groupMembers[i], membername[i], 64);
|
||||
@ -1095,7 +1095,7 @@ void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range)
|
||||
}
|
||||
|
||||
|
||||
void Group::BalanceHP(int32 penalty, int32 range, Mob* caster)
|
||||
void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit)
|
||||
{
|
||||
if (!caster)
|
||||
return;
|
||||
@ -1103,7 +1103,7 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster)
|
||||
if (!range)
|
||||
range = 200;
|
||||
|
||||
int dmgtaken = 0, numMem = 0;
|
||||
int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0;
|
||||
|
||||
float distance;
|
||||
float range2 = range*range;
|
||||
@ -1114,7 +1114,12 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster)
|
||||
if(members[gi]){
|
||||
distance = caster->DistNoRoot(*members[gi]);
|
||||
if(distance <= range2){
|
||||
dmgtaken += (members[gi]->GetMaxHP() - members[gi]->GetHP());
|
||||
|
||||
dmgtaken_tmp = members[gi]->GetMaxHP() - members[gi]->GetHP();
|
||||
if (limit && (dmgtaken_tmp > limit))
|
||||
dmgtaken_tmp = limit;
|
||||
|
||||
dmgtaken += (dmgtaken_tmp);
|
||||
numMem += 1;
|
||||
}
|
||||
}
|
||||
@ -1140,7 +1145,7 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster)
|
||||
}
|
||||
}
|
||||
|
||||
void Group::BalanceMana(int32 penalty, int32 range, Mob* caster)
|
||||
void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit)
|
||||
{
|
||||
if (!caster)
|
||||
return;
|
||||
@ -1151,14 +1156,19 @@ void Group::BalanceMana(int32 penalty, int32 range, Mob* caster)
|
||||
float distance;
|
||||
float range2 = range*range;
|
||||
|
||||
int manataken = 0, numMem = 0;
|
||||
int manataken = 0, numMem = 0, manataken_tmp = 0;
|
||||
unsigned int gi = 0;
|
||||
for(; gi < MAX_GROUP_MEMBERS; gi++)
|
||||
{
|
||||
if(members[gi]){
|
||||
if(members[gi] && (members[gi]->GetMaxMana() > 0)){
|
||||
distance = caster->DistNoRoot(*members[gi]);
|
||||
if(distance <= range2){
|
||||
manataken += (members[gi]->GetMaxMana() - members[gi]->GetMana());
|
||||
|
||||
manataken_tmp = members[gi]->GetMaxMana() - members[gi]->GetMana();
|
||||
if (limit && (manataken_tmp > limit))
|
||||
manataken_tmp = limit;
|
||||
|
||||
manataken += (manataken_tmp);
|
||||
numMem += 1;
|
||||
}
|
||||
}
|
||||
@ -1166,6 +1176,10 @@ void Group::BalanceMana(int32 penalty, int32 range, Mob* caster)
|
||||
|
||||
manataken += manataken * penalty / 100;
|
||||
manataken /= numMem;
|
||||
|
||||
if (limit && (manataken > limit))
|
||||
manataken = limit;
|
||||
|
||||
for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++)
|
||||
{
|
||||
if(members[gi]){
|
||||
|
||||
@ -86,8 +86,8 @@ public:
|
||||
uint16 GetAvgLevel();
|
||||
bool LearnMembers();
|
||||
void VerifyGroup();
|
||||
void BalanceHP(int32 penalty, int32 range = 0, Mob* caster = nullptr);
|
||||
void BalanceMana(int32 penalty, int32 range = 0, Mob* caster = nullptr);
|
||||
void BalanceHP(int32 penalty, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
|
||||
void BalanceMana(int32 penalty, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
|
||||
void HealGroup(uint32 heal_amt, Mob* caster, int32 range = 0);
|
||||
inline void SetGroupAAs(GroupLeadershipAA_Struct *From) { memcpy(&LeaderAbilities, From, sizeof(GroupLeadershipAA_Struct)); }
|
||||
inline void GetGroupAAs(GroupLeadershipAA_Struct *Into) { memcpy(Into, &LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); }
|
||||
|
||||
@ -27,7 +27,7 @@ struct Appearances { };
|
||||
|
||||
struct lua_registered_event {
|
||||
std::string encounter_name;
|
||||
luabind::object lua_reference;
|
||||
luabind::adl::object lua_reference;
|
||||
QuestEventID event_id;
|
||||
};
|
||||
|
||||
@ -43,7 +43,7 @@ void unload_encounter(std::string name) {
|
||||
parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0);
|
||||
}
|
||||
|
||||
void register_event(std::string package_name, std::string name, int evt, luabind::object func) {
|
||||
void register_event(std::string package_name, std::string name, int evt, luabind::adl::object func) {
|
||||
lua_registered_event e;
|
||||
e.encounter_name = name;
|
||||
e.lua_reference = func;
|
||||
@ -84,7 +84,7 @@ void unregister_event(std::string package_name, std::string name, int evt) {
|
||||
}
|
||||
}
|
||||
|
||||
void register_npc_event(std::string name, int evt, int npc_id, luabind::object func) {
|
||||
void register_npc_event(std::string name, int evt, int npc_id, luabind::adl::object func) {
|
||||
if(luabind::type(func) == LUA_TFUNCTION) {
|
||||
std::stringstream package_name;
|
||||
package_name << "npc_" << npc_id;
|
||||
@ -100,7 +100,7 @@ void unregister_npc_event(std::string name, int evt, int npc_id) {
|
||||
unregister_event(package_name.str(), name, evt);
|
||||
}
|
||||
|
||||
void register_player_event(std::string name, int evt, luabind::object func) {
|
||||
void register_player_event(std::string name, int evt, luabind::adl::object func) {
|
||||
if(luabind::type(func) == LUA_TFUNCTION) {
|
||||
register_event("player", name, evt, func);
|
||||
}
|
||||
@ -110,7 +110,7 @@ void unregister_player_event(std::string name, int evt) {
|
||||
unregister_event("player", name, evt);
|
||||
}
|
||||
|
||||
void register_item_event(std::string name, int evt, int item_id, luabind::object func) {
|
||||
void register_item_event(std::string name, int evt, int item_id, luabind::adl::object func) {
|
||||
std::string package_name = "item_";
|
||||
package_name += std::to_string(static_cast<long long>(item_id));
|
||||
|
||||
@ -126,7 +126,7 @@ void unregister_item_event(std::string name, int evt, int item_id) {
|
||||
unregister_event(package_name, name, evt);
|
||||
}
|
||||
|
||||
void register_spell_event(std::string name, int evt, int spell_id, luabind::object func) {
|
||||
void register_spell_event(std::string name, int evt, int spell_id, luabind::adl::object func) {
|
||||
if(luabind::type(func) == LUA_TFUNCTION) {
|
||||
std::stringstream package_name;
|
||||
package_name << "spell_" << spell_id;
|
||||
@ -392,7 +392,7 @@ bool lua_bury_player_corpse(uint32 char_id) {
|
||||
return quest_manager.buryplayercorpse(char_id);
|
||||
}
|
||||
|
||||
void lua_task_selector(luabind::object table) {
|
||||
void lua_task_selector(luabind::adl::object table) {
|
||||
if(luabind::type(table) != LUA_TTABLE) {
|
||||
return;
|
||||
}
|
||||
@ -422,7 +422,7 @@ void lua_task_set_selector(int task_set) {
|
||||
quest_manager.tasksetselector(task_set);
|
||||
}
|
||||
|
||||
void lua_enable_task(luabind::object table) {
|
||||
void lua_enable_task(luabind::adl::object table) {
|
||||
if(luabind::type(table) != LUA_TTABLE) {
|
||||
return;
|
||||
}
|
||||
@ -449,7 +449,7 @@ void lua_enable_task(luabind::object table) {
|
||||
quest_manager.enabletask(count, tasks);
|
||||
}
|
||||
|
||||
void lua_disable_task(luabind::object table) {
|
||||
void lua_disable_task(luabind::adl::object table) {
|
||||
if(luabind::type(table) != LUA_TTABLE) {
|
||||
return;
|
||||
}
|
||||
@ -743,8 +743,8 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons
|
||||
quest_manager.CrossZoneMessagePlayerByName(type, player, message);
|
||||
}
|
||||
|
||||
luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) {
|
||||
luabind::object ret = luabind::newtable(L);
|
||||
luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) {
|
||||
luabind::adl::object ret = luabind::newtable(L);
|
||||
|
||||
NPC *n = npc;
|
||||
Client *c = client;
|
||||
@ -759,8 +759,8 @@ luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
luabind::object lua_get_qglobals(lua_State *L, Lua_Client client) {
|
||||
luabind::object ret = luabind::newtable(L);
|
||||
luabind::adl::object lua_get_qglobals(lua_State *L, Lua_Client client) {
|
||||
luabind::adl::object ret = luabind::newtable(L);
|
||||
|
||||
NPC *n = nullptr;
|
||||
Client *c = client;
|
||||
@ -775,8 +775,8 @@ luabind::object lua_get_qglobals(lua_State *L, Lua_Client client) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc) {
|
||||
luabind::object ret = luabind::newtable(L);
|
||||
luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc) {
|
||||
luabind::adl::object ret = luabind::newtable(L);
|
||||
|
||||
NPC *n = npc;
|
||||
Client *c = nullptr;
|
||||
@ -791,8 +791,8 @@ luabind::object lua_get_qglobals(lua_State *L, Lua_NPC npc) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
luabind::object lua_get_qglobals(lua_State *L) {
|
||||
luabind::object ret = luabind::newtable(L);
|
||||
luabind::adl::object lua_get_qglobals(lua_State *L) {
|
||||
luabind::adl::object ret = luabind::newtable(L);
|
||||
|
||||
NPC *n = nullptr;
|
||||
Client *c = nullptr;
|
||||
@ -846,8 +846,8 @@ int lua_get_zone_instance_version() {
|
||||
return zone->GetInstanceVersion();
|
||||
}
|
||||
|
||||
luabind::object lua_get_characters_in_instance(lua_State *L, uint16 instance_id) {
|
||||
luabind::object ret = luabind::newtable(L);
|
||||
luabind::adl::object lua_get_characters_in_instance(lua_State *L, uint16 instance_id) {
|
||||
luabind::adl::object ret = luabind::newtable(L);
|
||||
|
||||
std::list<uint32> charid_list;
|
||||
uint16 i = 1;
|
||||
@ -868,11 +868,11 @@ int lua_get_zone_weather() {
|
||||
return zone->zone_weather;
|
||||
}
|
||||
|
||||
luabind::object lua_get_zone_time(lua_State *L) {
|
||||
luabind::adl::object lua_get_zone_time(lua_State *L) {
|
||||
TimeOfDay_Struct eqTime;
|
||||
zone->zone_time.getEQTimeOfDay(time(0), &eqTime);
|
||||
|
||||
luabind::object ret = luabind::newtable(L);
|
||||
luabind::adl::object ret = luabind::newtable(L);
|
||||
ret["zone_hour"] = eqTime.hour - 1;
|
||||
ret["zone_minute"] = eqTime.minute;
|
||||
ret["zone_time"] = (eqTime.hour - 1) * 100 + eqTime.minute;
|
||||
@ -909,7 +909,7 @@ void lua_remove_spawn_point(uint32 spawn2_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void lua_add_spawn_point(luabind::object table) {
|
||||
void lua_add_spawn_point(luabind::adl::object table) {
|
||||
if(!zone)
|
||||
return;
|
||||
|
||||
@ -1280,10 +1280,10 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id),
|
||||
luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name),
|
||||
luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name),
|
||||
luabind::def("get_qglobals", (luabind::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::object(*)(lua_State*,Lua_Client))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::object(*)(lua_State*))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_Client))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*))&lua_get_qglobals),
|
||||
luabind::def("get_entity_list", &lua_get_entity_list),
|
||||
luabind::def("get_zone_id", &lua_get_zone_id),
|
||||
luabind::def("get_zone_long_name", &lua_get_zone_long_name),
|
||||
|
||||
@ -103,7 +103,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
|
||||
return self->Attack(other, hand, from_riposte, is_strikethrough, is_from_spell);
|
||||
}
|
||||
|
||||
bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::object opts) {
|
||||
bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::adl::object opts) {
|
||||
Lua_Safe_Call_Bool();
|
||||
|
||||
ExtraAttackOptions options;
|
||||
@ -1429,7 +1429,7 @@ void Lua_Mob::SetGender(int in) {
|
||||
self->SendIllusionPacket(self->GetRace(), in);
|
||||
}
|
||||
|
||||
void Lua_Mob::SendIllusionPacket(luabind::object illusion) {
|
||||
void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
|
||||
Lua_Safe_Call_Void();
|
||||
|
||||
if(luabind::type(illusion) != LUA_TTABLE) {
|
||||
@ -1881,7 +1881,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool))&Lua_Mob::Attack)
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool))&Lua_Mob::Attack)
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool,bool))&Lua_Mob::Attack)
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool,bool,luabind::object))&Lua_Mob::Attack)
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool,bool,bool,luabind::adl::object))&Lua_Mob::Attack)
|
||||
.def("Damage", (void(Lua_Mob::*)(Lua_Mob,int,int,int))&Lua_Mob::Damage)
|
||||
.def("Damage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,bool))&Lua_Mob::Damage)
|
||||
.def("Damage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,bool,int))&Lua_Mob::Damage)
|
||||
@ -2125,7 +2125,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("SetTexture", (void(Lua_Mob::*)(int))&Lua_Mob::SetTexture)
|
||||
.def("SetRace", (void(Lua_Mob::*)(int))&Lua_Mob::SetRace)
|
||||
.def("SetGender", (void(Lua_Mob::*)(int))&Lua_Mob::SetGender)
|
||||
.def("SendIllusionPacket", (void(Lua_Mob::*)(luabind::object))&Lua_Mob::SendIllusionPacket)
|
||||
.def("SendIllusionPacket", (void(Lua_Mob::*)(luabind::adl::object))&Lua_Mob::SendIllusionPacket)
|
||||
.def("QuestReward", (void(Lua_Mob::*)(Lua_Client))&Lua_Mob::QuestReward)
|
||||
.def("QuestReward", (void(Lua_Mob::*)(Lua_Client,uint32))&Lua_Mob::QuestReward)
|
||||
.def("QuestReward", (void(Lua_Mob::*)(Lua_Client,uint32,uint32))&Lua_Mob::QuestReward)
|
||||
|
||||
@ -47,7 +47,7 @@ public:
|
||||
bool Attack(Lua_Mob other, int hand, bool from_riposte);
|
||||
bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough);
|
||||
bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell);
|
||||
bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::object opts);
|
||||
bool Attack(Lua_Mob other, int hand, bool from_riposte, bool is_strikethrough, bool is_from_spell, luabind::adl::object opts);
|
||||
void Damage(Lua_Mob from, int damage, int spell_id, int attack_skill);
|
||||
void Damage(Lua_Mob from, int damage, int spell_id, int attack_skill, bool avoidable);
|
||||
void Damage(Lua_Mob from, int damage, int spell_id, int attack_skill, bool avoidable, int buffslot);
|
||||
@ -294,7 +294,7 @@ public:
|
||||
void SetTexture(int in);
|
||||
void SetRace(int in);
|
||||
void SetGender(int in);
|
||||
void SendIllusionPacket(luabind::object illusion);
|
||||
void SendIllusionPacket(luabind::adl::object illusion);
|
||||
void QuestReward(Lua_Client c);
|
||||
void QuestReward(Lua_Client c, uint32 silver);
|
||||
void QuestReward(Lua_Client c, uint32 silver, uint32 gold);
|
||||
|
||||
@ -121,7 +121,7 @@ extern Zone *zone;
|
||||
|
||||
struct lua_registered_event {
|
||||
std::string encounter_name;
|
||||
luabind::object lua_reference;
|
||||
luabind::adl::object lua_reference;
|
||||
QuestEventID event_id;
|
||||
};
|
||||
|
||||
@ -257,7 +257,7 @@ int LuaParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string
|
||||
}
|
||||
|
||||
int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers, luabind::object *l_func) {
|
||||
std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
|
||||
const char *sub_name = LuaEvents[evt];
|
||||
|
||||
int start = lua_gettop(L);
|
||||
@ -275,7 +275,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M
|
||||
lua_createtable(L, 0, 0);
|
||||
//always push self
|
||||
Lua_NPC l_npc(npc);
|
||||
luabind::object l_npc_o = luabind::object(L, l_npc);
|
||||
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||
l_npc_o.push(L);
|
||||
lua_setfield(L, -2, "self");
|
||||
|
||||
@ -352,7 +352,7 @@ int LuaParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string d
|
||||
}
|
||||
|
||||
int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers, luabind::object *l_func) {
|
||||
std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
|
||||
const char *sub_name = LuaEvents[evt];
|
||||
int start = lua_gettop(L);
|
||||
|
||||
@ -369,7 +369,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *
|
||||
lua_createtable(L, 0, 0);
|
||||
//push self
|
||||
Lua_Client l_client(client);
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "self");
|
||||
|
||||
@ -429,7 +429,7 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *
|
||||
}
|
||||
|
||||
int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob,
|
||||
std::string data, uint32 extra_data, std::vector<void*> *extra_pointers, luabind::object *l_func) {
|
||||
std::string data, uint32 extra_data, std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
|
||||
const char *sub_name = LuaEvents[evt];
|
||||
|
||||
int start = lua_gettop(L);
|
||||
@ -446,12 +446,12 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
|
||||
lua_createtable(L, 0, 0);
|
||||
//always push self
|
||||
Lua_ItemInst l_item(item);
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "self");
|
||||
|
||||
Lua_Client l_client(client);
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "owner");
|
||||
|
||||
@ -508,7 +508,7 @@ int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spe
|
||||
}
|
||||
|
||||
int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers, luabind::object *l_func) {
|
||||
std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
|
||||
const char *sub_name = LuaEvents[evt];
|
||||
|
||||
int start = lua_gettop(L);
|
||||
@ -528,11 +528,11 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc,
|
||||
//always push self even if invalid
|
||||
if(IsValidSpell(spell_id)) {
|
||||
Lua_Spell l_spell(&spells[spell_id]);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
} else {
|
||||
Lua_Spell l_spell(nullptr);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
}
|
||||
lua_setfield(L, -2, "self");
|
||||
|
||||
@ -17,7 +17,9 @@ class NPC;
|
||||
|
||||
struct lua_registered_event;
|
||||
namespace luabind {
|
||||
class object;
|
||||
namespace adl {
|
||||
class object;
|
||||
}
|
||||
}
|
||||
|
||||
class LuaParser : public QuestInterface {
|
||||
@ -73,13 +75,13 @@ public:
|
||||
|
||||
private:
|
||||
int _EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers, luabind::object *l_func = nullptr);
|
||||
std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
|
||||
int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers, luabind::object *l_func = nullptr);
|
||||
std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
|
||||
int _EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data,
|
||||
uint32 extra_data, std::vector<void*> *extra_pointers, luabind::object *l_func = nullptr);
|
||||
uint32 extra_data, std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
|
||||
int _EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers, luabind::object *l_func = nullptr);
|
||||
std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
|
||||
int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers);
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in
|
||||
npc->DoQuestPause(init);
|
||||
|
||||
Lua_Client l_client(reinterpret_cast<Client*>(init));
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -45,7 +45,7 @@ void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in
|
||||
void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Client l_client(reinterpret_cast<Client*>(init));
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -57,7 +57,7 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *
|
||||
for(size_t i = 0; i < extra_pointers->size(); ++i) {
|
||||
std::string prefix = "item" + std::to_string(static_cast<long long>(i + 1));
|
||||
Lua_ItemInst l_inst = reinterpret_cast<ItemInst*>(extra_pointers->at(i));
|
||||
luabind::object l_inst_o = luabind::object(L, l_inst);
|
||||
luabind::adl::object l_inst_o = luabind::adl::object(L, l_inst);
|
||||
l_inst_o.push(L);
|
||||
|
||||
lua_setfield(L, -2, prefix.c_str());
|
||||
@ -98,7 +98,7 @@ void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini
|
||||
void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Mob l_mob(init);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
}
|
||||
@ -106,7 +106,7 @@ void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *i
|
||||
void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Client l_client(reinterpret_cast<Client*>(init));
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
}
|
||||
@ -114,7 +114,7 @@ void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob
|
||||
void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_NPC l_npc(reinterpret_cast<NPC*>(init));
|
||||
luabind::object l_npc_o = luabind::object(L, l_npc);
|
||||
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||
l_npc_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
}
|
||||
@ -122,7 +122,7 @@ void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *i
|
||||
void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Client l_client(reinterpret_cast<Client*>(init));
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -133,7 +133,7 @@ void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob
|
||||
void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Mob l_mob(init);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -144,7 +144,7 @@ void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init,
|
||||
void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Mob l_mob(init);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -155,7 +155,7 @@ void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini
|
||||
void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Mob l_mob(init);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -179,7 +179,7 @@ void handle_npc_timer(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init,
|
||||
void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Mob l_mob(init);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -190,12 +190,12 @@ void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init,
|
||||
int spell_id = std::stoi(sep.arg[1]);
|
||||
if(IsValidSpell(spell_id)) {
|
||||
Lua_Spell l_spell(&spells[spell_id]);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
} else {
|
||||
Lua_Spell l_spell(nullptr);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
}
|
||||
@ -209,12 +209,12 @@ void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
|
||||
int spell_id = std::stoi(data);
|
||||
if(IsValidSpell(spell_id)) {
|
||||
Lua_Spell l_spell(&spells[spell_id]);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
} else {
|
||||
Lua_Spell l_spell(nullptr);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
}
|
||||
@ -249,7 +249,7 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st
|
||||
|
||||
Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0]));
|
||||
Lua_Mob l_mob(o);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
@ -259,12 +259,12 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st
|
||||
int spell_id = std::stoi(sep.arg[2]);
|
||||
if(IsValidSpell(spell_id)) {
|
||||
Lua_Spell l_spell(&spells[spell_id]);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
} else {
|
||||
Lua_Spell l_spell(nullptr);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
}
|
||||
@ -284,12 +284,12 @@ void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* cl
|
||||
const Item_Struct *item = database.GetItem(extra_data);
|
||||
if(item) {
|
||||
Lua_Item l_item(item);
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
} else {
|
||||
Lua_Item l_item(nullptr);
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
}
|
||||
@ -298,7 +298,7 @@ void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* cl
|
||||
void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
}
|
||||
@ -306,7 +306,7 @@ void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Clie
|
||||
void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Object l_object(reinterpret_cast<Object*>(extra_pointers->at(0)));
|
||||
luabind::object l_object_o = luabind::object(L, l_object);
|
||||
luabind::adl::object l_object_o = luabind::adl::object(L, l_object);
|
||||
l_object_o.push(L);
|
||||
lua_setfield(L, -2, "object");
|
||||
}
|
||||
@ -314,7 +314,7 @@ void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* cli
|
||||
void handle_player_click_door(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Door l_door(reinterpret_cast<Doors*>(extra_pointers->at(0)));
|
||||
luabind::object l_door_o = luabind::object(L, l_door);
|
||||
luabind::adl::object l_door_o = luabind::adl::object(L, l_door);
|
||||
l_door_o.push(L);
|
||||
lua_setfield(L, -2, "door");
|
||||
}
|
||||
@ -334,7 +334,7 @@ void handle_player_popup_response(QuestInterface *parse, lua_State* L, Client* c
|
||||
void handle_player_pick_up(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
}
|
||||
@ -344,11 +344,11 @@ void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std
|
||||
int spell_id = std::stoi(data);
|
||||
if(IsValidSpell(spell_id)) {
|
||||
Lua_Spell l_spell(&spells[spell_id]);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
} else {
|
||||
Lua_Spell l_spell(nullptr);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
}
|
||||
|
||||
@ -370,7 +370,7 @@ void handle_player_zone(QuestInterface *parse, lua_State* L, Client* client, std
|
||||
void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Client l_client(reinterpret_cast<Client*>(extra_pointers->at(1)));
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
}
|
||||
@ -378,7 +378,7 @@ void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client,
|
||||
void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Client l_client(reinterpret_cast<Client*>(extra_pointers->at(0)));
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
}
|
||||
@ -386,12 +386,12 @@ void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client
|
||||
void handle_player_loot(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
|
||||
Lua_Corpse l_corpse(reinterpret_cast<Corpse*>(extra_pointers->at(1)));
|
||||
luabind::object l_corpse_o = luabind::object(L, l_corpse);
|
||||
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
|
||||
l_corpse_o.push(L);
|
||||
lua_setfield(L, -2, "corpse");
|
||||
}
|
||||
@ -426,7 +426,7 @@ void handle_player_command(QuestInterface *parse, lua_State* L, Client* client,
|
||||
lua_pushstring(L, command.c_str());
|
||||
lua_setfield(L, -2, "command");
|
||||
|
||||
luabind::object args = luabind::newtable(L);
|
||||
luabind::adl::object args = luabind::newtable(L);
|
||||
int max_args = sep.GetMaxArgNum();
|
||||
for(int i = 1; i < max_args; ++i) {
|
||||
if(strlen(sep.arg[i]) > 0) {
|
||||
@ -450,7 +450,7 @@ void handle_player_combine(QuestInterface *parse, lua_State* L, Client* client,
|
||||
void handle_player_feign(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_NPC l_npc(reinterpret_cast<NPC*>(extra_pointers->at(0)));
|
||||
luabind::object l_npc_o = luabind::object(L, l_npc);
|
||||
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||
l_npc_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
}
|
||||
@ -476,7 +476,7 @@ void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client,
|
||||
void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_Packet l_packet(reinterpret_cast<EQApplicationPacket*>(extra_pointers->at(0)));
|
||||
luabind::object l_packet_o = luabind::object(L, l_packet);
|
||||
luabind::adl::object l_packet_o = luabind::adl::object(L, l_packet);
|
||||
l_packet_o.push(L);
|
||||
lua_setfield(L, -2, "packet");
|
||||
|
||||
@ -505,18 +505,18 @@ void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemI
|
||||
std::vector<void*> *extra_pointers) {
|
||||
|
||||
Lua_Mob l_mob(mob);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "target");
|
||||
|
||||
if(IsValidSpell(extra_data)) {
|
||||
Lua_Spell l_spell(&spells[extra_data]);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
} else {
|
||||
Lua_Spell l_spell(nullptr);
|
||||
luabind::object l_spell_o = luabind::object(L, l_spell);
|
||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||
l_spell_o.push(L);
|
||||
lua_setfield(L, -2, "spell");
|
||||
}
|
||||
@ -526,12 +526,12 @@ void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemI
|
||||
std::vector<void*> *extra_pointers) {
|
||||
if(mob && mob->IsCorpse()) {
|
||||
Lua_Corpse l_corpse(mob->CastToCorpse());
|
||||
luabind::object l_corpse_o = luabind::object(L, l_corpse);
|
||||
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
|
||||
l_corpse_o.push(L);
|
||||
lua_setfield(L, -2, "corpse");
|
||||
} else {
|
||||
Lua_Corpse l_corpse(nullptr);
|
||||
luabind::object l_corpse_o = luabind::object(L, l_corpse);
|
||||
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
|
||||
l_corpse_o.push(L);
|
||||
lua_setfield(L, -2, "corpse");
|
||||
}
|
||||
@ -546,7 +546,7 @@ void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, Item
|
||||
void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "aug");
|
||||
|
||||
@ -557,7 +557,7 @@ void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, It
|
||||
void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
|
||||
@ -568,7 +568,7 @@ void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* cli
|
||||
void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
|
||||
std::vector<void*> *extra_pointers) {
|
||||
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
|
||||
luabind::object l_item_o = luabind::object(L, l_item);
|
||||
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
|
||||
l_item_o.push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
|
||||
@ -588,15 +588,15 @@ void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client*
|
||||
std::vector<void*> *extra_pointers) {
|
||||
if(npc) {
|
||||
Lua_Mob l_npc(npc);
|
||||
luabind::object l_npc_o = luabind::object(L, l_npc);
|
||||
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||
l_npc_o.push(L);
|
||||
} else if(client) {
|
||||
Lua_Mob l_client(client);
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
} else {
|
||||
Lua_Mob l_mob(nullptr);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
}
|
||||
|
||||
@ -613,15 +613,15 @@ void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* cli
|
||||
std::vector<void*> *extra_pointers) {
|
||||
if(npc) {
|
||||
Lua_Mob l_npc(npc);
|
||||
luabind::object l_npc_o = luabind::object(L, l_npc);
|
||||
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||
l_npc_o.push(L);
|
||||
} else if(client) {
|
||||
Lua_Mob l_client(client);
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
} else {
|
||||
Lua_Mob l_mob(nullptr);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
}
|
||||
|
||||
@ -644,15 +644,15 @@ void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl
|
||||
std::vector<void*> *extra_pointers) {
|
||||
if(npc) {
|
||||
Lua_Mob l_npc(npc);
|
||||
luabind::object l_npc_o = luabind::object(L, l_npc);
|
||||
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||
l_npc_o.push(L);
|
||||
} else if(client) {
|
||||
Lua_Mob l_client(client);
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
} else {
|
||||
Lua_Mob l_mob(nullptr);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
}
|
||||
|
||||
@ -669,15 +669,15 @@ void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Cl
|
||||
std::vector<void*> *extra_pointers) {
|
||||
if(npc) {
|
||||
Lua_Mob l_npc(npc);
|
||||
luabind::object l_npc_o = luabind::object(L, l_npc);
|
||||
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||
l_npc_o.push(L);
|
||||
} else if(client) {
|
||||
Lua_Mob l_client(client);
|
||||
luabind::object l_client_o = luabind::object(L, l_client);
|
||||
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
|
||||
l_client_o.push(L);
|
||||
} else {
|
||||
Lua_Mob l_mob(nullptr);
|
||||
luabind::object l_mob_o = luabind::object(L, l_mob);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
}
|
||||
|
||||
|
||||
36
zone/mob.cpp
36
zone/mob.cpp
@ -180,6 +180,8 @@ Mob::Mob(const char* in_name,
|
||||
trackable = true;
|
||||
has_shieldequiped = false;
|
||||
has_numhits = false;
|
||||
has_MGB = false;
|
||||
has_ProjectIllusion = false;
|
||||
|
||||
if(in_aa_title>0)
|
||||
aa_title = in_aa_title;
|
||||
@ -3155,7 +3157,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
|
||||
|
||||
if(IsValidSpell(trigger_spell_id) && GetTarget()){
|
||||
SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff);
|
||||
CheckNumHitsRemaining(7,0, focus_spell);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells,0, focus_spell);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3408,7 +3410,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
|
||||
value += tmp_focus;
|
||||
|
||||
if (tmp_buffslot >= 0)
|
||||
CheckNumHitsRemaining(7, tmp_buffslot);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -3509,7 +3511,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
|
||||
SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff);
|
||||
}
|
||||
|
||||
CheckNumHitsRemaining(7, 0, focus_spell);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells, 0, focus_spell);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4137,9 +4139,9 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
|
||||
{
|
||||
if (spell_id != SPELL_UNKNOWN)
|
||||
{
|
||||
if(IsEffectInSpell(spell_id, SE_SpellOnKill2)) {
|
||||
if(IsEffectInSpell(spell_id, SE_ProcOnSpellKillShot)) {
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
if (spells[spell_id].effectid[i] == SE_SpellOnKill2)
|
||||
if (spells[spell_id].effectid[i] == SE_ProcOnSpellKillShot)
|
||||
{
|
||||
if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level)
|
||||
{
|
||||
@ -4277,6 +4279,9 @@ int16 Mob::GetMeleeDamageMod_SE(uint16 skill)
|
||||
dmg_mod += itembonuses.DamageModifier[HIGHEST_SKILL+1] + spellbonuses.DamageModifier[HIGHEST_SKILL+1] + aabonuses.DamageModifier[HIGHEST_SKILL+1] +
|
||||
itembonuses.DamageModifier[skill] + spellbonuses.DamageModifier[skill] + aabonuses.DamageModifier[skill];
|
||||
|
||||
dmg_mod += itembonuses.DamageModifier2[HIGHEST_SKILL+1] + spellbonuses.DamageModifier2[HIGHEST_SKILL+1] + aabonuses.DamageModifier2[HIGHEST_SKILL+1] +
|
||||
itembonuses.DamageModifier2[skill] + spellbonuses.DamageModifier2[skill] + aabonuses.DamageModifier2[skill];
|
||||
|
||||
if (HasShieldEquiped() && !IsOffHandAtk())
|
||||
dmg_mod += itembonuses.ShieldEquipDmgMod[0] + spellbonuses.ShieldEquipDmgMod[0] + aabonuses.ShieldEquipDmgMod[0];
|
||||
|
||||
@ -4334,22 +4339,19 @@ int16 Mob::GetSkillDmgAmt(uint16 skill)
|
||||
|
||||
void Mob::MeleeLifeTap(int32 damage) {
|
||||
|
||||
if(damage > 0 && (spellbonuses.MeleeLifetap || itembonuses.MeleeLifetap || aabonuses.MeleeLifetap ))
|
||||
{
|
||||
int lifetap_amt = spellbonuses.MeleeLifetap + itembonuses.MeleeLifetap + aabonuses.MeleeLifetap;
|
||||
|
||||
if(lifetap_amt > 100)
|
||||
lifetap_amt = 100;
|
||||
|
||||
else if (lifetap_amt < -99)
|
||||
lifetap_amt = -99;
|
||||
int16 lifetap_amt = 0;
|
||||
lifetap_amt = spellbonuses.MeleeLifetap + itembonuses.MeleeLifetap + aabonuses.MeleeLifetap
|
||||
+ spellbonuses.Vampirism + itembonuses.Vampirism + aabonuses.Vampirism;
|
||||
|
||||
if(lifetap_amt && damage > 0){
|
||||
|
||||
lifetap_amt = damage * lifetap_amt / 100;
|
||||
|
||||
mlog(COMBAT__DAMAGE, "Melee lifetap healing for %d damage.", damage);
|
||||
//heal self for damage done..
|
||||
HealDamage(lifetap_amt);
|
||||
|
||||
if (lifetap_amt > 0)
|
||||
HealDamage(lifetap_amt); //Heal self for modified damage amount.
|
||||
else
|
||||
Damage(this, -lifetap_amt,0, SkillEvocation,false); //Dmg self for modified damage amount.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
zone/mob.h
15
zone/mob.h
@ -141,7 +141,8 @@ public:
|
||||
virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr);
|
||||
void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage);
|
||||
virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse);
|
||||
virtual bool TryHeadShot(Mob* defender, SkillUseTypes skillInUse);
|
||||
uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse);
|
||||
uint32 TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime);
|
||||
virtual void DoRiposte(Mob* defender);
|
||||
void ApplyMeleeDamageBonus(uint16 skill, int32 &damage);
|
||||
virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr);
|
||||
@ -268,6 +269,10 @@ public:
|
||||
void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN);
|
||||
bool HasNumhits() const { return has_numhits; }
|
||||
inline void Numhits(bool val) { has_numhits = val; }
|
||||
bool HasMGB() const { return has_MGB; }
|
||||
inline void SetMGB(bool val) { has_MGB = val; }
|
||||
bool HasProjectIllusion() const { return has_ProjectIllusion ; }
|
||||
inline void SetProjectIllusion(bool val) { has_ProjectIllusion = val; }
|
||||
void SpreadVirus(uint16 spell_id, uint16 casterID);
|
||||
bool IsNimbusEffectActive(uint32 nimbus_effect);
|
||||
void SetNimbusEffect(uint32 nimbus_effect);
|
||||
@ -690,7 +695,7 @@ public:
|
||||
int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker);
|
||||
int32 ReduceAllDamage(int32 damage);
|
||||
|
||||
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false);
|
||||
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true);
|
||||
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0);
|
||||
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false);
|
||||
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0);
|
||||
@ -800,7 +805,7 @@ public:
|
||||
uint16 GetInstrumentMod(uint16 spell_id) const;
|
||||
int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, Mob *caster = nullptr, int ticsremaining = 0);
|
||||
int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0);
|
||||
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr);
|
||||
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1);
|
||||
uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; }
|
||||
|
||||
// HP Event
|
||||
@ -987,6 +992,8 @@ protected:
|
||||
void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on);
|
||||
virtual float GetProcChances(float ProcBonus, uint16 weapon_speed = 30, uint16 hand = 13);
|
||||
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13);
|
||||
virtual float GetSpecialProcChances(uint16 hand);
|
||||
virtual float GetAssassinateProcChances(uint16 ReuseTime);
|
||||
int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item);
|
||||
int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr);
|
||||
int GetKickDamage();
|
||||
@ -1097,6 +1104,8 @@ protected:
|
||||
bool offhand;
|
||||
bool has_shieldequiped;
|
||||
bool has_numhits;
|
||||
bool has_MGB;
|
||||
bool has_ProjectIllusion;
|
||||
|
||||
// Bind wound
|
||||
Timer bindwound_timer;
|
||||
|
||||
12
zone/npc.cpp
12
zone/npc.cpp
@ -599,19 +599,19 @@ bool NPC::Process()
|
||||
//Lieka Edit:Fixing NPC regen.NPCs should regen to full during a set duration, not based on their HPs.Increase NPC's HPs by % of total HPs / tick.
|
||||
if((GetHP() < GetMaxHP()) && !IsPet()) {
|
||||
if(!IsEngaged()) {//NPC out of combat
|
||||
if(hp_regen > OOCRegen)
|
||||
SetHP(GetHP() + hp_regen);
|
||||
if(GetNPCHPRegen() > OOCRegen)
|
||||
SetHP(GetHP() + GetNPCHPRegen());
|
||||
else
|
||||
SetHP(GetHP() + OOCRegen);
|
||||
} else
|
||||
SetHP(GetHP()+hp_regen);
|
||||
SetHP(GetHP()+GetNPCHPRegen());
|
||||
} else if(GetHP() < GetMaxHP() && GetOwnerID() !=0) {
|
||||
if(!IsEngaged()) //pet
|
||||
SetHP(GetHP()+hp_regen+bonus+(GetLevel()/5));
|
||||
SetHP(GetHP()+GetNPCHPRegen()+bonus+(GetLevel()/5));
|
||||
else
|
||||
SetHP(GetHP()+hp_regen+bonus);
|
||||
SetHP(GetHP()+GetNPCHPRegen()+bonus);
|
||||
} else
|
||||
SetHP(GetHP()+hp_regen);
|
||||
SetHP(GetHP()+GetNPCHPRegen());
|
||||
|
||||
if(GetMana() < GetMaxMana()) {
|
||||
SetMana(GetMana()+mana_regen+bonus);
|
||||
|
||||
@ -256,6 +256,7 @@ public:
|
||||
virtual void DoClassAttacks(Mob *target);
|
||||
void CheckSignal();
|
||||
inline bool IsTargetableWithHotkey() const { return no_target_hotkey; }
|
||||
int32 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
|
||||
|
||||
//waypoint crap
|
||||
int GetMaxWp() const { return max_wp; }
|
||||
|
||||
@ -504,7 +504,7 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range)
|
||||
}
|
||||
|
||||
|
||||
void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster)
|
||||
void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster, int32 limit)
|
||||
{
|
||||
if (!caster)
|
||||
return;
|
||||
@ -512,7 +512,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster)
|
||||
if (!range)
|
||||
range = 200;
|
||||
|
||||
int dmgtaken = 0, numMem = 0;
|
||||
int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0;
|
||||
int gi = 0;
|
||||
|
||||
float distance;
|
||||
@ -525,7 +525,12 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster)
|
||||
{
|
||||
distance = caster->DistNoRoot(*members[gi].member);
|
||||
if(distance <= range2){
|
||||
dmgtaken += (members[gi].member->GetMaxHP() - members[gi].member->GetHP());
|
||||
|
||||
dmgtaken_tmp = members[gi].member->GetMaxHP() - members[gi].member->GetHP();
|
||||
if (limit && (dmgtaken_tmp > limit))
|
||||
dmgtaken_tmp = limit;
|
||||
|
||||
dmgtaken += (dmgtaken_tmp);
|
||||
numMem += 1;
|
||||
}
|
||||
}
|
||||
@ -555,7 +560,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster)
|
||||
}
|
||||
}
|
||||
|
||||
void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster)
|
||||
void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster, int32 limit)
|
||||
{
|
||||
if (!caster)
|
||||
return;
|
||||
@ -566,17 +571,24 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster)
|
||||
float distance;
|
||||
float range2 = range*range;
|
||||
|
||||
int manataken = 0, numMem = 0;
|
||||
int manataken = 0, numMem = 0, manataken_tmp = 0;
|
||||
int gi = 0;
|
||||
for(; gi < MAX_RAID_MEMBERS; gi++)
|
||||
{
|
||||
if(members[gi].member){
|
||||
if(members[gi].GroupNumber == gid)
|
||||
{
|
||||
distance = caster->DistNoRoot(*members[gi].member);
|
||||
if(distance <= range2){
|
||||
manataken += (members[gi].member->GetMaxMana() - members[gi].member->GetMana());
|
||||
numMem += 1;
|
||||
if (members[gi].member->GetMaxMana() > 0) {
|
||||
distance = caster->DistNoRoot(*members[gi].member);
|
||||
if(distance <= range2){
|
||||
|
||||
manataken_tmp = members[gi].member->GetMaxMana() - members[gi].member->GetMana();
|
||||
if (limit && (manataken_tmp > limit))
|
||||
manataken_tmp = limit;
|
||||
|
||||
manataken += (manataken_tmp);
|
||||
numMem += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -584,6 +596,7 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster)
|
||||
|
||||
manataken += manataken * penalty / 100;
|
||||
manataken /= numMem;
|
||||
|
||||
for(gi = 0; gi < MAX_RAID_MEMBERS; gi++)
|
||||
{
|
||||
if(members[gi].member){
|
||||
|
||||
@ -147,8 +147,8 @@ public:
|
||||
void CastGroupSpell(Mob* caster,uint16 spellid, uint32 gid);
|
||||
void SplitExp(uint32 exp, Mob* other);
|
||||
uint32 GetTotalRaidDamage(Mob* other);
|
||||
void BalanceHP(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr);
|
||||
void BalanceMana(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr);
|
||||
void BalanceHP(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
|
||||
void BalanceMana(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
|
||||
void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range = 0);
|
||||
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
|
||||
void GroupBardPulse(Mob* caster, uint16 spellid, uint32 gid);
|
||||
|
||||
@ -100,7 +100,8 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg)
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, bool HitChance) {
|
||||
void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime,
|
||||
bool HitChance, bool CanAvoid) {
|
||||
//this really should go through the same code as normal melee damage to
|
||||
//pick up all the special behavior there
|
||||
|
||||
@ -135,7 +136,9 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
if(skill == SkillThrowing || skill == SkillArchery) // changed from '&&'
|
||||
CanRiposte = false;
|
||||
|
||||
who->AvoidDamage(this, max_damage, CanRiposte);
|
||||
if (CanAvoid)
|
||||
who->AvoidDamage(this, max_damage, CanRiposte);
|
||||
|
||||
who->MeleeMitigation(this, max_damage, min_damage);
|
||||
|
||||
if(max_damage > 0) {
|
||||
@ -156,7 +159,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
if (HasDied()) return;
|
||||
|
||||
if (max_damage > 0)
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
//[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill
|
||||
if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){
|
||||
@ -373,8 +376,8 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
if (ca_atk->m_atk != 100 || ca_atk->m_skill != SkillBackstab) {
|
||||
break;
|
||||
}
|
||||
TryBackstab(GetTarget(), ReuseTime);
|
||||
ReuseTime = BackstabReuseTime-1 - skill_reduction;
|
||||
TryBackstab(GetTarget(), ReuseTime);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -527,64 +530,47 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
|
||||
if (FrontalBSChance && (FrontalBSChance > MakeRandomInt(0, 100)))
|
||||
bCanFrontalBS = true;
|
||||
}
|
||||
|
||||
|
||||
if (bIsBehind || bCanFrontalBS){ // Player is behind other OR can do Frontal Backstab
|
||||
|
||||
if (bCanFrontalBS) {
|
||||
if (bCanFrontalBS)
|
||||
CastToClient()->Message(0,"Your fierce attack is executed with such grace, your target did not see it coming!");
|
||||
}
|
||||
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
if (level > 54) {
|
||||
|
||||
// solar - chance to assassinate
|
||||
int chance = 10 + (GetDEX()/10) + (itembonuses.HeroicDEX/10); //18.5% chance at 85 dex 40% chance at 300 dex
|
||||
if(
|
||||
level >= 60 && // player is 60 or higher
|
||||
other->GetLevel() <= 45 && // mob 45 or under
|
||||
!other->CastToNPC()->IsEngaged() && // not aggro
|
||||
other->GetHP()<=32000
|
||||
&& other->IsNPC()
|
||||
&& MakeRandomFloat(0, 99) < chance // chance
|
||||
) {
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
RogueAssassinate(other);
|
||||
}
|
||||
else {
|
||||
RogueBackstab(other);
|
||||
if (level > 54) {
|
||||
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
|
||||
// Check for double attack with main hand assuming maxed DA Skill (MS)
|
||||
if(IsClient() && CastToClient()->CheckDoubleAttack(false))
|
||||
{
|
||||
if(other->GetHP() > 0)
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
|
||||
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
|
||||
{
|
||||
if(other->GetHP() > 0)
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
|
||||
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
}
|
||||
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
}
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
}
|
||||
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
|
||||
}
|
||||
//Live AA - Chaotic Backstab
|
||||
else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) {
|
||||
|
||||
//we can stab from any angle, we do min damage though.
|
||||
RogueBackstab(other, true);
|
||||
RogueBackstab(other, true, ReuseTime);
|
||||
if (level > 54) {
|
||||
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
|
||||
// Check for double attack with main hand assuming maxed DA Skill (MS)
|
||||
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
|
||||
if(IsClient() && CastToClient()->CheckDoubleAttack(false))
|
||||
if(other->GetHP() > 0)
|
||||
RogueBackstab(other,true, ReuseTime);
|
||||
|
||||
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
}
|
||||
|
||||
if(IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10);
|
||||
}
|
||||
else { //We do a single regular attack if we attack from the front without chaotic stab
|
||||
Attack(other, 13);
|
||||
@ -594,6 +580,9 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
|
||||
//heko: backstab
|
||||
void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
{
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
int32 ndamage = 0;
|
||||
int32 max_hit = 0;
|
||||
int32 min_hit = 0;
|
||||
@ -668,12 +657,20 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
}
|
||||
|
||||
ndamage = mod_backstab_damage(ndamage);
|
||||
|
||||
uint32 Assassinate_Dmg = 0;
|
||||
Assassinate_Dmg = TryAssassinate(other, SkillBackstab, ReuseTime);
|
||||
|
||||
if (Assassinate_Dmg) {
|
||||
ndamage = Assassinate_Dmg;
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
|
||||
}
|
||||
|
||||
DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime);
|
||||
DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false);
|
||||
DoAnim(animPiercing);
|
||||
}
|
||||
|
||||
// solar - assassinate
|
||||
// solar - assassinate [Kayen: No longer used for regular assassinate 6-29-14]
|
||||
void Mob::RogueAssassinate(Mob* other)
|
||||
{
|
||||
//can you dodge, parry, etc.. an assassinate??
|
||||
@ -861,8 +858,12 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
} else {
|
||||
mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName());
|
||||
|
||||
if(!TryHeadShot(other, SkillArchery))
|
||||
{
|
||||
|
||||
bool HeadShot = false;
|
||||
uint32 HeadShot_Dmg = TryHeadShot(other, SkillArchery);
|
||||
if (HeadShot_Dmg)
|
||||
HeadShot = true;
|
||||
|
||||
int32 TotalDmg = 0;
|
||||
int16 WDmg = 0;
|
||||
int16 ADmg = 0;
|
||||
@ -882,6 +883,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
uint32 MaxDmg = (RuleR(Combat, ArcheryBaseDamageBonus)*(WDmg+ADmg)*GetDamageTable(SkillArchery)) / 100;
|
||||
int32 hate = ((WDmg+ADmg));
|
||||
|
||||
if (HeadShot)
|
||||
MaxDmg = HeadShot_Dmg;
|
||||
|
||||
uint16 bonusArcheryDamageModifier = aabonuses.ArcheryDamageModifier + itembonuses.ArcheryDamageModifier + spellbonuses.ArcheryDamageModifier;
|
||||
|
||||
MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100;
|
||||
@ -938,7 +942,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
hate += (2*((GetLevel()-25)/3));
|
||||
}
|
||||
|
||||
other->AvoidDamage(this, TotalDmg, false);
|
||||
if (!HeadShot)
|
||||
other->AvoidDamage(this, TotalDmg, false);
|
||||
|
||||
other->MeleeMitigation(this, TotalDmg, minDmg);
|
||||
if(TotalDmg > 0)
|
||||
{
|
||||
@ -951,14 +957,17 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
|
||||
TryCriticalHit(other, SkillArchery, TotalDmg);
|
||||
other->AddToHateList(this, hate, 0, false);
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
}
|
||||
}
|
||||
else
|
||||
TotalDmg = -5;
|
||||
|
||||
if (HeadShot)
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName());
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//try proc on hits and misses
|
||||
@ -1056,7 +1065,7 @@ void NPC::RangedAttack(Mob* other)
|
||||
TryCriticalHit(GetTarget(), SkillArchery, TotalDmg);
|
||||
GetTarget()->AddToHateList(this, hate, 0, false);
|
||||
GetTarget()->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery);
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1264,13 +1273,24 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
|
||||
int32 TotalDmg = 0;
|
||||
|
||||
uint32 Assassinate_Dmg = 0;
|
||||
if (GetClass() == ROGUE && (BehindMob(other, GetX(), GetY())))
|
||||
Assassinate_Dmg = TryAssassinate(other, SkillThrowing, ranged_timer.GetDuration());
|
||||
|
||||
if(WDmg > 0)
|
||||
{
|
||||
int minDmg = 1;
|
||||
uint16 MaxDmg = GetThrownDamage(WDmg, TotalDmg, minDmg);
|
||||
|
||||
if (Assassinate_Dmg) {
|
||||
TotalDmg = Assassinate_Dmg;
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
|
||||
}
|
||||
|
||||
mlog(COMBAT__RANGED, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg);
|
||||
other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks.
|
||||
if (!Assassinate_Dmg)
|
||||
other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks.
|
||||
|
||||
other->MeleeMitigation(this, TotalDmg, minDmg);
|
||||
if(TotalDmg > 0)
|
||||
{
|
||||
@ -1281,7 +1301,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
TryCriticalHit(other, SkillThrowing, TotalDmg);
|
||||
int32 hate = (2*WDmg);
|
||||
other->AddToHateList(this, hate, 0, false);
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1854,92 +1874,6 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
||||
|
||||
if (who == nullptr)
|
||||
return;
|
||||
|
||||
if(DivineAura())
|
||||
return;
|
||||
|
||||
if(!CombatRange(who))
|
||||
return;
|
||||
|
||||
if(!always_succeed && IsClient())
|
||||
CastToClient()->CheckIncreaseSkill(TAUNT, who, 10);
|
||||
|
||||
int level = GetLevel();
|
||||
Mob *hate_top = who->GetHateMost();
|
||||
|
||||
// Check to see if we're already at the top of the target's hate list
|
||||
// a mob will not be taunted if its target's health is below 20%
|
||||
if ((hate_top != this)
|
||||
&& (who->GetLevel() < level)
|
||||
&& (hate_top == nullptr || hate_top->GetHPRatio() >= 20) ) {
|
||||
int32 newhate, tauntvalue;
|
||||
|
||||
float tauntchance;
|
||||
if(always_succeed) {
|
||||
tauntchance = 101;
|
||||
} else {
|
||||
|
||||
// no idea how taunt success is actually calculated
|
||||
// TODO: chance for level 50+ mobs should be lower
|
||||
int level_difference = level - who->GetLevel();
|
||||
if (level_difference <= 5) {
|
||||
tauntchance = 25.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 65.0)
|
||||
tauntchance = 65.0;
|
||||
}
|
||||
else if (level_difference <= 10) {
|
||||
tauntchance = 30.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 85.0)
|
||||
tauntchance = 85.0;
|
||||
}
|
||||
else if (level_difference <= 15) {
|
||||
tauntchance = 40.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 90.0)
|
||||
tauntchance = 90.0;
|
||||
}
|
||||
else {
|
||||
tauntchance = 50.0; // minimum
|
||||
tauntchance += tauntchance * (float)GetSkill(TAUNT) / 200.0; // skill modifier
|
||||
if (tauntchance > 95.0)
|
||||
tauntchance = 95.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (chance_bonus)
|
||||
tauntchance = tauntchance + (tauntchance*chance_bonus/100.0f);
|
||||
|
||||
if (tauntchance > MakeRandomFloat(0, 100)) {
|
||||
// this is the max additional hate added per succesfull taunt
|
||||
tauntvalue = (MakeRandomInt(2, 4) * level);
|
||||
//tauntvalue = (int32) ((float)level * 10.0 * (float)rand()/(float)RAND_MAX + 1);
|
||||
// new hate: find diff of player's hate and whoever's at top of list, add that plus tauntvalue to players hate
|
||||
newhate = who->GetNPCHate(hate_top) - who->GetNPCHate(this) + tauntvalue;
|
||||
// add the hate
|
||||
who->CastToNPC()->AddToHateList(this, newhate);
|
||||
}
|
||||
else{
|
||||
//generate at least some hate reguardless of the outcome.
|
||||
who->CastToNPC()->AddToHateList(this, (MakeRandomInt(2, 4)*level));
|
||||
}
|
||||
}
|
||||
|
||||
//generate at least some hate reguardless of the outcome.
|
||||
who->CastToNPC()->AddToHateList(this, (MakeRandomInt(2, 4)*level));
|
||||
if (HasSkillProcs()){
|
||||
float chance = (float)TauntReuseTime*RuleR(Combat, AvgProcsPerMinute)/60000.0f;
|
||||
TrySkillProc(who, TAUNT, chance);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
||||
|
||||
if (who == nullptr)
|
||||
@ -2074,30 +2008,134 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
|
||||
bool Result = false;
|
||||
uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
|
||||
|
||||
if(defender && skillInUse == SkillArchery) {
|
||||
if(GetAA(aaHeadshot) && defender->GetBodyType() == BT_Humanoid) {
|
||||
if((GetLevelCon(GetLevel(), defender->GetLevel()) == CON_LIGHTBLUE || GetLevelCon(GetLevel(), defender->GetLevel()) == CON_GREEN) && defender->GetLevel() <= 60 && !defender->IsClient()) {
|
||||
// WildcardX: These chance formula's below are arbitrary. If someone has a better formula that is more
|
||||
// consistent with live, feel free to update these.
|
||||
int AttackerChance = 20 + ((GetLevel() - 51) / 2) + (itembonuses.HeroicDEX / 10);
|
||||
int DefenderChance = MakeRandomInt(0, 100);
|
||||
if(AttackerChance > DefenderChance) {
|
||||
mlog(COMBAT__ATTACKS, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName());
|
||||
defender->Damage(this, 32000, SPELL_UNKNOWN, skillInUse);
|
||||
Result = true;
|
||||
}
|
||||
else {
|
||||
mlog(COMBAT__ATTACKS, "FAILED a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
|
||||
}
|
||||
}
|
||||
//Only works on YOUR target.
|
||||
if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient()
|
||||
&& (skillInUse == SkillArchery) && (GetTarget() == defender)) {
|
||||
|
||||
uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1];
|
||||
|
||||
uint8 HeadShot_Level = 0; //Get Highest Headshot Level
|
||||
HeadShot_Level = aabonuses.HSLevel;
|
||||
if (HeadShot_Level < spellbonuses.HSLevel)
|
||||
HeadShot_Level = spellbonuses.HSLevel;
|
||||
else if (HeadShot_Level < itembonuses.HSLevel)
|
||||
HeadShot_Level = itembonuses.HSLevel;
|
||||
|
||||
if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){
|
||||
|
||||
float ProcChance = GetSpecialProcChances(11);
|
||||
if(ProcChance > MakeRandomFloat(0,1))
|
||||
return HeadShot_Dmg;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Mob::GetSpecialProcChances(uint16 hand)
|
||||
{
|
||||
int mydex = GetDEX();
|
||||
|
||||
if (mydex > 255)
|
||||
mydex = 255;
|
||||
|
||||
uint16 weapon_speed;
|
||||
float ProcChance = 0.0f;
|
||||
float ProcBonus = 0.0f;
|
||||
|
||||
switch (hand) {
|
||||
case 13:
|
||||
weapon_speed = attack_timer.GetDuration();
|
||||
break;
|
||||
case 14:
|
||||
weapon_speed = attack_dw_timer.GetDuration();
|
||||
break;
|
||||
case 11:
|
||||
weapon_speed = ranged_timer.GetDuration();
|
||||
break;
|
||||
}
|
||||
|
||||
if (weapon_speed < RuleI(Combat, MinHastedDelay))
|
||||
weapon_speed = RuleI(Combat, MinHastedDelay);
|
||||
|
||||
if (RuleB(Combat, AdjustSpecialProcPerMinute)) {
|
||||
ProcChance = (static_cast<float>(weapon_speed) *
|
||||
RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f);
|
||||
ProcBonus += static_cast<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25);
|
||||
ProcChance += ProcChance * ProcBonus / 100.0f;
|
||||
} else {
|
||||
/*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.”
|
||||
Kayen: Most reports suggest a ~ 6% chance to Headshot which consistent with above.*/
|
||||
|
||||
ProcChance = (static_cast<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25))/100.0f;
|
||||
}
|
||||
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime) {
|
||||
|
||||
if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() &&
|
||||
(skillInUse == SkillBackstab || skillInUse == SkillThrowing)) {
|
||||
|
||||
uint32 Assassinate_Dmg = aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1];
|
||||
|
||||
uint8 Assassinate_Level = 0; //Get Highest Headshot Level
|
||||
Assassinate_Level = aabonuses.AssassinateLevel;
|
||||
if (Assassinate_Level < spellbonuses.AssassinateLevel)
|
||||
Assassinate_Level = spellbonuses.AssassinateLevel;
|
||||
else if (Assassinate_Level < itembonuses.AssassinateLevel)
|
||||
Assassinate_Level = itembonuses.AssassinateLevel;
|
||||
|
||||
if (GetLevel() >= 60){ //Innate Assassinate Ability if client as no bonuses.
|
||||
if (!Assassinate_Level)
|
||||
Assassinate_Level = 45;
|
||||
|
||||
if (!Assassinate_Dmg)
|
||||
Assassinate_Dmg = 32000;
|
||||
}
|
||||
|
||||
if(Assassinate_Dmg && Assassinate_Level && (defender->GetLevel() <= Assassinate_Level)){
|
||||
float ProcChance = 0.0f;
|
||||
|
||||
if (skillInUse == SkillThrowing)
|
||||
ProcChance = GetSpecialProcChances(11);
|
||||
else
|
||||
ProcChance = GetAssassinateProcChances(ReuseTime);
|
||||
|
||||
if(ProcChance > MakeRandomFloat(0,1))
|
||||
return Assassinate_Dmg;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Mob::GetAssassinateProcChances(uint16 ReuseTime)
|
||||
{
|
||||
int mydex = GetDEX();
|
||||
|
||||
if (mydex > 255)
|
||||
mydex = 255;
|
||||
|
||||
float ProcChance = 0.0f;
|
||||
float ProcBonus = 0.0f;
|
||||
|
||||
if (RuleB(Combat, AdjustSpecialProcPerMinute)) {
|
||||
ProcChance = (static_cast<float>(ReuseTime*1000) *
|
||||
RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f);
|
||||
ProcBonus += (10 + (static_cast<float>(mydex/10) + static_cast<float>(itembonuses.HeroicDEX /10)))/100.0f;
|
||||
ProcChance += ProcChance * ProcBonus / 100.0f;
|
||||
|
||||
} else {
|
||||
/*Kayen: Unable to find data on old proc rate of assassinate, no idea if our formula is real or made up.*/
|
||||
ProcChance = (10 + (static_cast<float>(mydex/10) + static_cast<float>(itembonuses.HeroicDEX /10)))/100.0f;
|
||||
|
||||
}
|
||||
|
||||
return ProcChance;
|
||||
}
|
||||
|
||||
void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte)
|
||||
@ -2196,7 +2234,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
if (HasDied())
|
||||
return;
|
||||
|
||||
CheckNumHitsRemaining(5);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||
|
||||
if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skillinuse){
|
||||
int kb_chance = 25;
|
||||
|
||||
@ -1551,15 +1551,22 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
GetPetType() != petCharmed
|
||||
)
|
||||
{
|
||||
int lvlmod = 4;
|
||||
if(caster->IsClient() && caster->CastToClient()->GetAA(aaImprovedReclaimEnergy))
|
||||
lvlmod = 8; //this is an unconfirmed number, I made it up
|
||||
if(caster->IsClient() && caster->CastToClient()->GetAA(aaImprovedReclaimEnergy2))
|
||||
lvlmod = 8; //this is an unconfirmed number, I made it up
|
||||
caster->SetMana(caster->GetMana()+(GetLevel()*lvlmod));
|
||||
uint16 pet_spellid = CastToNPC()->GetPetSpellID();
|
||||
uint16 pet_ActSpellCost = caster->GetActSpellCost(pet_spellid, spells[pet_spellid].mana);
|
||||
int16 ImprovedReclaimMod = caster->spellbonuses.ImprovedReclaimEnergy +
|
||||
caster->itembonuses.ImprovedReclaimEnergy +
|
||||
caster->aabonuses.ImprovedReclaimEnergy;
|
||||
|
||||
if (!ImprovedReclaimMod)
|
||||
ImprovedReclaimMod = 75; //Reclaim Energy default is 75% of actual mana cost
|
||||
|
||||
pet_ActSpellCost = pet_ActSpellCost*ImprovedReclaimMod/100;
|
||||
|
||||
caster->SetMana(caster->GetMana() + pet_ActSpellCost);
|
||||
|
||||
if(caster->IsClient())
|
||||
caster->CastToClient()->SetPet(0);
|
||||
|
||||
SetOwnerID(0); // this will kill the pet
|
||||
}
|
||||
break;
|
||||
@ -2183,12 +2190,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Fading Memories");
|
||||
#endif
|
||||
if(caster && caster->IsClient())
|
||||
caster->CastToClient()->Escape();
|
||||
else
|
||||
{
|
||||
entity_list.RemoveFromTargets(caster);
|
||||
SetInvisible(1);
|
||||
if(MakeRandomInt(0, 99) < spells[spell_id].base[i] ) {
|
||||
|
||||
if(caster && caster->IsClient())
|
||||
caster->CastToClient()->Escape();
|
||||
else
|
||||
{
|
||||
entity_list.RemoveFromTargets(caster);
|
||||
SetInvisible(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2234,8 +2244,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "AE Taunt");
|
||||
#endif
|
||||
if(caster && caster->IsClient())
|
||||
entity_list.AETaunt(caster->CastToClient());
|
||||
if(caster && caster->IsClient()){
|
||||
float range = 0.0f;
|
||||
if (spells[spell_id].base2[i])
|
||||
range = (float)spells[spell_id].base[i];
|
||||
|
||||
entity_list.AETaunt(caster->CastToClient(), range);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2279,12 +2294,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
#endif
|
||||
//meh dupe issue with npc casting this
|
||||
if(caster->IsClient()){
|
||||
//this spell doesn't appear to actually contain the information on duration inside of it oddly
|
||||
int dur = 60;
|
||||
if(spell_id == 3269)
|
||||
dur += 15;
|
||||
else if(spell_id == 3270)
|
||||
dur += 30;
|
||||
int dur = spells[spell_id].max[i];
|
||||
if (!dur)
|
||||
dur = 60;
|
||||
|
||||
caster->WakeTheDead(spell_id, caster->GetTarget(), dur);
|
||||
}
|
||||
@ -2393,7 +2405,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
gid = r->GetGroup(caster->GetName());
|
||||
if(gid < 11)
|
||||
{
|
||||
r->BalanceHP(spell.base[i], gid, spell.range, caster);
|
||||
r->BalanceHP(spell.base[i], gid, spell.range, caster, spell.base2[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2403,7 +2415,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
if(!g)
|
||||
break;
|
||||
|
||||
g->BalanceHP(spell.base[i], spell.range, caster);
|
||||
g->BalanceHP(spell.base[i], spell.range, caster, spell.base2[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2421,7 +2433,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
gid = r->GetGroup(caster->GetName());
|
||||
if(gid < 11)
|
||||
{
|
||||
r->BalanceMana(spell.base[i], gid, spell.range, caster);
|
||||
r->BalanceMana(spell.base[i], gid, spell.range, caster, spell.base2[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2431,7 +2443,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
if(!g)
|
||||
break;
|
||||
|
||||
g->BalanceMana(spell.base[i], spell.range, caster);
|
||||
g->BalanceMana(spell.base[i], spell.range, caster, spell.base2[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2643,9 +2655,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
|
||||
case SE_Taunt:
|
||||
{
|
||||
if (IsNPC())
|
||||
if (IsNPC()){
|
||||
caster->Taunt(this->CastToNPC(), false, spell.base[i]);
|
||||
|
||||
|
||||
if (spell.base2[i] > 0)
|
||||
CastToNPC()->SetHate(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2668,6 +2683,55 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
SlowMitigation(caster);
|
||||
break;
|
||||
|
||||
case SE_AddHatePct:
|
||||
{
|
||||
if (IsNPC()){
|
||||
int32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100;
|
||||
if (new_hate <= 0)
|
||||
new_hate = 1;
|
||||
|
||||
CastToNPC()->SetHate(caster, new_hate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Hate:{
|
||||
|
||||
if (buffslot >= 0)
|
||||
break;
|
||||
|
||||
if(caster){
|
||||
if(effect_value > 0){
|
||||
if(caster){
|
||||
if(caster->IsClient() && !caster->CastToClient()->GetFeigned())
|
||||
AddToHateList(caster, effect_value);
|
||||
else if(!caster->IsClient())
|
||||
AddToHateList(caster, effect_value);
|
||||
}
|
||||
}else{
|
||||
int32 newhate = GetHateAmount(caster) + effect_value;
|
||||
if (newhate < 1)
|
||||
SetHate(caster,1);
|
||||
else
|
||||
SetHate(caster,newhate);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_MassGroupBuff:{
|
||||
|
||||
SetMGB(true);
|
||||
Message_StringID(MT_Disciplines, MGB_STRING);
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_IllusionOther: {
|
||||
SetProjectIllusion(true);
|
||||
Message(10, "The power of your next illusion spell will flow to your grouped target in your place.");
|
||||
break;
|
||||
}
|
||||
|
||||
// Handled Elsewhere
|
||||
case SE_ImmuneFleeing:
|
||||
case SE_NegateSpellEffect:
|
||||
@ -2738,7 +2802,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_ChangeFrenzyRad:
|
||||
case SE_Harmony:
|
||||
case SE_ChangeAggro:
|
||||
case SE_Hate2:
|
||||
case SE_Identify:
|
||||
case SE_InstantHate:
|
||||
case SE_ReduceHate:
|
||||
@ -2797,8 +2860,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_CriticalHealChance:
|
||||
case SE_CriticalHealOverTime:
|
||||
case SE_CriticalDoTChance:
|
||||
case SE_SpellOnKill:
|
||||
case SE_SpellOnKill2:
|
||||
case SE_ProcOnKillShot:
|
||||
case SE_ProcOnSpellKillShot:
|
||||
case SE_CriticalDamageMob:
|
||||
case SE_LimitSpellGroup:
|
||||
case SE_ResistCorruption:
|
||||
@ -2823,7 +2886,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_ACv2:
|
||||
case SE_ManaRegen_v2:
|
||||
case SE_FcDamagePctCrit:
|
||||
case SE_FcHealAmt:
|
||||
case SE_FcHealAmt:
|
||||
case SE_FcHealPctIncoming:
|
||||
case SE_CriticalHealDecay:
|
||||
case SE_CriticalRegenDecay:
|
||||
@ -2837,6 +2900,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_PetCriticalHit:
|
||||
case SE_SlayUndead:
|
||||
case SE_GiveDoubleAttack:
|
||||
case SE_StrikeThrough:
|
||||
case SE_StrikeThrough2:
|
||||
case SE_SecondaryDmgInc:
|
||||
case SE_ArcheryDamageModifier:
|
||||
@ -2855,6 +2919,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_CombatStability:
|
||||
case SE_AddSingingMod:
|
||||
case SE_SongModCap:
|
||||
case SE_HeadShot:
|
||||
case SE_HeadShotLevel:
|
||||
case SE_PetAvoidance:
|
||||
case SE_GiveDoubleRiposte:
|
||||
case SE_Ambidexterity:
|
||||
@ -2886,6 +2952,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
case SE_LimitCastTimeMax:
|
||||
case SE_TriggerOnReqCaster:
|
||||
case SE_FrenziedDevastation:
|
||||
case SE_AStacker:
|
||||
case SE_BStacker:
|
||||
case SE_CStacker:
|
||||
case SE_DStacker:
|
||||
case SE_DoubleRiposte:
|
||||
case SE_Berserk:
|
||||
case SE_Vampirism:
|
||||
case SE_Metabolism:
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -3324,7 +3398,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_Hate2:{
|
||||
case SE_Hate:{
|
||||
effect_value = CalcSpellEffectValue(spell_id, i, caster_level);
|
||||
if(caster){
|
||||
if(effect_value > 0){
|
||||
@ -3518,6 +3592,18 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
}
|
||||
}
|
||||
|
||||
case SE_AddHateOverTimePct:
|
||||
{
|
||||
if (IsNPC()){
|
||||
int32 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base[i]) / 100;
|
||||
if (new_hate <= 0)
|
||||
new_hate = 1;
|
||||
|
||||
CastToNPC()->SetHate(caster, new_hate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// do we need to do anyting here?
|
||||
@ -5251,7 +5337,7 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
|
||||
1: [Incoming Hit Attempts] (323=SE_DefensiveProc, 172=SE_AvoidMeleeChance, 1=SE_ArmorClass, 40=SE_DivineAura)
|
||||
2: [Outgoing Hit Attempts] (185=SE_DamageModifer, 184=SE_HitChance)
|
||||
3: [Incoming Spells] (180=SE_ResistSpellChance, 296=SE_FcSpellVulnerability) //Note: Determinetal spells only unless proven otherwise
|
||||
4: NONE
|
||||
4: [Outgoing Spells]
|
||||
5: [Outgoing Hit Successes] (220=SE_SkillDamageAmount, 178=SE_MeleeLifetap, 121=SE_ReverseDS, ?373=SE_CastOnWearoff)
|
||||
6: [Incoming Hit Successes] (59=SE_DamageShield, 197=SE_SkillDamageTaken, 162=define SE_MitigateMeleeDamage)
|
||||
7: [Matching Spells] *When focus is triggered (focus effects)
|
||||
@ -5567,7 +5653,7 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill,
|
||||
}
|
||||
if ((!limit_exists) || (limit_exists && skill_found)){
|
||||
dmg += temp_dmg;
|
||||
CheckNumHitsRemaining(7,i);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells,i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5575,7 +5661,7 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill,
|
||||
int32 focus = caster->CalcFocusEffect(focusFcDamageAmtIncoming, buffs[i].spellid, spell_id);
|
||||
if(focus){
|
||||
dmg += focus;
|
||||
CheckNumHitsRemaining(7,i);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5629,7 +5715,7 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel
|
||||
value = tmp_focus;
|
||||
|
||||
if (tmp_buffslot >= 0)
|
||||
CheckNumHitsRemaining(7, tmp_buffslot);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5718,16 +5804,25 @@ uint16 Mob::GetSpellEffectResistChance(uint16 spell_id)
|
||||
|
||||
bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){
|
||||
|
||||
/*Live 5-20-14 Patch Note: Updated all spells which use Remove Detrimental and
|
||||
Cancel Beneficial spell effects to use a new method. The chances for those spells to
|
||||
affect their targets have not changed unless otherwise noted.*/
|
||||
|
||||
/*This should provide a somewhat accurate conversion between pre 5/14 base values and post.
|
||||
until more information is avialble - Kayen*/
|
||||
if (level_modifier >= 100)
|
||||
level_modifier = level_modifier/100;
|
||||
|
||||
//Dispels - Check level of caster agianst buffs level (level of the caster who cast the buff)
|
||||
//Effect value of dispels are treated as a level modifier.
|
||||
//Values for scaling were obtain from live parses, best estimates.
|
||||
|
||||
caster_level += level_modifier - 1;
|
||||
int dispel_chance = 36; //Baseline chance if no level difference and no modifier
|
||||
int dispel_chance = 32; //Baseline chance if no level difference and no modifier
|
||||
int level_diff = caster_level - buff_level;
|
||||
|
||||
if (level_diff > 0)
|
||||
dispel_chance += level_diff * 8;
|
||||
dispel_chance += level_diff * 7;
|
||||
|
||||
else if (level_diff < 0)
|
||||
dispel_chance += level_diff * 2;
|
||||
|
||||
@ -399,7 +399,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
|
||||
mana_cost = GetActSpellCost(spell_id, mana_cost);
|
||||
}
|
||||
|
||||
if(IsClient() && CastToClient()->CheckAAEffect(aaEffectMassGroupBuff) && spells[spell_id].can_mgb)
|
||||
if(HasMGB() && spells[spell_id].can_mgb)
|
||||
mana_cost *= 2;
|
||||
|
||||
// mana is checked for clients on the frontend. we need to recheck it for NPCs though
|
||||
@ -1250,7 +1250,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
|
||||
}
|
||||
|
||||
if(IsClient()) {
|
||||
CheckNumHitsRemaining(7);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells);
|
||||
TrySympatheticProc(target, spell_id);
|
||||
}
|
||||
|
||||
@ -1371,7 +1371,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
|
||||
&& IsClient()
|
||||
&& (IsGrouped() // still self only if not grouped
|
||||
|| IsRaidGrouped())
|
||||
&& CastToClient()->CheckAAEffect(aaEffectProjectIllusion)){
|
||||
&& (HasProjectIllusion())){
|
||||
mlog(AA__MESSAGE, "Project Illusion overwrote target caster: %s spell id: %d was ON", GetName(), spell_id);
|
||||
targetType = ST_GroupClientAndPet;
|
||||
}
|
||||
@ -1853,7 +1853,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
|
||||
range = GetActSpellRange(spell_id, range);
|
||||
if(IsPlayerIllusionSpell(spell_id)
|
||||
&& IsClient()
|
||||
&& CastToClient()->CheckAAEffect(aaEffectProjectIllusion)){
|
||||
&& (HasProjectIllusion())){
|
||||
range = 100;
|
||||
}
|
||||
if(spell_target != nullptr && spell_target != this) {
|
||||
@ -1912,9 +1912,9 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
|
||||
|
||||
if(IsPlayerIllusionSpell(spell_id)
|
||||
&& IsClient()
|
||||
&& CastToClient()->CheckAAEffect(aaEffectProjectIllusion)){
|
||||
&& (HasProjectIllusion())){
|
||||
mlog(AA__MESSAGE, "Effect Project Illusion for %s on spell id: %d was ON", GetName(), spell_id);
|
||||
CastToClient()->DisableAAEffect(aaEffectProjectIllusion);
|
||||
SetProjectIllusion(false);
|
||||
}
|
||||
else{
|
||||
mlog(AA__MESSAGE, "Effect Project Illusion for %s on spell id: %d was OFF", GetName(), spell_id);
|
||||
@ -1969,11 +1969,11 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
|
||||
}
|
||||
#endif //BOTS
|
||||
|
||||
if(spells[spell_id].can_mgb && IsClient() && CastToClient()->CheckAAEffect(aaEffectMassGroupBuff))
|
||||
if(spells[spell_id].can_mgb && HasMGB())
|
||||
{
|
||||
SpellOnTarget(spell_id, this);
|
||||
entity_list.MassGroupBuff(this, this, spell_id, true);
|
||||
CastToClient()->DisableAAEffect(aaEffectMassGroupBuff);
|
||||
SetMGB(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2542,7 +2542,7 @@ int CalcBuffDuration_formula(int level, int formula, int duration)
|
||||
// -1 if they can't stack and spellid2 should be stopped
|
||||
//currently, a spell will not land if it would overwrite a better spell on any effect
|
||||
//if all effects are better or the same, we overwrite, else we do nothing
|
||||
int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1, Mob* caster2)
|
||||
int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1, Mob* caster2, int buffslot)
|
||||
{
|
||||
const SPDat_Spell_Struct &sp1 = spells[spellid1];
|
||||
const SPDat_Spell_Struct &sp2 = spells[spellid2];
|
||||
@ -2621,6 +2621,36 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
|
||||
}
|
||||
}
|
||||
|
||||
/*Buff stacking prevention spell effects (446 - 449) works as follows... If B prevent A, if C prevent B, if D prevent C.
|
||||
If checking same type ie A vs A, which ever effect base value is higher will take hold.
|
||||
Special check is added to make sure the buffs stack properly when applied from fade on duration effect, since the buff
|
||||
is not fully removed at the time of the trgger*/
|
||||
if (spellbonuses.AStacker[0]) {
|
||||
if ((effect2 == SE_AStacker) && (sp2.effectid[i] <= spellbonuses.AStacker[1]))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spellbonuses.BStacker[0]) {
|
||||
if ((effect2 == SE_BStacker) && (sp2.effectid[i] <= spellbonuses.BStacker[1]))
|
||||
return -1;
|
||||
if ((effect2 == SE_AStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spellbonuses.CStacker[0]) {
|
||||
if ((effect2 == SE_CStacker) && (sp2.effectid[i] <= spellbonuses.CStacker[1]))
|
||||
return -1;
|
||||
if ((effect2 == SE_BStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spellbonuses.DStacker[0]) {
|
||||
if ((effect2 == SE_DStacker) && (sp2.effectid[i] <= spellbonuses.DStacker[1]))
|
||||
return -1;
|
||||
if ((effect2 == SE_CStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(effect2 == SE_StackingCommand_Overwrite)
|
||||
{
|
||||
overwrite_effect = sp2.base[i];
|
||||
@ -2901,7 +2931,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
if (curbuf.spellid != SPELL_UNKNOWN) {
|
||||
// there's a buff in this slot
|
||||
ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spell_id,
|
||||
caster_level, entity_list.GetMobID(curbuf.casterid), caster);
|
||||
caster_level, entity_list.GetMobID(curbuf.casterid), caster, buffslot);
|
||||
if (ret == -1) { // stop the spell
|
||||
mlog(SPELLS__BUFFS, "Adding buff %d failed: stacking prevented by spell %d in slot %d with caster level %d",
|
||||
spell_id, curbuf.spellid, buffslot, curbuf.casterlevel);
|
||||
@ -3047,7 +3077,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite)
|
||||
return(-1); //do not recast a buff we already have on, we recast fast enough that we dont need to refresh our buffs
|
||||
|
||||
// there's a buff in this slot
|
||||
ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spellid, caster_level);
|
||||
ret = CheckStackConflict(curbuf.spellid, curbuf.casterlevel, spellid, caster_level, nullptr, nullptr, i);
|
||||
if(ret == 1) {
|
||||
// should overwrite current slot
|
||||
if(iFailIfOverwrite) {
|
||||
@ -3383,7 +3413,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
if(IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) {
|
||||
focus = CalcFocusEffect(focusBlockNextSpell, buffs[b].spellid, spell_id);
|
||||
if(focus) {
|
||||
CheckNumHitsRemaining(7,b);
|
||||
CheckNumHitsRemaining(NUMHIT_MatchingSpells,b);
|
||||
Message_StringID(MT_SpellFailure, SPELL_WOULDNT_HOLD);
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
@ -3432,7 +3462,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
}
|
||||
if(reflect_chance) {
|
||||
Message_StringID(MT_Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName());
|
||||
CheckNumHitsRemaining(9);
|
||||
CheckNumHitsRemaining(NUMHIT_ReflectSpell);
|
||||
SpellOnTarget(spell_id, this, true, use_resist_adjust, resist_adjust);
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
@ -3483,7 +3513,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
}
|
||||
}
|
||||
|
||||
spelltar->CheckNumHitsRemaining(3);
|
||||
spelltar->CheckNumHitsRemaining(NUMHIT_IncomingSpells);
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingSpells);
|
||||
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
@ -3636,8 +3667,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
}
|
||||
|
||||
|
||||
if (spelltar && IsDetrimentalSpell(spell_id))
|
||||
spelltar->CheckNumHitsRemaining(3); //Incoming spells
|
||||
if (IsDetrimentalSpell(spell_id)) {
|
||||
|
||||
CheckNumHitsRemaining(NUMHIT_OutgoingSpells);
|
||||
|
||||
if (spelltar)
|
||||
spelltar->CheckNumHitsRemaining(NUMHIT_IncomingSpells);
|
||||
}
|
||||
|
||||
// send the action packet again now that the spell is successful
|
||||
// NOTE: this is what causes the buff icon to appear on the client, if
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user