diff --git a/common/ruletypes.h b/common/ruletypes.h index f066b9115..4c9430998 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -20,604 +20,605 @@ -RULE_CATEGORY( Character ) -RULE_INT ( Character, MaxLevel, 65 ) -RULE_BOOL ( Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level -RULE_INT ( Character, MaxExpLevel, 0 ) //Sets the Max Level attainable via Experience -RULE_INT ( Character, DeathExpLossLevel, 10 ) // Any level greater than this will lose exp on death -RULE_INT ( Character, DeathExpLossMaxLevel, 255 ) // Any level greater than this will no longer lose exp on death -RULE_INT ( Character, DeathItemLossLevel, 10 ) -RULE_INT ( Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost -RULE_BOOL( Character, UseDeathExpLossMult, false ) //Adjust to use the above multiplier or to use code default. -RULE_INT ( Character, CorpseDecayTimeMS, 10800000 ) -RULE_INT ( Character, CorpseResTimeMS, 10800000 ) // time before cant res corpse(3 hours) -RULE_BOOL( Character, LeaveCorpses, true ) -RULE_BOOL( Character, LeaveNakedCorpses, false ) -RULE_INT ( Character, MaxDraggedCorpses, 2 ) -RULE_REAL( Character, DragCorpseDistance, 400) // If the corpse is <= this distance from the player, it won't move -RULE_REAL( Character, ExpMultiplier, 0.5 ) -RULE_REAL( Character, AAExpMultiplier, 0.5 ) -RULE_REAL( Character, GroupExpMultiplier, 0.5 ) -RULE_REAL( Character, RaidExpMultiplier, 0.2 ) -RULE_BOOL( Character, UseXPConScaling, true ) -RULE_INT ( Character, LightBlueModifier, 40 ) -RULE_INT ( Character, BlueModifier, 90 ) -RULE_INT ( Character, WhiteModifier, 100 ) -RULE_INT ( Character, YellowModifier, 125 ) -RULE_INT ( Character, RedModifier, 150 ) -RULE_INT ( Character, AutosaveIntervalS, 300 ) //0=disabled -RULE_INT ( Character, HPRegenMultiplier, 100) -RULE_INT ( Character, ManaRegenMultiplier, 100) -RULE_INT ( Character, EnduranceRegenMultiplier, 100) -RULE_INT ( Character, ConsumptionMultiplier, 100) //item's hunger restored = this value * item's food level, 100 = normal, 50 = people eat 2x as fast, 200 = people eat 2x as slow -RULE_BOOL( Character, HealOnLevel, false) -RULE_BOOL( Character, FeignKillsPet, false) -RULE_INT ( Character, ItemManaRegenCap, 15) -RULE_INT ( Character, ItemHealthRegenCap, 35) -RULE_INT ( Character, ItemDamageShieldCap, 30) -RULE_INT ( Character, ItemAccuracyCap, 150) -RULE_INT ( Character, ItemAvoidanceCap, 100) -RULE_INT ( Character, ItemCombatEffectsCap, 100) -RULE_INT ( Character, ItemShieldingCap, 35) -RULE_INT ( Character, ItemSpellShieldingCap, 35) -RULE_INT ( Character, ItemDoTShieldingCap, 35) -RULE_INT ( Character, ItemStunResistCap, 35) -RULE_INT ( Character, ItemStrikethroughCap, 35) -RULE_INT ( Character, ItemATKCap, 250) -RULE_INT ( Character, ItemHealAmtCap, 250) -RULE_INT ( Character, ItemSpellDmgCap, 250) -RULE_INT ( Character, ItemClairvoyanceCap, 250) -RULE_INT ( Character, ItemDSMitigationCap, 50) -RULE_INT ( Character, ItemEnduranceRegenCap, 15) -RULE_INT ( Character, ItemExtraDmgCap, 150) // Cap for bonuses to melee skills like Bash, Frenzy, etc -RULE_INT ( Character, HasteCap, 100) // Haste cap for non-v3(overhaste) haste. -RULE_INT ( Character, SkillUpModifier, 100) //skill ups are at 100% -RULE_BOOL ( Character, SharedBankPlat, false) //off by default to prevent duping for now -RULE_BOOL ( Character, BindAnywhere, false) -RULE_INT ( Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen. -RULE_INT ( Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in. -RULE_INT ( Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target. -RULE_BOOL ( Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not. -RULE_INT ( Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA -RULE_INT ( Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA -RULE_INT ( Character, MaxFearDurationForPlayerCharacter, 4) //4 tics, each tic calculates every 6 seconds. -RULE_INT ( Character, MaxCharmDurationForPlayerCharacter, 15) -RULE_INT ( Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values -RULE_BOOL ( Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas -RULE_BOOL ( Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses -RULE_BOOL ( Character, RespawnFromHover, false) // Use Respawn window, or not. -RULE_INT ( Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS -RULE_BOOL ( Character, UseNewStatsWindow, true) // New stats window shows everything -RULE_BOOL ( Character, ItemCastsUseFocus, false) // If true, this allows item clickies to use focuses that have limited max levels on them -RULE_INT ( Character, MinStatusForNoDropExemptions, 80) // This allows status x and higher to trade no drop items. -RULE_INT ( Character, SkillCapMaxLevel, 75 ) // Sets the Max Level used for Skill Caps (from skill_caps table). -1 makes it use MaxLevel rule value. It is set to 75 because PEQ only has skillcaps up to that level, and grabbing the players' skill past 75 will return 0, breaking all skills past that level. This helps servers with obsurd level caps (75+ level cap) function without any modifications. -RULE_INT ( Character, StatCap, 0 ) -RULE_BOOL ( Character, CheckCursorEmptyWhenLooting, true ) // If true, a player cannot loot a corpse (player or NPC) with an item on their cursor -RULE_BOOL ( Character, MaintainIntoxicationAcrossZones, true ) // If true, alcohol effects are maintained across zoning and logging out/in. -RULE_BOOL ( Character, EnableDiscoveredItems, true ) // If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered. -RULE_BOOL ( Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. -RULE_BOOL ( Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap -RULE_INT ( Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update -RULE_INT ( Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. -RULE_BOOL ( Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field -RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. -RULE_INT ( Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type +RULE_CATEGORY(Character) +RULE_INT(Character, MaxLevel, 65) +RULE_BOOL(Character, PerCharacterQglobalMaxLevel, false) // This will check for qglobal 'CharMaxLevel' character qglobal (Type 5), if player tries to level beyond that point, it will not go beyond that level +RULE_INT(Character, MaxExpLevel, 0) //Sets the Max Level attainable via Experience +RULE_INT(Character, DeathExpLossLevel, 10) // Any level greater than this will lose exp on death +RULE_INT(Character, DeathExpLossMaxLevel, 255) // Any level greater than this will no longer lose exp on death +RULE_INT(Character, DeathItemLossLevel, 10) +RULE_INT(Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost +RULE_BOOL(Character, UseDeathExpLossMult, false) //Adjust to use the above multiplier or to use code default. +RULE_INT(Character, CorpseDecayTimeMS, 10800000) +RULE_INT(Character, CorpseResTimeMS, 10800000) // time before cant res corpse(3 hours) +RULE_BOOL(Character, LeaveCorpses, true) +RULE_BOOL(Character, LeaveNakedCorpses, false) +RULE_INT(Character, MaxDraggedCorpses, 2) +RULE_REAL(Character, DragCorpseDistance, 400) // If the corpse is <= this distance from the player, it won't move +RULE_REAL(Character, ExpMultiplier, 0.5) +RULE_REAL(Character, AAExpMultiplier, 0.5) +RULE_REAL(Character, GroupExpMultiplier, 0.5) +RULE_REAL(Character, RaidExpMultiplier, 0.2) +RULE_BOOL(Character, UseXPConScaling, true) +RULE_INT(Character, LightBlueModifier, 40) +RULE_INT(Character, BlueModifier, 90) +RULE_INT(Character, WhiteModifier, 100) +RULE_INT(Character, YellowModifier, 125) +RULE_INT(Character, RedModifier, 150) +RULE_INT(Character, AutosaveIntervalS, 300) //0=disabled +RULE_INT(Character, HPRegenMultiplier, 100) +RULE_INT(Character, ManaRegenMultiplier, 100) +RULE_INT(Character, EnduranceRegenMultiplier, 100) +RULE_INT(Character, ConsumptionMultiplier, 100) //item's hunger restored = this value * item's food level, 100 = normal, 50 = people eat 2x as fast, 200 = people eat 2x as slow +RULE_BOOL(Character, HealOnLevel, false) +RULE_BOOL(Character, FeignKillsPet, false) +RULE_INT(Character, ItemManaRegenCap, 15) +RULE_INT(Character, ItemHealthRegenCap, 35) +RULE_INT(Character, ItemDamageShieldCap, 30) +RULE_INT(Character, ItemAccuracyCap, 150) +RULE_INT(Character, ItemAvoidanceCap, 100) +RULE_INT(Character, ItemCombatEffectsCap, 100) +RULE_INT(Character, ItemShieldingCap, 35) +RULE_INT(Character, ItemSpellShieldingCap, 35) +RULE_INT(Character, ItemDoTShieldingCap, 35) +RULE_INT(Character, ItemStunResistCap, 35) +RULE_INT(Character, ItemStrikethroughCap, 35) +RULE_INT(Character, ItemATKCap, 250) +RULE_INT(Character, ItemHealAmtCap, 250) +RULE_INT(Character, ItemSpellDmgCap, 250) +RULE_INT(Character, ItemClairvoyanceCap, 250) +RULE_INT(Character, ItemDSMitigationCap, 50) +RULE_INT(Character, ItemEnduranceRegenCap, 15) +RULE_INT(Character, ItemExtraDmgCap, 150) // Cap for bonuses to melee skills like Bash, Frenzy, etc +RULE_INT(Character, HasteCap, 100) // Haste cap for non-v3(overhaste) haste. +RULE_INT(Character, SkillUpModifier, 100) //skill ups are at 100% +RULE_BOOL(Character, SharedBankPlat, false) //off by default to prevent duping for now +RULE_BOOL(Character, BindAnywhere, false) +RULE_INT(Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen. +RULE_INT(Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in. +RULE_INT(Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target. +RULE_BOOL(Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not. +RULE_INT(Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA +RULE_INT(Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA +RULE_INT(Character, MaxFearDurationForPlayerCharacter, 4) //4 tics, each tic calculates every 6 seconds. +RULE_INT(Character, MaxCharmDurationForPlayerCharacter, 15) +RULE_INT(Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values +RULE_BOOL(Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas +RULE_BOOL(Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses +RULE_BOOL(Character, RespawnFromHover, false) // Use Respawn window, or not. +RULE_INT(Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS +RULE_BOOL(Character, UseNewStatsWindow, true) // New stats window shows everything +RULE_BOOL(Character, ItemCastsUseFocus, false) // If true, this allows item clickies to use focuses that have limited max levels on them +RULE_INT(Character, MinStatusForNoDropExemptions, 80) // This allows status x and higher to trade no drop items. +RULE_INT(Character, SkillCapMaxLevel, 75) // Sets the Max Level used for Skill Caps (from skill_caps table). -1 makes it use MaxLevel rule value. It is set to 75 because PEQ only has skillcaps up to that level, and grabbing the players' skill past 75 will return 0, breaking all skills past that level. This helps servers with obsurd level caps (75+ level cap) function without any modifications. +RULE_INT(Character, StatCap, 0) +RULE_BOOL(Character, CheckCursorEmptyWhenLooting, true) // If true, a player cannot loot a corpse (player or NPC) with an item on their cursor +RULE_BOOL(Character, MaintainIntoxicationAcrossZones, true) // If true, alcohol effects are maintained across zoning and logging out/in. +RULE_BOOL(Character, EnableDiscoveredItems, true) // If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered. +RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. +RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap +RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update +RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. +RULE_BOOL(Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field +RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. +RULE_INT(Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type RULE_REAL(Character, EnvironmentDamageMulipliter, 1) RULE_BOOL(Character, UnmemSpellsOnDeath, true) -RULE_INT ( Character, TradeskillUpAlchemy, 2 ) // Alchemy skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpBaking, 2 ) // Baking skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpBlacksmithing, 2 ) // Blacksmithing skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpBrewing, 3 ) // Brewing skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpFletching, 2 ) // Fletching skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpJewelcrafting, 2 ) // Jewelcrafting skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpMakePoison, 2 ) // Make Poison skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpPottery, 4 ) // Pottery skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpResearch, 1 ) // Research skillup rate adjust. Lower is faster. -RULE_INT ( Character, TradeskillUpTinkering, 2 ) // Tinkering skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpAlchemy, 2) // Alchemy skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpBaking, 2) // Baking skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpBlacksmithing, 2) // Blacksmithing skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpBrewing, 3) // Brewing skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpFletching, 2) // Fletching skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpJewelcrafting, 2) // Jewelcrafting skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster. +RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster. RULE_CATEGORY_END() -RULE_CATEGORY( Mercs ) -RULE_INT (Mercs, SuspendIntervalMS, 10000) -RULE_INT (Mercs, UpkeepIntervalMS, 180000) -RULE_INT (Mercs, SuspendIntervalS, 10) -RULE_INT (Mercs, UpkeepIntervalS, 180) -RULE_BOOL (Mercs, AllowMercs, false) -RULE_BOOL (Mercs, ChargeMercPurchaseCost, false) -RULE_BOOL (Mercs, ChargeMercUpkeepCost, false) -RULE_INT (Mercs, AggroRadius, 100) // Determines the distance from which a merc will aggro group member's target(also used to determine the distance at which a healer merc will begin healing a group member) -RULE_INT (Mercs, AggroRadiusPuller, 25) // Determines the distance from which a merc will aggro group member's target, if they have the group role of puller (also used to determine the distance at which a healer merc will begin healing a group member, if they have the group role of puller) -RULE_INT (Mercs, ResurrectRadius, 50) // Determines the distance from which a healer merc will attempt to resurrect a group member's corpse -RULE_INT (Mercs, ScaleRate, 100) +RULE_CATEGORY(Mercs) +RULE_INT(Mercs, SuspendIntervalMS, 10000) +RULE_INT(Mercs, UpkeepIntervalMS, 180000) +RULE_INT(Mercs, SuspendIntervalS, 10) +RULE_INT(Mercs, UpkeepIntervalS, 180) +RULE_BOOL(Mercs, AllowMercs, false) +RULE_BOOL(Mercs, ChargeMercPurchaseCost, false) +RULE_BOOL(Mercs, ChargeMercUpkeepCost, false) +RULE_INT(Mercs, AggroRadius, 100) // Determines the distance from which a merc will aggro group member's target(also used to determine the distance at which a healer merc will begin healing a group member) +RULE_INT(Mercs, AggroRadiusPuller, 25) // Determines the distance from which a merc will aggro group member's target, if they have the group role of puller (also used to determine the distance at which a healer merc will begin healing a group member, if they have the group role of puller) +RULE_INT(Mercs, ResurrectRadius, 50) // Determines the distance from which a healer merc will attempt to resurrect a group member's corpse +RULE_INT(Mercs, ScaleRate, 100) RULE_CATEGORY_END() -RULE_CATEGORY( Guild ) -RULE_INT ( Guild, MaxMembers, 2048 ) -RULE_BOOL ( Guild, PlayerCreationAllowed, false) // Allow players to create a guild using the window in Underfoot+ -RULE_INT ( Guild, PlayerCreationLimit, 1) // Only allow use of the UF+ window if the account has < than this number of guild leaders on it -RULE_INT ( Guild, PlayerCreationRequiredStatus, 0) // Required admin status. -RULE_INT ( Guild, PlayerCreationRequiredLevel, 0) // Required Level of the player attempting to create the guild. -RULE_INT ( Guild, PlayerCreationRequiredTime, 0) // Required Time Entitled On Account (in Minutes) to create the guild. +RULE_CATEGORY(Guild) +RULE_INT(Guild, MaxMembers, 2048) +RULE_BOOL(Guild, PlayerCreationAllowed, false) // Allow players to create a guild using the window in Underfoot+ +RULE_INT(Guild, PlayerCreationLimit, 1) // Only allow use of the UF+ window if the account has < than this number of guild leaders on it +RULE_INT(Guild, PlayerCreationRequiredStatus, 0) // Required admin status. +RULE_INT(Guild, PlayerCreationRequiredLevel, 0) // Required Level of the player attempting to create the guild. +RULE_INT(Guild, PlayerCreationRequiredTime, 0) // Required Time Entitled On Account (in Minutes) to create the guild. RULE_CATEGORY_END() -RULE_CATEGORY( Skills ) -RULE_INT ( Skills, MaxTrainTradeskills, 21 ) -RULE_BOOL ( Skills, UseLimitTradeskillSearchSkillDiff, true ) -RULE_INT ( Skills, MaxTradeskillSearchSkillDiff, 50 ) -RULE_INT ( Skills, MaxTrainSpecializations, 50 ) // Max level a GM trainer will train casting specializations -RULE_INT ( Skills, SwimmingStartValue, 100 ) -RULE_BOOL ( Skills, TrainSenseHeading, false ) -RULE_INT ( Skills, SenseHeadingStartValue, 200 ) +RULE_CATEGORY(Skills) +RULE_INT(Skills, MaxTrainTradeskills, 21) +RULE_BOOL(Skills, UseLimitTradeskillSearchSkillDiff, true) +RULE_INT(Skills, MaxTradeskillSearchSkillDiff, 50) +RULE_INT(Skills, MaxTrainSpecializations, 50) // Max level a GM trainer will train casting specializations +RULE_INT(Skills, SwimmingStartValue, 100) +RULE_BOOL(Skills, TrainSenseHeading, false) +RULE_INT(Skills, SenseHeadingStartValue, 200) RULE_CATEGORY_END() -RULE_CATEGORY( Pets ) -RULE_REAL( Pets, AttackCommandRange, 150 ) -RULE_BOOL( Pets, UnTargetableSwarmPet, false ) -RULE_REAL( Pets, PetPowerLevelCap, 10 ) // Max number of levels your pet can go up with pet power +RULE_CATEGORY(Pets) +RULE_REAL(Pets, AttackCommandRange, 150) +RULE_BOOL(Pets, UnTargetableSwarmPet, false) +RULE_REAL(Pets, PetPowerLevelCap, 10) // Max number of levels your pet can go up with pet power RULE_CATEGORY_END() -RULE_CATEGORY( GM ) -RULE_INT ( GM, MinStatusToSummonItem, 250) -RULE_INT ( GM, MinStatusToZoneAnywhere, 250 ) +RULE_CATEGORY(GM) +RULE_INT(GM, MinStatusToSummonItem, 250) +RULE_INT(GM, MinStatusToZoneAnywhere, 250) RULE_CATEGORY_END() -RULE_CATEGORY( World ) -RULE_INT ( World, ZoneAutobootTimeoutMS, 60000 ) -RULE_INT ( World, ClientKeepaliveTimeoutMS, 65000 ) -RULE_BOOL ( World, UseBannedIPsTable, false ) // Toggle whether or not to check incoming client connections against the Banned_IPs table. Set this value to false to disable this feature. -RULE_BOOL ( World, EnableTutorialButton, true) -RULE_BOOL ( World, EnableReturnHomeButton, true) -RULE_INT ( World, MaxLevelForTutorial, 10) -RULE_INT ( World, TutorialZoneID, 189) -RULE_INT ( World, GuildBankZoneID, 345) -RULE_INT ( World, MinOfflineTimeToReturnHome, 21600) // 21600 seconds is 6 Hours -RULE_INT ( World, MaxClientsPerIP, -1 ) // Maximum number of clients allowed to connect per IP address if account status is < AddMaxClientsStatus. Default value: -1 (feature disabled) -RULE_INT ( World, ExemptMaxClientsStatus, -1 ) // Exempt accounts from the MaxClientsPerIP and AddMaxClientsStatus rules, if their status is >= this value. Default value: -1 (feature disabled) -RULE_INT ( World, AddMaxClientsPerIP, -1 ) // Maximum number of clients allowed to connect per IP address if account status is < ExemptMaxClientsStatus. Default value: -1 (feature disabled) -RULE_INT ( World, AddMaxClientsStatus, -1 ) // Accounts with status >= this rule will be allowed to use the amount of accounts defined in the AddMaxClientsPerIP. Default value: -1 (feature disabled) -RULE_BOOL ( World, MaxClientsSetByStatus, false) // If True, IP Limiting will be set to the status on the account as long as the status is > MaxClientsPerIP -RULE_BOOL ( World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots. -RULE_BOOL ( World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks. -RULE_INT ( World, AccountSessionLimit, -1 ) //Max number of characters allowed on at once from a single account (-1 is disabled) -RULE_INT ( World, ExemptAccountLimitStatus, -1 ) //Min status required to be exempt from multi-session per account limiting (-1 is disabled) -RULE_BOOL ( World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. -RULE_INT ( World, MinGMAntiHackStatus, 1 ) //Minimum GM status to check against AntiHack list -RULE_INT ( World, SoFStartZoneID, -1 ) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) -RULE_INT ( World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method. -RULE_INT ( World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS. -RULE_INT ( World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules. +RULE_CATEGORY(World) +RULE_INT(World, ZoneAutobootTimeoutMS, 60000) +RULE_INT(World, ClientKeepaliveTimeoutMS, 65000) +RULE_BOOL(World, UseBannedIPsTable, false) // Toggle whether or not to check incoming client connections against the Banned_IPs table. Set this value to false to disable this feature. +RULE_BOOL(World, EnableTutorialButton, true) +RULE_BOOL(World, EnableReturnHomeButton, true) +RULE_INT(World, MaxLevelForTutorial, 10) +RULE_INT(World, TutorialZoneID, 189) +RULE_INT(World, GuildBankZoneID, 345) +RULE_INT(World, MinOfflineTimeToReturnHome, 21600) // 21600 seconds is 6 Hours +RULE_INT(World, MaxClientsPerIP, -1) // Maximum number of clients allowed to connect per IP address if account status is < AddMaxClientsStatus. Default value: -1 (feature disabled) +RULE_INT(World, ExemptMaxClientsStatus, -1) // Exempt accounts from the MaxClientsPerIP and AddMaxClientsStatus rules, if their status is >= this value. Default value: -1 (feature disabled) +RULE_INT(World, AddMaxClientsPerIP, -1) // Maximum number of clients allowed to connect per IP address if account status is < ExemptMaxClientsStatus. Default value: -1 (feature disabled) +RULE_INT(World, AddMaxClientsStatus, -1) // Accounts with status >= this rule will be allowed to use the amount of accounts defined in the AddMaxClientsPerIP. Default value: -1 (feature disabled) +RULE_BOOL(World, MaxClientsSetByStatus, false) // If True, IP Limiting will be set to the status on the account as long as the status is > MaxClientsPerIP +RULE_BOOL(World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots. +RULE_BOOL(World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks. +RULE_INT(World, AccountSessionLimit, -1) //Max number of characters allowed on at once from a single account (-1 is disabled) +RULE_INT(World, ExemptAccountLimitStatus, -1) //Min status required to be exempt from multi-session per account limiting (-1 is disabled) +RULE_BOOL(World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. +RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against AntiHack list +RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) +RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method. +RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS. +RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules. RULE_BOOL (World, IsGMPetitionWindowEnabled, false) RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items. RULE_BOOL (World, IPLimitDisconnectAll, false) RULE_INT (World, TellQueueSize, 20) RULE_CATEGORY_END() -RULE_CATEGORY( Zone ) -RULE_INT ( Zone, NPCPositonUpdateTicCount, 32 ) //ms between intervals of sending a position update to the entire zone. -RULE_INT ( Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection -RULE_INT ( Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone -RULE_BOOL ( Zone, EnableShadowrest, 1 ) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. -RULE_BOOL ( Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. -RULE_INT ( Zone, MQWarpExemptStatus, -1 ) // Required status level to exempt the MQWarpDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQZoneExemptStatus, -1 ) // Required status level to exempt the MQZoneDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQGateExemptStatus, -1 ) // Required status level to exempt the MQGateDetector. Set to -1 to disable this feature. -RULE_INT ( Zone, MQGhostExemptStatus, -1 ) // Required status level to exempt the MGhostDetector. Set to -1 to disable this feature. -RULE_BOOL ( Zone, EnableMQWarpDetector, true ) // Enable the MQWarp Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQZoneDetector, true ) // Enable the MQZone Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQGateDetector, true ) // Enable the MQGate Detector. Set to False to disable this feature. -RULE_BOOL ( Zone, EnableMQGhostDetector, true ) // Enable the MQGhost Detector. Set to False to disable this feature. -RULE_REAL ( Zone, MQWarpDetectionDistanceFactor, 9.0) //clients move at 4.4 about if in a straight line but with movement and to acct for lag we raise it a bit -RULE_BOOL ( Zone, MarkMQWarpLT, false ) -RULE_INT ( Zone, AutoShutdownDelay, 5000 ) //How long a dynamic zone stays loaded while empty -RULE_INT ( Zone, PEQZoneReuseTime, 900 ) //How long, in seconds, until you can reuse the #peqzone command. -RULE_INT ( Zone, PEQZoneDebuff1, 4454 ) //First debuff casted by #peqzone Default is Cursed Keeper's Blight. -RULE_INT ( Zone, PEQZoneDebuff2, 2209 ) //Second debuff casted by #peqzone Default is Tendrils of Apathy. -RULE_BOOL ( Zone, UsePEQZoneDebuffs, true ) //Will determine if #peqzone will debuff players or not when used. -RULE_REAL ( Zone, HotZoneBonus, 0.75 ) -RULE_INT ( Zone, ReservedInstances, 30 ) //Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running. -RULE_INT ( Zone, EbonCrystalItemID, 40902) -RULE_INT ( Zone, RadiantCrystalItemID, 40903) -RULE_BOOL ( Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mods table in consideration to your players EXP hits -RULE_INT ( Zone, WeatherTimer, 600) // Weather timer when no duration is available -RULE_BOOL ( Zone, EnableLoggedOffReplenishments, true) -RULE_INT ( Zone, MinOfflineTimeToReplenishments, 21600) // 21600 seconds is 6 Hours +RULE_CATEGORY(Zone) +RULE_INT(Zone, NPCPositonUpdateTicCount, 32) //ms between intervals of sending a position update to the entire zone. +RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection +RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone +RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. +RULE_BOOL(Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. +RULE_INT(Zone, MQWarpExemptStatus, -1) // Required status level to exempt the MQWarpDetector. Set to -1 to disable this feature. +RULE_INT(Zone, MQZoneExemptStatus, -1) // Required status level to exempt the MQZoneDetector. Set to -1 to disable this feature. +RULE_INT(Zone, MQGateExemptStatus, -1) // Required status level to exempt the MQGateDetector. Set to -1 to disable this feature. +RULE_INT(Zone, MQGhostExemptStatus, -1) // Required status level to exempt the MGhostDetector. Set to -1 to disable this feature. +RULE_BOOL(Zone, EnableMQWarpDetector, true) // Enable the MQWarp Detector. Set to False to disable this feature. +RULE_BOOL(Zone, EnableMQZoneDetector, true) // Enable the MQZone Detector. Set to False to disable this feature. +RULE_BOOL(Zone, EnableMQGateDetector, true) // Enable the MQGate Detector. Set to False to disable this feature. +RULE_BOOL(Zone, EnableMQGhostDetector, true) // Enable the MQGhost Detector. Set to False to disable this feature. +RULE_REAL(Zone, MQWarpDetectionDistanceFactor, 9.0) //clients move at 4.4 about if in a straight line but with movement and to acct for lag we raise it a bit +RULE_BOOL(Zone, MarkMQWarpLT, false) +RULE_INT(Zone, AutoShutdownDelay, 5000) //How long a dynamic zone stays loaded while empty +RULE_INT(Zone, PEQZoneReuseTime, 900) //How long, in seconds, until you can reuse the #peqzone command. +RULE_INT(Zone, PEQZoneDebuff1, 4454) //First debuff casted by #peqzone Default is Cursed Keeper's Blight. +RULE_INT(Zone, PEQZoneDebuff2, 2209) //Second debuff casted by #peqzone Default is Tendrils of Apathy. +RULE_BOOL(Zone, UsePEQZoneDebuffs, true) //Will determine if #peqzone will debuff players or not when used. +RULE_REAL(Zone, HotZoneBonus, 0.75) +RULE_INT(Zone, ReservedInstances, 30) //Will reserve this many instance ids for globals... probably not a good idea to change this while a server is running. +RULE_INT(Zone, EbonCrystalItemID, 40902) +RULE_INT(Zone, RadiantCrystalItemID, 40903) +RULE_BOOL(Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mods table in consideration to your players EXP hits +RULE_INT(Zone, WeatherTimer, 600) // Weather timer when no duration is available +RULE_BOOL(Zone, EnableLoggedOffReplenishments, true) +RULE_INT(Zone, MinOfflineTimeToReplenishments, 21600) // 21600 seconds is 6 Hours RULE_CATEGORY_END() -RULE_CATEGORY( Map ) +RULE_CATEGORY(Map) //enable these to help prevent mob hopping when they are pathing -RULE_BOOL ( Map, FixPathingZWhenLoading, true ) //increases zone boot times a bit to reduce hopping. -RULE_BOOL ( Map, FixPathingZAtWaypoints, false ) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time. -RULE_BOOL ( Map, FixPathingZWhenMoving, false ) //very CPU intensive, but helps hopping with widely spaced waypoints. -RULE_BOOL ( Map, FixPathingZOnSendTo, false ) //try to repair Z coords in the SendTo routine as well. -RULE_REAL ( Map, FixPathingZMaxDeltaMoving, 20 ) //at runtime while pathing: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaWaypoint, 20 ) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaSendTo, 20 ) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. -RULE_REAL ( Map, FixPathingZMaxDeltaLoading, 45 ) //while loading each waypoint: max change in Z to allow the BestZ code to apply. -RULE_INT ( Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position +RULE_BOOL(Map, FixPathingZWhenLoading, true) //increases zone boot times a bit to reduce hopping. +RULE_BOOL(Map, FixPathingZAtWaypoints, false) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time. +RULE_BOOL(Map, FixPathingZWhenMoving, false) //very CPU intensive, but helps hopping with widely spaced waypoints. +RULE_BOOL(Map, FixPathingZOnSendTo, false) //try to repair Z coords in the SendTo routine as well. +RULE_REAL(Map, FixPathingZMaxDeltaMoving, 20) //at runtime while pathing: max change in Z to allow the BestZ code to apply. +RULE_REAL(Map, FixPathingZMaxDeltaWaypoint, 20) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. +RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. +RULE_REAL(Map, FixPathingZMaxDeltaLoading, 45) //while loading each waypoint: max change in Z to allow the BestZ code to apply. +RULE_INT(Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position RULE_CATEGORY_END() -RULE_CATEGORY( Pathing ) +RULE_CATEGORY(Pathing) // Some of these rules may benefit by being made into columns in the zone table, // for instance, in dungeons, the min LOS distances could be substantially lowered. -RULE_BOOL ( Pathing, Aggro, true ) // Enable pathing for aggroed mobs. -RULE_BOOL ( Pathing, AggroReturnToGrid, true ) // Enable pathing for aggroed roaming mobs returning to their previous waypoint. -RULE_BOOL ( Pathing, Guard, true ) // Enable pathing for mobs moving to their guard point. -RULE_BOOL ( Pathing, Find, true ) // Enable pathing for FindPerson requests from the client. -RULE_BOOL ( Pathing, Fear, true ) // Enable pathing for fear -RULE_REAL ( Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. -RULE_INT ( Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). -RULE_INT ( Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved. -RULE_INT ( Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved. +RULE_BOOL(Pathing, Aggro, true) // Enable pathing for aggroed mobs. +RULE_BOOL(Pathing, AggroReturnToGrid, true) // Enable pathing for aggroed roaming mobs returning to their previous waypoint. +RULE_BOOL(Pathing, Guard, true) // Enable pathing for mobs moving to their guard point. +RULE_BOOL(Pathing, Find, true) // Enable pathing for FindPerson requests from the client. +RULE_BOOL(Pathing, Fear, true) // Enable pathing for fear +RULE_REAL(Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. +RULE_INT(Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). +RULE_INT(Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved. +RULE_INT(Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved. // When a path has a path node route and it's target changes position, if it has RouteUpdateFrequencyNodeCount or less nodes to go on it's // current path, it will recalculate it's path based on the RouteUpdateFrequencyShort timer, otherwise it will use the // RouteUpdateFrequencyLong timer. -RULE_INT ( Pathing, RouteUpdateFrequencyNodeCount, 5) -RULE_REAL ( Pathing, MinDistanceForLOSCheckShort, 40000) // (NoRoot). While following a path, only check for LOS to target within this distance. -RULE_REAL ( Pathing, MinDistanceForLOSCheckLong, 1000000) // (NoRoot). Min distance when initially attempting to acquire the target. -RULE_INT ( Pathing, MinNodesLeftForLOSCheck, 4) // Only check for LOS when we are down to this many path nodes left to run. +RULE_INT(Pathing, RouteUpdateFrequencyNodeCount, 5) +RULE_REAL(Pathing, MinDistanceForLOSCheckShort, 40000) // (NoRoot). While following a path, only check for LOS to target within this distance. +RULE_REAL(Pathing, MinDistanceForLOSCheckLong, 1000000) // (NoRoot). Min distance when initially attempting to acquire the target. +RULE_INT(Pathing, MinNodesLeftForLOSCheck, 4) // Only check for LOS when we are down to this many path nodes left to run. // This next rule was put in for situations where the mob and it's target may be on different sides of a 'hazard', e.g. a pit // If the mob has LOS to it's target, even though there is a hazard in it's way, it may break off from the node path and run at // the target, only to later detect the hazard and re-acquire a node path. Depending upon the placement of the path nodes, this // can lead to the mob looping. The rule is intended to allow the mob to at least get closer to it's target each time before // checking LOS and trying to head straight for it. -RULE_INT ( Pathing, MinNodesTraversedForLOSCheck, 3) // Only check for LOS after we have traversed this many path nodes. -RULE_INT ( Pathing, CullNodesFromStart, 1) // Checks LOS from Start point to second node for this many nodes and removes first node if there is LOS -RULE_INT ( Pathing, CullNodesFromEnd, 1) // Checks LOS from End point to second to last node for this many nodes and removes last node if there is LOS -RULE_REAL ( Pathing, CandidateNodeRangeXY, 400) // When searching for path start/end nodes, only nodes within this range will be considered. -RULE_REAL ( Pathing, CandidateNodeRangeZ, 10) // When searching for path start/end nodes, only nodes within this range will be considered. +RULE_INT(Pathing, MinNodesTraversedForLOSCheck, 3) // Only check for LOS after we have traversed this many path nodes. +RULE_INT(Pathing, CullNodesFromStart, 1) // Checks LOS from Start point to second node for this many nodes and removes first node if there is LOS +RULE_INT(Pathing, CullNodesFromEnd, 1) // Checks LOS from End point to second to last node for this many nodes and removes last node if there is LOS +RULE_REAL(Pathing, CandidateNodeRangeXY, 400) // When searching for path start/end nodes, only nodes within this range will be considered. +RULE_REAL(Pathing, CandidateNodeRangeZ, 10) // When searching for path start/end nodes, only nodes within this range will be considered. RULE_CATEGORY_END() -RULE_CATEGORY( Watermap ) +RULE_CATEGORY(Watermap) // enable these to use the water detection code. Requires Water Maps generated by awater utility -RULE_BOOL ( Watermap, CheckWaypointsInWaterWhenLoading, false ) // Does not apply BestZ as waypoints are loaded if they are in water -RULE_BOOL ( Watermap, CheckForWaterAtWaypoints, false) // Check if a mob has moved into/out of water when at waypoints and sets flymode -RULE_BOOL ( Watermap, CheckForWaterWhenMoving, false) // Checks if a mob has moved into/out of water each time it's loc is recalculated -RULE_BOOL ( Watermap, CheckForWaterOnSendTo, false) // Checks if a mob has moved into/out of water on SendTo -RULE_BOOL ( Watermap, CheckForWaterWhenFishing, false) // Only lets a player fish near water (if a water map exists for the zone) -RULE_REAL ( Watermap, FishingRodLength, 30) // How far in front of player water must be for fishing to work -RULE_REAL ( Watermap, FishingLineLength, 100) // If water is more than this far below the player, it is considered too far to fish -RULE_REAL ( Watermap, FishingLineStepSize, 1) // Basic step size for fishing calc, too small and it will eat cpu, too large and it will miss potential water +RULE_BOOL(Watermap, CheckWaypointsInWaterWhenLoading, false) // Does not apply BestZ as waypoints are loaded if they are in water +RULE_BOOL(Watermap, CheckForWaterAtWaypoints, false) // Check if a mob has moved into/out of water when at waypoints and sets flymode +RULE_BOOL(Watermap, CheckForWaterWhenMoving, false) // Checks if a mob has moved into/out of water each time it's loc is recalculated +RULE_BOOL(Watermap, CheckForWaterOnSendTo, false) // Checks if a mob has moved into/out of water on SendTo +RULE_BOOL(Watermap, CheckForWaterWhenFishing, false) // Only lets a player fish near water (if a water map exists for the zone) +RULE_REAL(Watermap, FishingRodLength, 30) // How far in front of player water must be for fishing to work +RULE_REAL(Watermap, FishingLineLength, 100) // If water is more than this far below the player, it is considered too far to fish +RULE_REAL(Watermap, FishingLineStepSize, 1) // Basic step size for fishing calc, too small and it will eat cpu, too large and it will miss potential water RULE_CATEGORY_END() -RULE_CATEGORY( Spells ) -RULE_INT ( Spells, AutoResistDiff, 15) -RULE_REAL ( Spells, ResistChance, 2.0) //chance to resist given no resists and same level -RULE_REAL ( Spells, ResistMod, 0.40) //multiplier, chance to resist = this * ResistAmount -RULE_REAL ( Spells, PartialHitChance, 0.7) //The chance when a spell is resisted that it will partial hit. -RULE_REAL ( Spells, PartialHitChanceFear, 0.25) //The chance when a fear spell is resisted that it will partial hit. -RULE_INT ( Spells, BaseCritChance, 0) //base % chance that everyone has to crit a spell -RULE_INT ( Spells, BaseCritRatio, 100) //base % bonus to damage on a successful spell crit. 100 = 2x damage -RULE_INT ( Spells, WizCritLevel, 12) //level wizards first get spell crits -RULE_INT ( Spells, WizCritChance, 7) //wiz's crit chance, on top of BaseCritChance -RULE_INT ( Spells, WizCritRatio, 0) //wiz's crit bonus, on top of BaseCritRatio (should be 0 for Live-like) -RULE_INT ( Spells, ResistPerLevelDiff, 85) //8.5 resist per level difference. -RULE_INT ( Spells, TranslocateTimeLimit, 0) // If not zero, time in seconds to accept a Translocate. -RULE_INT ( Spells, SacrificeMinLevel, 46) //first level Sacrifice will work on -RULE_INT ( Spells, SacrificeMaxLevel, 69) //last level Sacrifice will work on -RULE_INT ( Spells, SacrificeItemID, 9963) //Item ID of the item Sacrifice will return (defaults to an EE) -RULE_BOOL ( Spells, EnableSpellGlobals, false) // If Enabled, spells check the spell_globals table and compare character data from the quest globals before allowing that spell to scribe with scribespells -RULE_INT ( Spells, MaxBuffSlotsNPC, 25) -RULE_INT ( Spells, MaxSongSlotsNPC, 10) -RULE_INT ( Spells, MaxDiscSlotsNPC, 1) -RULE_INT ( Spells, MaxTotalSlotsNPC, 36) -RULE_INT ( Spells, MaxTotalSlotsPET, 25) // do not set this higher than 25 until the player profile is removed from the blob +RULE_CATEGORY(Spells) +RULE_INT(Spells, AutoResistDiff, 15) +RULE_REAL(Spells, ResistChance, 2.0) //chance to resist given no resists and same level +RULE_REAL(Spells, ResistMod, 0.40) //multiplier, chance to resist = this * ResistAmount +RULE_REAL(Spells, PartialHitChance, 0.7) //The chance when a spell is resisted that it will partial hit. +RULE_REAL(Spells, PartialHitChanceFear, 0.25) //The chance when a fear spell is resisted that it will partial hit. +RULE_INT(Spells, BaseCritChance, 0) //base % chance that everyone has to crit a spell +RULE_INT(Spells, BaseCritRatio, 100) //base % bonus to damage on a successful spell crit. 100 = 2x damage +RULE_INT(Spells, WizCritLevel, 12) //level wizards first get spell crits +RULE_INT(Spells, WizCritChance, 7) //wiz's crit chance, on top of BaseCritChance +RULE_INT(Spells, WizCritRatio, 0) //wiz's crit bonus, on top of BaseCritRatio (should be 0 for Live-like) +RULE_INT(Spells, ResistPerLevelDiff, 85) //8.5 resist per level difference. +RULE_INT(Spells, TranslocateTimeLimit, 0) // If not zero, time in seconds to accept a Translocate. +RULE_INT(Spells, SacrificeMinLevel, 46) //first level Sacrifice will work on +RULE_INT(Spells, SacrificeMaxLevel, 69) //last level Sacrifice will work on +RULE_INT(Spells, SacrificeItemID, 9963) //Item ID of the item Sacrifice will return (defaults to an EE) +RULE_BOOL(Spells, EnableSpellGlobals, false) // If Enabled, spells check the spell_globals table and compare character data from the quest globals before allowing that spell to scribe with scribespells +RULE_INT(Spells, MaxBuffSlotsNPC, 25) +RULE_INT(Spells, MaxSongSlotsNPC, 10) +RULE_INT(Spells, MaxDiscSlotsNPC, 1) +RULE_INT(Spells, MaxTotalSlotsNPC, 36) +RULE_INT(Spells, MaxTotalSlotsPET, 25) // do not set this higher than 25 until the player profile is removed from the blob RULE_BOOL (Spells, EnableBlockedBuffs, true) -RULE_INT ( Spells, ReflectType, 1) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells -RULE_INT ( Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim -RULE_BOOL( Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized -RULE_INT ( Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0. -RULE_BOOL ( Spells, NPCIgnoreBaseImmunity, true) // Whether or not NPCs get to ignore the BaseImmunityLevel for their spells. -RULE_REAL ( Spells, AvgSpellProcsPerMinute, 6.0) //Adjust rate for sympathetic spell procs -RULE_INT ( Spells, ResistFalloff, 67) //Max that level that will adjust our resist chance based on level modifiers -RULE_INT ( Spells, CharismaEffectiveness, 10) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. -RULE_INT ( Spells, CharismaEffectivenessCap, 255) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. -RULE_BOOL ( Spells, CharismaCharmDuration, false) // Allow CHA resist mod to extend charm duration. -RULE_INT ( Spells, CharmBreakCheckChance, 25) //Determines chance for a charm break check to occur each buff tick. -RULE_INT ( Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time can be reduced by spell haste -RULE_INT ( Spells, RootBreakFromSpells, 55) //Chance for root to break when cast on. -RULE_INT ( Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. -RULE_INT ( Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. -RULE_INT ( Spells, AdditiveBonusWornType, 0) //Calc worn bonuses to add together (instead of taking highest) if set to THIS worn type. (2=Will covert live items automatically) -RULE_BOOL ( Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? -RULE_BOOL ( Spells, BuffLevelRestrictions, true) //Buffs will not land on low level toons like live -RULE_INT ( Spells, RootBreakCheckChance, 70) //Determines chance for a root break check to occur each buff tick. -RULE_INT ( Spells, FearBreakCheckChance, 70) //Determines chance for a fear break check to occur each buff tick. -RULE_INT ( Spells, SuccorFailChance, 2) //Determines chance for a succor spell not to teleport an invidual player -RULE_INT ( Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'. -RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'. -RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. -RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. -RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. -RULE_BOOL ( Spells, PreNerfBardAEDoT, false) //Allow bard AOE dots to damage targets when moving. -RULE_INT ( Spells, AI_SpellCastFinishedFailRecast, 800) // AI spell recast time(MS) when an spell is cast but fails (ie stunned). -RULE_INT ( Spells, AI_EngagedNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while engaged. (min time in random) -RULE_INT ( Spells, AI_EngagedNoSpellMaxRecast, 1000) // AI spell recast time(MS) check when no spell is cast engaged.(max time in random) -RULE_INT ( Spells, AI_EngagedBeneficialSelfChance, 100) // Chance during first AI Cast check to do a beneficial spell on self. -RULE_INT ( Spells, AI_EngagedBeneficialOtherChance, 25) // Chance during second AI Cast check to do a beneficial spell on others. -RULE_INT ( Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast check to do a determental spell on others. -RULE_INT ( Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random) -RULE_INT ( Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) -RULE_INT ( Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell. -RULE_INT ( Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random) -RULE_INT ( Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) -RULE_INT ( Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others. -RULE_BOOL ( Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false) -RULE_BOOL ( Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014 -RULE_BOOL ( Spells, SwarmPetTargetLock, false) // Use old method of swarm pets target locking till target dies then despawning. -RULE_BOOL ( Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell derived focus effects. -RULE_BOOL ( Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects. -RULE_BOOL ( Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. -RULE_BOOL ( Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true +RULE_INT(Spells, ReflectType, 1) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells +RULE_INT(Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim +RULE_BOOL(Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized +RULE_INT(Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0. +RULE_BOOL(Spells, NPCIgnoreBaseImmunity, true) // Whether or not NPCs get to ignore the BaseImmunityLevel for their spells. +RULE_REAL(Spells, AvgSpellProcsPerMinute, 6.0) //Adjust rate for sympathetic spell procs +RULE_INT(Spells, ResistFalloff, 67) //Max that level that will adjust our resist chance based on level modifiers +RULE_INT(Spells, CharismaEffectiveness, 10) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. +RULE_INT(Spells, CharismaEffectivenessCap, 255) // Deterimes how much resist modification charisma applies to charm/pacify checks. Default 10 CHA = -1 resist mod. +RULE_BOOL(Spells, CharismaCharmDuration, false) // Allow CHA resist mod to extend charm duration. +RULE_INT(Spells, CharmBreakCheckChance, 25) //Determines chance for a charm break check to occur each buff tick. +RULE_INT(Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time can be reduced by spell haste +RULE_INT(Spells, RootBreakFromSpells, 55) //Chance for root to break when cast on. +RULE_INT(Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. +RULE_INT(Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. +RULE_INT(Spells, AdditiveBonusWornType, 0) //Calc worn bonuses to add together (instead of taking highest) if set to THIS worn type. (2=Will covert live items automatically) +RULE_BOOL(Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? +RULE_BOOL(Spells, BuffLevelRestrictions, true) //Buffs will not land on low level toons like live +RULE_INT(Spells, RootBreakCheckChance, 70) //Determines chance for a root break check to occur each buff tick. +RULE_INT(Spells, FearBreakCheckChance, 70) //Determines chance for a fear break check to occur each buff tick. +RULE_INT(Spells, SuccorFailChance, 2) //Determines chance for a succor spell not to teleport an invidual player +RULE_INT(Spells, FRProjectileItem_Titanium, 1113) // Item id for Titanium clients for Fire 'spell projectile'. +RULE_INT(Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for Fire 'spell projectile'. +RULE_INT(Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. +RULE_BOOL(Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. +RULE_BOOL(Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. +RULE_BOOL(Spells, PreNerfBardAEDoT, false) //Allow bard AOE dots to damage targets when moving. +RULE_INT(Spells, AI_SpellCastFinishedFailRecast, 800) // AI spell recast time(MS) when an spell is cast but fails (ie stunned). +RULE_INT(Spells, AI_EngagedNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while engaged. (min time in random) +RULE_INT(Spells, AI_EngagedNoSpellMaxRecast, 1000) // AI spell recast time(MS) check when no spell is cast engaged.(max time in random) +RULE_INT(Spells, AI_EngagedBeneficialSelfChance, 100) // Chance during first AI Cast check to do a beneficial spell on self. +RULE_INT(Spells, AI_EngagedBeneficialOtherChance, 25) // Chance during second AI Cast check to do a beneficial spell on others. +RULE_INT(Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast check to do a determental spell on others. +RULE_INT(Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random) +RULE_INT(Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) +RULE_INT(Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell. +RULE_INT(Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random) +RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) +RULE_INT(Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others. +RULE_BOOL(Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false) +RULE_BOOL(Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014 +RULE_BOOL(Spells, SwarmPetTargetLock, false) // Use old method of swarm pets target locking till target dies then despawning. +RULE_BOOL(Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell derived focus effects. +RULE_BOOL(Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects. +RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. +RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true RULE_CATEGORY_END() -RULE_CATEGORY( Combat ) -RULE_INT ( Combat, MeleeBaseCritChance, 0 ) //The base crit chance for non warriors, NOTE: This will apply to NPCs as well -RULE_INT ( Combat, WarBerBaseCritChance, 3 ) //The base crit chance for warriors and berserkers, only applies to clients -RULE_INT ( Combat, BerserkBaseCritChance, 6 ) //The bonus base crit chance you get when you're berserk -RULE_INT ( Combat, NPCBashKickLevel, 6 ) //The level that npcs can KICK/BASH -RULE_INT ( Combat, NPCBashKickStunChance, 15 ) //Percent chance that a bash/kick will stun -RULE_INT ( Combat, RogueCritThrowingChance, 25) //Rogue throwing crit bonus -RULE_INT ( Combat, RogueDeadlyStrikeChance, 80) //Rogue chance throwing from behind crit becomes a deadly strike -RULE_INT ( Combat, RogueDeadlyStrikeMod, 2) //Deadly strike modifier to crit damage -RULE_INT ( Combat, ClientBaseCritChance, 0 ) //The base crit chance for all clients, this will stack with warrior's/zerker's crit chance. -RULE_BOOL ( Combat, UseIntervalAC, true) -RULE_INT ( Combat, PetAttackMagicLevel, 30) -RULE_BOOL ( Combat, EnableFearPathing, true) -RULE_REAL ( Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker. -RULE_INT ( Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee. -RULE_BOOL ( Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it. -RULE_BOOL ( Combat, AdjustProcPerMinute, true) -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 -RULE_REAL ( Combat, HitFalloffModerate, 7.0) //hit will fall off up to 7% over the three levels after the initial level range -RULE_REAL ( Combat, HitFalloffMajor, 50.0) //hit will fall off sharply if we're outside the minor and moderate range -RULE_REAL ( Combat, HitBonusPerLevel, 1.2) //You gain this % of hit for every level you are above your target -RULE_REAL ( Combat, WeaponSkillFalloff, 0.33) //For every weapon skill point that's not maxed you lose this % of hit -RULE_REAL ( Combat, ArcheryHitPenalty, 0.25) //Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it -RULE_REAL ( Combat, AgiHitFactor, 0.01) -RULE_REAL ( Combat, MinChancetoHit, 5.0) //Minimum % chance to hit with regular melee/ranged -RULE_REAL ( Combat, MaxChancetoHit, 95.0) //Maximum % chance to hit with regular melee/ranged -RULE_INT ( Combat, MinRangedAttackDist, 25) //Minimum Distance to use Ranged Attacks -RULE_BOOL ( Combat, ArcheryBonusRequiresStationary, true) //does the 2x archery bonus chance require a stationary npc -RULE_REAL ( Combat, ArcheryBaseDamageBonus, 1) // % Modifier to Base Archery Damage (.5 = 50% base damage, 1 = 100%, 2 = 200%) -RULE_REAL ( Combat, ArcheryNPCMultiplier, 1.0) // this is multiplied by the regular dmg to get the archery dmg -RULE_BOOL ( Combat, AssistNoTargetSelf, true) //when assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like) -RULE_INT ( Combat, MaxRampageTargets, 3) //max number of people hit with rampage -RULE_INT ( Combat, DefaultRampageTargets, 1) // default number of people to hit with rampage -RULE_BOOL ( Combat, RampageHitsTarget, false) // rampage will hit the target if it still has targets left -RULE_INT ( Combat, MaxFlurryHits, 2) //max number of extra hits from flurry -RULE_INT ( Combat, MonkDamageTableBonus, 5) //% bonus monks get to their damage table calcs -RULE_INT ( Combat, FlyingKickBonus, 25) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, DragonPunchBonus, 20) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, EagleStrikeBonus, 15) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, TigerClawBonus, 10) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, RoundKickBonus, 5) //% Modifier that this skill gets to str and skill bonuses -RULE_INT ( Combat, FrenzyBonus, 0) //% Modifier to damage -RULE_BOOL ( Combat, ProcTargetOnly, true) //true = procs will only affect our target, false = procs will affect all of our targets -RULE_REAL ( Combat, NPCACFactor, 2.25) -RULE_INT ( Combat, ClothACSoftcap, 75) -RULE_INT ( Combat, LeatherACSoftcap, 100) -RULE_INT ( Combat, MonkACSoftcap, 120) -RULE_INT ( Combat, ChainACSoftcap, 200) -RULE_INT ( Combat, PlateACSoftcap, 300) -RULE_REAL ( Combat, AAMitigationACFactor, 3.0) -RULE_REAL ( Combat, WarriorACSoftcapReturn, 0.45) -RULE_REAL ( Combat, KnightACSoftcapReturn, 0.33) -RULE_REAL ( Combat, LowPlateChainACSoftcapReturn, 0.23) -RULE_REAL ( Combat, LowChainLeatherACSoftcapReturn, 0.17) -RULE_REAL ( Combat, CasterACSoftcapReturn, 0.06) -RULE_REAL ( Combat, MiscACSoftcapReturn, 0.3) -RULE_BOOL ( Combat, OldACSoftcapRules, false) // use old softcaps -RULE_BOOL ( Combat, UseOldDamageIntervalRules, false) // use old damage formulas for everything -RULE_REAL ( Combat, WarACSoftcapReturn, 0.3448) // new AC returns -RULE_REAL ( Combat, ClrRngMnkBrdACSoftcapReturn, 0.3030) -RULE_REAL ( Combat, PalShdACSoftcapReturn, 0.3226) -RULE_REAL ( Combat, DruNecWizEncMagACSoftcapReturn, 0.2000) -RULE_REAL ( Combat, RogShmBstBerACSoftcapReturn, 0.2500) -RULE_REAL ( Combat, SoftcapFactor, 1.88) -RULE_REAL ( Combat, ACthac0Factor, 0.55) -RULE_REAL ( Combat, ACthac20Factor, 0.55) -RULE_INT ( Combat, HitCapPre20, 40) // live has it capped at 40 for whatever dumb reason... this is mainly for custom servers -RULE_INT ( Combat, HitCapPre10, 20) // live has it capped at 20, see above :p -RULE_INT ( Combat, MinHastedDelay, 400) // how fast we can get with haste. -RULE_REAL ( Combat, AvgDefProcsPerMinute, 2.0) -RULE_REAL ( Combat, DefProcPerMinAgiContrib, 0.075) //How much agility contributes to defensive proc rate -RULE_INT ( Combat, SpecialAttackACBonus, 15) //Percent amount of damage per AC gained for certain special attacks (damage = AC*SpecialAttackACBonus/100). -RULE_INT ( Combat, NPCFlurryChance, 20) // Chance for NPC to flurry. +RULE_CATEGORY(Combat) +RULE_INT(Combat, MeleeBaseCritChance, 0) //The base crit chance for non warriors, NOTE: This will apply to NPCs as well +RULE_INT(Combat, WarBerBaseCritChance, 3) //The base crit chance for warriors and berserkers, only applies to clients +RULE_INT(Combat, BerserkBaseCritChance, 6) //The bonus base crit chance you get when you're berserk +RULE_INT(Combat, NPCBashKickLevel, 6) //The level that npcs can KICK/BASH +RULE_INT(Combat, NPCBashKickStunChance, 15) //Percent chance that a bash/kick will stun +RULE_INT(Combat, RogueCritThrowingChance, 25) //Rogue throwing crit bonus +RULE_INT(Combat, RogueDeadlyStrikeChance, 80) //Rogue chance throwing from behind crit becomes a deadly strike +RULE_INT(Combat, RogueDeadlyStrikeMod, 2) //Deadly strike modifier to crit damage +RULE_INT(Combat, ClientBaseCritChance, 0) //The base crit chance for all clients, this will stack with warrior's/zerker's crit chance. +RULE_BOOL(Combat, UseIntervalAC, true) +RULE_INT(Combat, PetAttackMagicLevel, 30) +RULE_BOOL(Combat, EnableFearPathing, true) +RULE_REAL(Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker. +RULE_INT(Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee. +RULE_BOOL(Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it. +RULE_BOOL(Combat, AdjustProcPerMinute, true) +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 +RULE_REAL(Combat, HitFalloffModerate, 7.0) //hit will fall off up to 7% over the three levels after the initial level range +RULE_REAL(Combat, HitFalloffMajor, 50.0) //hit will fall off sharply if we're outside the minor and moderate range +RULE_REAL(Combat, HitBonusPerLevel, 1.2) //You gain this % of hit for every level you are above your target +RULE_REAL(Combat, WeaponSkillFalloff, 0.33) //For every weapon skill point that's not maxed you lose this % of hit +RULE_REAL(Combat, ArcheryHitPenalty, 0.25) //Archery has a hit penalty to try to help balance it with the plethora of long term +hit modifiers for it +RULE_REAL(Combat, AgiHitFactor, 0.01) +RULE_REAL(Combat, MinChancetoHit, 5.0) //Minimum % chance to hit with regular melee/ranged +RULE_REAL(Combat, MaxChancetoHit, 95.0) //Maximum % chance to hit with regular melee/ranged +RULE_INT(Combat, MinRangedAttackDist, 25) //Minimum Distance to use Ranged Attacks +RULE_BOOL(Combat, ArcheryBonusRequiresStationary, true) //does the 2x archery bonus chance require a stationary npc +RULE_REAL(Combat, ArcheryBaseDamageBonus, 1) // % Modifier to Base Archery Damage (.5 = 50% base damage, 1 = 100%, 2 = 200%) +RULE_REAL(Combat, ArcheryNPCMultiplier, 1.0) // this is multiplied by the regular dmg to get the archery dmg +RULE_BOOL(Combat, AssistNoTargetSelf, true) //when assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like) +RULE_INT(Combat, MaxRampageTargets, 3) //max number of people hit with rampage +RULE_INT(Combat, DefaultRampageTargets, 1) // default number of people to hit with rampage +RULE_BOOL(Combat, RampageHitsTarget, false) // rampage will hit the target if it still has targets left +RULE_INT(Combat, MaxFlurryHits, 2) //max number of extra hits from flurry +RULE_INT(Combat, MonkDamageTableBonus, 5) //% bonus monks get to their damage table calcs +RULE_INT(Combat, FlyingKickBonus, 25) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, DragonPunchBonus, 20) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, EagleStrikeBonus, 15) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, TigerClawBonus, 10) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, RoundKickBonus, 5) //% Modifier that this skill gets to str and skill bonuses +RULE_INT(Combat, FrenzyBonus, 0) //% Modifier to damage +RULE_INT(Combat, BackstabBonus, 0) //% Modifier to damage +RULE_BOOL(Combat, ProcTargetOnly, true) //true = procs will only affect our target, false = procs will affect all of our targets +RULE_REAL(Combat, NPCACFactor, 2.25) +RULE_INT(Combat, ClothACSoftcap, 75) +RULE_INT(Combat, LeatherACSoftcap, 100) +RULE_INT(Combat, MonkACSoftcap, 120) +RULE_INT(Combat, ChainACSoftcap, 200) +RULE_INT(Combat, PlateACSoftcap, 300) +RULE_REAL(Combat, AAMitigationACFactor, 3.0) +RULE_REAL(Combat, WarriorACSoftcapReturn, 0.45) +RULE_REAL(Combat, KnightACSoftcapReturn, 0.33) +RULE_REAL(Combat, LowPlateChainACSoftcapReturn, 0.23) +RULE_REAL(Combat, LowChainLeatherACSoftcapReturn, 0.17) +RULE_REAL(Combat, CasterACSoftcapReturn, 0.06) +RULE_REAL(Combat, MiscACSoftcapReturn, 0.3) +RULE_BOOL(Combat, OldACSoftcapRules, false) // use old softcaps +RULE_BOOL(Combat, UseOldDamageIntervalRules, false) // use old damage formulas for everything +RULE_REAL(Combat, WarACSoftcapReturn, 0.3448) // new AC returns +RULE_REAL(Combat, ClrRngMnkBrdACSoftcapReturn, 0.3030) +RULE_REAL(Combat, PalShdACSoftcapReturn, 0.3226) +RULE_REAL(Combat, DruNecWizEncMagACSoftcapReturn, 0.2000) +RULE_REAL(Combat, RogShmBstBerACSoftcapReturn, 0.2500) +RULE_REAL(Combat, SoftcapFactor, 1.88) +RULE_REAL(Combat, ACthac0Factor, 0.55) +RULE_REAL(Combat, ACthac20Factor, 0.55) +RULE_INT(Combat, HitCapPre20, 40) // live has it capped at 40 for whatever dumb reason... this is mainly for custom servers +RULE_INT(Combat, HitCapPre10, 20) // live has it capped at 20, see above :p +RULE_INT(Combat, MinHastedDelay, 400) // how fast we can get with haste. +RULE_REAL(Combat, AvgDefProcsPerMinute, 2.0) +RULE_REAL(Combat, DefProcPerMinAgiContrib, 0.075) //How much agility contributes to defensive proc rate +RULE_INT(Combat, SpecialAttackACBonus, 15) //Percent amount of damage per AC gained for certain special attacks (damage = AC*SpecialAttackACBonus/100). +RULE_INT(Combat, NPCFlurryChance, 20) // Chance for NPC to flurry. RULE_BOOL (Combat,TauntOverLevel, 1) //Allows you to taunt NPC's over warriors level. RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's not maxed you lose this % chance to taunt. RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain. -RULE_INT ( Combat, MonkACBonusWeight, 15) -RULE_INT ( Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target -RULE_INT ( Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers -RULE_BOOL ( Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll -RULE_INT ( Combat, ArcheryBonusChance, 50) -RULE_INT ( Combat, BerserkerFrenzyStart, 35) -RULE_INT ( Combat, BerserkerFrenzyEnd, 45) -RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round -RULE_BOOL ( Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly. -RULE_BOOL ( Combat, MeleePush, true) // enable melee push -RULE_INT ( Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad +RULE_INT(Combat, MonkACBonusWeight, 15) +RULE_INT(Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target +RULE_INT(Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers +RULE_BOOL(Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll +RULE_INT(Combat, ArcheryBonusChance, 50) +RULE_INT(Combat, BerserkerFrenzyStart, 35) +RULE_INT(Combat, BerserkerFrenzyEnd, 45) +RULE_BOOL(Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round +RULE_BOOL(Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly. +RULE_BOOL(Combat, MeleePush, true) // enable melee push +RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad RULE_CATEGORY_END() -RULE_CATEGORY( NPC ) -RULE_INT ( NPC, MinorNPCCorpseDecayTimeMS, 450000 ) //level<55 -RULE_INT ( NPC, MajorNPCCorpseDecayTimeMS, 1500000 ) //level>=55 -RULE_INT ( NPC, CorpseUnlockTimer, 150000 ) -RULE_INT ( NPC, EmptyNPCCorpseDecayTimeMS, 0 ) +RULE_CATEGORY(NPC) +RULE_INT(NPC, MinorNPCCorpseDecayTimeMS, 450000) //level<55 +RULE_INT(NPC, MajorNPCCorpseDecayTimeMS, 1500000) //level>=55 +RULE_INT(NPC, CorpseUnlockTimer, 150000) +RULE_INT(NPC, EmptyNPCCorpseDecayTimeMS, 0) RULE_BOOL (NPC, UseItemBonusesForNonPets, true) -RULE_INT ( NPC, SayPauseTimeInSec, 5) -RULE_INT ( NPC, OOCRegen, 0) -RULE_BOOL ( NPC, BuffFriends, false ) -RULE_BOOL ( NPC, EnableNPCQuestJournal, false) -RULE_INT ( NPC, LastFightingDelayMovingMin, 10000) -RULE_INT ( NPC, LastFightingDelayMovingMax, 20000) -RULE_BOOL ( NPC, SmartLastFightingDelayMoving, true) -RULE_BOOL ( NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPCs that don't have an EVENT_TRADE sub in their script -RULE_INT ( NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage -RULE_BOOL ( NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage -RULE_BOOL ( NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid) +RULE_INT(NPC, SayPauseTimeInSec, 5) +RULE_INT(NPC, OOCRegen, 0) +RULE_BOOL(NPC, BuffFriends, false) +RULE_BOOL(NPC, EnableNPCQuestJournal, false) +RULE_INT(NPC, LastFightingDelayMovingMin, 10000) +RULE_INT(NPC, LastFightingDelayMovingMax, 20000) +RULE_BOOL(NPC, SmartLastFightingDelayMoving, true) +RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPCs that don't have an EVENT_TRADE sub in their script +RULE_INT(NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage +RULE_BOOL(NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage +RULE_BOOL(NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid) RULE_CATEGORY_END() -RULE_CATEGORY ( Aggro ) -RULE_BOOL ( Aggro, SmartAggroList, true ) -RULE_INT ( Aggro, SittingAggroMod, 35 ) //35% -RULE_INT ( Aggro, MeleeRangeAggroMod, 10 ) //10% -RULE_INT ( Aggro, CurrentTargetAggroMod, 0 ) //0% -- will prefer our current target to any other; makes it harder for our npcs to switch targets. -RULE_INT ( Aggro, CriticallyWoundedAggroMod, 100 ) //100% -RULE_INT ( Aggro, SpellAggroMod, 100 ) -RULE_INT ( Aggro, SongAggroMod, 33 ) -RULE_INT ( Aggro, PetSpellAggroMod, 10 ) -RULE_REAL ( Aggro, TunnelVisionAggroMod, 0.75 ) //people not currently the top hate generate this much hate on a Tunnel Vision mob -RULE_INT ( Aggro, MaxStunProcAggro, 400 ) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add. -RULE_INT ( Aggro, IntAggroThreshold, 75 ) // Int <= this will aggro regardless of level difference. +RULE_CATEGORY(Aggro) +RULE_BOOL(Aggro, SmartAggroList, true) +RULE_INT(Aggro, SittingAggroMod, 35) //35% +RULE_INT(Aggro, MeleeRangeAggroMod, 10) //10% +RULE_INT(Aggro, CurrentTargetAggroMod, 0) //0% -- will prefer our current target to any other; makes it harder for our npcs to switch targets. +RULE_INT(Aggro, CriticallyWoundedAggroMod, 100) //100% +RULE_INT(Aggro, SpellAggroMod, 100) +RULE_INT(Aggro, SongAggroMod, 33) +RULE_INT(Aggro, PetSpellAggroMod, 10) +RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob +RULE_INT(Aggro, MaxStunProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add. +RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference. RULE_CATEGORY_END() -RULE_CATEGORY ( TaskSystem) -RULE_BOOL ( TaskSystem, EnableTaskSystem, true) // Globally enable or disable the Task system -RULE_INT ( TaskSystem, PeriodicCheckTimer, 5) // Seconds between checks for failed tasks. Also used by the 'Touch' activity -RULE_BOOL ( TaskSystem, RecordCompletedTasks, true) -RULE_BOOL ( TaskSystem, RecordCompletedOptionalActivities, false) -RULE_BOOL ( TaskSystem, KeepOneRecordPerCompletedTask, true) -RULE_BOOL ( TaskSystem, EnableTaskProximity, true) +RULE_CATEGORY(TaskSystem) +RULE_BOOL(TaskSystem, EnableTaskSystem, true) // Globally enable or disable the Task system +RULE_INT(TaskSystem, PeriodicCheckTimer, 5) // Seconds between checks for failed tasks. Also used by the 'Touch' activity +RULE_BOOL(TaskSystem, RecordCompletedTasks, true) +RULE_BOOL(TaskSystem, RecordCompletedOptionalActivities, false) +RULE_BOOL(TaskSystem, KeepOneRecordPerCompletedTask, true) +RULE_BOOL(TaskSystem, EnableTaskProximity, true) RULE_CATEGORY_END() #ifdef BOTS -RULE_CATEGORY ( Bots ) -RULE_REAL ( Bots, BotManaRegen, 2.0 ) // Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players. -RULE_BOOL ( Bots, BotFinishBuffing, false ) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. -RULE_INT ( Bots, CreateBotCount, 150 ) // Number of bots that each account can create -RULE_INT ( Bots, SpawnBotCount, 71 ) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid -RULE_BOOL ( Bots, BotQuest, false ) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl -RULE_BOOL ( Bots, BotGroupBuffing, false ) // Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB. -RULE_BOOL ( Bots, BotSpellQuest, false ) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. -RULE_INT ( Bots, BotAAExpansion, 8 ) // Bots get AAs through this expansion -RULE_BOOL ( Bots, BotGroupXP, false ) // Determines whether client gets xp for bots outside their group. -RULE_BOOL ( Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs. -RULE_BOOL ( Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) +RULE_CATEGORY(Bots) +RULE_REAL(Bots, BotManaRegen, 2.0) // Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players. +RULE_BOOL(Bots, BotFinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. +RULE_INT(Bots, CreateBotCount, 150) // Number of bots that each account can create +RULE_INT(Bots, SpawnBotCount, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid +RULE_BOOL(Bots, BotQuest, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl +RULE_BOOL(Bots, BotGroupBuffing, false) // Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB. +RULE_BOOL(Bots, BotSpellQuest, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. +RULE_INT(Bots, BotAAExpansion, 8) // Bots get AAs through this expansion +RULE_BOOL(Bots, BotGroupXP, false) // Determines whether client gets xp for bots outside their group. +RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs. +RULE_BOOL(Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) RULE_CATEGORY_END() #endif -RULE_CATEGORY ( Chat ) -RULE_BOOL ( Chat, ServerWideOOC, true) -RULE_BOOL ( Chat, ServerWideAuction, true) -RULE_BOOL ( Chat, EnableVoiceMacros, true) -RULE_BOOL ( Chat, EnableMailKeyIPVerification, true) -RULE_BOOL ( Chat, EnableAntiSpam, true) -RULE_BOOL ( Chat, SuppressCommandErrors, false) // Do not suppress by default -RULE_INT ( Chat, MinStatusToBypassAntiSpam, 100) -RULE_INT ( Chat, MinimumMessagesPerInterval, 4) -RULE_INT ( Chat, MaximumMessagesPerInterval, 12) -RULE_INT ( Chat, MaxMessagesBeforeKick, 20) -RULE_INT ( Chat, IntervalDurationMS, 60000) -RULE_INT ( Chat, KarmaUpdateIntervalMS, 1200000) -RULE_INT ( Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit -RULE_INT ( Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low. +RULE_CATEGORY(Chat) +RULE_BOOL(Chat, ServerWideOOC, true) +RULE_BOOL(Chat, ServerWideAuction, true) +RULE_BOOL(Chat, EnableVoiceMacros, true) +RULE_BOOL(Chat, EnableMailKeyIPVerification, true) +RULE_BOOL(Chat, EnableAntiSpam, true) +RULE_BOOL(Chat, SuppressCommandErrors, false) // Do not suppress by default +RULE_INT(Chat, MinStatusToBypassAntiSpam, 100) +RULE_INT(Chat, MinimumMessagesPerInterval, 4) +RULE_INT(Chat, MaximumMessagesPerInterval, 12) +RULE_INT(Chat, MaxMessagesBeforeKick, 20) +RULE_INT(Chat, IntervalDurationMS, 60000) +RULE_INT(Chat, KarmaUpdateIntervalMS, 1200000) +RULE_INT(Chat, KarmaGlobalChatLimit, 72) //amount of karma you need to be able to talk in ooc/auction/chat below the level limit +RULE_INT(Chat, GlobalChatLevelLimit, 8) //level limit you need to of reached to talk in ooc/auction/chat if your karma is too low. RULE_CATEGORY_END() -RULE_CATEGORY ( Merchant ) -RULE_BOOL ( Merchant, UsePriceMod, true) // Use faction/charisma price modifiers. -RULE_REAL ( Merchant, SellCostMod, 1.05) // Modifier for NPC sell price. -RULE_REAL ( Merchant, BuyCostMod, 0.95) // Modifier for NPC buy price. -RULE_INT ( Merchant, PriceBonusPct, 4) // Determines maximum price bonus from having good faction/CHA. Value is a percent. -RULE_INT ( Merchant, PricePenaltyPct, 4) // Determines maximum price penalty from having bad faction/CHA. Value is a percent. -RULE_REAL( Merchant, ChaBonusMod, 3.45) // Determines CHA cap, from 104 CHA. 3.45 is 132 CHA at apprehensive. 0.34 is 400 CHA at apprehensive. -RULE_REAL ( Merchant, ChaPenaltyMod, 1.52) // Determines CHA bottom, up to 102 CHA. 1.52 is 37 CHA at apprehensive. 0.98 is 0 CHA at apprehensive. -RULE_BOOL ( Merchant, EnableAltCurrencySell, true) // Enables the ability to resell items to alternate currency merchants +RULE_CATEGORY(Merchant) +RULE_BOOL(Merchant, UsePriceMod, true) // Use faction/charisma price modifiers. +RULE_REAL(Merchant, SellCostMod, 1.05) // Modifier for NPC sell price. +RULE_REAL(Merchant, BuyCostMod, 0.95) // Modifier for NPC buy price. +RULE_INT(Merchant, PriceBonusPct, 4) // Determines maximum price bonus from having good faction/CHA. Value is a percent. +RULE_INT(Merchant, PricePenaltyPct, 4) // Determines maximum price penalty from having bad faction/CHA. Value is a percent. +RULE_REAL(Merchant, ChaBonusMod, 3.45) // Determines CHA cap, from 104 CHA. 3.45 is 132 CHA at apprehensive. 0.34 is 400 CHA at apprehensive. +RULE_REAL(Merchant, ChaPenaltyMod, 1.52) // Determines CHA bottom, up to 102 CHA. 1.52 is 37 CHA at apprehensive. 0.98 is 0 CHA at apprehensive. +RULE_BOOL(Merchant, EnableAltCurrencySell, true) // Enables the ability to resell items to alternate currency merchants RULE_CATEGORY_END() -RULE_CATEGORY ( Bazaar ) -RULE_BOOL ( Bazaar, AuditTrail, false) -RULE_INT ( Bazaar, MaxSearchResults, 50) -RULE_BOOL ( Bazaar, EnableWarpToTrader, true) -RULE_INT ( Bazaar, MaxBarterSearchResults, 200) // The max results returned in the /barter search +RULE_CATEGORY(Bazaar) +RULE_BOOL(Bazaar, AuditTrail, false) +RULE_INT(Bazaar, MaxSearchResults, 50) +RULE_BOOL(Bazaar, EnableWarpToTrader, true) +RULE_INT(Bazaar, MaxBarterSearchResults, 200) // The max results returned in the /barter search RULE_CATEGORY_END() -RULE_CATEGORY ( Mail ) -RULE_BOOL ( Mail, EnableMailSystem, true) // If false, client won't bring up the Mail window. -RULE_INT ( Mail, ExpireTrash, 0) // Time in seconds. 0 will delete all messages in the trash when the mailserver starts -RULE_INT ( Mail, ExpireRead, 31536000 ) // 1 Year. Set to -1 for never -RULE_INT ( Mail, ExpireUnread, 31536000 ) // 1 Year. Set to -1 for never +RULE_CATEGORY(Mail) +RULE_BOOL(Mail, EnableMailSystem, true) // If false, client won't bring up the Mail window. +RULE_INT(Mail, ExpireTrash, 0) // Time in seconds. 0 will delete all messages in the trash when the mailserver starts +RULE_INT(Mail, ExpireRead, 31536000) // 1 Year. Set to -1 for never +RULE_INT(Mail, ExpireUnread, 31536000) // 1 Year. Set to -1 for never RULE_CATEGORY_END() -RULE_CATEGORY ( Channels ) -RULE_INT ( Channels, RequiredStatusAdmin, 251) // Required status to administer chat channels -RULE_INT ( Channels, RequiredStatusListAll, 251) // Required status to list all chat channels -RULE_INT ( Channels, DeleteTimer, 1440) // Empty password protected channels will be deleted after this many minutes +RULE_CATEGORY(Channels) +RULE_INT(Channels, RequiredStatusAdmin, 251) // Required status to administer chat channels +RULE_INT(Channels, RequiredStatusListAll, 251) // Required status to list all chat channels +RULE_INT(Channels, DeleteTimer, 1440) // Empty password protected channels will be deleted after this many minutes RULE_CATEGORY_END() -RULE_CATEGORY ( EventLog ) -RULE_BOOL ( EventLog, RecordSellToMerchant, false ) // Record sales from a player to an NPC merchant in eventlog table -RULE_BOOL ( EventLog, RecordBuyFromMerchant, false ) // Record purchases by a player from an NPC merchant in eventlog table +RULE_CATEGORY(EventLog) +RULE_BOOL(EventLog, RecordSellToMerchant, false) // Record sales from a player to an NPC merchant in eventlog table +RULE_BOOL(EventLog, RecordBuyFromMerchant, false) // Record purchases by a player from an NPC merchant in eventlog table RULE_CATEGORY_END() -RULE_CATEGORY ( Adventure ) -RULE_INT ( Adventure, MinNumberForGroup, 2 ) -RULE_INT ( Adventure, MaxNumberForGroup, 6 ) -RULE_INT ( Adventure, MinNumberForRaid, 18 ) -RULE_INT ( Adventure, MaxNumberForRaid, 36 ) -RULE_INT ( Adventure, MaxLevelRange, 9 ) -RULE_INT ( Adventure, NumberKillsForBossSpawn, 45) -RULE_REAL ( Adventure, DistanceForRescueAccept, 10000.0) -RULE_REAL ( Adventure, DistanceForRescueComplete, 2500.0) -RULE_INT ( Adventure, ItemIDToEnablePorts, 41000 ) //0 to disable, otherwise using a LDoN portal will require the user to have this item. -RULE_INT ( Adventure, LDoNTrapDistanceUse, 625 ) -RULE_REAL ( Adventure, LDoNBaseTrapDifficulty, 15.0 ) -RULE_REAL ( Adventure, LDoNCriticalFailTrapThreshold, 10.0 ) -RULE_INT ( Adventure, LDoNAdventureExpireTime, 1800) //30 minutes to expire +RULE_CATEGORY(Adventure) +RULE_INT(Adventure, MinNumberForGroup, 2) +RULE_INT(Adventure, MaxNumberForGroup, 6) +RULE_INT(Adventure, MinNumberForRaid, 18) +RULE_INT(Adventure, MaxNumberForRaid, 36) +RULE_INT(Adventure, MaxLevelRange, 9) +RULE_INT(Adventure, NumberKillsForBossSpawn, 45) +RULE_REAL(Adventure, DistanceForRescueAccept, 10000.0) +RULE_REAL(Adventure, DistanceForRescueComplete, 2500.0) +RULE_INT(Adventure, ItemIDToEnablePorts, 41000) //0 to disable, otherwise using a LDoN portal will require the user to have this item. +RULE_INT(Adventure, LDoNTrapDistanceUse, 625) +RULE_REAL(Adventure, LDoNBaseTrapDifficulty, 15.0) +RULE_REAL(Adventure, LDoNCriticalFailTrapThreshold, 10.0) +RULE_INT(Adventure, LDoNAdventureExpireTime, 1800) //30 minutes to expire RULE_CATEGORY_END() -RULE_CATEGORY ( AA ) -RULE_INT ( AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52. -RULE_BOOL ( AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients. +RULE_CATEGORY(AA) +RULE_INT(AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52. +RULE_BOOL(AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients. RULE_CATEGORY_END() -RULE_CATEGORY( Console ) -RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the console session to time out +RULE_CATEGORY(Console) +RULE_INT(Console, SessionTimeOut, 600000) // Amount of time in ms for the console session to time out RULE_CATEGORY_END() -RULE_CATEGORY( QueryServ ) -RULE_BOOL( QueryServ, PlayerLogChat, false) // Logs Player Chat -RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades -RULE_BOOL( QueryServ, PlayerLogHandins, false) // Logs Player Handins -RULE_BOOL( QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills -RULE_BOOL( QueryServ, PlayerLogDeletes, false) // Logs Player Deletes -RULE_BOOL( QueryServ, PlayerLogMoves, false) // Logs Player Moves -RULE_BOOL( QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions -RULE_BOOL( QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events -RULE_BOOL( QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item -RULE_BOOL( QueryServ, PlayerLogZone, false) // Logs Player Zone Events -RULE_BOOL( QueryServ, PlayerLogDeaths, false) // Logs Player Deaths -RULE_BOOL( QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State -RULE_BOOL( QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling -RULE_BOOL( QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates -RULE_BOOL( QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates -RULE_BOOL( QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates -RULE_BOOL( QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions -RULE_BOOL( QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases -RULE_BOOL( QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions -RULE_BOOL( QueryServ, PlayerLogIssuedCommandes, false ) // Log Player Issued Commands -RULE_BOOL( QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits -RULE_BOOL( QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions +RULE_CATEGORY(QueryServ) +RULE_BOOL(QueryServ, PlayerLogChat, false) // Logs Player Chat +RULE_BOOL(QueryServ, PlayerLogTrades, false) // Logs Player Trades +RULE_BOOL(QueryServ, PlayerLogHandins, false) // Logs Player Handins +RULE_BOOL(QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills +RULE_BOOL(QueryServ, PlayerLogDeletes, false) // Logs Player Deletes +RULE_BOOL(QueryServ, PlayerLogMoves, false) // Logs Player Moves +RULE_BOOL(QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions +RULE_BOOL(QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events +RULE_BOOL(QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item +RULE_BOOL(QueryServ, PlayerLogZone, false) // Logs Player Zone Events +RULE_BOOL(QueryServ, PlayerLogDeaths, false) // Logs Player Deaths +RULE_BOOL(QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State +RULE_BOOL(QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling +RULE_BOOL(QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates +RULE_BOOL(QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates +RULE_BOOL(QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates +RULE_BOOL(QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions +RULE_BOOL(QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases +RULE_BOOL(QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions +RULE_BOOL(QueryServ, PlayerLogIssuedCommandes, false) // Log Player Issued Commands +RULE_BOOL(QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits +RULE_BOOL(QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions RULE_CATEGORY_END() -RULE_CATEGORY( Inventory ) -RULE_BOOL ( Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions -RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item usability -RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation -RULE_BOOL ( Inventory, DeleteTransformationMold, true) //False if you want mold to last forever -RULE_BOOL ( Inventory, AllowAnyWeaponTransformation, false) //Weapons can use any weapon transformation -RULE_BOOL ( Inventory, TransformSummonedBags, false) //Transforms summoned bags into disenchanted ones instead of deleting +RULE_CATEGORY(Inventory) +RULE_BOOL(Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions +RULE_BOOL(Inventory, EnforceAugmentUsability, true) // Forces augmented item usability +RULE_BOOL(Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation +RULE_BOOL(Inventory, DeleteTransformationMold, true) //False if you want mold to last forever +RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false) //Weapons can use any weapon transformation +RULE_BOOL(Inventory, TransformSummonedBags, false) //Transforms summoned bags into disenchanted ones instead of deleting RULE_CATEGORY_END() -RULE_CATEGORY( Client ) -RULE_BOOL( Client, UseLiveFactionMessage, false) // Allows players to see faction adjustments like Live +RULE_CATEGORY(Client) +RULE_BOOL(Client, UseLiveFactionMessage, false) // Allows players to see faction adjustments like Live RULE_CATEGORY_END() #undef RULE_CATEGORY diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index b22cc66d5..5e67f4c11 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -295,8 +295,8 @@ OP_MarkNPC=0x1fb5 OP_MarkRaidNPC=0x5a58 #unimplemented OP_ClearNPCMarks=0x2003 OP_ClearRaidNPCMarks=0x20d3 #unimplemented -OP_DelegateAbility=0x4c9d -OP_SetGroupTarget=0x026 +OP_DelegateAbility=0x76b8 +OP_SetGroupTarget=0x2814 OP_Charm=0x5d92 OP_Stun=0x36a4 OP_SendFindableNPCs=0x4613 diff --git a/zone/attack.cpp b/zone/attack.cpp index 146bcdce6..6a8125507 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4248,7 +4248,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack } #ifdef BOTS - if (this->IsPet() && this->GetOwner()->IsBot()) { + if (this->IsPet() && this->GetOwner() && this->GetOwner()->IsBot()) { this->TryPetCriticalHit(defender,skill,damage); return; } diff --git a/zone/bot.cpp b/zone/bot.cpp index ea6739c79..0d601dec7 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -13,19 +13,16 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm if(botOwner) { this->SetBotOwner(botOwner); this->_botOwnerCharacterID = botOwner->CharacterID(); - } - else { + } else { this->SetBotOwner(0); this->_botOwnerCharacterID = 0; } _guildRank = 0; _guildId = 0; - _lastTotalPlayTime = 0; _startTotalPlayTime = time(&_startTotalPlayTime); _lastZoneId = 0; - _baseMR = npcTypeData.MR; _baseCR = npcTypeData.CR; _baseDR = npcTypeData.DR; @@ -46,7 +43,6 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; - SetBotID(0); SetBotSpellID(0); SetSpawnStatus(false); @@ -67,55 +63,43 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm SetHealRotationTimer(0); SetNumHealRotationMembers(0); SetBardUseOutOfCombatSongs(GetClass() == BARD); + SetShowHelm(true); CalcChanceToCast(); rest_timer.Disable(); - SetFollowDistance(184); - // Do this once and only in this constructor GenerateAppearance(); - GenerateBaseStats(); GenerateArmorClass(); - // Calculate HitPoints Last As It Uses Base Stats cur_hp = GenerateBaseHitPoints(); cur_mana = GenerateBaseManaPoints(); cur_end = CalcBaseEndurance(); - hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); end_regen = CalcEnduranceRegen(); - - for (int i = 0; i < MaxTimer; i++) { + for (int i = 0; i < MaxTimer; i++) timers[i] = 0; - } - for(int i = 0; i < MaxHealRotationTargets; i++) { + for(int i = 0; i < MaxHealRotationTargets; i++) _healRotationTargets[i] = 0; - } strcpy(this->name, this->GetCleanName()); - memset(&m_Light, 0, sizeof(LightProfile_Struct)); } // This constructor is used when the bot is loaded out of the database Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) { this->_botOwnerCharacterID = botOwnerCharacterID; - - if(this->_botOwnerCharacterID > 0) { + if(this->_botOwnerCharacterID > 0) this->SetBotOwner(entity_list.GetClientByCharID(this->_botOwnerCharacterID)); - } _guildRank = 0; _guildId = 0; - _lastTotalPlayTime = totalPlayTime; _startTotalPlayTime = time(&_startTotalPlayTime); _lastZoneId = lastZoneId; berserk = false; - _baseMR = npcTypeData.MR; _baseCR = npcTypeData.CR; _baseDR = npcTypeData.DR; @@ -135,11 +119,9 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to _baseGender = npcTypeData.gender; cur_hp = npcTypeData.cur_hp; cur_mana = npcTypeData.Mana; - RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; - SetBotID(botID); SetBotSpellID(botSpellsID); SetSpawnStatus(false); @@ -163,61 +145,49 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetNumHealRotationMembers(0); CalcChanceToCast(); rest_timer.Disable(); - SetFollowDistance(184); - strcpy(this->name, this->GetCleanName()); - database.GetBotInspectMessage(this->GetBotID(), &_botInspectMessage); - LoadGuildMembership(&_guildId, &_guildRank, &_guildName); - std::string TempErrorMessage; - EquipBot(&TempErrorMessage); - if(!TempErrorMessage.empty()) { - // TODO: log error message to zone error log if(GetBotOwner()) GetBotOwner()->Message(13, TempErrorMessage.c_str()); } - for (int i = 0; i < MaxTimer; i++) { + for (int i = 0; i < MaxTimer; i++) timers[i] = 0; - } - for(int i = 0; i < MaxHealRotationTargets; i++) { + for(int i = 0; i < MaxHealRotationTargets; i++) _healRotationTargets[i] = 0; - } GenerateBaseStats(); - LoadTimers(); LoadAAs(); LoadBuffs(); - CalcBotStats(false); - hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); end_regen = CalcEnduranceRegen(); - if(cur_hp > max_hp) cur_hp = max_hp; + if(cur_hp <= 0) { SetHP(max_hp/5); SetMana(0); BuffFadeAll(); SpellOnTarget(756, this); // Rezz effects } + if(cur_mana > max_mana) cur_mana = max_mana; + cur_end = max_end; } Bot::~Bot() { AI_Stop(); - if(HasGroup()) Bot::RemoveBotFromGroup(this, GetGroup()); @@ -236,57 +206,39 @@ void Bot::SetBotSpellID(uint32 newSpellID) { this->npc_spells_id = newSpellID; } -uint32 Bot::GetBotArcheryRange() -{ +uint32 Bot::GetBotArcheryRange() { const ItemInst *range_inst = GetBotItem(MainRange); const ItemInst *ammo_inst = GetBotItem(MainAmmo); - - // empty slots if (!range_inst || !ammo_inst) return 0; const Item_Struct *range_item = range_inst->GetItem(); const Item_Struct *ammo_item = ammo_inst->GetItem(); - - // no item struct for whatever reason - if (!range_item || !ammo_item) - return 0; - - // bad item types - if (range_item->ItemType != ItemTypeBow || ammo_item->ItemType != ItemTypeArrow) + if (!range_item || !ammo_item || range_item->ItemType != ItemTypeBow || ammo_item->ItemType != ItemTypeArrow) return 0; // everything is good! - return range_item->Range + ammo_item->Range; + return (range_item->Range + ammo_item->Range); } void Bot::ChangeBotArcherWeapons(bool isArcher) { - if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) - || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) - { + if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) { if(!isArcher) { BotAddEquipItem(MainPrimary, GetBotItemBySlot(MainPrimary)); BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainSecondary)); - //archerbot->SendWearChange(MATERIAL_PRIMARY); - //archerbot->SendWearChange(MATERIAL_SECONDARY); SetAttackTimer(); - Say("My blade is ready."); - } - else { - //archerbot->SendWearChange(MATERIAL_PRIMARY); - //archerbot->SendWearChange(MATERIAL_SECONDARY); + BotGroupSay(this, "My blade is ready."); + } else { BotRemoveEquipItem(MainPrimary); BotRemoveEquipItem(MainSecondary); - //archerbot->SendBotArcheryWearChange(MATERIAL_PRIMARY, archeryMaterial, archeryColor); BotAddEquipItem(MainAmmo, GetBotItemBySlot(MainAmmo)); BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainRange)); SetAttackTimer(); - Say("My bow is true and ready."); + BotGroupSay(this, "My bow is true and ready."); } } - else { - Say("I don't know how to use a bow."); - } + else + BotGroupSay(this, "I don't know how to use a bow."); } void Bot::Sit() { @@ -305,7 +257,6 @@ void Bot::Stand() { bool Bot::IsSitting() { bool result = false; - if(GetAppearance() == eaSitting && !IsMoving()) result = true; @@ -314,7 +265,6 @@ bool Bot::IsSitting() { bool Bot::IsStanding() { bool result = false; - if(GetAppearance() == eaStanding) result = true; @@ -324,15 +274,12 @@ bool Bot::IsStanding() { NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack) { NPCType BotNPCType; int CopyLength = 0; - CopyLength = botName.copy(BotNPCType.name, 63); BotNPCType.name[CopyLength] = '\0'; CopyLength = 0; - CopyLength = botLastName.copy(BotNPCType.lastname, 69); BotNPCType.lastname[CopyLength] = '\0'; CopyLength = 0; - BotNPCType.npc_spells_id = botSpellsID; BotNPCType.level = botLevel; BotNPCType.race = botRace; @@ -366,7 +313,6 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str BotNPCType.WIS = wis; BotNPCType.CHA = cha; BotNPCType.ATK = attack; - BotNPCType.npc_id = 0; BotNPCType.texture = 0; BotNPCType.d_melee_texture1 = 0; @@ -379,29 +325,23 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str BotNPCType.hp_regen = 1; BotNPCType.mana_regen = 1; BotNPCType.maxlevel = botLevel; - BotNPCType.light = NOT_USED; // due to the way that bots are coded..this is sent post-spawn - return BotNPCType; } NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender) { NPCType Result; int CopyLength = 0; - CopyLength = botName.copy(Result.name, 63); Result.name[CopyLength] = '\0'; CopyLength = 0; - CopyLength = botLastName.copy(Result.lastname, 69); Result.lastname[CopyLength] = '\0'; CopyLength = 0; - Result.level = botLevel; Result.race = botRace; Result.class_ = botClass; Result.gender = gender; - // default values Result.maxlevel = botLevel; Result.size = 6.0; @@ -436,13 +376,11 @@ NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string b Result.CR = 25; Result.Corrup = 15; Result.AC = 12; - return Result; } void Bot::GenerateBaseStats() { int BotSpellID = 0; - // base stats uint32 Strength = _baseSTR; uint32 Stamina = _baseSTA; @@ -458,286 +396,284 @@ void Bot::GenerateBaseStats() { int32 PoisonResist = _basePR; int32 ColdResist = _baseCR; int32 CorruptionResist = _baseCorrup; - switch(this->GetClass()) { - case 1: // Warrior (why not just use 'case WARRIOR:'?) - Strength += 10; - Stamina += 20; - Agility += 10; - Dexterity += 10; - Attack += 12; - break; - case 2: // Cleric - BotSpellID = 701; - Strength += 5; - Stamina += 5; - Agility += 10; - Wisdom += 30; - Attack += 8; - break; - case 3: // Paladin - BotSpellID = 708; - Strength += 15; - Stamina += 5; - Wisdom += 15; - Charisma += 10; - Dexterity += 5; - Attack += 17; - break; - case 4: // Ranger - BotSpellID = 710; - Strength += 15; - Stamina += 10; - Agility += 10; - Wisdom += 15; - Attack += 17; - break; - case 5: // Shadowknight - BotSpellID = 709; - Strength += 10; - Stamina += 15; - Intelligence += 20; - Charisma += 5; - Attack += 17; - break; - case 6: // Druid - BotSpellID = 707; - Stamina += 15; - Wisdom += 35; - Attack += 5; - break; - case 7: // Monk - Strength += 5; - Stamina += 15; - Agility += 15; - Dexterity += 15; - Attack += 17; - break; - case 8: // Bard - BotSpellID = 711; - Strength += 15; - Dexterity += 10; - Charisma += 15; - Intelligence += 10; - Attack += 17; - break; - case 9: // Rogue - Strength += 10; - Stamina += 20; - Agility += 10; - Dexterity += 10; - Attack += 12; - break; - case 10: // Shaman - BotSpellID = 706; - Stamina += 10; - Wisdom += 30; - Charisma += 10; - Attack += 28; - break; - case 11: // Necromancer - BotSpellID = 703; - Dexterity += 10; - Agility += 10; - Intelligence += 30; - Attack += 5; - break; - case 12: // Wizard - BotSpellID = 702; - Stamina += 20; - Intelligence += 30; - Attack += 5; - break; - case 13: // Magician - BotSpellID = 704; - Stamina += 20; - Intelligence += 30; - Attack += 5; - break; - case 14: // Enchanter - BotSpellID = 705; - Intelligence += 25; - Charisma += 25; - Attack += 5; - break; - case 15: // Beastlord - BotSpellID = 712; - Stamina += 10; - Agility += 10; - Dexterity += 5; - Wisdom += 20; - Charisma += 5; - Attack += 31; - break; - case 16: // Berserker - Strength += 10; - Stamina += 15; - Dexterity += 15; - Agility += 10; - Attack += 25; - break; + case 1: // Warrior (why not just use 'case WARRIOR:'?) + Strength += 10; + Stamina += 20; + Agility += 10; + Dexterity += 10; + Attack += 12; + break; + case 2: // Cleric + BotSpellID = 701; + Strength += 5; + Stamina += 5; + Agility += 10; + Wisdom += 30; + Attack += 8; + break; + case 3: // Paladin + BotSpellID = 708; + Strength += 15; + Stamina += 5; + Wisdom += 15; + Charisma += 10; + Dexterity += 5; + Attack += 17; + break; + case 4: // Ranger + BotSpellID = 710; + Strength += 15; + Stamina += 10; + Agility += 10; + Wisdom += 15; + Attack += 17; + break; + case 5: // Shadowknight + BotSpellID = 709; + Strength += 10; + Stamina += 15; + Intelligence += 20; + Charisma += 5; + Attack += 17; + break; + case 6: // Druid + BotSpellID = 707; + Stamina += 15; + Wisdom += 35; + Attack += 5; + break; + case 7: // Monk + Strength += 5; + Stamina += 15; + Agility += 15; + Dexterity += 15; + Attack += 17; + break; + case 8: // Bard + BotSpellID = 711; + Strength += 15; + Dexterity += 10; + Charisma += 15; + Intelligence += 10; + Attack += 17; + break; + case 9: // Rogue + Strength += 10; + Stamina += 20; + Agility += 10; + Dexterity += 10; + Attack += 12; + break; + case 10: // Shaman + BotSpellID = 706; + Stamina += 10; + Wisdom += 30; + Charisma += 10; + Attack += 28; + break; + case 11: // Necromancer + BotSpellID = 703; + Dexterity += 10; + Agility += 10; + Intelligence += 30; + Attack += 5; + break; + case 12: // Wizard + BotSpellID = 702; + Stamina += 20; + Intelligence += 30; + Attack += 5; + break; + case 13: // Magician + BotSpellID = 704; + Stamina += 20; + Intelligence += 30; + Attack += 5; + break; + case 14: // Enchanter + BotSpellID = 705; + Intelligence += 25; + Charisma += 25; + Attack += 5; + break; + case 15: // Beastlord + BotSpellID = 712; + Stamina += 10; + Agility += 10; + Dexterity += 5; + Wisdom += 20; + Charisma += 5; + Attack += 31; + break; + case 16: // Berserker + Strength += 10; + Stamina += 15; + Dexterity += 15; + Agility += 10; + Attack += 25; + break; } float BotSize = GetSize(); switch(this->GetRace()) { - case 1: // Humans have no race bonus - break; - case 2: // Barbarian - Strength += 28; - Stamina += 20; - Agility += 7; - Dexterity -= 5; - Wisdom -= 5; - Intelligence -= 10; - Charisma -= 20; - BotSize = 7.0; - ColdResist += 10; - break; - case 3: // Erudite - Strength -= 15; - Stamina -= 5; - Agility -= 5; - Dexterity -= 5; - Wisdom += 8; - Intelligence += 32; - Charisma -= 5; - MagicResist += 5; - DiseaseResist -= 5; - break; - case 4: // Wood Elf - Strength -= 10; - Stamina -= 10; - Agility += 20; - Dexterity += 5; - Wisdom += 5; - BotSize = 5.0; - break; - case 5: // High Elf - Strength -= 20; - Stamina -= 10; - Agility += 10; - Dexterity -= 5; - Wisdom += 20; - Intelligence += 12; - Charisma += 5; - break; - case 6: // Dark Elf - Strength -= 15; - Stamina -= 10; - Agility += 15; - Wisdom += 8; - Intelligence += 24; - Charisma -= 15; - BotSize = 5.0; - break; - case 7: // Half Elf - Strength -= 5; - Stamina -= 5; - Agility += 15; - Dexterity += 10; - Wisdom -= 15; - BotSize = 5.5; - break; - case 8: // Dwarf - Strength += 15; - Stamina += 15; - Agility -= 5; - Dexterity += 15; - Wisdom += 8; - Intelligence -= 15; - Charisma -= 30; - BotSize = 4.0; - MagicResist -= 5; - PoisonResist += 5; - break; - case 9: // Troll - Strength += 33; - Stamina += 34; - Agility += 8; - Wisdom -= 15; - Intelligence -= 23; - Charisma -= 35; - BotSize = 8.0; - FireResist -= 20; - break; - case 10: // Ogre - Strength += 55; - Stamina += 77; - Agility -= 5; - Dexterity -= 5; - Wisdom -= 8; - Intelligence -= 15; - Charisma -= 38; - BotSize = 9.0; - break; - case 11: // Halfling - Strength -= 5; - Agility += 20; - Dexterity += 15; - Wisdom += 5; - Intelligence -= 8; - Charisma -= 25; - BotSize = 3.5; - PoisonResist += 5; - DiseaseResist += 5; - break; - case 12: // Gnome - Strength -= 15; - Stamina -= 5; - Agility += 10; - Dexterity += 10; - Wisdom -= 8; - Intelligence += 23; - Charisma -= 15; - BotSize = 3.0; - break; - case 128: // Iksar - Strength -= 5; - Stamina -= 5; - Agility += 15; - Dexterity += 10; - Wisdom += 5; - Charisma -= 20; - MagicResist -= 5; - FireResist -= 5; - break; - case 130: // Vah Shir - Strength += 15; - Agility += 15; - Dexterity -= 5; - Wisdom -= 5; - Intelligence -= 10; - Charisma -= 10; - BotSize = 7.0; - MagicResist -= 5; - FireResist -= 5; - break; - case 330: // Froglok - Strength -= 5; - Stamina += 5; - Agility += 25; - Dexterity += 25; - Charisma -= 25; - BotSize = 5.0; - MagicResist -= 5; - FireResist -= 5; - break; - case 522: // Drakkin - Strength -= 5; - Stamina += 5; - Agility += 10; - Intelligence += 10; - Wisdom += 5; - BotSize = 5.0; - PoisonResist += 2; - DiseaseResist += 2; - MagicResist += 2; - FireResist += 2; - ColdResist += 2; - break; + case 1: // Humans have no race bonus + break; + case 2: // Barbarian + Strength += 28; + Stamina += 20; + Agility += 7; + Dexterity -= 5; + Wisdom -= 5; + Intelligence -= 10; + Charisma -= 20; + BotSize = 7.0; + ColdResist += 10; + break; + case 3: // Erudite + Strength -= 15; + Stamina -= 5; + Agility -= 5; + Dexterity -= 5; + Wisdom += 8; + Intelligence += 32; + Charisma -= 5; + MagicResist += 5; + DiseaseResist -= 5; + break; + case 4: // Wood Elf + Strength -= 10; + Stamina -= 10; + Agility += 20; + Dexterity += 5; + Wisdom += 5; + BotSize = 5.0; + break; + case 5: // High Elf + Strength -= 20; + Stamina -= 10; + Agility += 10; + Dexterity -= 5; + Wisdom += 20; + Intelligence += 12; + Charisma += 5; + break; + case 6: // Dark Elf + Strength -= 15; + Stamina -= 10; + Agility += 15; + Wisdom += 8; + Intelligence += 24; + Charisma -= 15; + BotSize = 5.0; + break; + case 7: // Half Elf + Strength -= 5; + Stamina -= 5; + Agility += 15; + Dexterity += 10; + Wisdom -= 15; + BotSize = 5.5; + break; + case 8: // Dwarf + Strength += 15; + Stamina += 15; + Agility -= 5; + Dexterity += 15; + Wisdom += 8; + Intelligence -= 15; + Charisma -= 30; + BotSize = 4.0; + MagicResist -= 5; + PoisonResist += 5; + break; + case 9: // Troll + Strength += 33; + Stamina += 34; + Agility += 8; + Wisdom -= 15; + Intelligence -= 23; + Charisma -= 35; + BotSize = 8.0; + FireResist -= 20; + break; + case 10: // Ogre + Strength += 55; + Stamina += 77; + Agility -= 5; + Dexterity -= 5; + Wisdom -= 8; + Intelligence -= 15; + Charisma -= 38; + BotSize = 9.0; + break; + case 11: // Halfling + Strength -= 5; + Agility += 20; + Dexterity += 15; + Wisdom += 5; + Intelligence -= 8; + Charisma -= 25; + BotSize = 3.5; + PoisonResist += 5; + DiseaseResist += 5; + break; + case 12: // Gnome + Strength -= 15; + Stamina -= 5; + Agility += 10; + Dexterity += 10; + Wisdom -= 8; + Intelligence += 23; + Charisma -= 15; + BotSize = 3.0; + break; + case 128: // Iksar + Strength -= 5; + Stamina -= 5; + Agility += 15; + Dexterity += 10; + Wisdom += 5; + Charisma -= 20; + MagicResist -= 5; + FireResist -= 5; + break; + case 130: // Vah Shir + Strength += 15; + Agility += 15; + Dexterity -= 5; + Wisdom -= 5; + Intelligence -= 10; + Charisma -= 10; + BotSize = 7.0; + MagicResist -= 5; + FireResist -= 5; + break; + case 330: // Froglok + Strength -= 5; + Stamina += 5; + Agility += 25; + Dexterity += 25; + Charisma -= 25; + BotSize = 5.0; + MagicResist -= 5; + FireResist -= 5; + break; + case 522: // Drakkin + Strength -= 5; + Stamina += 5; + Agility += 10; + Intelligence += 10; + Wisdom += 5; + BotSize = 5.0; + PoisonResist += 2; + DiseaseResist += 2; + MagicResist += 2; + FireResist += 2; + ColdResist += 2; + break; } - this->STR = Strength; this->STA = Stamina; this->DEX = Dexterity; @@ -755,7 +691,6 @@ void Bot::GenerateBaseStats() { this->Corrup = CorruptionResist; SetBotSpellID(BotSpellID); this->size = BotSize; - this->pAggroRange = 0; this->pAssistRange = 0; this->raid_target = false; @@ -764,12 +699,10 @@ void Bot::GenerateBaseStats() { void Bot::GenerateAppearance() { // Randomize facial appearance int iFace = 0; - if(this->GetRace() == 2) { // Barbarian w/Tatoo + if(this->GetRace() == 2) // Barbarian w/Tatoo iFace = zone->random.Int(0, 79); - } - else { + else iFace = zone->random.Int(0, 7); - } int iHair = 0; int iBeard = 0; @@ -778,40 +711,32 @@ void Bot::GenerateAppearance() { iHair = zone->random.Int(0, 8); iBeard = zone->random.Int(0, 11); iBeardColor = zone->random.Int(0, 3); - } - else if(this->GetGender()) { + } else if(this->GetGender()) { iHair = zone->random.Int(0, 2); if(this->GetRace() == 8) { // Dwarven Females can have a beard - if(zone->random.Int(1, 100) < 50) { + if(zone->random.Int(1, 100) < 50) iFace += 10; - } } - } - else { + } else { iHair = zone->random.Int(0, 3); iBeard = zone->random.Int(0, 5); iBeardColor = zone->random.Int(0, 19); } int iHairColor = 0; - if(this->GetRace() == 522) { + if(this->GetRace() == 522) iHairColor = zone->random.Int(0, 3); - } - else { + else iHairColor = zone->random.Int(0, 19); - } uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9); uint8 iEyeColor2 = 0; - if(this->GetRace() == 522) { + if(this->GetRace() == 522) iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11); - } - else if(zone->random.Int(1, 100) > 96) { + else if(zone->random.Int(1, 100) > 96) iEyeColor2 = zone->random.Int(0, 9); - } - else { + else iEyeColor2 = iEyeColor1; - } int iHeritage = 0; int iTattoo = 0; @@ -821,7 +746,6 @@ void Bot::GenerateAppearance() { iTattoo = zone->random.Int(0, 7); iDetails = zone->random.Int(0, 7); } - this->luclinface = iFace; this->hairstyle = iHair; this->beard = iBeard; @@ -832,77 +756,71 @@ void Bot::GenerateAppearance() { this->drakkin_heritage = iHeritage; this->drakkin_tattoo = iTattoo; this->drakkin_details = iDetails; - } -int32 Bot::acmod() -{ +int32 Bot::acmod() { int agility = GetAGI(); int level = GetLevel(); if(agility < 1 || level < 1) return 0; - if(agility <= 74) - { + if(agility <= 74) { if(agility == 1) return -24; - else if(agility <=3) + else if(agility <= 3) return -23; else if(agility == 4) return -22; - else if(agility <=6) + else if(agility <= 6) return -21; - else if(agility <=8) + else if(agility <= 8) return -20; else if(agility == 9) return -19; - else if(agility <=11) + else if(agility <= 11) return -18; else if(agility == 12) return -17; - else if(agility <=14) + else if(agility <= 14) return -16; - else if(agility <=16) + else if(agility <= 16) return -15; else if(agility == 17) return -14; - else if(agility <=19) + else if(agility <= 19) return -13; else if(agility == 20) return -12; - else if(agility <=22) + else if(agility <= 22) return -11; - else if(agility <=24) + else if(agility <= 24) return -10; else if(agility == 25) return -9; - else if(agility <=27) + else if(agility <= 27) return -8; else if(agility == 28) return -7; - else if(agility <=30) + else if(agility <= 30) return -6; - else if(agility <=32) + else if(agility <= 32) return -5; else if(agility == 33) return -4; - else if(agility <=35) + else if(agility <= 35) return -3; else if(agility == 36) return -2; - else if(agility <=38) + else if(agility <= 38) return -1; - else if(agility <=65) + else if(agility <= 65) return 0; - else if(agility <=70) + else if(agility <= 70) return 1; - else if(agility <=74) + else if(agility <= 74) return 5; - } - else if(agility <= 137) - { - if(agility == 75) - { + } else if(agility <= 137) { + if(agility == 75) { if(level <= 6) return 9; else if(level <= 19) @@ -911,9 +829,7 @@ int32 Bot::acmod() return 33; else return 39; - } - else if(agility >= 76 && agility <= 79) - { + } else if(agility >= 76 && agility <= 79) { if(level <= 6) return 10; else if(level <= 19) @@ -922,9 +838,7 @@ int32 Bot::acmod() return 33; else return 40; - } - else if(agility == 80) - { + } else if(agility == 80) { if(level <= 6) return 11; else if(level <= 19) @@ -933,9 +847,7 @@ int32 Bot::acmod() return 34; else return 41; - } - else if(agility >= 81 && agility <= 85) - { + } else if(agility >= 81 && agility <= 85) { if(level <= 6) return 12; else if(level <= 19) @@ -944,9 +856,7 @@ int32 Bot::acmod() return 35; else return 42; - } - else if(agility >= 86 && agility <= 90) - { + } else if(agility >= 86 && agility <= 90) { if(level <= 6) return 12; else if(level <= 19) @@ -955,9 +865,7 @@ int32 Bot::acmod() return 36; else return 42; - } - else if(agility >= 91 && agility <= 95) - { + } else if(agility >= 91 && agility <= 95) { if(level <= 6) return 13; else if(level <= 19) @@ -966,8 +874,7 @@ int32 Bot::acmod() return 36; else return 43; - } - else if(agility >= 96 && agility <= 99){ + } else if(agility >= 96 && agility <= 99) { if(level <= 6) return 14; else if(level <= 19) @@ -976,9 +883,7 @@ int32 Bot::acmod() return 37; else return 44; - } - else if(agility == 100 && level >= 7) - { + } else if(agility == 100 && level >= 7) { if(level <= 19) return 28; else if (level <= 39) @@ -987,39 +892,30 @@ int32 Bot::acmod() return 45; } else if(level <= 6) - { return 15; - } //level is >6 - else if(agility >= 101 && agility <= 105) - { + else if(agility >= 101 && agility <= 105) { if(level <= 19) return 29; else if(level <= 39) return 39;// not verified else return 45; - } - else if(agility >= 106 && agility <= 110) - { + } else if(agility >= 106 && agility <= 110) { if(level <= 19) return 29; else if(level <= 39) return 39;// not verified else return 46; - } - else if(agility >= 111 && agility <= 115) - { + } else if(agility >= 111 && agility <= 115) { if(level <= 19) return 30; else if(level <= 39) return 40;// not verified else return 47; - } - else if(agility >= 116 && agility <= 119) - { + } else if(agility >= 116 && agility <= 119) { if(level <= 19) return 31; else if(level <= 39) @@ -1028,307 +924,269 @@ int32 Bot::acmod() return 47; } else if(level <= 19) - { return 32; - } //level is > 19 - else if(agility == 120) - { + else if(agility == 120) { if(level <= 39) return 42; else return 48; - } - else if(agility <= 125) - { + } else if(agility <= 125) { if(level <= 39) return 42; else return 49; - } - else if(agility <= 135) - { + } else if(agility <= 135) { if(level <= 39) return 42; else return 50; - } - else { + } else { if(level <= 39) return 42; else return 51; } - } - else if(agility <= 300) - { + } else if(agility <= 300) { if(level <= 6) { if(agility <= 139) - return(21); + return 21; else if(agility == 140) - return(22); + return 22; else if(agility <= 145) - return(23); + return 23; else if(agility <= 150) - return(23); + return 23; else if(agility <= 155) - return(24); + return 24; else if(agility <= 159) - return(25); + return 25; else if(agility == 160) - return(26); + return 26; else if(agility <= 165) - return(26); + return 26; else if(agility <= 170) - return(27); + return 27; else if(agility <= 175) - return(28); + return 28; else if(agility <= 179) - return(28); + return 28; else if(agility == 180) - return(29); + return 29; else if(agility <= 185) - return(30); + return 30; else if(agility <= 190) - return(31); + return 31; else if(agility <= 195) - return(31); + return 31; else if(agility <= 199) - return(32); + return 32; else if(agility <= 219) - return(33); + return 33; else if(agility <= 239) - return(34); + return 34; else - return(35); - } - else if(level <= 19) - { + return 35; + } else if(level <= 19) { if(agility <= 139) - return(34); + return 34; else if(agility == 140) - return(35); + return 35; else if(agility <= 145) - return(36); + return 36; else if(agility <= 150) - return(37); + return 37; else if(agility <= 155) - return(37); + return 37; else if(agility <= 159) - return(38); + return 38; else if(agility == 160) - return(39); + return 39; else if(agility <= 165) - return(40); + return 40; else if(agility <= 170) - return(40); + return 40; else if(agility <= 175) - return(41); + return 41; else if(agility <= 179) - return(42); + return 42; else if(agility == 180) - return(43); + return 43; else if(agility <= 185) - return(43); + return 43; else if(agility <= 190) - return(44); + return 44; else if(agility <= 195) - return(45); + return 45; else if(agility <= 199) - return(45); + return 45; else if(agility <= 219) - return(46); + return 46; else if(agility <= 239) - return(47); + return 47; else - return(48); - } - else if(level <= 39) - { + return 48; + } else if(level <= 39) { if(agility <= 139) - return(44); + return 44; else if(agility == 140) - return(45); + return 45; else if(agility <= 145) - return(46); + return 46; else if(agility <= 150) - return(47); + return 47; else if(agility <= 155) - return(47); + return 47; else if(agility <= 159) - return(48); + return 48; else if(agility == 160) - return(49); + return 49; else if(agility <= 165) - return(50); + return 50; else if(agility <= 170) - return(50); + return 50; else if(agility <= 175) - return(51); + return 51; else if(agility <= 179) - return(52); + return 52; else if(agility == 180) - return(53); + return 53; else if(agility <= 185) - return(53); + return 53; else if(agility <= 190) - return(54); + return 54; else if(agility <= 195) - return(55); + return 55; else if(agility <= 199) - return(55); + return 55; else if(agility <= 219) - return(56); + return 56; else if(agility <= 239) - return(57); + return 57; else - return(58); - } - else - { //lvl >= 40 + return 58; + } else { //lvl >= 40 if(agility <= 139) - return(51); + return 51; else if(agility == 140) - return(52); + return 52; else if(agility <= 145) - return(53); + return 53; else if(agility <= 150) - return(53); + return 53; else if(agility <= 155) - return(54); + return 54; else if(agility <= 159) - return(55); + return 55; else if(agility == 160) - return(56); + return 56; else if(agility <= 165) - return(56); + return 56; else if(agility <= 170) - return(57); + return 57; else if(agility <= 175) - return(58); + return 58; else if(agility <= 179) - return(58); + return 58; else if(agility == 180) - return(59); + return 59; else if(agility <= 185) - return(60); + return 60; else if(agility <= 190) - return(61); + return 61; else if(agility <= 195) - return(61); + return 61; else if(agility <= 199) - return(62); + return 62; else if(agility <= 219) - return(63); + return 63; else if(agility <= 239) - return(64); + return 64; else - return(65); + return 65; } } else - { - //seems about 21 agil per extra AC pt over 300... - return (65 + ((agility-300) / 21)); - } + return (65 + ((agility - 300) / 21)); #if EQDEBUG >= 11 Log.Out(Logs::General, Logs::Error, "Error in Bot::acmod(): Agility: %i, Level: %i",agility,level); #endif return 0; } -void Bot::GenerateArmorClass() -{ +void Bot::GenerateArmorClass() { /// new formula int avoidance = 0; - avoidance = (acmod() + ((GetSkill(SkillDefense)*16)/9)); + avoidance = (acmod() + ((GetSkill(SkillDefense) * 16) / 9)); if(avoidance < 0) avoidance = 0; int mitigation = 0; - if(GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER) - { - mitigation = GetSkill(SkillDefense)/4 + (itembonuses.AC+1); + if(GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER) { + mitigation = (GetSkill(SkillDefense) / 4 + (itembonuses.AC + 1)); mitigation -= 4; - } - else - { - mitigation = GetSkill(SkillDefense)/3 + ((itembonuses.AC*4)/3); + } else { + mitigation = (GetSkill(SkillDefense) / 3 + ((itembonuses.AC * 4) / 3)); if(GetClass() == MONK) - mitigation += GetLevel() * 13/10; //the 13/10 might be wrong, but it is close... + mitigation += (GetLevel() * 13 / 10); //the 13/10 might be wrong, but it is close... } int displayed = 0; - displayed += ((avoidance+mitigation)*1000)/847; //natural AC + displayed += (((avoidance + mitigation) * 1000) / 847); //natural AC //Iksar AC, untested - if(GetRace() == IKSAR) - { + if(GetRace() == IKSAR) { displayed += 12; int iksarlevel = GetLevel(); iksarlevel -= 10; if(iksarlevel > 25) iksarlevel = 25; + if(iksarlevel > 0) - displayed += iksarlevel * 12 / 10; + displayed += (iksarlevel * 12 / 10); } //spell AC bonuses are added directly to natural total displayed += spellbonuses.AC; - this->AC = displayed; } -uint16 Bot::GetPrimarySkillValue() -{ +uint16 Bot::GetPrimarySkillValue() { SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill bool equiped = m_inv.GetItem(MainPrimary); - if(!equiped) - { skill = SkillHandtoHand; - } - else - { + else { uint8 type = m_inv.GetItem(MainPrimary)->GetItem()->ItemType; //is this the best way to do this? - switch(type) - { - case ItemType1HSlash: // 1H Slashing - { + switch(type) { + case ItemType1HSlash: { skill = Skill1HSlashing; break; } - case ItemType2HSlash: // 2H Slashing - { + case ItemType2HSlash: { skill = Skill2HSlashing; break; } - case ItemType1HPiercing: // Piercing - { + case ItemType1HPiercing: { skill = Skill1HPiercing; break; } - case ItemType1HBlunt: // 1H Blunt - { + case ItemType1HBlunt: { skill = Skill1HBlunt; break; } - case ItemType2HBlunt: // 2H Blunt - { + case ItemType2HBlunt: { skill = Skill2HBlunt; break; } - case ItemType2HPiercing: // 2H Piercing - { + case ItemType2HPiercing: { skill = Skill1HPiercing; // change to Skill2HPiercing once activated break; } - case ItemTypeMartial: // Hand to Hand - { + case ItemTypeMartial: { skill = SkillHandtoHand; break; } - default: // All other types default to Hand to Hand - { + default: { skill = SkillHandtoHand; break; } @@ -1342,15 +1200,12 @@ uint16 Bot::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { return(database.GetSkillCap(class_, skillid, level)); } -uint32 Bot::GetTotalATK() -{ +uint32 Bot::GetTotalATK() { uint32 AttackRating = 0; uint32 WornCap = itembonuses.ATK; - if(IsBot()) { AttackRating = ((WornCap * 1.342) + (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69)); AttackRating += aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); - if (AttackRating < 10) AttackRating = 10; } @@ -1358,34 +1213,27 @@ uint32 Bot::GetTotalATK() AttackRating = GetATK(); AttackRating += spellbonuses.ATK; - return AttackRating; } -uint32 Bot::GetATKRating() -{ +uint32 Bot::GetATKRating() { uint32 AttackRating = 0; if(IsBot()) { AttackRating = (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); - if (AttackRating < 10) AttackRating = 10; } return AttackRating; } -int32 Bot::GenerateBaseHitPoints() -{ +int32 Bot::GenerateBaseHitPoints() { // Calc Base Hit Points int new_base_hp = 0; uint32 lm = GetClassLevelFactor(); int32 Post255; int32 NormalSTA = GetSTA(); - - if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) - { + if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { float SoDPost255; - if(((NormalSTA - 255) / 2) > 0) SoDPost255 = ((NormalSTA - 255) / 2); else @@ -1394,33 +1242,20 @@ int32 Bot::GenerateBaseHitPoints() int hp_factor = GetClassHPFactor(); if(level < 41) - { new_base_hp = (5 + (GetLevel() * hp_factor / 12) + ((NormalSTA - SoDPost255) * GetLevel() * hp_factor / 3600)); - } else if(level < 81) - { - new_base_hp = (5 + (40 * hp_factor / 12) + ((GetLevel() - 40) * hp_factor / 6) + - ((NormalSTA - SoDPost255) * hp_factor / 90) + - ((NormalSTA - SoDPost255) * (GetLevel() - 40) * hp_factor / 1800)); - } + new_base_hp = (5 + (40 * hp_factor / 12) + ((GetLevel() - 40) * hp_factor / 6) + ((NormalSTA - SoDPost255) * hp_factor / 90) + ((NormalSTA - SoDPost255) * (GetLevel() - 40) * hp_factor / 1800)); else - { - new_base_hp = (5 + (80 * hp_factor / 8) + ((GetLevel() - 80) * hp_factor / 10) + - ((NormalSTA - SoDPost255) * hp_factor / 90) + - ((NormalSTA - SoDPost255) * hp_factor / 45)); - } - } - else - { - if((NormalSTA-255)/2 > 0) - Post255 = (NormalSTA-255)/2; + new_base_hp = (5 + (80 * hp_factor / 8) + ((GetLevel() - 80) * hp_factor / 10) + ((NormalSTA - SoDPost255) * hp_factor / 90) + ((NormalSTA - SoDPost255) * hp_factor / 45)); + } else { + if(((NormalSTA - 255) / 2) > 0) + Post255 = ((NormalSTA - 255) / 2); else Post255 = 0; - new_base_hp = (5)+(GetLevel()*lm/10) + (((NormalSTA-Post255)*GetLevel()*lm/3000)) + ((Post255*1)*lm/6000); + new_base_hp = (5) + (GetLevel() * lm / 10) + (((NormalSTA - Post255) * GetLevel() * lm / 3000)) + ((Post255 * 1) * lm / 6000); } this->base_hp = new_base_hp; - return new_base_hp; } @@ -1683,18 +1518,16 @@ bool Bot::IsValidName() { std::string TempBotName = std::string(this->GetCleanName()); for(int iCounter = 0; iCounter < TempBotName.length(); iCounter++) { - if(isalpha(TempBotName[iCounter]) || TempBotName[iCounter] == '_') { + if(isalpha(TempBotName[iCounter]) || TempBotName[iCounter] == '_') Result = true; - } } return Result; } bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { - if (botName == "" || strlen(botName) > 15 || !database.CheckNameFilter(botName) || !database.CheckUsedName(botName)) { - return false; //Check if Botname is Empty / Check if Botname larger than 15 char / Valid to Player standards / Not used by a player! - } + if (botName == "" || strlen(botName) > 15 || !database.CheckNameFilter(botName) || !database.CheckUsedName(botName)) + return false; std::string query = StringFormat("SELECT id FROM vwBotCharacterMobs WHERE name LIKE '%s'", botName); auto results = database.QueryDatabase(query); @@ -1702,15 +1535,14 @@ bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { *errorMessage = std::string(results.ErrorMessage()); return false; } - if (results.RowCount()) { //Name already in use! + + if (results.RowCount()) return false; - } return true; //We made it with a valid name! } bool Bot::Save() { - if(this->GetBotID() == 0) { // New bot record std::string query = StringFormat("INSERT INTO bots (BotOwnerCharacterID, BotSpellsID, Name, LastName, " @@ -1736,6 +1568,7 @@ bool Bot::Save() { auto botOwner = GetBotOwner(); if (botOwner) botOwner->Message(13, results.ErrorMessage().c_str()); + return false; } @@ -1774,36 +1607,28 @@ bool Bot::Save() { auto botOwner = GetBotOwner(); if (botOwner) botOwner->Message(13, results.ErrorMessage().c_str()); + return false; } - SaveBuffs(); SavePet(); SaveStance(); SaveTimers(); - return true; } // Returns the current total play time for the bot uint32 Bot::GetTotalPlayTime() { uint32 Result = 0; - double TempTotalPlayTime = 0; - time_t currentTime = time(¤tTime); - TempTotalPlayTime = difftime(currentTime, _startTotalPlayTime); - TempTotalPlayTime += _lastTotalPlayTime; - Result = (uint32)TempTotalPlayTime; - return Result; } void Bot::SaveBuffs() { - // Remove any existing buff saves std::string query = StringFormat("DELETE FROM botbuffs WHERE BotId = %u", GetBotID()); auto results = database.QueryDatabase(query); @@ -1820,7 +1645,7 @@ void Bot::SaveBuffs() { "CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, " "caston_x, Persistent, caston_y, caston_z, ExtraDIChance) " "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, " - "%i, %i, %i);", + "%i, %i, %i)", GetBotID(), buffs[buffIndex].spellid, buffs[buffIndex].casterlevel, spells[buffs[buffIndex].spellid].buffdurationformula, buffs[buffIndex].ticsremaining, @@ -1835,24 +1660,16 @@ void Bot::SaveBuffs() { auto results = database.QueryDatabase(query); if(!results.Success()) return; - } - } void Bot::LoadBuffs() { - - std::string query = StringFormat("SELECT SpellId, CasterLevel, DurationFormula, TicsRemaining, " - "PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, " - "HitCount, MeleeRune, MagicRune, dot_rune, caston_x, Persistent, " - "caston_y, caston_z, ExtraDIChance FROM botbuffs WHERE BotId = %u", - GetBotID()); + std::string query = StringFormat("SELECT SpellId, CasterLevel, DurationFormula, TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, caston_x, Persistent, caston_y, caston_z, ExtraDIChance FROM botbuffs WHERE BotId = %u", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success()) return; int buffCount = 0; - for (auto row = results.begin(); row != results.end(); ++row) { if(buffCount == BUFF_COUNT) break; @@ -1860,7 +1677,6 @@ void Bot::LoadBuffs() { buffs[buffCount].spellid = atoi(row[0]); buffs[buffCount].casterlevel = atoi(row[1]); buffs[buffCount].ticsremaining = atoi(row[3]); - if(CalculatePoisonCounters(buffs[buffCount].spellid) > 0) buffs[buffCount].counters = atoi(row[4]); else if(CalculateDiseaseCounters(buffs[buffCount].spellid) > 0) @@ -1876,49 +1692,35 @@ void Bot::LoadBuffs() { buffs[buffCount].dot_rune = atoi(row[11]); buffs[buffCount].caston_x = atoi(row[12]); buffs[buffCount].casterid = 0; - buffs[buffCount].persistant_buff = atoi(row[13])? true: false; - buffs[buffCount].caston_y = atoi(row[14]); buffs[buffCount].caston_z = atoi(row[15]); buffs[buffCount].ExtraDIChance = atoi(row[16]); - buffCount++; } - query = StringFormat("DELETE FROM botbuffs WHERE BotId = %u", GetBotID()); results = database.QueryDatabase(query); - } uint32 Bot::GetPetSaveId() { - - std::string query = StringFormat("SELECT BotPetsId FROM botpets WHERE BotId = %u;", GetBotID()); + std::string query = StringFormat("SELECT BotPetsId FROM botpets WHERE BotId = %u", GetBotID()); auto results = database.QueryDatabase(query); - if(!results.Success()) + if(!results.Success() || results.RowCount() == 0) return 0; - if (results.RowCount() == 0) - return 0; - auto row = results.begin(); - return atoi(row[0]); } void Bot::LoadPet() { uint32 PetSaveId = GetPetSaveId(); - if(PetSaveId > 0 && !GetPet() && PetSaveId <= SPDAT_RECORDS) { std::string petName; uint32 petMana = 0; uint32 petHitPoints = 0; uint32 botPetId = 0; - LoadPetStats(&petName, &petMana, &petHitPoints, &botPetId, PetSaveId); - MakePet(botPetId, spells[botPetId].teleport_zone, petName.c_str()); - if(GetPet() && GetPet()->IsNPC()) { NPC *pet = GetPet()->CastToNPC(); SpellBuff_Struct petBuffs[BUFF_COUNT]; @@ -1933,7 +1735,6 @@ void Bot::LoadPet() { pet->SetHP(petHitPoints); pet->SetMana(petMana); } - DeletePetStats(PetSaveId); } } @@ -1942,18 +1743,12 @@ void Bot::LoadPetStats(std::string* petName, uint32* petMana, uint32* petHitPoin if(botPetSaveId == 0) return; - std::string query = StringFormat("SELECT PetId, Name, Mana, HitPoints " - "FROM botpets WHERE BotPetsId = %u;", - botPetSaveId); + std::string query = StringFormat("SELECT PetId, Name, Mana, HitPoints FROM botpets WHERE BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - if(!results.Success()) - return; - - if (results.RowCount() == 0) + if(!results.Success() || results.RowCount() == 0) return; auto row = results.begin(); - *botPetId = atoi(row[0]); *petName = std::string(row[1]); *petMana = atoi(row[2]); @@ -1964,15 +1759,12 @@ void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { if(!petBuffs || botPetSaveId == 0) return; - std::string query = StringFormat("SELECT SpellId, CasterLevel, Duration " - "FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("SELECT SpellId, CasterLevel, Duration FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); auto results = database.QueryDatabase(query); if(!results.Success()) return; - int buffIndex = 0; - for (auto row = results.begin();row != results.end(); ++row) { if(buffIndex == BUFF_COUNT) break; @@ -1980,39 +1772,31 @@ void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { petBuffs[buffIndex].spellid = atoi(row[0]); petBuffs[buffIndex].level = atoi(row[1]); petBuffs[buffIndex].duration = atoi(row[2]); - buffIndex++; } - query = StringFormat("DELETE FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); results = database.QueryDatabase(query); - } void Bot::LoadPetItems(uint32* petItems, uint32 botPetSaveId) { if(!petItems || botPetSaveId == 0) return; - std::string query = StringFormat("SELECT ItemId FROM botpetinventory " - "WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("SELECT ItemId FROM botpetinventory WHERE BotPetsId = %u;", botPetSaveId); auto results = database.QueryDatabase(query); if(!results.Success()) return; int itemIndex = 0; - for(auto row = results.begin(); row != results.end(); ++row) { if(itemIndex == EmuConstants::EQUIPMENT_SIZE) break; petItems[itemIndex] = atoi(row[0]); - itemIndex++; } - - query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u;", botPetSaveId); + query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u", botPetSaveId); results = database.QueryDatabase(query); - } void Bot::SavePet() { @@ -2024,40 +1808,28 @@ void Bot::SavePet() { char* tempPetName = new char[64]; SpellBuff_Struct petBuffs[BUFF_COUNT]; uint32 petItems[EmuConstants::EQUIPMENT_SIZE]; - pet->GetPetState(petBuffs, petItems, tempPetName); - uint32 existingBotPetSaveId = GetPetSaveId(); - if(existingBotPetSaveId > 0) { // Remove any existing pet buffs DeletePetBuffs(existingBotPetSaveId); - // Remove any existing pet items DeletePetItems(existingBotPetSaveId); } - // Save pet stats and get a new bot pet save id uint32 botPetSaveId = SavePetStats(std::string(tempPetName), petMana, petHitPoints, botPetId); - // Save pet buffs SavePetBuffs(petBuffs, botPetSaveId); - // Save pet items SavePetItems(petItems, botPetSaveId); - if(tempPetName) safe_delete_array(tempPetName); } } uint32 Bot::SavePetStats(std::string petName, uint32 petMana, uint32 petHitPoints, uint32 botPetId) { - - std::string query = StringFormat("REPLACE INTO botpets SET PetId = %u, BotId = %u, Name = '%s', " - "Mana = %u, HitPoints = %u;", botPetId, GetBotID(), petName.c_str(), - petMana, petHitPoints); + std::string query = StringFormat("REPLACE INTO botpets SET PetId = %u, BotId = %u, Name = '%s', Mana = %u, HitPoints = %u", botPetId, GetBotID(), petName.c_str(), petMana, petHitPoints); auto results = database.QueryDatabase(query); - return 0; } @@ -2066,21 +1838,14 @@ void Bot::SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { return; int buffIndex = 0; - while(buffIndex < BUFF_COUNT) { if(petBuffs[buffIndex].spellid > 0 && petBuffs[buffIndex].spellid != SPELL_UNKNOWN) { - std::string query = StringFormat("INSERT INTO botpetbuffs " - "(BotPetsId, SpellId, CasterLevel, Duration) " - "VALUES(%u, %u, %u, %u);", - botPetSaveId, petBuffs[buffIndex].spellid, - petBuffs[buffIndex].level, petBuffs[buffIndex].duration); + std::string query = StringFormat("INSERT INTO botpetbuffs (BotPetsId, SpellId, CasterLevel, Duration) VALUES(%u, %u, %u, %u)", botPetSaveId, petBuffs[buffIndex].spellid, petBuffs[buffIndex].level, petBuffs[buffIndex].duration); auto results = database.QueryDatabase(query); if(!results.Success()) break; - } - buffIndex++; } @@ -2094,55 +1859,46 @@ void Bot::SavePetItems(uint32* petItems, uint32 botPetSaveId) { if(petItems[itemIndex] == 0) continue; - std::string query = StringFormat("INSERT INTO botpetinventory " - "(BotPetsId, ItemId) VALUES(%u, %u);", - botPetSaveId, petItems[itemIndex]); + std::string query = StringFormat("INSERT INTO botpetinventory (BotPetsId, ItemId) VALUES(%u, %u)", botPetSaveId, petItems[itemIndex]); auto results = database.QueryDatabase(query); if(!results.Success()) break; } - } void Bot::DeletePetBuffs(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE FROM botpetbuffs WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("DELETE FROM botpetbuffs WHERE BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - } void Bot::DeletePetItems(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("DELETE FROM botpetinventory WHERE BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - } void Bot::DeletePetStats(uint32 botPetSaveId) { if(botPetSaveId == 0) return; - std::string query = StringFormat("DELETE from botpets where BotPetsId = %u;", botPetSaveId); + std::string query = StringFormat("DELETE from botpets where BotPetsId = %u", botPetSaveId); auto results = database.QueryDatabase(query); - } void Bot::LoadStance() { - - std::string query = StringFormat("SELECT StanceID FROM botstances WHERE BotID = %u;", GetBotID()); + std::string query = StringFormat("SELECT StanceID FROM botstances WHERE BotID = %u", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success() || results.RowCount() == 0) { Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadStance()"); SetDefaultBotStance(); return; } - auto row = results.begin(); - SetBotStance((BotStanceType)atoi(row[0])); } @@ -2150,22 +1906,19 @@ void Bot::SaveStance() { if(_baseBotStance == _botStance) return; - std::string query = StringFormat("REPLACE INTO botstances (BotID, StanceId) " - "VALUES(%u, %u);", GetBotID(), GetBotStance()); + std::string query = StringFormat("REPLACE INTO botstances (BotID, StanceId) VALUES(%u, %u)", GetBotID(), GetBotStance()); auto results = database.QueryDatabase(query); if(!results.Success()) Log.Out(Logs::General, Logs::Error, "Error in Bot::SaveStance()"); - } void Bot::LoadTimers() { - std::string query = StringFormat("SELECT IfNull(bt.TimerID, 0) As TimerID, IfNull(bt.Value, 0) As Value, " "IfNull(MAX(sn.recast_time), 0) AS MaxTimer FROM bottimers bt, spells_new sn " "WHERE bt.BotID = %u AND sn.EndurTimerIndex = " "(SELECT case WHEN TimerID > %i THEN TimerID - %i ELSE TimerID END AS TimerID " "FROM bottimers WHERE TimerID = bt.TimerID AND BotID = bt.BotID ) " - "AND sn.classes%i <= %i;", + "AND sn.classes%i <= %i", GetBotID(), DisciplineReuseStart-1, DisciplineReuseStart-1, GetClass(), GetLevel()); auto results = database.QueryDatabase(query); if(!results.Success()) { @@ -2176,12 +1929,10 @@ void Bot::LoadTimers() { int timerID = 0; uint32 value = 0; uint32 maxValue = 0; - for (auto row = results.begin(); row != results.end(); ++row) { timerID = atoi(row[0]) - 1; value = atoi(row[1]); maxValue = atoi(row[2]); - if(timerID >= 0 && timerID < MaxTimer && value < (Timer::GetCurrentTime() + maxValue)) timers[timerID] = value; } @@ -2190,8 +1941,7 @@ void Bot::LoadTimers() { void Bot::SaveTimers() { bool hadError = false; - - std::string query = StringFormat("DELETE FROM bottimers WHERE BotID = %u;", GetBotID()); + std::string query = StringFormat("DELETE FROM bottimers WHERE BotID = %u", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success()) hadError = true; @@ -2200,10 +1950,8 @@ void Bot::SaveTimers() { if(timers[timerIndex] <= Timer::GetCurrentTime()) continue; - query = StringFormat("REPLACE INTO bottimers (BotID, TimerID, Value) VALUES(%u, %u, %u);", - GetBotID(), timerIndex+1, timers[timerIndex]); + query = StringFormat("REPLACE INTO bottimers (BotID, TimerID, Value) VALUES(%u, %u, %u)", GetBotID(), timerIndex + 1, timers[timerIndex]); results = database.QueryDatabase(query); - if(!results.Success()) hadError = true; } @@ -2213,16 +1961,14 @@ void Bot::SaveTimers() { } -bool Bot::Process() -{ +bool Bot::Process() { if(IsStunned() && stunned_timer.Check()) Mob::UnStun(); if(!GetBotOwner()) return false; - if (GetDepop()) - { + if (GetDepop()) { _botOwner = 0; _botOwnerCharacterID = 0; _previousTarget = 0; @@ -2231,25 +1977,18 @@ bool Bot::Process() SpellProcess(); - if(tic_timer.Check()) - { + if(tic_timer.Check()) { //6 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting - if(!IsMoving() && !IsEngaged()) - { + if(!IsMoving() && !IsEngaged()) { SendPosition(); - if(IsSitting()) - { + if(IsSitting()) { if(!rest_timer.Enabled()) - { rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } } } BuffProcess(); - CalcRestState(); - if(curfp) ProcessFlee(); @@ -2266,7 +2005,6 @@ bool Bot::Process() if (sendhpupdate_timer.Check(false)) { SendHPUpdate(); - if(HasPet()) GetPet()->SendHPUpdate(); } @@ -2277,24 +2015,14 @@ bool Bot::Process() if (IsStunned() || IsMezzed()) return true; - //Handle assists... - /*if(assist_timer.Check() && !Charmed() && GetTarget() != nullptr) { - entity_list.AIYellForHelp(this, GetTarget()); - }*/ - // Bot AI AI_Process(); - return true; } -void Bot::SpellProcess() -{ - // check the rapid recast prevention timer - if(spellend_timer.Check(false)) - { +void Bot::SpellProcess() { + if(spellend_timer.Check(false)) { NPC::SpellProcess(); - if(GetClass() == BARD) { if (casting_spell_id != 0) casting_spell_id = 0; @@ -2304,34 +2032,24 @@ void Bot::SpellProcess() void Bot::BotMeditate(bool isSitting) { if(isSitting) { - // If the bot is a caster has less than 99% mana while its not engaged, he needs to sit to meditate - if(GetManaRatio() < 99.0f || GetHPRatio() < 99.0f) - { + if(GetManaRatio() < 99.0f || GetHPRatio() < 99.0f) { if (!IsEngaged() && !IsSitting()) Sit(); - } - else - { + } else { if(IsSitting()) Stand(); } - } - else - { + } else { if(IsSitting()) Stand(); } - if(IsSitting()) - { + + if(IsSitting()) { if(!rest_timer.Enabled()) - { rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000); - } } else - { rest_timer.Disable(); - } } void Bot::BotRangedAttack(Mob* other) { @@ -2357,21 +2075,11 @@ void Bot::BotRangedAttack(Mob* other) { return; Log.Out(Logs::Detail, Logs::Combat, "Shooting %s with bow %s (%d) and arrow %s (%d)", other->GetCleanName(), RangeWeapon->Name, RangeWeapon->ID, Ammo->Name, Ammo->ID); - - if(!IsAttackAllowed(other) || - IsCasting() || - DivineAura() || - IsStunned() || - IsMezzed() || - (GetAppearance() == eaDead)) - { + if(!IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) return; - } SendItemAnimation(other, Ammo, SkillArchery); - DoArcheryAttackDmg(GetTarget(), rangedItem, ammoItem); - //break invis when you attack if(invisible) { Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility due to melee attack."); @@ -2379,13 +2087,15 @@ void Bot::BotRangedAttack(Mob* other) { BuffFadeByEffect(SE_Invisibility2); invisible = false; } + if(invisible_undead) { Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. undead due to melee attack."); BuffFadeByEffect(SE_InvisVsUndead); BuffFadeByEffect(SE_InvisVsUndead2); invisible_undead = false; } - if(invisible_animals){ + + if(invisible_animals) { Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. animals due to melee attack."); BuffFadeByEffect(SE_InvisVsAnimals); invisible_animals = false; @@ -2408,26 +2118,21 @@ void Bot::BotRangedAttack(Mob* other) { } bool Bot::CheckBotDoubleAttack(bool tripleAttack) { - //Check for bonuses that give you a double attack chance regardless of skill (ie Bestial Frenzy/Harmonious Attack AA) - uint32 bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack; - + uint32 bonusGiveDA = (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack); // If you don't have the double attack skill, return if(!GetSkill(SkillDoubleAttack) && !(GetClass() == BARD || GetClass() == BEASTLORD)) return false; // You start with no chance of double attacking float chance = 0.0f; - uint16 skill = GetSkill(SkillDoubleAttack); - - int32 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; - + int32 bonusDA = (aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance); //Use skill calculations otherwise, if you only have AA applied GiveDoubleAttack chance then use that value as the base. if (skill) - chance = (float(skill+GetLevel()) * (float(100.0f+bonusDA+bonusGiveDA) /100.0f)) /500.0f; + chance = ((float(skill + GetLevel()) * (float(100.0f + bonusDA + bonusGiveDA) / 100.0f)) / 500.0f); else - chance = (float(bonusGiveDA) * (float(100.0f+bonusDA)/100.0f) ) /100.0f; + chance = ((float(bonusGiveDA) * (float(100.0f + bonusDA) / 100.0f)) / 100.0f); //Live now uses a static Triple Attack skill (lv 46 = 2% lv 60 = 20%) - We do not have this skill on EMU ATM. //A reasonable forumla would then be TA = 20% * chance @@ -2435,9 +2140,9 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { //Kayen: Need to decide if we can implement triple attack skill before working in over the cap effect. if(tripleAttack) { // Only some Double Attack classes get Triple Attack [This is already checked in client_processes.cpp] - int32 triple_bonus = spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; + int32 triple_bonus = (spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance); chance *= 0.2f; //Baseline chance is 20% of your double attack chance. - chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers. + chance *= (float(100.0f + triple_bonus) / 100.0f); //Apply modifiers. } if((zone->random.Real(0, 1) < chance)) @@ -2446,44 +2151,37 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { return false; } -void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) -{ +void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) { if (!CanDoSpecialAttack(other)) return; //For spells using skill value 98 (feral swipe ect) server sets this to 67 automatically. - //Kayen: This is unlikely to be completely accurate but use OFFENSE skill value for these effects. if (skillinuse == SkillBegging) skillinuse = SkillOffense; int damage = 0; uint32 hate = 0; int Hand = MainPrimary; - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; + if (hate == 0 && weapon_damage > 1) + hate = weapon_damage; - if(weapon_damage > 0){ - - if(GetClass() == BERSERKER){ - int bonus = 3 + GetLevel()/10; - weapon_damage = weapon_damage * (100+bonus) / 100; + if(weapon_damage > 0) { + if(GetClass() == BERSERKER) { + int bonus = (3 + GetLevel( )/ 10); + weapon_damage = (weapon_damage * (100 + bonus) / 100); } int32 min_hit = 1; - int32 max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; - - if(GetLevel() >= 28 && IsWarriorClass() ) - { - int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr ); - + int32 max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); + if(GetLevel() >= 28 && IsWarriorClass()) { + int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; } ApplySpecialAttackMod(skillinuse, max_hit, min_hit); - - min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; - + min_hit += (min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100); if(max_hit < min_hit) max_hit = min_hit; @@ -2492,16 +2190,16 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { + if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) damage = 0; - } else { + else { other->AvoidDamage(this, damage, CanRiposte); other->MeleeMitigation(this, damage, min_hit); if(damage > 0) { damage += damage*focus/100; ApplyMeleeDamageBonus(skillinuse, damage); damage += other->GetFcDamageAmtIncoming(this, 0, true, skillinuse); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); + damage += ((itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse)); TryCriticalHit(other, skillinuse, damage, nullptr); } } @@ -2512,7 +2210,6 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes return; } } - else damage = -5; @@ -2521,11 +2218,12 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); + if(botweapon) { - if(botweapon->ItemType == ItemTypeShield) { + if(botweapon->ItemType == ItemTypeShield) hate += botweapon->AC; - } - hate = hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100; + + hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); } } @@ -2538,7 +2236,6 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes } other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - if (HasDied()) return; @@ -2558,27 +2255,22 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes } void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) { - int item_slot = -1; //1: Apply bonus from AC (BOOT/SHIELD/HANDS) est. 40AC=6dmg - - switch (skill){ - + switch (skill) { case SkillFlyingKick: case SkillRoundKick: case SkillKick: item_slot = MainFeet; - break; - + break; case SkillBash: item_slot = MainSecondary; - break; - + break; case SkillDragonPunch: case SkillEagleStrike: case SkillTigerClaw: item_slot = MainHands; - break; + break; } if (item_slot >= EmuConstants::EQUIPMENT_BEGIN){ @@ -2586,13 +2278,13 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); + if(botweapon) dmg += botweapon->AC * (RuleI(Combat, SpecialAttackACBonus))/100; } } -bool Bot::CanDoSpecialAttack(Mob *other) -{ +bool Bot::CanDoSpecialAttack(Mob *other) { //Make sure everything is valid before doing any attacks. if (!other) { SetTarget(nullptr); @@ -2602,12 +2294,7 @@ bool Bot::CanDoSpecialAttack(Mob *other) if(!GetTarget()) SetTarget(other); - if ((other == nullptr || ((GetAppearance() == eaDead) || (other->IsClient() && other->CastToClient()->IsDead())) - || HasDied() || (!IsAttackAllowed(other)))) { - return false; - } - - if(other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)) + if ((other == nullptr || ((GetAppearance() == eaDead) || (other->IsClient() && other->CastToClient()->IsDead())) || HasDied() || (!IsAttackAllowed(other))) || other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)) return false; return true; @@ -2624,7 +2311,6 @@ void Bot::SetTarget(Mob* mob) { float Bot::GetMaxMeleeRangeToTarget(Mob* target) { float result = 0; - if(target) { float size_mod = GetSize(); float other_size_mod = target->GetSize(); @@ -2639,22 +2325,19 @@ float Bot::GetMaxMeleeRangeToTarget(Mob* target) { else if (other_size_mod < 6.0) other_size_mod = 8.0f; - if (other_size_mod > size_mod) { + if (other_size_mod > size_mod) size_mod = other_size_mod; - } - - // this could still use some work, but for now it's an improvement.... if (size_mod > 29) size_mod *= size_mod; else if (size_mod > 19) - size_mod *= size_mod * 2; + size_mod *= (size_mod * 2); else - size_mod *= size_mod * 4; + size_mod *= (size_mod * 4); // prevention of ridiculously sized hit boxes if (size_mod > 10000) - size_mod = size_mod / 7; + size_mod = (size_mod / 7); result = size_mod; } @@ -2669,21 +2352,14 @@ void Bot::AI_Process() { uint8 botClass = GetClass(); uint8 botLevel = GetLevel(); - if(IsCasting() && (botClass != BARD)) return; // A bot wont start its AI if not grouped - if(!GetBotOwner() || !IsGrouped()) { - return; - } - - if(GetAppearance() == eaDead) + if(!GetBotOwner() || !IsGrouped() || GetAppearance() == eaDead) return; Mob* BotOwner = GetBotOwner(); - - // The bots need an owner if(!BotOwner) return; @@ -2705,9 +2381,8 @@ void Bot::AI_Process() { SetHasHealedThisCycle(true); NotifyNextHealRotationMember(); } - else { + else NotifyNextHealRotationMember(true); - } } if(GetHasBeenSummoned()) { @@ -2716,11 +2391,10 @@ void Bot::AI_Process() { if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast(m_Position), m_PreSummonLocation) < 10)) { if(GetTarget()) FaceTarget(GetTarget()); + SetHasBeenSummoned(false); - } - else if(!IsRooted()) { - if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) - { + } else if(!IsRooted()) { + if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { Log.Out(Logs::Detail, Logs::AI, "Returning to location prior to being summoned."); CalculateNewPosition2(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetRunspeed()); SetHeading(CalculateHeadingToTarget(m_PreSummonLocation.x, m_PreSummonLocation.y)); @@ -2733,35 +2407,29 @@ void Bot::AI_Process() { else SendPosition(); } - } - else { + } else { if(GetTarget()) FaceTarget(GetTarget()); + SetHasBeenSummoned(false); } - return; } if(!IsEngaged()) { if(GetFollowID()) { - if(BotOwner && BotOwner->GetTarget() && BotOwner->GetTarget()->IsNPC() && (BotOwner->GetTarget()->GetHateAmount(BotOwner) - || BotOwner->CastToClient()->AutoAttackEnabled()) && IsAttackAllowed(BotOwner->GetTarget())) { + if(BotOwner && BotOwner->GetTarget() && BotOwner->GetTarget()->IsNPC() && (BotOwner->GetTarget()->GetHateAmount(BotOwner) || BotOwner->CastToClient()->AutoAttackEnabled()) && IsAttackAllowed(BotOwner->GetTarget())) { AddToHateList(BotOwner->GetTarget(), 1); - if(HasPet()) GetPet()->AddToHateList(BotOwner->GetTarget(), 1); - } - else { + } else { Group* g = GetGroup(); - if(g) { for(int counter = 0; counter < g->GroupCount(); counter++) { if(g->members[counter]) { Mob* tar = g->members[counter]->GetTarget(); if(tar && tar->IsNPC() && tar->GetHateAmount(g->members[counter]) && IsAttackAllowed(g->members[counter]->GetTarget())) { AddToHateList(tar, 1); - if(HasPet()) GetPet()->AddToHateList(tar, 1); @@ -2774,9 +2442,7 @@ void Bot::AI_Process() { } } - if(IsEngaged()) - { - + if(IsEngaged()) { if(rest_timer.Enabled()) rest_timer.Disable(); @@ -2802,17 +2468,13 @@ void Bot::AI_Process() { // Else, it was causing the bot to aggro behind wall etc... causing massive trains. if(!CheckLosFN(GetTarget()) || GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) { WipeHateList(); - if(IsMoving()) { SetHeading(0); SetRunAnimSpeed(0); SetCurrentSpeed(GetRunspeed()); - - if(moved) { + if(moved) SetCurrentSpeed(0); - } } - return; } @@ -2820,15 +2482,11 @@ void Bot::AI_Process() { SendAddPlayerState(PlayerState::Aggressive); bool atCombatRange = false; - float meleeDistance = GetMaxMeleeRangeToTarget(GetTarget()); - - if(botClass == SHADOWKNIGHT || botClass == PALADIN || botClass == WARRIOR) { - meleeDistance = meleeDistance * .30; - } - else { + if(botClass == SHADOWKNIGHT || botClass == PALADIN || botClass == WARRIOR) + meleeDistance = (meleeDistance * .30); + else meleeDistance *= (float)zone->random.Real(.50, .85); - } bool atArcheryRange = IsArcheryRange(GetTarget()); @@ -2838,8 +2496,7 @@ void Bot::AI_Process() { if(atArcheryRange && !IsBotArcher()) { SetBotArcher(true); changeWeapons = true; - } - else if(!atArcheryRange && IsBotArcher()) { + } else if(!atArcheryRange && IsBotArcher()) { SetBotArcher(false); changeWeapons = true; } @@ -2858,16 +2515,13 @@ void Bot::AI_Process() { SetCurrentSpeed(0); } } - atCombatRange = true; - } - else if(IsBotCaster() && GetLevel() > 12) { + } else if(IsBotCaster() && GetLevel() > 12) { if(IsBotCasterCombatRange(GetTarget())) atCombatRange = true; } - else if(DistanceSquared(m_Position, GetTarget()->GetPosition()) <= meleeDistance) { + else if(DistanceSquared(m_Position, GetTarget()->GetPosition()) <= meleeDistance) atCombatRange = true; - } if(atCombatRange) { if(IsMoving()) { @@ -2885,7 +2539,6 @@ void Bot::AI_Process() { float newX = 0; float newY = 0; float newZ = 0; - if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); return; @@ -2896,7 +2549,6 @@ void Bot::AI_Process() { float newX = 0; float newY = 0; float newZ = 0; - if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) { CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); return; @@ -2911,35 +2563,24 @@ void Bot::AI_Process() { if(IsBotArcher() && ranged_timer.Check(false)) { if(GetTarget()->GetHPRatio() <= 99.0f) - // Mob::DoArcheryAttackDmg() takes care of Bot Range and Ammo procs BotRangedAttack(GetTarget()); } else if(!IsBotArcher() && (!(IsBotCaster() && GetLevel() > 12)) && GetTarget() && !IsStunned() && !IsMezzed() && (GetAppearance() != eaDead)) { // we can't fight if we don't have a target, are stun/mezzed or dead.. // Stop attacking if the target is enraged - if(IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged()) - return; - - if(GetBotStance() == BotStancePassive) + if((IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged()) || GetBotStance() == BotStancePassive) return; // First, special attack per class (kick, backstab etc..) DoClassAttacks(GetTarget()); - - //try main hand first if(attack_timer.Check()) { Attack(GetTarget(), MainPrimary); - ItemInst *wpn = GetBotItem(MainPrimary); TryWeaponProc(wpn, GetTarget(), MainPrimary); - bool tripleSuccess = false; - if(BotOwner && GetTarget() && CanThisClassDoubleAttack()) { - - if(BotOwner && CheckBotDoubleAttack()) { + if(BotOwner && CheckBotDoubleAttack()) Attack(GetTarget(), MainPrimary, true); - } if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { tripleSuccess = true; @@ -2947,37 +2588,27 @@ void Bot::AI_Process() { } //quad attack, does this belong here?? - if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) { + if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) Attack(GetTarget(), MainPrimary, true); - } } //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). - int32 flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; - - if (GetTarget() && flurrychance) - { - if(zone->random.Int(0, 100) < flurrychance) - { + int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance); + if (GetTarget() && flurrychance) { + if(zone->random.Int(0, 100) < flurrychance) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); Attack(GetTarget(), MainPrimary, false); Attack(GetTarget(), MainPrimary, false); } } - int32 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; - + int32 ExtraAttackChanceBonus = (spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance); if (GetTarget() && ExtraAttackChanceBonus) { ItemInst *wpn = GetBotItem(MainPrimary); - if(wpn){ - if(wpn->GetItem()->ItemType == ItemType2HSlash || - wpn->GetItem()->ItemType == ItemType2HBlunt || - wpn->GetItem()->ItemType == ItemType2HPiercing ) - { + if(wpn) { + if(wpn->GetItem()->ItemType == ItemType2HSlash || wpn->GetItem()->ItemType == ItemType2HBlunt || wpn->GetItem()->ItemType == ItemType2HPiercing) { if(zone->random.Int(0, 100) < ExtraAttackChanceBonus) - { Attack(GetTarget(), MainPrimary, false); - } } } } @@ -2988,6 +2619,7 @@ void Bot::AI_Process() { entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); this->berserk = true; } + if (berserk && this->GetHPRatio() > 30) { entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); this->berserk = false; @@ -3005,7 +2637,6 @@ void Bot::AI_Process() { int weapontype = 0; // No weapon type. bool bIsFist = true; - if(weapon) { weapontype = weapon->ItemType; bIsFist = false; @@ -3013,21 +2644,15 @@ void Bot::AI_Process() { if(bIsFist || ((weapontype != ItemType2HSlash) && (weapontype != ItemType2HPiercing) && (weapontype != ItemType2HBlunt))) { float DualWieldProbability = 0.0f; - - int32 Ambidexterity = aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; - DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f; // 78.0 max - int32 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; - DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - + int32 Ambidexterity = (aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity); + DualWieldProbability = ((GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f); // 78.0 max + int32 DWBonus = (spellbonuses.DualWieldChance + itembonuses.DualWieldChance); + DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); float random = zone->random.Real(0, 1); - if (random < DualWieldProbability){ // Max 78% of DW - Attack(GetTarget(), MainSecondary); // Single attack with offhand - ItemInst *wpn = GetBotItem(MainSecondary); TryWeaponProc(wpn, GetTarget(), MainSecondary); - if( CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) Attack(GetTarget(), MainSecondary); // Single attack with offhand @@ -3037,8 +2662,7 @@ void Bot::AI_Process() { } } } - } // end in combat range - else { + } else { if(GetTarget()->IsFeared() && !spellend_timer.Enabled()){ // This is a mob that is fleeing either because it has been feared or is low on hitpoints if(GetBotStance() != BotStancePassive) @@ -3063,17 +2687,13 @@ void Bot::AI_Process() { if(GetBotStance() == BotStancePassive) return; - if(AI_EngagedCastCheck()) { + if(AI_EngagedCastCheck()) BotMeditate(false); - } else if(GetArchetype() == ARCHETYPE_CASTER) BotMeditate(true); } - } // end IsEngaged() - else { - // Not engaged in combat + } else { SetTarget(0); - if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); @@ -3082,20 +2702,16 @@ void Bot::AI_Process() { if(!AI_IdleCastCheck() && !IsCasting()) BotMeditate(true); } - else { + else BotMeditate(true); - } - } if(AImovement_timer->Check()) { if(GetFollowID()) { Mob* follow = entity_list.GetMob(GetFollowID()); - if(follow) { float dist = DistanceSquared(m_Position, follow->GetPosition()); int speed = follow->GetRunspeed(); - if(dist < GetFollowDistance() + 1000) speed = follow->GetWalkspeed(); @@ -3104,11 +2720,8 @@ void Bot::AI_Process() { if(rest_timer.Enabled()) rest_timer.Disable(); return; - } - else - { - if(moved) - { + } else { + if(moved) { moved = false; SetCurrentSpeed(0); } @@ -3121,33 +2734,20 @@ void Bot::AI_Process() { // AI Processing for a Bot object's pet void Bot::PetAIProcess() { - if( !HasPet() || !GetPet() || !GetPet()->IsNPC()) return; Mob* BotOwner = this->GetBotOwner(); NPC* botPet = this->GetPet()->CastToNPC(); - if(!botPet->GetOwner() || !botPet->GetID() || !botPet->GetOwnerID()) { Kill(); return; } - if (!botPet->IsAIControlled()) - return; - - if(botPet->GetAttackTimer().Check(false)) - return; - - if (botPet->IsCasting()) - return; - - // Return if the owner of the bot pet isnt a bot. - if (!botPet->GetOwner()->IsBot()) + if (!botPet->IsAIControlled() || botPet->GetAttackTimer().Check(false) || botPet->IsCasting() || !botPet->GetOwner()->IsBot()) return; if (IsEngaged()) { - if (botPet->IsRooted()) botPet->SetTarget(hate_list.GetClosestEntOnHateList(botPet)); else @@ -3159,40 +2759,22 @@ void Bot::PetAIProcess() { if(!botPet->CheckLosFN(botPet->GetTarget()) || botPet->GetTarget()->IsMezzed() || !botPet->IsAttackAllowed(GetTarget())) { botPet->WipeHateList(); botPet->SetTarget(botPet->GetOwner()); - return; } botPet->FaceTarget(botPet->GetTarget()); - - // Lets see if we can let the main tank build a little aggro - /*if(GetBotRaidID()) { - BotRaids *br = entity_list.GetBotRaidByMob(GetOwner()); - if(br) { - if(br->GetBotMainTank() && (br->GetBotMainTank() != this)) { - if(br->GetBotMainTarget() && (br->GetBotMainTarget()->GetHateAmount(br->GetBotMainTank()) < 5000)) { - if(GetTarget() == br->GetBotMainTarget()) { - return; - } - } - } - } - }*/ - bool is_combat_range = botPet->CombatRange(botPet->GetTarget()); - // Ok, we're engaged, each class type has a special AI // Only melee class will go to melee. Casters and healers will stay behind, following the leader by default. // I should probably make the casters staying in place so they can cast.. // Ok, we 're a melee or any other class lvl<12. Yes, because after it becomes hard to go in melee for casters.. even for bots.. - if( is_combat_range ) { + if(is_combat_range) { botPet->GetAIMovementTimer()->Check(); - if(botPet->IsMoving()) { botPet->SetHeading(botPet->GetTarget()->GetHeading()); if(moved) { - moved=false; + moved = false; botPet->SetRunAnimSpeed(0); } } @@ -3202,10 +2784,8 @@ void Bot::PetAIProcess() { float newY = 0; float newZ = 0; bool petHasAggro = false; - - if(botPet->GetTarget() && botPet->GetTarget()->GetHateTop() && botPet->GetTarget()->GetHateTop() == botPet) { + if(botPet->GetTarget() && botPet->GetTarget()->GetHateTop() && botPet->GetTarget()->GetHateTop() == botPet) petHasAggro = true; - } if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { // Move the rogue to behind the mob @@ -3225,7 +2805,6 @@ void Bot::PetAIProcess() { // Let's try to adjust our melee range so we don't appear to be bunched up bool isBehindMob = false; bool moveBehindMob = false; - if(botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) isBehindMob = true; @@ -3248,14 +2827,11 @@ void Bot::PetAIProcess() { return; if(botPet->Attack(GetTarget(), MainPrimary)) // try the main hand - if (botPet->GetTarget()) // Do we still have a target? - { + if (botPet->GetTarget()) { // We're a pet so we re able to dual attack int32 RandRoll = zone->random.Int(0, 99); - if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) - { - if(botPet->Attack(botPet->GetTarget(), MainPrimary)) - {} + if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { + if(botPet->Attack(botPet->GetTarget(), MainPrimary)) {} } } @@ -3268,19 +2844,18 @@ void Bot::PetAIProcess() { aa_skill += botPet->GetOwner()->GetAA(aaQuickeningofDeath); // Beastlord AA aa_skill += botPet->GetOwner()->GetAA(aaWardersAlacrity); - - if(aa_skill >= 1) { - aa_chance += (aa_skill > 5 ? 5 : aa_skill) * 4; - } - if(aa_skill >= 6) { - aa_chance += (aa_skill-5 > 3 ? 3 : aa_skill-5) * 7; - } - if(aa_skill >= 9) { - aa_chance += (aa_skill-8 > 3 ? 3 : aa_skill-8) * 3; - } - if(aa_skill >= 12) { - aa_chance += (aa_skill - 11) * 1; - } + if(aa_skill >= 1) + aa_chance += ((aa_skill > 5 ? 5 : aa_skill) * 4); + + if(aa_skill >= 6) + aa_chance += ((aa_skill - 5 > 3 ? 3 : aa_skill - 5) * 7); + + if(aa_skill >= 9) + aa_chance += ((aa_skill - 8 > 3 ? 3 : aa_skill - 8) * 3); + + if(aa_skill >= 12) + aa_chance += ((aa_skill - 11) * 1); + //aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3; @@ -3289,21 +2864,16 @@ void Bot::PetAIProcess() { } // Ok now, let's check pet's offhand. - if (botPet->GetAttackDWTimer().Check() && botPet->GetOwnerID() && botPet->GetOwner() && ((botPet->GetOwner()->GetClass() == MAGICIAN) || (botPet->GetOwner()->GetClass() == NECROMANCER) || (botPet->GetOwner()->GetClass() == SHADOWKNIGHT) || (botPet->GetOwner()->GetClass() == BEASTLORD))) - { - if(botPet->GetOwner()->GetLevel() >= 24) - { - float DualWieldProbability = (botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f; + if (botPet->GetAttackDWTimer().Check() && botPet->GetOwnerID() && botPet->GetOwner() && ((botPet->GetOwner()->GetClass() == MAGICIAN) || (botPet->GetOwner()->GetClass() == NECROMANCER) || (botPet->GetOwner()->GetClass() == SHADOWKNIGHT) || (botPet->GetOwner()->GetClass() == BEASTLORD))) { + if(botPet->GetOwner()->GetLevel() >= 24) { + float DualWieldProbability = ((botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f); DualWieldProbability -= zone->random.Real(0, 1); - if(DualWieldProbability < 0){ + if(DualWieldProbability < 0) { botPet->Attack(botPet->GetTarget(), MainSecondary); - if (botPet->CanThisClassDoubleAttack()) - { + if (botPet->CanThisClassDoubleAttack()) { int32 RandRoll = zone->random.Int(0, 99); if (RandRoll < (botPet->GetLevel() + 20)) - { botPet->Attack(botPet->GetTarget(), MainSecondary); - } } } } @@ -3317,25 +2887,20 @@ void Bot::PetAIProcess() { // See if the pet can cast any spell botPet->AI_EngagedCastCheck(); } - }// end of the combat in range - else{ + } else { // Now, if we cannot reach our target - if (!botPet->HateSummon()) - { - if(botPet->GetTarget() && botPet->AI_PursueCastCheck()) - {} - else if (botPet->GetTarget() && botPet->GetAIMovementTimer()->Check()) - { + if (!botPet->HateSummon()) { + if(botPet->GetTarget() && botPet->AI_PursueCastCheck()) {} + else if (botPet->GetTarget() && botPet->GetAIMovementTimer()->Check()) { botPet->SetRunAnimSpeed(0); if(!botPet->IsRooted()) { Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName()); botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetRunspeed()); return; - } - else { + } else { botPet->SetHeading(botPet->GetTarget()->GetHeading()); if(moved) { - moved=false; + moved = false; SetCurrentSpeed(0); botPet->SendPosition(); botPet->SetMoving(false); @@ -3344,39 +2909,33 @@ void Bot::PetAIProcess() { } } } - } - else{ - // Franck: EQoffline + } else { // Ok if we're not engaged, what's happening.. - if(botPet->GetTarget() != botPet->GetOwner()) { + if(botPet->GetTarget() != botPet->GetOwner()) botPet->SetTarget(botPet->GetOwner()); - } - if(!IsMoving()) { + if(!IsMoving()) botPet->AI_IdleCastCheck(); - } if(botPet->GetAIMovementTimer()->Check()) { switch(pStandingPetOrder) { - case SPO_Follow: - { - float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition()); - botPet->SetRunAnimSpeed(0); - if(dist > 184) { - botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed()); - return; - } - else { - botPet->SetHeading(botPet->GetTarget()->GetHeading()); - if(moved) { - moved=false; - SetCurrentSpeed(0); - botPet->SendPosition(); - botPet->SetMoving(false); - } + case SPO_Follow: { + float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition()); + botPet->SetRunAnimSpeed(0); + if(dist > 184) { + botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed()); + return; + } else { + botPet->SetHeading(botPet->GetTarget()->GetHeading()); + if(moved) { + moved = false; + SetCurrentSpeed(0); + botPet->SendPosition(); + botPet->SetMoving(false); } } break; + } case SPO_Sit: botPet->SetAppearance(eaSitting); break; @@ -3390,26 +2949,21 @@ void Bot::PetAIProcess() { void Bot::Depop() { WipeHateList(); - entity_list.RemoveFromHateLists(this); - if(HasGroup()) Bot::RemoveBotFromGroup(this, GetGroup()); - if(HasPet()) { + if(HasPet()) GetPet()->Depop(); - } _botOwner = 0; _botOwnerCharacterID = 0; _previousTarget = 0; - NPC::Depop(false); } bool Bot::DeleteBot(std::string* errorMessage) { bool hadError = false; - if(this->GetBotID() == 0) return false; @@ -3469,27 +3023,19 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { // Make the bot look at the bot owner FaceTarget(botCharacterOwner); - - // Level the bot to the same level as the bot owner - //this->SetLevel(botCharacterOwner->GetLevel()); - UpdateEquipmentLight(); UpdateActiveLight(); - entity_list.AddBot(this, true, true); - // Load pet LoadPet(); - this->SendPosition(); - // there is something askew with spawn struct appearance fields... // I re-enabled this until I can sort it out uint32 itemID = 0; uint8 materialFromSlot = 0xFF; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); - if(itemID != 0) { + if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); if(materialFromSlot != 0xFF) this->SendWearChange(materialFromSlot); @@ -3500,9 +3046,7 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { // Saves the specified item as an inventory record in the database for this bot. void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, std::string *errorMessage) { - uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (this->GetBotID() == 0 || slotID < EmuConstants::EQUIPMENT_BEGIN || itemID <= NO_ITEM) return; @@ -3527,13 +3071,10 @@ void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, s // Deletes the inventory record for the specified item from the database for this bot. void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) { - if(this->GetBotID() == 0) return; - std::string query = StringFormat("DELETE FROM botinventory " - "WHERE botid = %i AND slotid = %i", - this->GetBotID(), slotID); + std::string query = StringFormat("DELETE FROM botinventory WHERE botid = %i AND slotid = %i", this->GetBotID(), slotID); auto results = database.QueryDatabase(query); if(!results.Success()) *errorMessage = std::string(results.ErrorMessage()); @@ -3544,7 +3085,6 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) { // Retrieves all the inventory records from the database for this bot. void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { - if(this->GetBotID() == 0) return; @@ -3559,10 +3099,10 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { } for (auto row = results.begin(); row != results.end(); ++row) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - uint16 charges = atoi(row[2]); - uint32 color = atoul(row[3]); + int16 slot_id = atoi(row[0]); + uint32 item_id = atoi(row[1]); + uint16 charges = atoi(row[2]); + uint32 color = atoul(row[3]); uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoul(row[4]); aug[1] = (uint32)atoul(row[5]); @@ -3570,7 +3110,6 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { aug[3] = (uint32)atoul(row[7]); aug[4] = (uint32)atoul(row[8]); bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; - ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]); if (!inst) { Log.Out(Logs::General, Logs::Error, "Warning: botid %i has an invalid item_id %i in inventory slot %i", this->GetBotID(), item_id, slot_id); @@ -3579,13 +3118,13 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { int16 put_slot_id = INVALID_INDEX; - if (instnodrop || ((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) && inst->GetItem()->Attuneable)) + if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999) && inst->GetItem()->Attuneable)) inst->SetAttuned(true); if (color > 0) inst->SetColor(color); - if (charges==255) + if (charges == 255) inst->SetCharges(-1); else inst->SetCharges(charges); @@ -3598,7 +3137,6 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { // Save ptr to item in inventory if (put_slot_id == INVALID_INDEX) Log.Out(Logs::General, Logs::Error, "Warning: Invalid slot_id for item in inventory: botid=%i, item_id=%i, slot_id=%i",this->GetBotID(), item_id, slot_id); - } UpdateEquipmentLight(); @@ -3606,26 +3144,20 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { // Returns the inventory record for this bot from the database for the specified equipment slot. uint32 Bot::GetBotItemBySlot(uint32 slotID) { - if(this->GetBotID() == 0 || slotID < EmuConstants::EQUIPMENT_BEGIN) return 0; - std::string query = StringFormat("SELECT itemid FROM botinventory WHERE botid=%i AND slotid = %i", GetBotID(), slotID); + std::string query = StringFormat("SELECT itemid FROM botinventory WHERE botid = %i AND slotid = %i", GetBotID(), slotID); auto results = database.QueryDatabase(query); - if(!results.Success()) - return 0; - - if(results.RowCount() != 1) + if(!results.Success() || results.RowCount() != 1) return 0; auto row = results.begin(); - return atoi(row[0]); } // Returns the number of inventory records the bot has in the database. uint32 Bot::GetBotItemsCount(std::string *errorMessage) { - if(this->GetBotID() == 0) return 0; @@ -3645,50 +3177,35 @@ uint32 Bot::GetBotItemsCount(std::string *errorMessage) { bool Bot::MesmerizeTarget(Mob* target) { bool Result = false; - if(target) { int mezid = 0; int mezlevel = GetLevel(); - - if(mezlevel >= 69) { + if(mezlevel >= 69) mezid = 5520; - } - else if(mezlevel == 68) { + else if(mezlevel == 68) mezid = 8035; - } - else if(mezlevel == 67) { + else if(mezlevel == 67) mezid = 5503; - } - else if(mezlevel >= 64) { + else if(mezlevel >= 64) mezid = 3358; - } - else if(mezlevel == 63) { + else if(mezlevel == 63) mezid = 3354; - } - else if(mezlevel >= 61) { + else if(mezlevel >= 61) mezid = 3341; - } - else if(mezlevel == 60) { + else if(mezlevel == 60) mezid = 2120; - } - else if(mezlevel == 59) { + else if(mezlevel == 59) mezid = 1692; - } - else if(mezlevel >= 54) { + else if(mezlevel >= 54) mezid = 1691; - } - else if(mezlevel >= 47) { + else if(mezlevel >= 47) mezid = 190; - } - else if(mezlevel >= 30) { + else if(mezlevel >= 30) mezid = 188; - } - else if(mezlevel >= 13) { + else if(mezlevel >= 13) mezid = 187; - } - else if(mezlevel >= 2) { + else if(mezlevel >= 2) mezid = 292; - } if(mezid > 0) { uint32 DontRootMeBeforeTime = 0; CastSpell(mezid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); @@ -3701,16 +3218,13 @@ bool Bot::MesmerizeTarget(Mob* target) { } void Bot::SetLevel(uint8 in_level, bool command) { - if(in_level > 0) { + if(in_level > 0) Mob::SetLevel(in_level, command); - } } void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { - if(ns) - { + if(ns) { Mob::FillSpawnStruct(ns, ForWho); - ns->spawn.afk = 0; ns->spawn.lfg = 0; ns->spawn.anon = 0; @@ -3722,78 +3236,55 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.is_npc = 0; // 0=no, 1=yes ns->spawn.is_pet = 0; ns->spawn.guildrank = 0; - ns->spawn.showhelm = 1; + ns->spawn.showhelm = GetShowHelm(); ns->spawn.flymode = 0; ns->spawn.size = 0; ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse - UpdateActiveLight(); ns->spawn.light = m_Light.Type.Active; - - ns->spawn.helm = helmtexture; //0xFF; + ns->spawn.helm = (GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; - const Item_Struct* item = 0; const ItemInst* inst = 0; - uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); - - for (int i = 0; i < MaterialPrimary; i++) - { + for (int i = 0; i < MaterialPrimary; i++) { inst = GetBotItem(i); - if (inst) - { + if (inst) { item = inst->GetItem(); - if (item != 0) - { + if (item != 0) { ns->spawn.equipment[i].Material = item->Material; ns->spawn.equipment[i].EliteMaterial = item->EliteMaterial; ns->spawn.equipment[i].HeroForgeModel = item->HerosForgeModel; if (armor_tint[i]) - { ns->spawn.colors[i].Color = armor_tint[i]; - - } else - { ns->spawn.colors[i].Color = item->Color; - } - } - else - { + } else { if (armor_tint[i]) - { ns->spawn.colors[i].Color = armor_tint[i]; - } } } } inst = GetBotItem(MainPrimary); - if(inst) - { + if(inst) { item = inst->GetItem(); - if(item) - { + if(item) { if(strlen(item->IDFile) > 2) - { ns->spawn.equipment[MaterialPrimary].Material = atoi(&item->IDFile[2]); - } + ns->spawn.colors[MaterialPrimary].Color = GetEquipmentColor(MaterialPrimary); } } inst = GetBotItem(MainSecondary); - if(inst) - { + if(inst) { item = inst->GetItem(); - if(item) - { + if(item) { if(strlen(item->IDFile) > 2) - { ns->spawn.equipment[MaterialSecondary].Material = atoi(&item->IDFile[2]); - } + ns->spawn.colors[MaterialSecondary].Color = GetEquipmentColor(MaterialSecondary); } } @@ -3806,10 +3297,7 @@ uint32 Bot::GetBotIDByBotName(std::string botName) { std::string query = StringFormat("SELECT BotID FROM bots WHERE Name = '%s'", botName.c_str()); auto results = database.QueryDatabase(query); - if(!results.Success()) - return 0; - - if (results.RowCount() == 0) + if(!results.Success() || results.RowCount() == 0) return 0; auto row = results.begin(); @@ -3818,7 +3306,6 @@ uint32 Bot::GetBotIDByBotName(std::string botName) { Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { Bot* loadedBot = nullptr; - if(botID == 0) return nullptr; @@ -3839,9 +3326,7 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { return nullptr; auto row = results.begin(); - NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), - atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); - + NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7])); NPCType tempNPCStruct = FillNPCTypeStruct(atoi(row[1]), std::string(row[2]), std::string(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), atoi(row[7]), atof(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11]), atoi(row[12]), atoi(row[13]), atoi(row[14]), @@ -3852,21 +3337,16 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) { defaultNPCTypeStruct.STA, defaultNPCTypeStruct.DEX, defaultNPCTypeStruct.AGI, defaultNPCTypeStruct.INT, defaultNPCTypeStruct.WIS, defaultNPCTypeStruct.CHA, defaultNPCTypeStruct.ATK); - loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[38]), atoi(row[39]), tempNPCStruct); - return loadedBot; } std::list Bot::GetGroupedBotsByGroupId(uint32 groupId, std::string* errorMessage) { std::list groupedBots; - if(groupId == 0) return groupedBots; - std::string query = StringFormat("SELECT g.mobid AS BotID FROM vwGroups AS g " - "JOIN bots AS b ON g.mobid = b.BotId AND g.mobtype = 'B' " - "WHERE g.groupid = %u", groupId); + std::string query = StringFormat("SELECT g.mobid AS BotID FROM vwGroups AS g JOIN bots AS b ON g.mobid = b.BotId AND g.mobtype = 'B' WHERE g.groupid = %u", groupId); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -3888,11 +3368,9 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { uint32 TempGroupId = g->GetID(); std::string errorMessage; std::list ActiveBots = Bot::GetGroupedBotsByGroupId(botOwner->GetGroup()->GetID(), &errorMessage); - if(errorMessage.empty() && !ActiveBots.empty()) { for(std::list::iterator itr = ActiveBots.begin(); itr != ActiveBots.end(); ++itr) { Bot* activeBot = Bot::LoadBot(*itr, &errorMessage); - if(!errorMessage.empty()) { safe_delete(activeBot); break; @@ -3900,9 +3378,7 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { if(activeBot) { activeBot->Spawn(botOwner, &errorMessage); - g->UpdatePlayer(activeBot); - if(g->GetLeader()) activeBot->SetFollowID(g->GetLeader()->GetID()); } @@ -3911,11 +3387,6 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { database.SetGroupID(activeBot->GetCleanName(), 0, activeBot->GetBotID()); } } - - // Catch all condition for error messages destined for the zone error log - if(!errorMessage.empty()) { - // TODO: Log this error message to zone error log - } } } } @@ -3924,12 +3395,10 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { // Returns TRUE if there is atleast 1 bot in the specified group bool Bot::GroupHasBot(Group* group) { bool Result = false; - if(group) { for(int Counter = 0; Counter < MAX_GROUP_MEMBERS; Counter++) { - if (group->members[Counter] == nullptr) { + if (group->members[Counter] == nullptr) continue; - } if(group->members[Counter]->IsBot()) { Result = true; @@ -3937,18 +3406,15 @@ bool Bot::GroupHasBot(Group* group) { } } } - return Result; } std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::string* errorMessage) { std::list ownersBots; - if(botOwnerCharacterID == 0) return ownersBots; - std::string query = StringFormat("SELECT BotID, Name, Class, BotLevel, Race " - "FROM bots WHERE BotOwnerCharacterID = '%u'", botOwnerCharacterID); + std::string query = StringFormat("SELECT BotID, Name, Class, BotLevel, Race FROM bots WHERE BotOwnerCharacterID = '%u'", botOwnerCharacterID); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -3962,20 +3428,17 @@ std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::st availableBot.BotClass = atoi(row[2]); availableBot.BotLevel = atoi(row[3]); availableBot.BotRace = atoi(row[4]); - ownersBots.push_back(availableBot); } - return ownersBots; } std::list Bot::ListSpawnedBots(uint32 characterID, std::string* errorMessage) { std::list spawnedBots; - if(characterID == 0) return spawnedBots; - std::string query = StringFormat("SELECT bot_name, zone_name FROM botleader WHERE leaderid=%i", characterID); + std::string query = StringFormat("SELECT bot_name, zone_name FROM botleader WHERE leaderid = %i", characterID); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -3987,7 +3450,6 @@ std::list Bot::ListSpawnedBots(uint32 characterID, std::string* spawnedBotsList.BotLeaderCharID = characterID; strcpy(spawnedBotsList.BotName, row[0]); strcpy(spawnedBotsList.ZoneName, row[1]); - spawnedBots.push_back(spawnedBotsList); } @@ -3999,15 +3461,12 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e return; Mob* tempGroupLeader = botGroup->GetLeader(); - if(!tempGroupLeader->IsBot()) return; uint32 botGroupId = 0; uint32 botGroupLeaderBotId = tempGroupLeader->CastToBot()->GetBotID(); - - std::string query = StringFormat("INSERT INTO botgroup (BotGroupLeaderBotId, BotGroupName) " - "VALUES (%u, '%s')", botGroupLeaderBotId, botGroupName.c_str()); + std::string query = StringFormat("INSERT INTO botgroup (BotGroupLeaderBotId, BotGroupName) VALUES (%u, '%s')", botGroupLeaderBotId, botGroupName.c_str()); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4019,14 +3478,11 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e for(int groupMemberIndex = 0; groupMemberIndex < botGroup->GroupCount(); groupMemberIndex++) { Mob* tempBot = botGroup->members[groupMemberIndex]; - if(!tempBot || !tempBot->IsBot()) continue; uint32 botGroupMemberBotId = tempBot->CastToBot()->GetBotID(); - - query = StringFormat("INSERT INTO botgroupmembers (BotGroupId, BotId) " - "VALUES (%u, %u)", botGroupId, botGroupMemberBotId); + query = StringFormat("INSERT INTO botgroupmembers (BotGroupId, BotId) VALUES (%u, %u)", botGroupId, botGroupMemberBotId); results = database.QueryDatabase(query); if(!results.Success()) *errorMessage = std::string(results.ErrorMessage()); @@ -4035,12 +3491,10 @@ void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* e } void Bot::DeleteBotGroup(std::string botGroupName, std::string* errorMessage) { - if(botGroupName.empty()) return; uint32 botGroupId = GetBotGroupIdByBotGroupName(botGroupName, errorMessage); - if(!errorMessage->empty() || botGroupId== 0) return; @@ -4059,12 +3513,10 @@ void Bot::DeleteBotGroup(std::string botGroupName, std::string* errorMessage) { std::list Bot::LoadBotGroup(std::string botGroupName, std::string* errorMessage) { std::list botGroup; - if(botGroupName.empty()) return botGroup; uint32 botGroupId = GetBotGroupIdByBotGroupName(botGroupName, errorMessage); - if(botGroupId == 0) return botGroup; @@ -4079,21 +3531,17 @@ std::list Bot::LoadBotGroup(std::string botGroupName, std::string* err BotGroup tempBotGroup; tempBotGroup.BotGroupID = botGroupId; tempBotGroup.BotID = atoi(row[0]); - botGroup.push_back(tempBotGroup); } - return botGroup; } std::list Bot::GetBotGroupListByBotOwnerCharacterId(uint32 botOwnerCharacterId, std::string* errorMessage) { std::list botGroups; - if(botOwnerCharacterId == 0) return botGroups; - std::string query = StringFormat("SELECT BotGroupName, BotGroupLeaderName FROM vwBotGroups " - "WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); + std::string query = StringFormat("SELECT BotGroupName, BotGroupLeaderName FROM vwBotGroups WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4104,20 +3552,16 @@ std::list Bot::GetBotGroupListByBotOwnerCharacterId(uint32 botOwne BotGroupList botGroupList; botGroupList.BotGroupName = std::string(row[0]); botGroupList.BotGroupLeaderName = std::string(row[1]); - botGroups.push_back(botGroupList); } - return botGroups; } bool Bot::DoesBotGroupNameExist(std::string botGroupName) { - if(botGroupName.empty()) return false; - std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups " - "WHERE BotGroupName = '%s'", botGroupName.c_str()); + std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups WHERE BotGroupName = '%s'", botGroupName.c_str()); auto results = database.QueryDatabase(query); if (!results.Success() || results.RowCount() == 0) return false; @@ -4125,7 +3569,6 @@ bool Bot::DoesBotGroupNameExist(std::string botGroupName) { for(auto row = results.begin(); row != results.end(); ++row) { uint32 tempBotGroupId = atoi(row[0]); std::string tempBotGroupName = std::string(row[1]); - if (botGroupName == tempBotGroupName && tempBotGroupId != 0) return true; } @@ -4134,12 +3577,10 @@ bool Bot::DoesBotGroupNameExist(std::string botGroupName) { } uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName, std::string* errorMessage) { - if(botOwnerCharacterId == 0 || botGroupName.empty()) return 0; - std::string query = StringFormat("SELECT BotGroupId, BotGroupName FROM vwBotGroups " - "WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); + std::string query = StringFormat("SELECT BotGroupId, BotGroupName FROM vwBotGroups WHERE BotOwnerCharacterId = %u", botOwnerCharacterId); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4150,10 +3591,8 @@ uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName return 0; for(auto row = results.begin(); row != results.end(); ++row) { - uint32 tempBotGroupId = atoi(row[0]); - std::string tempBotGroupName = std::string(row[1]); - + std::string tempBotGroupName = std::string(row[1]); if(botGroupName == tempBotGroupName) return tempBotGroupId; } @@ -4162,12 +3601,10 @@ uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName } uint32 Bot::GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* errorMessage) { - if(botGroupName.empty()) return 0; - std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups " - "WHERE BotGroupName = '%s'", botGroupName.c_str()); + std::string query = StringFormat("SELECT BotGroupId FROM vwBotGroups WHERE BotGroupName = '%s'", botGroupName.c_str()); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4182,7 +3619,6 @@ uint32 Bot::GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* e } uint32 Bot::GetBotGroupLeaderIdByBotGroupName(std::string botGroupName) { - if(botGroupName.empty()) return 0; @@ -4196,13 +3632,10 @@ uint32 Bot::GetBotGroupLeaderIdByBotGroupName(std::string botGroupName) { } uint32 Bot::AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessage) { - if(botOwnerCharacterID == 0) return 0; - std::string query = StringFormat("SELECT value FROM quest_globals " - "WHERE name = 'bot_spawn_limit' AND charid = %i", - botOwnerCharacterID); + std::string query = StringFormat("SELECT value FROM quest_globals WHERE name = 'bot_spawn_limit' AND charid = %i", botOwnerCharacterID); auto results = database.QueryDatabase(query); if (!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4218,23 +3651,18 @@ uint32 Bot::AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessa uint32 Bot::SpawnedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage) { uint32 Result = 0; - if(botOwnerCharacterID > 0) { std::list SpawnedBots = entity_list.GetBotsByBotOwnerCharacterID(botOwnerCharacterID); - Result = SpawnedBots.size(); } - return Result; } uint32 Bot::CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage) { - if(botOwnerCharacterID == 0) return 0; - std::string query = StringFormat("SELECT COUNT(BotID) FROM bots " - "WHERE BotOwnerCharacterID=%i", botOwnerCharacterID); + std::string query = StringFormat("SELECT COUNT(BotID) FROM bots WHERE BotOwnerCharacterID=%i", botOwnerCharacterID); auto results = database.QueryDatabase(query); if (!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -4423,9 +3851,8 @@ void Bot::SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 // Returns the item id that is in the bot inventory collection for the specified slot. ItemInst* Bot::GetBotItem(uint32 slotID) { ItemInst* item = m_inv.GetItem(slotID); - if(item){ + if(item) return item; - } return nullptr; } @@ -4502,190 +3929,148 @@ bool Bot::Bot_Command_Resist(int resisttype, int level) { int resistid = 0; switch(resisttype) { case 1: // Poison Cleric - if(level >= 30) { + if(level >= 30) resistid = 62; - } - else if(level >= 6) { + else if(level >= 6) resistid = 227; - } break; case 2: // Disease Cleric - if(level >= 36) { + if(level >= 36) resistid = 63; - } - else if(level >= 11) { + else if(level >= 11) resistid = 226; - } break; case 3: // Fire Cleric - if(level >= 33) { + if(level >= 33) resistid = 60; - } - else if(level >= 8) { + else if(level >= 8) resistid = 224; - } break; case 4: // Cold Cleric - if(level >= 38) { + if(level >= 38) resistid = 61; - } - else if(level >= 13) { + else if(level >= 13) resistid = 225; - } break; case 5: // Magic Cleric - if(level >= 43) { + if(level >= 43) resistid = 64; - } - else if(level >= 16) { + else if(level >= 16) resistid = 228; - } break; case 6: // Magic Enchanter - if(level >= 37) { + if(level >= 37) resistid = 64; - } - else if(level >= 17) { + else if(level >= 17) resistid = 228; - } break; case 7: // Poison Druid - if(level >= 44) { + if(level >= 44) resistid = 62; - } - else if(level >= 19) { + else if(level >= 19) resistid = 227; - } break; case 8: // Disease Druid - if(level >= 44) { + if(level >= 44) resistid = 63; - } - else if(level >= 19) { + else if(level >= 19) resistid = 226; - } break; case 9: // Fire Druid - if(level >= 20) { + if(level >= 20) resistid = 60; - } - else if(level >= 1) { + else if(level >= 1) resistid = 224; - } break; case 10: // Cold Druid - if(level >= 30) { + if(level >= 30) resistid = 61; - } - else if(level >= 9) { + else if(level >= 9) resistid = 225; - } break; case 11: // Magic Druid - if(level >= 49) { + if(level >= 49) resistid = 64; - } - else if(level >= 34) { + else if(level >= 34) resistid = 228; - } break; case 12: // Poison Shaman - if(level >= 35) { + if(level >= 35) resistid = 62; - } - else if(level >= 20) { + else if(level >= 20) resistid = 227; - } break; case 13: // Disease Shaman - if(level >= 30) { + if(level >= 30) resistid = 63; - } - else if(level >= 8) { + else if(level >= 8) resistid = 226; - } break; case 14: // Fire Shaman - if(level >= 27) { + if(level >= 27) resistid = 60; - } - else if(level >= 5) { + else if(level >= 5) resistid = 224; - } break; case 15: // Cold Shaman - if(level >= 24) { + if(level >= 24) resistid = 61; - } - else if(level >= 1) { + else if(level >= 1) resistid = 225; - } break; case 16: // Magic Shaman - if(level >= 43) { + if(level >= 43) resistid = 64; - } - else if(level >= 19) { + else if(level >= 19) resistid = 228; - } break; } if(resistid > 0) { Group* g = GetGroup(); if(g) { - for(int k=0; kmembers[k]) { + for(int k = 0; k < MAX_GROUP_MEMBERS; k++) { + if(g->members[k]) SpellOnTarget(resistid, g->members[k]); - } } return true; } } - return false; } bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) { bool Result = false; - if(bot && group) { if(bot->HasGroup()) { if(!group->IsLeader(bot)) { bot->SetFollowID(0); - if(group->DelMember(bot)) database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); - } - else { + } else { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(!group->members[i]) continue; group->members[i]->SetFollowID(0); } - group->DisbandGroup(); database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID()); } - Result = true; } } - return Result; } bool Bot::AddBotToGroup(Bot* bot, Group* group) { bool Result = false; - if(bot && group) { if(!bot->HasGroup()) { // Add bot to this group if(group->AddMember(bot)) { if(group->GetLeader()) { bot->SetFollowID(group->GetLeader()->GetID()); - // Need to send this only once when a group is formed with a bot so the client knows it is also the group leader if(group->GroupCount() == 2 && group->GetLeader()->IsClient()) { group->UpdateGroupAAs(); @@ -4693,45 +4078,35 @@ bool Bot::AddBotToGroup(Bot* bot, Group* group) { group->SendUpdate(groupActUpdate, TempLeader); } } - Result = true; } } } - return Result; } bool Bot::BotGroupCreate(std::string botGroupLeaderName) { bool Result = false; - if(!botGroupLeaderName.empty()) { Bot* botGroupLeader = entity_list.GetBotByBotName(botGroupLeaderName); - if(botGroupLeader) Result = BotGroupCreate(botGroupLeader); } - return Result; } bool Bot::BotGroupCreate(Bot* botGroupLeader) { bool Result = false; - if(botGroupLeader && !botGroupLeader->HasGroup()) { Group* newGroup = new Group(botGroupLeader); - if(newGroup) { entity_list.AddGroup(newGroup); database.SetGroupID(botGroupLeader->GetName(), newGroup->GetID(), botGroupLeader->GetBotID()); database.SetGroupLeaderName(newGroup->GetID(), botGroupLeader->GetName()); - botGroupLeader->SetFollowID(botGroupLeader->GetBotOwner()->GetID()); - Result = true; } } - return Result; } @@ -4741,64 +4116,46 @@ bool Bot::Bot_Command_CharmTarget(int charmtype, Mob *target) { if(target) { switch(charmtype) { case 1: // Enchanter - if((charmlevel >= 64) && (charmlevel <= 75)) { + if((charmlevel >= 64) && (charmlevel <= 75)) charmid = 3355; - } - else if((charmlevel >= 62) && (charmlevel <= 63)) { + else if((charmlevel >= 62) && (charmlevel <= 63)) charmid = 3347; - } - else if((charmlevel >= 60) && (charmlevel <= 61)) { + else if((charmlevel >= 60) && (charmlevel <= 61)) charmid = 1707; - } - else if((charmlevel >= 53) && (charmlevel <= 59)) { + else if((charmlevel >= 53) && (charmlevel <= 59)) charmid = 1705; - } - else if((charmlevel >= 37) && (charmlevel <= 52)) { + else if((charmlevel >= 37) && (charmlevel <= 52)) charmid = 183; - } - else if((charmlevel >= 23) && (charmlevel <= 36)) { + else if((charmlevel >= 23) && (charmlevel <= 36)) charmid = 182; - } - else if((charmlevel >= 11) && (charmlevel <= 22)) { + else if((charmlevel >= 11) && (charmlevel <= 22)) charmid = 300; - } break; case 2: // Necromancer - if((charmlevel >= 60) && (charmlevel <= 75)) { + if((charmlevel >= 60) && (charmlevel <= 75)) charmid = 1629; - } - else if((charmlevel >=47) && (charmlevel <= 59)) { + else if((charmlevel >=47) && (charmlevel <= 59)) charmid = 198; - } - else if((charmlevel >= 31) && (charmlevel <= 46)) { + else if((charmlevel >= 31) && (charmlevel <= 46)) charmid = 197; - } - else if((charmlevel >= 18) && (charmlevel <= 30)) { + else if((charmlevel >= 18) && (charmlevel <= 30)) charmid = 196; - } break; case 3: // Druid - if((charmlevel >= 63) && (charmlevel <= 75)) { + if((charmlevel >= 63) && (charmlevel <= 75)) charmid = 3445; - } - else if((charmlevel >= 55) && (charmlevel <= 62)) { + else if((charmlevel >= 55) && (charmlevel <= 62)) charmid = 1556; - } - else if((charmlevel >= 52) && (charmlevel <= 54)) { + else if((charmlevel >= 52) && (charmlevel <= 54)) charmid = 1553; - } - else if((charmlevel >= 43) && (charmlevel <= 51)) { + else if((charmlevel >= 43) && (charmlevel <= 51)) charmid = 142; - } - else if((charmlevel >= 33) && (charmlevel <= 42)) { + else if((charmlevel >= 33) && (charmlevel <= 42)) charmid = 141; - } - else if((charmlevel >= 23) && (charmlevel <= 32)) { + else if((charmlevel >= 23) && (charmlevel <= 32)) charmid = 260; - } - else if((charmlevel >= 13) && (charmlevel <= 22)) { + else if((charmlevel >= 13) && (charmlevel <= 22)) charmid = 242; - } break; } if(charmid > 0) { @@ -4817,28 +4174,22 @@ bool Bot::Bot_Command_DireTarget(int diretype, Mob *target) { if(target) { switch(diretype) { case 1: // Enchanter - if(direlevel >= 65) { + if(direlevel >= 65) direid = 5874; - } - else if(direlevel >= 55) { + else if(direlevel >= 55) direid = 2761; - } break; case 2: // Necromancer - if(direlevel >= 65) { + if(direlevel >= 65) direid = 5876; - } - else if(direlevel >= 55) { + else if(direlevel >= 55) direid = 2759; - } break; case 3: // Druid - if(direlevel >= 65) { + if(direlevel >= 65) direid = 5875; - } - else if(direlevel >= 55) { + else if(direlevel >= 55) direid = 2760; - } break; } if(direid > 0) { @@ -4855,24 +4206,18 @@ bool Bot::Bot_Command_CalmTarget(Mob *target) { if(target) { int calmid = 0; int calmlevel = GetLevel(); - if((calmlevel >= 67) && (calmlevel <= 75)) { + if((calmlevel >= 67) && (calmlevel <= 75)) calmid = 5274; - } - else if((calmlevel >= 62) && (calmlevel <= 66)) { + else if((calmlevel >= 62) && (calmlevel <= 66)) calmid = 3197; - } - else if((calmlevel >= 35) && (calmlevel <= 61)) { + else if((calmlevel >= 35) && (calmlevel <= 61)) calmid = 45; - } - else if((calmlevel >= 18) && (calmlevel <= 34)) { + else if((calmlevel >= 18) && (calmlevel <= 34)) calmid = 47; - } - else if((calmlevel >= 6) && (calmlevel <= 17)) { + else if((calmlevel >= 6) && (calmlevel <= 17)) calmid = 501; - } - else if((calmlevel >= 1) && (calmlevel <= 5)) { + else if((calmlevel >= 1) && (calmlevel <= 5)) calmid = 208; - } if(calmid > 0) { uint32 DontRootMeBeforeTime = 0; CastSpell(calmid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); @@ -4887,30 +4232,22 @@ bool Bot::Bot_Command_RezzTarget(Mob *target) { if(target) { int rezid = 0; int rezlevel = GetLevel(); - if(rezlevel >= 56) { + if(rezlevel >= 56) rezid = 1524; - } - else if(rezlevel >= 47) { + else if(rezlevel >= 47) rezid = 392; - } - else if(rezlevel >= 42) { + else if(rezlevel >= 42) rezid = 2172; - } - else if(rezlevel >= 37) { + else if(rezlevel >= 37) rezid = 388; - } - else if(rezlevel >= 32) { + else if(rezlevel >= 32) rezid = 2171; - } - else if(rezlevel >= 27) { + else if(rezlevel >= 27) rezid = 391; - } - else if(rezlevel >= 22) { + else if(rezlevel >= 22) rezid = 2170; - } - else if(rezlevel >= 18) { + else if(rezlevel >= 18) rezid = 2169; - } if(rezid > 0) { uint32 DontRootMeBeforeTime = 0; CastSpell(rezid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); @@ -4925,58 +4262,45 @@ bool Bot::Bot_Command_Cure(int curetype, int level) { int cureid = 0; switch(curetype) { case 1: // Poison - if(level >= 58) { + if(level >= 58) cureid = 1525; - } - else if(level >= 48) { + else if(level >= 48) cureid = 97; - } - else if(level >= 22) { + else if(level >= 22) cureid = 95; - } - else if(level >= 1) { + else if(level >= 1) cureid = 203; - } break; case 2: // Disease - if(level >= 51) { + if(level >= 51) cureid = 3693; - } - else if(level >= 28) { + else if(level >= 28) cureid = 96; - } - else if(level >= 4) { + else if(level >= 4) cureid = 213; - } break; case 3: // Curse - if(level >= 54) { + if(level >= 54) cureid = 2880; - } - else if(level >= 38) { + else if(level >= 38) cureid = 2946; - } - else if(level >= 23) { + else if(level >= 23) cureid = 4057; - } - else if(level >= 8) { + else if(level >= 8) cureid = 4056; - } break; case 4: // Blindness - if(level >= 3) { + if(level >= 3) cureid = 212; - } break; } if(cureid > 0) { Group* g = GetGroup(); if(g) { - for(int k=0; kmembers[k]) { + for(int k = 0; k < MAX_GROUP_MEMBERS; k++) { + if(g->members[k]) SpellOnTarget(cureid, g->members[k]); - } } return true; } @@ -5013,7 +4337,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli uint8 charges[MAX_SLOT_ID] = {0}; bool botCanWear[MAX_SLOT_ID] = {0}; - for(int16 i=beginSlotID; i<=endSlotID; ++i) { + for(int16 i = beginSlotID; i <= endSlotID; ++i) { bool BotCanWear = false; bool UpdateClient = false; bool already_returned = false; @@ -5053,13 +4377,16 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli botCanWear[i] = BotCanWear; ItemInst* swap_item = nullptr; - const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + const char* equipped[EmuConstants::EQUIPMENT_SIZE + 1] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", - "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo" }; + "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; bool success = false; int how_many_slots = 0; - for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= EmuConstants::EQUIPMENT_END; ++j) { + for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= (EmuConstants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { + if (j == 22) + j = 9999; + how_many_slots++; if(!GetBotItem(j)) { if(j == MainPrimary) { @@ -5089,7 +4416,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli success = true; } else { - Say("I can't Dual Wield yet."); + BotGroupSay(this, "I can't Dual Wield yet."); --how_many_slots; } } @@ -5116,8 +4443,11 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } if(!success) { - for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= EmuConstants::EQUIPMENT_END; ++j) { + for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= (EmuConstants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { + if (j == 22) + j = 9999; + swap_item = GetBotItem(j); failedLoreCheck = false; for (int k = AUG_BEGIN; k < EmuConstants::ITEM_COMMON_SIZE; ++k) { @@ -5159,7 +4489,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } else { botCanWear[i] = false; - Say("I can't Dual Wield yet."); + BotGroupSay(this, "I can't Dual Wield yet."); } } else { @@ -5205,14 +4535,14 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } const Item_Struct* item2 = 0; - for(int y=beginSlotID; y<=endSlotID; ++y) { + for(int y = beginSlotID; y <= endSlotID; ++y) { item2 = database.GetItem(items[y]); if(item2) { if(botCanWear[y]) { - Say("Thank you for the %s, %s.", item2->Name, client->GetName()); + BotGroupSay(this, "Thank you for the %s, %s!", item2->Name, client->GetName()); } else { - Say("I can't use this %s!", item2->Name); + BotGroupSay(this, "I can't use this %s!", item2->Name); } } } @@ -5224,40 +4554,35 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att return false; Save(); - Mob *give_exp = hate_list.GetDamageTopOnHateList(this); Client *give_exp_client = nullptr; - if(give_exp && give_exp->IsClient()) give_exp_client = give_exp->CastToClient(); bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); - if(entity_list.GetCorpseByID(GetID())) entity_list.GetCorpseByID(GetID())->Depop(); Group *g = GetGroup(); if(g) { - for(int i=0; imembers[i]) { if(g->members[i] == this) { // If the leader dies, make the next bot the leader // and reset all bots followid if(g->IsLeader(g->members[i])) { - if(g->members[i+1]) { - g->SetLeader(g->members[i+1]); - g->members[i+1]->SetFollowID(g->members[i]->GetFollowID()); - for(int j=0; jmembers[j] && (g->members[j] != g->members[i+1])) { - g->members[j]->SetFollowID(g->members[i+1]->GetID()); - } + if(g->members[i + 1]) { + g->SetLeader(g->members[i + 1]); + g->members[i + 1]->SetFollowID(g->members[i]->GetFollowID()); + for(int j = 0; j < MAX_GROUP_MEMBERS; j++) { + if(g->members[j] && (g->members[j] != g->members[i + 1])) + g->members[j]->SetFollowID(g->members[i + 1]->GetID()); } } } // delete from group data RemoveBotFromGroup(this, g); - //Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup g = GetGroup(); if (!g) @@ -5265,8 +4590,8 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att // if group members exist below this one, move // them all up one slot in the group list - int j = i+1; - for(; jmembers[j]) { g->members[j-1] = g->members[j]; strcpy(g->membername[j-1], g->members[j]->GetCleanName()); @@ -5282,55 +4607,26 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att gu->action = groupActLeave; strcpy(gu->membername, GetCleanName()); if(g) { - for(int k=0; kmembers[k] && g->members[k]->IsClient()) g->members[k]->CastToClient()->QueuePacket(outapp); } } safe_delete(outapp); - - // now that's done, lets see if all we have left is the client - // and we can clean up the clients raid group and group - /*if(GetBotRaidID()) { - BotRaids* br = entity_list.GetBotRaidByMob(this); - if(br) { - if(this == br->botmaintank) { - br->botmaintank = nullptr; - } - if(this == br->botsecondtank) { - br->botsecondtank = nullptr; - } - } - if(g->GroupCount() == 0) { - uint32 gid = g->GetID(); - if(br) { - br->RemoveEmptyBotGroup(); - } - entity_list.RemoveGroup(gid); - } - if(br && (br->RaidBotGroupsCount() == 1)) { - br->RemoveClientGroup(br->GetRaidBotLeader()); - } - if(br && (br->RaidBotGroupsCount() == 0)) { - br->DisbandBotRaid(); - } - }*/ } } } } - if(GetInHealRotation()) { + if(GetInHealRotation()) GetHealRotationLeader()->RemoveHealRotationMember(this); - } entity_list.RemoveBot(this->GetID()); - return true; } void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) { - if(spell_id==0) + if(spell_id == 0) spell_id = SPELL_UNKNOWN; //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds @@ -5338,13 +4634,8 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ Log.Out(Logs::Detail, Logs::Combat, "Triggering EVENT_ATTACK due to attack by %s", from->GetName()); parse->EventNPC(EVENT_ATTACK, this, from, "", 0); } - + attacked_timer.Start(CombatEventTimer_expire); - - // TODO: A bot doesnt call this, right? - /*if (!IsEngaged()) - zone->AddAggroMob();*/ - // if spell is lifetap add hp to the caster if (spell_id != SPELL_UNKNOWN && IsLifetapSpell(spell_id)) { int healed = GetActSpellHealing(spell_id, damage); @@ -5354,7 +4645,6 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ } CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); - if(GetHP() < 0) { if(IsCasting()) InterruptSpell(); @@ -5362,35 +4652,26 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ } SendHPUpdate(); - - if(this == from) { + if(this == from) return; - } // Aggro the bot's group members - if(IsGrouped()) - { + if(IsGrouped()) { Group *g = GetGroup(); - if(g) - { - for(int i=0; imembers[i] && g->members[i]->IsBot() && from && !g->members[i]->CheckAggro(from) && g->members[i]->IsAttackAllowed(from)) - { g->members[i]->AddToHateList(from, 1); - } } } } } -void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/) -{ +void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/) { Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); } -bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) -{ +bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { if (!other) { SetTarget(nullptr); Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Bot::Attack for evaluation!"); @@ -5401,15 +4682,10 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b SetTarget(other); Log.Out(Logs::Detail, Logs::Combat, "Attacking %s with hand %d %s", other?other->GetCleanName():"(nullptr)", Hand, FromRiposte?"(this is a riposte)":""); - - if ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) || - other == nullptr || - (GetHP() < 0) || - (GetAppearance() == eaDead) || - (!IsAttackAllowed(other))) - { + if ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) || other == nullptr || (GetHP() < 0) || (GetAppearance() == eaDead) || (!IsAttackAllowed(other))) { if(this->GetOwnerID()) entity_list.MessageClose(this, 1, 200, 10, "%s says, '%s is not a legal target master.'", this->GetCleanName(), this->GetTarget()->GetCleanName()); + if(other) { RemoveFromHateList(other); Log.Out(Logs::Detail, Logs::Combat, "I am not allowed to attack %s", other->GetCleanName()); @@ -5421,22 +4697,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Divine Aura is in effect."); return false; } - - // TODO: Uncomment this block after solved the bug that is assigning a null value to GetTarget() for bots while in combat. Appears to happen at random, but frequently. - /*if(HasGroup() && _previousTarget != GetTarget()) { - std::ostringstream attackMessage; - attackMessage << "Attacking " << other->GetCleanName() << "."; - - GetGroup()->GroupMessage(this, 0, 100, attackMessage.str().c_str()); - }*/ - + FaceTarget(GetTarget()); - ItemInst* weapon = nullptr; if(Hand == MainPrimary) { weapon = GetBotItem(MainPrimary); OffHandAtk(false); } + if(Hand == MainSecondary) { weapon = GetBotItem(MainSecondary); OffHandAtk(true); @@ -5445,46 +4713,46 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if(weapon != nullptr) { if (!weapon->IsWeapon()) { Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID()); - return(false); + return false; } Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID()); - } else { - Log.Out(Logs::Detail, Logs::Combat, "Attacking without a weapon."); } + else + Log.Out(Logs::Detail, Logs::Combat, "Attacking without a weapon."); // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients SkillUseTypes skillinuse; AttackAnimation(skillinuse, Hand, weapon); Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); - /// Now figure out damage int damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; - if (weapon) hate = weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt; + if (weapon) + hate = (weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt); + int weapon_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; + if (hate == 0 && weapon_damage > 1) + hate = weapon_damage; //if weapon damage > 0 then we know we can hit the target with this weapon //otherwise we cannot and we set the damage to -5 later on - if(weapon_damage > 0){ - + if(weapon_damage > 0) { //Berserker Berserk damage bonus if(berserk && (GetClass() == BERSERKER)){ - int bonus = 3 + GetLevel()/10; //unverified - weapon_damage = weapon_damage * (100+bonus) / 100; + int bonus = (3 + GetLevel() / 10); //unverified + weapon_damage = (weapon_damage * (100 + bonus) / 100); Log.Out(Logs::Detail, Logs::Combat, "Berserker damage bonus increases DMG to %d", weapon_damage); } //try a finishing blow.. if successful end the attack - if(TryFinishingBlow(other, skillinuse)) { - return (true); - } + if(TryFinishingBlow(other, skillinuse)) + return true; //damage formula needs some work int min_hit = 1; - int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; + int max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) max_hit = (RuleI(Combat, HitCapPre10)); @@ -5502,16 +4770,11 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output // of weapons wielded by higher-level melee characters (especially for two-handed weapons). - int ucDamageBonus = 0; - - if( Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass() ) - { + if(Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); - + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -5520,16 +4783,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. if (Hand==MainSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); - + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; } } - min_hit = min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; + min_hit = (min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100); if(max_hit < min_hit) max_hit = min_hit; @@ -5559,7 +4820,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b other->MeleeMitigation(this, damage, min_hit, opts); if(damage > 0) { ApplyMeleeDamageBonus(skillinuse, damage); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); + damage += ((itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse)); TryCriticalHit(other, skillinuse, damage, opts); Log.Out(Logs::Detail, Logs::Combat, "Generating hate %d towards %s", hate, GetCleanName()); // now add done damage to the hate list @@ -5573,12 +4834,13 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //riposte bool slippery_attack = false; // Part of hack to allow riposte to become a miss, but still allow a Strikethrough chance (like on Live) if (damage == -3) { - if (FromRiposte) return false; + if (FromRiposte) + return false; else { if (Hand == MainSecondary) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations //Live AA - SlipperyAttacks //This spell effect most likely directly modifies the actual riposte chance when using offhand attack. - int32 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; + int32 OffhandRiposteFail = (aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail); OffhandRiposteFail *= -1; //Live uses a negative value for this. if (OffhandRiposteFail && @@ -5587,17 +4849,18 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b slippery_attack = true; } else DoRiposte(other); - if (GetHP() < 0) return false; + if (GetHP() < 0) + return false; } else DoRiposte(other); - if (GetHP() < 0) return false; + if (GetHP() < 0) + return false; } } if (((damage < 0) || slippery_attack) && !FromRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA - int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - + int32 bonusStrikeThrough = (itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough); if(bonusStrikeThrough && (zone->random.Int(0, 100) < bonusStrikeThrough)) { Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit @@ -5605,22 +4868,21 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } } } - else{ + else damage = -5; - } // Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same. // If we are this far, this means we are atleast making a swing. - if (!FromRiposte) {// Ripostes never generate any aggro. + if (!FromRiposte) other->AddToHateList(this, hate); - } /////////////////////////////////////////////////////////// ////// Send Attack Damage /////////////////////////////////////////////////////////// other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - if (GetHP() < 0) return false; + if (GetHP() < 0) + return false; MeleeLifeTap(damage); @@ -5634,12 +4896,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b BuffFadeByEffect(SE_Invisibility2); invisible = false; } + if(invisible_undead) { Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. undead due to melee attack."); BuffFadeByEffect(SE_InvisVsUndead); BuffFadeByEffect(SE_InvisVsUndead2); invisible_undead = false; } + if(invisible_animals){ Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. animals due to melee attack."); BuffFadeByEffect(SE_InvisVsAnimals); @@ -5666,7 +4930,6 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (damage > 0) return true; - else return false; } @@ -5674,7 +4937,6 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id) { const SPDat_Spell_Struct &spell = spells[spell_id]; - int32 value = 0; int lvlModifier = 100; int spell_level = 0; @@ -5685,7 +4947,6 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 int32 base1 = 0; int32 base2 = 0; uint32 slot = 0; - bool LimitFound = false; int FocusCount = 0; @@ -5707,95 +4968,79 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 //To handle this we will not automatically return zero if a limit is found. //Instead if limit is found and multiple effects, we will reset the limit check //when the next valid focus effect is found. - if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ + if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)) { FocusCount++; //If limit found on prior check next, else end loop. - if (FocusCount > 1){ - if (LimitFound){ + if (FocusCount > 1) { + if (LimitFound) { value = 0; LimitFound = false; } - - else{ + else break; - } } } - - - switch (effect) - { + + + switch (effect) { case SE_Blank: break; - - //Handle Focus Limits case SE_LimitResist: - if(base1) - { + if(base1) { if(spell.resisttype != base1) LimitFound = true; } - break; + break; case SE_LimitInstant: if(spell.buffduration) LimitFound = true; - break; + break; case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass()%16) - 1]; + spell_level = spell.classes[(GetClass() % 16) - 1]; lvldiff = spell_level - base1; //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) - { - if(base2 > 0) - { - lvlModifier -= base2*lvldiff; + if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { + if(base2 > 0) { + lvlModifier -= (base2 * lvldiff); if(lvlModifier < 1) LimitFound = true; } - else { + else LimitFound = true; - } } - break; + break; case SE_LimitMinLevel: - if((spell.classes[(GetClass()%16) - 1]) < base1) + if((spell.classes[(GetClass() % 16) - 1]) < base1) LimitFound = true; - break; + break; case SE_LimitCastTimeMin: if (spell.cast_time < base1) LimitFound = true; - break; + break; case SE_LimitSpell: - // Exclude spell(any but this) if(base1 < 0) { if (spell_id == (base1*-1)) LimitFound = true; - } - else { - // Include Spell(only this) + } else { if (spell_id != base1) LimitFound = true; } - break; + break; case SE_LimitMinDur: if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) LimitFound = true; - break; + break; case SE_LimitEffect: - // Exclude effect(any but this) if(base1 < 0) { if(IsEffectInSpell(spell_id,(base1*-1))) LimitFound = true; - } - else { - // Include effect(only this) + } else { if(!IsEffectInSpell(spell_id,base1)) LimitFound = true; } - break; + break; case SE_LimitSpellType: - switch(base1) - { + switch(base1) { case 0: if (!IsDetrimentalSpell(spell_id)) LimitFound = true; @@ -5805,181 +5050,130 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 LimitFound = true; break; } - break; - + break; + case SE_LimitManaMin: if(spell.mana < base1) LimitFound = true; - break; - + break; case SE_LimitTarget: - // Exclude - if(base1 < 0){ - if(-base1 == spell.targettype) - LimitFound = true; - } - // Include - else { - if(base1 != spell.targettype) - LimitFound = true; - } - break; - + if(base1 < 0) { + if(-base1 == spell.targettype) + LimitFound = true; + } else { + if(base1 != spell.targettype) + LimitFound = true; + } + break; case SE_LimitCombatSkills: - // 1 is for disciplines only - if(base1 == 1 && !IsDiscipline(spell_id)) - LimitFound = true; - // 0 is spells only - else if(base1 == 0 && IsDiscipline(spell_id)) + if((base1 == 1 && !IsDiscipline(spell_id)) || (base1 == 0 && IsDiscipline(spell_id))) LimitFound = true; break; - case SE_LimitSpellGroup: - if(base1 > 0 && base1 != spell.spellgroup) + if((base1 > 0 && base1 != spell.spellgroup) || (base1 < 0 && base1 == spell.spellgroup)) LimitFound = true; - else if(base1 < 0 && base1 == spell.spellgroup) - LimitFound = true; - break; - - + break; case SE_LimitCastingSkill: LimitSpellSkill = true; if(base1 == spell.skill) SpellSkill_Found = true; - break; - + break; case SE_LimitClass: //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(base1, GetClass())) - LimitFound = true; - break; - - + if (!PassLimitClass(base1, GetClass())) + LimitFound = true; + break; //Handle Focus Effects case SE_ImprovedDamage: if (type == focusImprovedDamage && base1 > value) value = base1; - break; - + break; case SE_ImprovedHeal: if (type == focusImprovedHeal && base1 > value) value = base1; - break; - + break; case SE_ReduceManaCost: - if (type == focusManaCost ) + if (type == focusManaCost) value = base1; - break; - + break; case SE_IncreaseSpellHaste: if (type == focusSpellHaste && base1 > value) value = base1; break; - case SE_IncreaseSpellDuration: if (type == focusSpellDuration && base1 > value) value = base1; break; - case SE_SpellDurationIncByTic: if (type == focusSpellDurByTic && base1 > value) value = base1; break; - case SE_SwarmPetDuration: if (type == focusSwarmPetDuration && base1 > value) value = base1; break; - case SE_IncreaseRange: if (type == focusRange && base1 > value) value = base1; break; - case SE_ReduceReagentCost: if (type == focusReagentCost && base1 > value) value = base1; break; - case SE_PetPowerIncrease: if (type == focusPetPower && base1 > value) value = base1; break; - case SE_SpellResistReduction: if (type == focusResistRate && base1 > value) value = base1; break; - case SE_SpellHateMod: - if (type == focusSpellHateMod) - { - if(value != 0) - { - if(value > 0) - { + if (type == focusSpellHateMod) { + if(value != 0) { + if(value > 0) { if(base1 > value) - { value = base1; - } - } - else - { + } else { if(base1 < value) - { value = base1; - } } } else value = base1; } break; - - case SE_ReduceReuseTimer: - { + + case SE_ReduceReuseTimer: { if(type == focusReduceRecastTime) - value = base1 / 1000; - + value = (base1 / 1000); break; } - - case SE_TriggerOnCast: - { - if(type == focusTriggerOnCast) - { - if(zone->random.Int(0, 100) <= base1){ + case SE_TriggerOnCast: { + if(type == focusTriggerOnCast) { + if(zone->random.Int(0, 100) <= base1) value = base2; - } - - else{ + else { value = 0; LimitFound = true; } } break; } - case SE_FcSpellVulnerability: - { + case SE_FcSpellVulnerability: { if(type == focusSpellVulnerability) - { value = base1; - } break; } - case SE_BlockNextSpellFocus: - { - if(type == focusBlockNextSpell) - { + case SE_BlockNextSpellFocus: { + if(type == focusBlockNextSpell) { if(zone->random.Int(1, 100) <= base1) value = 1; } break; } - case SE_FcTwincast: - { + case SE_FcTwincast: { if(type == focusTwincast) - { value = base1; } break; @@ -6002,92 +5196,69 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 value = 0; } break; - } - */ - case SE_FcDamageAmt: - { + }*/ + case SE_FcDamageAmt: { if(type == focusFcDamageAmt) value = base1; - break; } - - case SE_FcDamageAmtCrit: - { + case SE_FcDamageAmtCrit: { if(type == focusFcDamageAmtCrit) value = base1; - break; } - - case SE_FcDamageAmtIncoming: - { + case SE_FcDamageAmtIncoming: { if(type == focusFcDamageAmtIncoming) value = base1; - break; } - case SE_FcHealAmtIncoming: if(type == focusFcHealAmtIncoming) value = base1; break; - case SE_FcHealPctCritIncoming: if (type == focusFcHealPctCritIncoming) value = base1; break; - case SE_FcHealAmtCrit: if(type == focusFcHealAmtCrit) value = base1; break; - case SE_FcHealAmt: if(type == focusFcHealAmt) value = base1; break; - case SE_FcHealPctIncoming: if(type == focusFcHealPctIncoming) value = base1; break; - - case SE_FcBaseEffects: - { + case SE_FcBaseEffects: { if (type == focusFcBaseEffects) value = base1; - break; } - case SE_FcDamagePctCrit: - { + case SE_FcDamagePctCrit: { if(type == focusFcDamagePctCrit) value = base1; - break; } - - case SE_FcIncreaseNumHits: - { + case SE_FcIncreaseNumHits: { if(type == focusIncreaseNumHits) value = base1; - break; } } - //Check for spell skill limits. - if ((LimitSpellSkill) && (!SpellSkill_Found)) { - return 0; + //Check for spell skill limits. + if ((LimitSpellSkill) && (!SpellSkill_Found)) + return 0; } } - if (LimitFound) { + if (LimitFound) return 0; - } - return(value*lvlModifier/100); + return (value * lvlModifier / 100); } int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { @@ -6098,18 +5269,13 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { int32 realTotal2 = 0; int32 realTotal3 = 0; bool rand_effectiveness = false; - //Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages //In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance - if((bottype == BotfocusManaCost || bottype == BotfocusImprovedHeal || bottype == BotfocusImprovedDamage) - && RuleB(Spells, LiveLikeFocusEffects)) - { + if((bottype == BotfocusManaCost || bottype == BotfocusImprovedHeal || bottype == BotfocusImprovedDamage) && RuleB(Spells, LiveLikeFocusEffects)) rand_effectiveness = true; - } //Check if item focus effect exists for the client. - if (itembonuses.FocusEffects[bottype]){ - + if (itembonuses.FocusEffects[bottype]) { const Item_Struct* TempItem = 0; const Item_Struct* UsedItem = 0; const ItemInst* TempInst = 0; @@ -6117,35 +5283,25 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { int32 Total = 0; int32 focus_max = 0; int32 focus_max_real = 0; - //item focus - for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) - { + for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetBotItem(x); if (!ins) continue; + TempItem = ins->GetItem(); if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcBotFocusEffect(bottype, TempItem->Focus.Effect, spell_id, true); - if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } else if (focus_max < 0 && focus_max < focus_max_real) { + if ((focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) || (focus_max < 0 && focus_max < focus_max_real)) { focus_max_real = focus_max; UsedItem = TempItem; UsedFocusID = TempItem->Focus.Effect; } - } - else { + } else { Total = CalcBotFocusEffect(bottype, TempItem->Focus.Effect, spell_id); - if (Total > 0 && realTotal >= 0 && Total > realTotal) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItem->Focus.Effect; - } else if (Total < 0 && Total < realTotal) { + if ((Total > 0 && realTotal >= 0 && Total > realTotal) || (Total < 0 && Total < realTotal)) { realTotal = Total; UsedItem = TempItem; UsedFocusID = TempItem->Focus.Effect; @@ -6153,33 +5309,22 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } } - for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y) - { + for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); - if(aug) - { + if(aug) { const Item_Struct* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id, true); - if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) { - focus_max_real = focus_max; - UsedItem = TempItem; - UsedFocusID = TempItemAug->Focus.Effect; - } else if (focus_max < 0 && focus_max < focus_max_real) { + if ((focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) || (focus_max < 0 && focus_max < focus_max_real)) { focus_max_real = focus_max; UsedItem = TempItem; UsedFocusID = TempItemAug->Focus.Effect; } - } - else { + } else { Total = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id); - if (Total > 0 && realTotal >= 0 && Total > realTotal) { - realTotal = Total; - UsedItem = TempItem; - UsedFocusID = TempItemAug->Focus.Effect; - } else if (Total < 0 && Total < realTotal) { + if ((Total > 0 && realTotal >= 0 && Total > realTotal) || (Total < 0 && Total < realTotal)) { realTotal = Total; UsedItem = TempItem; UsedFocusID = TempItemAug->Focus.Effect; @@ -6195,13 +5340,11 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } //Check if spell focus effect exists for the client. - if (spellbonuses.FocusEffects[bottype]){ - + if (spellbonuses.FocusEffects[bottype]) { //Spell Focus int32 Total2 = 0; int32 focus_max2 = 0; int32 focus_max_real2 = 0; - int buff_tracker = -1; int buff_slot = 0; uint32 focusspellid = 0; @@ -6214,23 +5357,14 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { if(rand_effectiveness) { focus_max2 = CalcBotFocusEffect(bottype, focusspellid, spell_id, true); - if (focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) { - focus_max_real2 = focus_max2; - buff_tracker = buff_slot; - focusspell_tracker = focusspellid; - } else if (focus_max2 < 0 && focus_max2 < focus_max_real2) { + if ((focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) || (focus_max2 < 0 && focus_max2 < focus_max_real2)) { focus_max_real2 = focus_max2; buff_tracker = buff_slot; focusspell_tracker = focusspellid; } - } - else { + } else { Total2 = CalcBotFocusEffect(bottype, focusspellid, spell_id); - if (Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) { - realTotal2 = Total2; - buff_tracker = buff_slot; - focusspell_tracker = focusspellid; - } else if (Total2 < 0 && Total2 < realTotal2) { + if ((Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) || (Total2 < 0 && Total2 < realTotal2)) { realTotal2 = Total2; buff_tracker = buff_slot; focusspell_tracker = focusspellid; @@ -6242,9 +5376,8 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { realTotal2 = CalcBotFocusEffect(bottype, focusspell_tracker, spell_id); // For effects like gift of mana that only fire once, save the spellid into an array that consists of all available buff slots. - if(buff_tracker >= 0 && buffs[buff_tracker].numhits > 0) { + if(buff_tracker >= 0 && buffs[buff_tracker].numhits > 0) m_spellHitsLeft[buff_tracker] = focusspell_tracker; - } } // AA Focus @@ -6281,13 +5414,10 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { if(bottype == BotfocusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) return 100; - if(bottype == BotfocusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))){ + if(bottype == BotfocusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) return 0; - //Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected - //by reagent conservation for obvious reasons. - } - return realTotal + realTotal2; + return (realTotal + realTotal2); } int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus) { @@ -6296,433 +5426,317 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel const SPDat_Spell_Struct &focus_spell = spells[focus_id]; const SPDat_Spell_Struct &spell = spells[spell_id]; - int32 value = 0; int lvlModifier = 100; int spell_level = 0; int lvldiff = 0; bool LimitSpellSkill = false; bool SpellSkill_Found = false; - for (int i = 0; i < EFFECT_COUNT; i++) { switch (focus_spell.effectid[i]) { - case SE_Blank: - break; - //check limits - - case SE_LimitResist:{ - if(focus_spell.base[i]){ - if(spell.resisttype != focus_spell.base[i]) - return(0); - } - break; - } - case SE_LimitInstant:{ - if(spell.buffduration) - return(0); - break; - } - - case SE_LimitMaxLevel:{ - if (IsNPC()) + case SE_Blank: break; - spell_level = spell.classes[(GetClass()%16) - 1]; - lvldiff = spell_level - focus_spell.base[i]; - //every level over cap reduces the effect by focus_spell.base2[i] percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) - { - if(focus_spell.base2[i] > 0) - { - lvlModifier -= focus_spell.base2[i]*lvldiff; - if(lvlModifier < 1) + case SE_LimitResist:{ + if(focus_spell.base[i]) { + if(spell.resisttype != focus_spell.base[i]) return 0; } - else - { - return 0; - } - } - break; - } - - case SE_LimitMinLevel: - if (IsNPC()) break; - if (spell.classes[(GetClass()%16) - 1] < focus_spell.base[i]) - return(0); - break; - - case SE_LimitCastTimeMin: - if (spells[spell_id].cast_time < (uint32)focus_spell.base[i]) - return(0); - break; - - case SE_LimitSpell: - if(focus_spell.base[i] < 0) { //exclude spell - if (spell_id == (focus_spell.base[i]*-1)) - return(0); - } else { - //this makes the assumption that only one spell can be explicitly included... - if (spell_id != focus_spell.base[i]) - return(0); } - break; - - case SE_LimitMinDur: - if (focus_spell.base[i] > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - return(0); - break; - - case SE_LimitEffect: - if(focus_spell.base[i] < 0){ - if(IsEffectInSpell(spell_id,focus_spell.base[i])){ //we limit this effect, can't have + case SE_LimitInstant: { + if(spell.buffduration) return 0; - } + break; } - else{ - if(focus_spell.base[i] == SE_SummonPet) //summoning haste special case - { //must have one of the three pet effects to qualify - if(!IsEffectInSpell(spell_id, SE_SummonPet) && - !IsEffectInSpell(spell_id, SE_NecPet) && - !IsEffectInSpell(spell_id, SE_SummonBSTPet)) - { - return 0; + case SE_LimitMaxLevel:{ + if (IsNPC()) + break; + spell_level = spell.classes[(GetClass() % 16) - 1]; + lvldiff = (spell_level - focus_spell.base[i]); + if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { + if(focus_spell.base2[i] > 0) { + lvlModifier -= (focus_spell.base2[i] * lvldiff); + if(lvlModifier < 1) + return 0; } + else + return 0; } - else if(!IsEffectInSpell(spell_id,focus_spell.base[i])){ //we limit this effect, must have + break; + } + case SE_LimitMinLevel: + if (IsNPC()) + break; + if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) return 0; + break; + + case SE_LimitCastTimeMin: + if (spells[spell_id].cast_time < (uint32)focus_spell.base[i]) + return 0; + break; + case SE_LimitSpell: + if(focus_spell.base[i] < 0) { + if (spell_id == (focus_spell.base[i] * -1)) + return 0; + } else { + if (spell_id != focus_spell.base[i]) + return 0; } - } - break; - - - case SE_LimitSpellType: - switch( focus_spell.base[i] ) - { - case 0: - if (!IsDetrimentalSpell(spell_id)) + break; + case SE_LimitMinDur: + if (focus_spell.base[i] > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + return 0; + break; + case SE_LimitEffect: + if(focus_spell.base[i] < 0) { + if(IsEffectInSpell(spell_id,focus_spell.base[i])) return 0; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) + } else { + if(focus_spell.base[i] == SE_SummonPet) { + if(!IsEffectInSpell(spell_id, SE_SummonPet) && !IsEffectInSpell(spell_id, SE_NecPet) && !IsEffectInSpell(spell_id, SE_SummonBSTPet)) { + return 0; + } + } else if(!IsEffectInSpell(spell_id,focus_spell.base[i])) return 0; - break; - default: - Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]); - } - break; - - case SE_LimitManaMin: + } + break; + + + case SE_LimitSpellType: + switch(focus_spell.base[i]) { + case 0: + if (!IsDetrimentalSpell(spell_id)) + return 0; + break; + case 1: + if (!IsBeneficialSpell(spell_id)) + return 0; + break; + default: + Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]); + } + break; + + case SE_LimitManaMin: if(spell.mana < focus_spell.base[i]) return 0; - break; - - case SE_LimitTarget: - // Exclude - if((focus_spell.base[i] < 0) && -focus_spell.base[i] == spell.targettype) - return 0; - // Include - else if (focus_spell.base[i] > 0 && focus_spell.base[i] != spell.targettype) - return 0; - - break; - - case SE_LimitCombatSkills: - // 1 is for disciplines only + break; + case SE_LimitTarget: + if((focus_spell.base[i] < 0) && -focus_spell.base[i] == spell.targettype) + return 0; + else if (focus_spell.base[i] > 0 && focus_spell.base[i] != spell.targettype) + return 0; + break; + case SE_LimitCombatSkills: if(focus_spell.base[i] == 1 && !IsDiscipline(spell_id)) return 0; - // 0 is for spells only else if(focus_spell.base[i] == 0 && IsDiscipline(spell_id)) return 0; - break; - - case SE_LimitSpellGroup: + break; + case SE_LimitSpellGroup: if(focus_spell.base[i] > 0 && focus_spell.base[i] != spell.spellgroup) return 0; else if(focus_spell.base[i] < 0 && focus_spell.base[i] == spell.spellgroup) return 0; - break; - - case SE_LimitCastingSkill: + break; + case SE_LimitCastingSkill: LimitSpellSkill = true; if(focus_spell.base[i] == spell.skill) SpellSkill_Found = true; - break; - - case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(focus_spell.base[i], GetClass())) - return 0; - break; - - //handle effects - case SE_ImprovedDamage: - // No Spell used this, its handled by different spell effect IDs. - if (bottype == BotfocusImprovedDamage) { - // This is used to determine which focus should be used for the random calculation - if(best_focus) { - // If the spell contains a value in the base2 field then that is the max value - if (focus_spell.base2[i] != 0) { - value = focus_spell.base2[i]; - } - // If the spell does not contain a base2 value, then its a straight non random value - else { - value = focus_spell.base[i]; - } - } - // Actual focus calculation starts here - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { - value = focus_spell.base[i]; - } - else { - value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); - } - } - break; - case SE_ImprovedHeal: - if (bottype == BotfocusImprovedHeal) { - if(best_focus) { - if (focus_spell.base2[i] != 0) { - value = focus_spell.base2[i]; - } - else { - value = focus_spell.base[i]; - } - } - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { - value = focus_spell.base[i]; - } - else { - value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); - } - } - break; - case SE_ReduceManaCost: - if (bottype == BotfocusManaCost) { - if(best_focus) { - if (focus_spell.base2[i] != 0) { - value = focus_spell.base2[i]; - } - else { - value = focus_spell.base[i]; - } - } - else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { - value = focus_spell.base[i]; - } - else { - value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); - } - } - break; - - case SE_IncreaseSpellHaste: - if (bottype == BotfocusSpellHaste && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_IncreaseSpellDuration: - if (bottype == BotfocusSpellDuration && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SpellDurationIncByTic: - if (bottype == BotfocusSpellDurByTic && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SwarmPetDuration: - if (bottype == BotfocusSwarmPetDuration && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_IncreaseRange: - if (bottype == BotfocusRange && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_ReduceReagentCost: - if (bottype == BotfocusReagentCost && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_PetPowerIncrease: - if (bottype == BotfocusPetPower && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SpellResistReduction: - if (bottype == BotfocusResistRate && focus_spell.base[i] > value) - { - value = focus_spell.base[i]; - } - break; - case SE_SpellHateMod: - if (bottype == BotfocusSpellHateMod) - { - if(value != 0) - { - if(value > 0) - { - if(focus_spell.base[i] > value) - { + break; + case SE_LimitClass: + if (!PassLimitClass(focus_spell.base[i], GetClass())) + return 0; + break; + case SE_ImprovedDamage: + if (bottype == BotfocusImprovedDamage) { + if(best_focus) { + if (focus_spell.base2[i] != 0) + value = focus_spell.base2[i]; + else value = focus_spell.base[i]; - } } + else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) + value = focus_spell.base[i]; else - { - if(focus_spell.base[i] < value) - { - value = focus_spell.base[i]; - } - } + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); } - else + break; + case SE_ImprovedHeal: + if (bottype == BotfocusImprovedHeal) { + if(best_focus) { + if (focus_spell.base2[i] != 0) + value = focus_spell.base2[i]; + else + value = focus_spell.base[i]; + } + else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) + value = focus_spell.base[i]; + else + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); + } + break; + case SE_ReduceManaCost: + if (bottype == BotfocusManaCost) { + if(best_focus) { + if (focus_spell.base2[i] != 0) + value = focus_spell.base2[i]; + else + value = focus_spell.base[i]; + } + else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) + value = focus_spell.base[i]; + else + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); + } + break; + case SE_IncreaseSpellHaste: + if (bottype == BotfocusSpellHaste && focus_spell.base[i] > value) value = focus_spell.base[i]; + break; + case SE_IncreaseSpellDuration: + if (bottype == BotfocusSpellDuration && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SpellDurationIncByTic: + if (bottype == BotfocusSpellDurByTic && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SwarmPetDuration: + if (bottype == BotfocusSwarmPetDuration && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_IncreaseRange: + if (bottype == BotfocusRange && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_ReduceReagentCost: + if (bottype == BotfocusReagentCost && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_PetPowerIncrease: + if (bottype == BotfocusPetPower && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SpellResistReduction: + if (bottype == BotfocusResistRate && focus_spell.base[i] > value) + value = focus_spell.base[i]; + break; + case SE_SpellHateMod: + if (bottype == BotfocusSpellHateMod) { + if(value != 0) { + if(value > 0) { + if(focus_spell.base[i] > value) + value = focus_spell.base[i]; + } + else { + if(focus_spell.base[i] < value) + value = focus_spell.base[i]; + } + } else + value = focus_spell.base[i]; + } + break; + case SE_ReduceReuseTimer: { + if(bottype == BotfocusReduceRecastTime) + value = (focus_spell.base[i] / 1000); + break; } - break; - - case SE_ReduceReuseTimer: - { - if(bottype == BotfocusReduceRecastTime) - value = focus_spell.base[i] / 1000; - - break; - } - - case SE_TriggerOnCast: - { - if(bottype == BotfocusTriggerOnCast) - - if(zone->random.Int(0, 100) <= focus_spell.base[i]) - value = focus_spell.base2[i]; - - else - value = 0; - - break; - } - case SE_FcSpellVulnerability: - { - if(bottype == BotfocusSpellVulnerability) - { - value = focus_spell.base[i]; + case SE_TriggerOnCast: { + if(bottype == BotfocusTriggerOnCast) { + if(zone->random.Int(0, 100) <= focus_spell.base[i]) + value = focus_spell.base2[i]; + else + value = 0; + } + break; } - break; - } - case SE_BlockNextSpellFocus: - { - if(bottype == BotfocusBlockNextSpell) - { - if(zone->random.Int(1, 100) <= focus_spell.base[i]) - value = 1; + case SE_FcSpellVulnerability: { + if(bottype == BotfocusSpellVulnerability) + value = focus_spell.base[i]; + break; } - break; - } - case SE_FcTwincast: - { - if(bottype == BotfocusTwincast) - { - value = focus_spell.base[i]; + case SE_BlockNextSpellFocus: { + if(bottype == BotfocusBlockNextSpell) { + if(zone->random.Int(1, 100) <= focus_spell.base[i]) + value = 1; + } + break; } - break; - } - case SE_SympatheticProc: - { - if(bottype == BotfocusSympatheticProc) - { - - float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]); - - if(zone->random.Real(0, 1) <= ProcChance) - value = focus_id; - - else - value = 0; + case SE_FcTwincast: { + if(bottype == BotfocusTwincast) + value = focus_spell.base[i]; + break; } - break; - } - case SE_FcDamageAmt: - { - if(bottype == BotfocusFcDamageAmt) - value = focus_spell.base[i]; - - break; - } - - case SE_FcDamageAmtCrit: - { - if(bottype == BotfocusFcDamageAmtCrit) - value = focus_spell.base[i]; - - break; - } - - case SE_FcHealAmtIncoming: - if(bottype == BotfocusFcHealAmtIncoming) - value = focus_spell.base[i]; - break; - - case SE_FcHealPctCritIncoming: - if (bottype == BotfocusFcHealPctCritIncoming) - value = focus_spell.base[i]; - break; - - case SE_FcHealAmtCrit: - if(bottype == BotfocusFcHealAmtCrit) - value = focus_spell.base[i]; - break; - - case SE_FcHealAmt: - if(bottype == BotfocusFcHealAmt) - value = focus_spell.base[i]; - break; - - case SE_FcHealPctIncoming: - if(bottype == BotfocusFcHealPctIncoming) - value = focus_spell.base[i]; - break; - - case SE_FcBaseEffects: - { - if (bottype == BotfocusFcBaseEffects) - value = focus_spell.base[i]; - - break; - } - case SE_FcDamagePctCrit: - { - if(bottype == BotfocusFcDamagePctCrit) - value = focus_spell.base[i]; - - break; - } - - case SE_FcIncreaseNumHits: - { - if(bottype == BotfocusIncreaseNumHits) - value = focus_spell.base[i]; - - break; - } - //this spits up a lot of garbage when calculating spell focuses - //since they have all kinds of extra effects on them. - default: - Log.Out(Logs::General, Logs::Spells, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]); + case SE_SympatheticProc: { + if(bottype == BotfocusSympatheticProc) { + float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]); + if(zone->random.Real(0, 1) <= ProcChance) + value = focus_id; + else + value = 0; + } + break; + } + case SE_FcDamageAmt: { + if(bottype == BotfocusFcDamageAmt) + value = focus_spell.base[i]; + break; + } + case SE_FcDamageAmtCrit: { + if(bottype == BotfocusFcDamageAmtCrit) + value = focus_spell.base[i]; + break; + } + case SE_FcHealAmtIncoming: + if(bottype == BotfocusFcHealAmtIncoming) + value = focus_spell.base[i]; + break; + case SE_FcHealPctCritIncoming: + if (bottype == BotfocusFcHealPctCritIncoming) + value = focus_spell.base[i]; + break; + case SE_FcHealAmtCrit: + if(bottype == BotfocusFcHealAmtCrit) + value = focus_spell.base[i]; + break; + case SE_FcHealAmt: + if(bottype == BotfocusFcHealAmt) + value = focus_spell.base[i]; + break; + case SE_FcHealPctIncoming: + if(bottype == BotfocusFcHealPctIncoming) + value = focus_spell.base[i]; + break; + case SE_FcBaseEffects: { + if (bottype == BotfocusFcBaseEffects) + value = focus_spell.base[i]; + + break; + } + case SE_FcDamagePctCrit: { + if(bottype == BotfocusFcDamagePctCrit) + value = focus_spell.base[i]; + + break; + } + case SE_FcIncreaseNumHits: { + if(bottype == BotfocusIncreaseNumHits) + value = focus_spell.base[i]; + + break; + } + default: + Log.Out(Logs::General, Logs::Spells, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]); + break; } } //Check for spell skill limits. if ((LimitSpellSkill) && (!SpellSkill_Found)) return 0; - return(value*lvlModifier/100); + return(value * lvlModifier / 100); } //proc chance includes proc bonus @@ -6742,38 +5756,23 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { break; } - //calculate the weapon speed in ms, so we can use the rule to compare against. - // fast as a client can swing, so should be the floor of the proc chance if (weapon_speed < RuleI(Combat, MinHastedDelay)) weapon_speed = RuleI(Combat, MinHastedDelay); if (RuleB(Combat, AdjustProcPerMinute)) { - ProcChance = (static_cast(weapon_speed) * - RuleR(Combat, AvgProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms + ProcChance = (static_cast(weapon_speed) * RuleR(Combat, AvgProcsPerMinute) / 60000.0f); ProcBonus += static_cast(mydex) * RuleR(Combat, ProcPerMinDexContrib); - ProcChance += ProcChance * ProcBonus / 100.0f; + ProcChance += (ProcChance * ProcBonus / 100.0f); } else { - ProcChance = RuleR(Combat, BaseProcChance) + - static_cast(mydex) / RuleR(Combat, ProcDexDivideBy); - ProcChance += ProcChance*ProcBonus / 100.0f; + ProcChance = (RuleR(Combat, BaseProcChance) + static_cast(mydex) / RuleR(Combat, ProcDexDivideBy)); + ProcChance += (ProcChance * ProcBonus / 100.0f); } Log.Out(Logs::Detail, Logs::Combat, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); return ProcChance; } -bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) -{ - /* called when a mob is attacked, does the checks to see if it's a hit - * and does other mitigation checks. 'this' is the mob being attacked. - * - * special return values: - * -1 - block - * -2 - parry - * -3 - riposte - * -4 - dodge - * - */ +bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) { if(GetAppearance() == eaDead) return false; @@ -6781,76 +5780,52 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float bonus = 0; float RollTable[4] = {0,0,0,0}; float roll = 0; - Mob *attacker=other; - Mob *defender=this; + Mob *attacker = other; + Mob *defender = this; - //garunteed hit bool ghit = false; if((attacker->GetSpellBonuses().MeleeSkillCheck + attacker->GetItemBonuses().MeleeSkillCheck) > 500) ghit = true; - ////////////////////////////////////////////////////////// - // make enrage same as riposte - ///////////////////////////////////////////////////////// if (IsEnraged() && !other->BehindMob(this, other->GetX(), other->GetY())) { damage = -3; Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); } - - ///////////////////////////////////////////////////////// - // riposte - ///////////////////////////////////////////////////////// + float riposte_chance = 0.0f; - if (CanRiposte && damage > 0 && CanThisClassRiposte() && !other->BehindMob(this, other->GetX(), other->GetY())) - { - riposte_chance = (100.0f + (float)defender->GetAABonuses().RiposteChance + (float)defender->GetSpellBonuses().RiposteChance + (float)defender->GetItemBonuses().RiposteChance) / 100.0f; + if (CanRiposte && damage > 0 && CanThisClassRiposte() && !other->BehindMob(this, other->GetX(), other->GetY())) { + riposte_chance = ((100.0f + (float)defender->GetAABonuses().RiposteChance + (float)defender->GetSpellBonuses().RiposteChance + (float)defender->GetItemBonuses().RiposteChance) / 100.0f); skill = GetSkill(SkillRiposte); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); + if (!ghit) { + bonus = (2.0 + skill / 60.0 + (GetDEX() / 200)); bonus *= riposte_chance; - RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block + RollTable[0] = (bonus + (itembonuses.HeroicDEX / 25)); } } - - /////////////////////////////////////////////////////// - // block - /////////////////////////////////////////////////////// - + bool bBlockFromRear = false; bool bShieldBlockFromRear = false; - if (this->IsBot()) { int aaChance = 0; - - // a successful roll on this does not mean a successful block is forthcoming. only that a chance to block - // from a direction other than the rear is granted. - - //Live AA - HightenedAwareness - int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind; - + int BlockBehindChance = (aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind); if (BlockBehindChance && (BlockBehindChance > zone->random.Int(1, 100))){ bBlockFromRear = true; - if (spellbonuses.BlockBehind || itembonuses.BlockBehind) - bShieldBlockFromRear = true; //This bonus should allow a chance to Shield Block from behind. + bShieldBlockFromRear = true; } } float block_chance = 0.0f; if (damage > 0 && CanThisClassBlock() && (!other->BehindMob(this, other->GetX(), other->GetY()) || bBlockFromRear)) { - block_chance = (100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f; + block_chance = ((100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f); skill = GetSkill(SkillBlock); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/35.0 + (GetDEX()/200); - RollTable[1] = RollTable[0] + (bonus * block_chance) - riposte_chance; - block_chance *= bonus; // set this so we can remove it from the parry calcs + if (!ghit) { + bonus = (2.0 + skill / 35.0 + (GetDEX() / 200)); + RollTable[1] = (RollTable[0] + (bonus * block_chance) - riposte_chance); + block_chance *= bonus; } - } - else{ + } else RollTable[1] = RollTable[0]; - } if(damage > 0 && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (!other->BehindMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { @@ -6859,10 +5834,8 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) uint8 shield = GetBotItem(MainSecondary)->GetItem()->ItemType; float bonusShieldBlock = 0.0f; if(shield == ItemTypeShield) { - - //Live AA - Shield Block - bonusShieldBlock = aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock; - RollTable[1] = RollTable[0] + bonusShieldBlock; + bonusShieldBlock = (aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock); + RollTable[1] = (RollTable[0] + bonusShieldBlock); } } } @@ -6874,79 +5847,58 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) uint8 TwoHandBlunt = GetBotItem(MainPrimary)->GetItem()->ItemType; float bonusStaffBlock = 0.0f; if(TwoHandBlunt == ItemType2HBlunt) { - - bonusStaffBlock = aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock; - RollTable[1] = RollTable[0] + bonusStaffBlock; + bonusStaffBlock = (aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock); + RollTable[1] = (RollTable[0] + bonusStaffBlock); } } } - ////////////////////////////////////////////////////// - // parry - ////////////////////////////////////////////////////// float parry_chance = 0.0f; - if (damage > 0 && CanThisClassParry() && !other->BehindMob(this, other->GetX(), other->GetY())) - { - parry_chance = (100.0f + (float)defender->GetSpellBonuses().ParryChance + (float)defender->GetItemBonuses().ParryChance) / 100.0f; + if (damage > 0 && CanThisClassParry() && !other->BehindMob(this, other->GetX(), other->GetY())) { + parry_chance = ((100.0f + (float)defender->GetSpellBonuses().ParryChance + (float)defender->GetItemBonuses().ParryChance) / 100.0f); skill = GetSkill(SkillParry); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); + if (!ghit) { + bonus = (2.0 + skill / 60.0 + (GetDEX() / 200)); bonus *= parry_chance; - RollTable[2] = RollTable[1] + bonus - block_chance; + RollTable[2] = (RollTable[1] + bonus - block_chance); } - } - else{ - RollTable[2] = RollTable[1] - block_chance; - } + } else + RollTable[2] = (RollTable[1] - block_chance); - //////////////////////////////////////////////////////// - // dodge - //////////////////////////////////////////////////////// float dodge_chance = 0.0f; - if (damage > 0 && CanThisClassDodge() && !other->BehindMob(this, other->GetX(), other->GetY())) - { - dodge_chance = (100.0f + (float)defender->GetSpellBonuses().DodgeChance + (float)defender->GetItemBonuses().DodgeChance) / 100.0f; + if (damage > 0 && CanThisClassDodge() && !other->BehindMob(this, other->GetX(), other->GetY())) { + dodge_chance = ((100.0f + (float)defender->GetSpellBonuses().DodgeChance + (float)defender->GetItemBonuses().DodgeChance) / 100.0f); skill = GetSkill(SkillDodge); - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetAGI()/200); + if (!ghit) { + bonus = (2.0 + skill / 60.0 + (GetAGI() / 200)); bonus *= dodge_chance; - RollTable[3] = RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance; // Remove the dex as it doesnt count for dodge + RollTable[3] = (RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance); } - } - else{ - RollTable[3] = RollTable[2] - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance; + } else { + RollTable[3] = (RollTable[2] - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25) - parry_chance); } - if(damage > 0) - { + if(damage > 0) { roll = zone->random.Real(0,100); - if(roll <= RollTable[0]){ + if(roll <= RollTable[0]) damage = -3; - } - else if(roll <= RollTable[1]){ + else if(roll <= RollTable[1]) damage = -1; - } - else if(roll <= RollTable[2]){ + else if(roll <= RollTable[2]) damage = -2; - } - else if(roll <= RollTable[3]){ + else if(roll <= RollTable[3]) damage = -4; - } } Log.Out(Logs::Detail, Logs::Combat, "Final damage after all avoidances: %d", damage); if (damage < 0) return true; + return false; } -int Bot::GetMonkHandToHandDamage(void) -{ - // Kaiyodo - Determine a monk's fist damage. Table data from www.monkly-business.com - // saved as static array - this should speed this function up considerably +int Bot::GetMonkHandToHandDamage(void) { static int damage[66] = { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 99, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, @@ -6954,15 +5906,11 @@ int Bot::GetMonkHandToHandDamage(void) 12,12,12,12,12,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14, 14,14,15,15,15,15 }; - // Have a look to see if we have epic fists on - uint32 botWeaponId = INVALID_ID; botWeaponId = CastToNPC()->GetEquipment(MaterialHands); - if(botWeaponId == 10652) { //Monk Epic ID + if(botWeaponId == 10652) return 9; - } - else - { + else { int Level = GetLevel(); if(Level > 65) return 19; @@ -6972,30 +5920,25 @@ int Bot::GetMonkHandToHandDamage(void) int Level = GetLevel(); if (Level > 65) - return(19); + return 19; else return damage[Level]; } -bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) -{ +bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) { if (!defender) return false; - if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10){ - - uint32 chance = aabonuses.FinishingBlow[0]/10; //500 = 5% chance. + if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10) { + uint32 chance = (aabonuses.FinishingBlow[0] / 10); uint32 damage = aabonuses.FinishingBlow[1]; uint16 levelreq = aabonuses.FinishingBlowLvl[0]; - if(defender->GetLevel() <= levelreq && (chance >= zone->random.Int(0, 1000))){ Log.Out(Logs::Detail, Logs::Combat, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse); return true; - } - else - { + } else { Log.Out(Logs::Detail, Logs::Combat, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); return false; } @@ -7005,27 +5948,17 @@ bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) void Bot::DoRiposte(Mob* defender) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a riposte"); - if (!defender) return; defender->Attack(this, MainPrimary, true); - - //double riposte - int32 DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[0] + - defender->GetSpellBonuses().GiveDoubleRiposte[0] + - defender->GetItemBonuses().GiveDoubleRiposte[0]; - + int32 DoubleRipChance = (defender->GetAABonuses().GiveDoubleRiposte[0] + defender->GetSpellBonuses().GiveDoubleRiposte[0] + defender->GetItemBonuses().GiveDoubleRiposte[0]); if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposte (%d percent chance)", DoubleRipChance); - defender->Attack(this, MainPrimary, true); } - //Double Riposte effect, allows for a chance to do RIPOSTE with a skill specfic special attack (ie Return Kick). - //Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill] DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1]; - if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { if (defender->GetClass() == MONK) defender->MonkSpecialAttack(this, defender->GetAABonuses().GiveDoubleRiposte[2]); @@ -7035,9 +5968,6 @@ void Bot::DoRiposte(Mob* defender) { } void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, bool HitChance) { - //this really should go through the same code as normal melee damage to - //pick up all the special behavior there - int32 hate = max_damage; if(hate_override > -1) hate = hate_override; @@ -7047,22 +5977,21 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); + if(botweapon) { - if(botweapon->ItemType == ItemTypeShield) { + if(botweapon->ItemType == ItemTypeShield) hate += botweapon->AC; - } - hate = hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100; + + hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); } } - min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; - + min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); if(HitChance && !who->CheckHitChance(this, skill, MainPrimary)) max_damage = 0; - - else{ + else { bool CanRiposte = true; - if(skill == SkillThrowing || skill == SkillArchery) // changed from '&&' + if(skill == SkillThrowing || skill == SkillArchery) CanRiposte = false; who->AvoidDamage(this, max_damage, CanRiposte); @@ -7071,18 +6000,18 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(max_damage > 0) { ApplyMeleeDamageBonus(skill, max_damage); max_damage += who->GetFcDamageAmtIncoming(this, 0, true, skill); - max_damage += (itembonuses.HeroicSTR / 10) + (max_damage * who->GetSkillDmgTaken(skill) / 100) + GetSkillDmgAmt(skill); + max_damage += ((itembonuses.HeroicSTR / 10) + (max_damage * who->GetSkillDmgTaken(skill) / 100) + GetSkillDmgAmt(skill)); TryCriticalHit(who, skill, max_damage); } } - if(max_damage >= 0) //You should probably get aggro no matter what, but unclear why it was set like this. + if(max_damage >= 0) who->AddToHateList(this, hate); who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false); - if(!GetTarget())return; - if (HasDied()) return; + if(!GetTarget() || HasDied()) + return; if (max_damage > 0) CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); @@ -7090,7 +6019,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill /* if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){ int kb_chance = 25; - kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100; + kb_chance += (kb_chance * (100 - aabonuses.SpecialAttackKBProc[0]) / 100); if (zone->random.Int(0, 99) < kb_chance) SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff); @@ -7098,10 +6027,10 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, }*/ if (HasSkillProcs()) - TrySkillProc(who, skill, ReuseTime*1000); + TrySkillProc(who, skill, (ReuseTime * 1000)); if (max_damage > 0 && HasSkillProcSuccess()) - TrySkillProc(who, skill, ReuseTime*1000, true); + TrySkillProc(who, skill, (ReuseTime * 1000), true); if(max_damage == -3 && !(who->GetHP() <= 0)) DoRiposte(who); @@ -7113,53 +6042,35 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; - const ItemInst* inst = GetBotItem(MainPrimary); const Item_Struct* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); + if(!botpiercer || (botpiercer->ItemType != ItemType1HPiercing)) { - Say("I can't backstab with this weapon!"); + BotGroupSay(this, "I can't backstab with this weapon!"); return; } - //Live AA - Triple Backstab - int tripleChance = itembonuses.TripleBackstab + spellbonuses.TripleBackstab + aabonuses.TripleBackstab; - - if (BehindMob(other, GetX(), GetY())) { + int tripleChance = (itembonuses.TripleBackstab + spellbonuses.TripleBackstab + aabonuses.TripleBackstab); + if (BehindMob(other, GetX(), GetY())) bIsBehind = true; - } else { - //Live AA - Seized Opportunity - int FrontalBSChance = itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance; - + int FrontalBSChance = (itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance); if (FrontalBSChance && (FrontalBSChance > zone->random.Int(0, 100))) bCanFrontalBS = true; } - if (bIsBehind || bCanFrontalBS){ // Bot is behind other OR can do Frontal Backstab - - // 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 && // bot is 60 or higher - other->GetLevel() <= 45 && // mob 45 or under - !other->CastToNPC()->IsEngaged() && // not aggro - other->GetHP()<=32000 - && other->IsNPC() - && zone->random.Real(0, 99) < chance // chance - ) { + if (bIsBehind || bCanFrontalBS) { + int chance = (10 + (GetDEX() / 10) + (itembonuses.HeroicDEX / 10)); + if(level >= 60 && other->GetLevel() <= 45 && !other->CastToNPC()->IsEngaged() && other->GetHP()<= 32000 && other->IsNPC() && zone->random.Real(0, 99) < chance) { entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); RogueAssassinate(other); - } - else { + } 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(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA - { + float DoubleAttackProbability = ((GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f); + if(zone->random.Real(0, 1) < DoubleAttackProbability) { if(other->GetHP() > 0) RogueBackstab(other,false,ReuseTime); @@ -7168,169 +6079,125 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } } } - } - //Live AA - Chaotic Backstab - else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { - - //we can stab from any angle, we do min damage though. + } else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { RogueBackstab(other, true); 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(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA + float DoubleAttackProbability = ((GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f); + if(zone->random.Real(0, 1) < DoubleAttackProbability) if(other->GetHP() > 0) RogueBackstab(other,true, ReuseTime); if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100)) - RogueBackstab(other,false,ReuseTime); + RogueBackstab(other,false,ReuseTime); } } - else { //We do a single regular attack if we attack from the front without chaotic stab + else Attack(other, MainPrimary); - } } -//heko: backstab -void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) -{ +void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { int32 ndamage = 0; int32 max_hit = 0; int32 min_hit = 0; int32 hate = 0; int32 primaryweapondamage = 0; int32 backstab_dmg = 0; - ItemInst* botweaponInst = GetBotItem(MainPrimary); if(botweaponInst) { primaryweapondamage = GetWeaponDamage(other, botweaponInst); backstab_dmg = botweaponInst->GetItem()->BackstabDmg; - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) - { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = botweaponInst->GetAugment(i); if(aug) - { backstab_dmg += aug->GetItem()->BackstabDmg; - } } - } - else - { - primaryweapondamage = (GetLevel()/7)+1; // fallback incase it's a npc without a weapon, 2 dmg at 10, 10 dmg at 65 + } else { + primaryweapondamage = ((GetLevel() / 7) + 1); backstab_dmg = primaryweapondamage; } - if(primaryweapondamage > 0){ - if(level > 25){ - max_hit = (((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level-25)/3) + 1; - hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; - } - else{ - max_hit = (((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1; - hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; + if(primaryweapondamage > 0) { + if(level > 25) { + max_hit = (((((2 * backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level - 25) / 3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); + hate = (20 * backstab_dmg * GetSkill(SkillBackstab) / 355); + } else { + max_hit = (((((2 * backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); + hate = (20 * backstab_dmg * GetSkill(SkillBackstab) / 355); } - // determine minimum hits if (level < 51) - { - min_hit = (level*15/10); - } + min_hit = (level * 15 / 10); else - { - // Trumpcard: Replaced switch statement with formula calc. This will give minhit increases all the way to 65. - min_hit = (level * ( level*5 - 105)) / 100; - } + min_hit = ((level * ( level * 5 - 105)) / 100); - if(!other->CheckHitChance(this, SkillBackstab, 0)) { + if(!other->CheckHitChance(this, SkillBackstab, 0)) ndamage = 0; - } - else{ - if(min_damage){ + else { + if (min_damage) { ndamage = min_hit; - } - else - { + } else { if (max_hit < min_hit) max_hit = min_hit; - if(RuleB(Combat, UseIntervalAC)) - ndamage = max_hit; - else - ndamage = zone->random.Int(min_hit, max_hit); - + ndamage = (RuleB(Combat, UseIntervalAC) ? max_hit : zone->random.Int(min_hit, max_hit)); } } - } - else{ + } else ndamage = -5; - } DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime); DoAnim(animPiercing); } -void Bot::RogueAssassinate(Mob* other) -{ +void Bot::RogueAssassinate(Mob* other) { ItemInst* botweaponInst = GetBotItem(MainPrimary); if(botweaponInst) { - if(GetWeaponDamage(other, botweaponInst)) { + if(GetWeaponDamage(other, botweaponInst)) other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); - } - else { + else other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); - } } - DoAnim(animPiercing); //piercing animation + DoAnim(animPiercing); } void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { - if(!target) - return; - - if(spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0) - return; - - if(!IsAttackAllowed(target)) + if(!target || spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || GetHP() < 0 || !IsAttackAllowed(target)) return; bool taunt_time = taunt_timer.Check(); bool ca_time = classattack_timer.Check(false); bool ka_time = knightattack_timer.Check(false); - - //only check attack allowed if we are going to do something if((taunt_time || ca_time || ka_time) && !IsAttackAllowed(target)) return; if(ka_time){ - int knightreuse = 1000; //lets give it a small cooldown actually. + int knightreuse = 1000; switch(GetClass()){ - case SHADOWKNIGHT: case SHADOWKNIGHTGM:{ + case SHADOWKNIGHT: + case SHADOWKNIGHTGM: { CastSpell(SPELL_NPC_HARM_TOUCH, target->GetID()); - knightreuse = HarmTouchReuseTime * 1000; + knightreuse = (HarmTouchReuseTime * 1000); break; } - case PALADIN: case PALADINGM:{ + case PALADIN: + case PALADINGM: { if(GetHPRatio() < 20) { CastSpell(SPELL_LAY_ON_HANDS, GetID()); - knightreuse = LayOnHandsReuseTime * 1000; - } else { - knightreuse = 2000; //Check again in two seconds. + knightreuse = (LayOnHandsReuseTime * 1000); } + else + knightreuse = 2000; + break; } } knightattack_timer.Start(knightreuse); } - //general stuff, for all classes.... - //only gets used when their primary ability get used too - - //franck-add: EQoffline. Warrior bots must taunt the target. - if(taunting && target && target->IsNPC() && taunt_time ) { - //Only taunt if we are not top on target's hate list - //This ensures we have taunt available to regain aggro if needed + if(taunting && target && target->IsNPC() && taunt_time) { if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { - Say("Taunting %s", target->GetCleanName()); + BotGroupSay(this, "Taunting %s", target->GetCleanName()); Taunt(target->CastToNPC(), false); taunt_timer.Start(TauntReuseTime * 1000); } @@ -7339,287 +6206,193 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(!ca_time) return; - float HasteModifier = GetHaste() * 0.01f; + float HasteModifier = (GetHaste() * 0.01f); int32 dmg = 0; - uint16 skill_to_use = -1; - int level = GetLevel(); - int reuse = TauntReuseTime * 1000; //make this very long since if they dont use it once, they prolly never will + int reuse = (TauntReuseTime * 1000); bool did_attack = false; - - switch(GetClass()) - { - case WARRIOR: - if(level >= RuleI(Combat, NPCBashKickLevel)){ - bool canBash = false; - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) // Racial Slam - || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) //Using Shield - || (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash - || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt - || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing) - && GetAA(aa2HandBash) >= 1)) { //Using 2 hand weapon, but has AA 2 Hand Bash - canBash = true; + switch(GetClass()) { + case WARRIOR: + if(level >= RuleI(Combat, NPCBashKickLevel)){ + bool canBash = false; + if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + canBash = true; + + if(!canBash || zone->random.Int(0, 100) > 25) + skill_to_use = SkillKick; + else + skill_to_use = SkillBash; } - - if(!canBash || zone->random.Int(0, 100) > 25) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference. - skill_to_use = SkillKick; - } - else { - skill_to_use = SkillBash; - } - } - case RANGER: - case BEASTLORD: - skill_to_use = SkillKick; - break; - case BERSERKER: - skill_to_use = SkillFrenzy; - break; - case CLERIC: - case SHADOWKNIGHT: - case PALADIN: - if(level >= RuleI(Combat, NPCBashKickLevel)){ - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) // Racial Slam - || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) //Using Shield - || (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash - || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt - || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing) - && GetAA(aa2HandBash) >= 1)) { //Using 2 hand weapon, but has AA 2 Hand Bash - skill_to_use = SkillBash; - } - } - break; - case MONK: - if(GetLevel() >= 30) - { - skill_to_use = SkillFlyingKick; - } - else if(GetLevel() >= 25) - { - skill_to_use = SkillDragonPunch; - } - else if(GetLevel() >= 20) - { - skill_to_use = SkillEagleStrike; - } - else if(GetLevel() >= 10) - { - skill_to_use = SkillTigerClaw; - } - else if(GetLevel() >= 5) - { - skill_to_use = SkillRoundKick; - } - else - { + case RANGER: + case BEASTLORD: skill_to_use = SkillKick; - } - break; - case ROGUE: - skill_to_use = SkillBackstab; - break; + break; + case BERSERKER: + skill_to_use = SkillFrenzy; + break; + case CLERIC: + case SHADOWKNIGHT: + case PALADIN: + if(level >= RuleI(Combat, NPCBashKickLevel)){ + if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + skill_to_use = SkillBash; + } + break; + case MONK: + if(GetLevel() >= 30) + skill_to_use = SkillFlyingKick; + else if(GetLevel() >= 25) + skill_to_use = SkillDragonPunch; + else if(GetLevel() >= 20) + skill_to_use = SkillEagleStrike; + else if(GetLevel() >= 10) + skill_to_use = SkillTigerClaw; + else if(GetLevel() >= 5) + skill_to_use = SkillRoundKick; + else + skill_to_use = SkillKick; + break; + case ROGUE: + skill_to_use = SkillBackstab; + break; } if(skill_to_use == -1) return; - - if(skill_to_use == SkillBash) - { - if (target!=this) - { + if(skill_to_use == SkillBash) { + if (target != this) { DoAnim(animTailRake); - - if(GetWeaponDamage(target, GetBotItem(MainSecondary)) <= 0 && - GetWeaponDamage(target, GetBotItem(MainShoulders)) <= 0){ + if(GetWeaponDamage(target, GetBotItem(MainSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(MainShoulders)) <= 0) dmg = -5; - } - else{ - if(!target->CheckHitChance(this, SkillBash, 0)) { + else { + if(!target->CheckHitChance(this, SkillBash, 0)) dmg = 0; - } - else{ + else { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else dmg = zone->random.Int(1, GetBashDamage()); - } } - - reuse = BashReuseTime * 1000; - //reuse = (reuse*HasteModifier)/100; - - DoSpecialAttackDamage(target, SkillBash, dmg, 1,-1,reuse); - + reuse = (BashReuseTime * 1000); + DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1,reuse); did_attack = true; - - if(reuse > 0 && !IsRiposte) - { - //p_timers.Start(pTimerCombatAbility, reuse); - } } } - if(skill_to_use == SkillFrenzy) - { + if(skill_to_use == SkillFrenzy) { int AtkRounds = 3; int skillmod = 0; - if(MaxSkill(SkillFrenzy) > 0) - skillmod = 100*GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy); + skillmod = (100 * GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy)); - int32 max_dmg = (26 + ((((GetLevel()-6) * 2)*skillmod)/100)) * ((100+RuleI(Combat, FrenzyBonus))/100); + int32 max_dmg = (26 + ((((GetLevel() - 6) * 2) * skillmod) / 100)) * ((100 + RuleI(Combat, FrenzyBonus)) / 100); int32 min_dmg = 0; DoAnim(anim2HSlashing); if (GetLevel() < 51) min_dmg = 1; else - min_dmg = GetLevel()*8/10; + min_dmg = (GetLevel() * 8 / 10); if (min_dmg > max_dmg) max_dmg = min_dmg; - reuse = FrenzyReuseTime * 1000; - //reuse = (reuse * HasteModifier)/100; - + reuse = (FrenzyReuseTime * 1000); did_attack = true; - - //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. while(AtkRounds > 0) { - - if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0,100) < 75)){ - DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , reuse, true); + if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0, 100) < 75)) { + DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg, reuse, true); } - AtkRounds--; - } - if(reuse > 0 && !IsRiposte) { - //p_timers.Start(pTimerCombatAbility, reuse); + AtkRounds--; } } - if(skill_to_use == SkillKick) - { - if(target!=this) - { + if(skill_to_use == SkillKick) { + if(target != this) { DoAnim(animKick); - - if(GetWeaponDamage(target, GetBotItem(MainFeet)) <= 0){ + if(GetWeaponDamage(target, GetBotItem(MainFeet)) <= 0) dmg = -5; - } - else{ - if(!target->CheckHitChance(this, SkillKick, 0)) { + else { + if(!target->CheckHitChance(this, SkillKick, 0)) dmg = 0; - } - else{ + else { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else dmg = zone->random.Int(1, GetKickDamage()); } } - - reuse = KickReuseTime * 1000; - - DoSpecialAttackDamage(target, SkillKick, dmg, 1,-1, reuse); - + reuse = (KickReuseTime * 1000); + DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse); did_attack = true; } } - if(skill_to_use == SkillFlyingKick || - skill_to_use == SkillDragonPunch || - skill_to_use == SkillEagleStrike || - skill_to_use == SkillTigerClaw || - skill_to_use == SkillRoundKick) - { - reuse = MonkSpecialAttack(target, skill_to_use) - 1; + if(skill_to_use == SkillFlyingKick || skill_to_use == SkillDragonPunch || skill_to_use == SkillEagleStrike || skill_to_use == SkillTigerClaw || skill_to_use == SkillRoundKick) { + reuse = (MonkSpecialAttack(target, skill_to_use) - 1); MonkSpecialAttack(target, skill_to_use); - - //Live AA - Technique of Master Wu - uint32 bDoubleSpecialAttack = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; - if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0,100))) { - + uint32 bDoubleSpecialAttack = (itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack); + if(bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0, 100))) { int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick }; - MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]); - + MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]); int TripleChance = 25; - if (bDoubleSpecialAttack > 100) - TripleChance += TripleChance*(100-bDoubleSpecialAttack)/100; + TripleChance += (TripleChance * (100 - bDoubleSpecialAttack) / 100); - if(TripleChance > zone->random.Int(0,100)) { - MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]); - } + if(TripleChance > zone->random.Int(0,100)) + MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]); } reuse *= 1000; did_attack = true; } - if(skill_to_use == SkillBackstab) - { - reuse = BackstabReuseTime * 1000; + if(skill_to_use == SkillBackstab) { + reuse = (BackstabReuseTime * 1000); did_attack = true; - if (IsRiposte) - reuse=0; + reuse = 0; TryBackstab(target,reuse); } - classattack_timer.Start(reuse / HasteModifier); } bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { bool Result = false; - if(defender && (defender->GetBodyType() == BT_Humanoid) && (skillInUse == SkillArchery) && (GetClass() == RANGER) && (GetLevel() >= 62)) { int defenderLevel = defender->GetLevel(); int rangerLevel = GetLevel(); - // Bot Ranger Headshot AA through level 85(Underfoot) - if( GetAA(aaHeadshot) && ((defenderLevel - 46) <= GetAA(aaHeadshot) * 2) ) { - // 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. + if(GetAA(aaHeadshot) && ((defenderLevel - 46) <= GetAA(aaHeadshot) * 2)) { float AttackerChance = 0.20f + ((float)(rangerLevel - 51) * 0.005f); float DefenderChance = (float)zone->random.Real(0.00f, 1.00f); if(AttackerChance > DefenderChance) { Log.Out(Logs::Detail, Logs::Combat, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance); - // WildcardX: At the time I wrote this, there wasnt a string id for something like HEADSHOT_BLOW - //entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); entity_list.MessageClose(this, false, 200, MT_CritMelee, "%s has scored a leathal HEADSHOT!", GetName()); defender->Damage(this, (defender->GetMaxHP()+50), SPELL_UNKNOWN, skillInUse); Result = true; - } - else { + } else Log.Out(Logs::Detail, Logs::Combat, "FAILED a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance); - } } } - return Result; } -//offensive spell aggro int32 Bot::CheckAggroAmount(uint16 spellid) { int32 AggroAmount = Mob::CheckAggroAmount(spellid); - int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid); - AggroAmount = (AggroAmount * (100+focusAggro) / 100); - + AggroAmount = (AggroAmount * (100 + focusAggro) / 100); return AggroAmount; } int32 Bot::CheckHealAggroAmount(uint16 spellid, uint32 heal_possible) { int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, heal_possible); - int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid); - AggroAmount = (AggroAmount * (100 + focusAggro) / 100); - return AggroAmount; } @@ -7632,20 +6405,15 @@ void Bot::AI_Stop() { Mob::AI_Stop(); } -//this is called with 'this' as the mob being looked at, and -//iOther the mob who is doing the looking. It should figure out -//what iOther thinks about 'this' FACTION_VALUE Bot::GetReverseFactionCon(Mob* iOther) { - if(iOther->IsBot()) { + if(iOther->IsBot()) return FACTION_ALLY; - } return NPC::GetReverseFactionCon(iOther); } Mob* Bot::GetOwnerOrSelf() { Mob* Result = 0; - if(this->GetBotOwner()) Result = GetBotOwner(); else @@ -7656,103 +6424,61 @@ Mob* Bot::GetOwnerOrSelf() { Mob* Bot::GetOwner() { Mob* Result = 0; - Result = GetBotOwner(); - - if(!Result) { + if(!Result) this->SetBotOwner(0); - } return Result; } -bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) -{ +bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { bool Result = false; - - if(attacker && target) - { - if(attacker == target) - { + if(attacker && target) { + if(attacker == target) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) - { + } else if(attacker->IsClient() && target->IsBot() && attacker->CastToClient()->GetPVP() && target->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { hasRuleDefined = true; Result = true; - } - else if(attacker->IsClient() && target->IsBot()) - { + } else if(attacker->IsClient() && target->IsBot()) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsBot() && target->IsNPC()) - { + } else if(attacker->IsBot() && target->IsNPC()) { hasRuleDefined = true; Result = true; - } - else if(attacker->IsBot() && !target->IsNPC()) - { + } else if(attacker->IsBot() && !target->IsNPC()) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsPet() && attacker->IsFamiliar()) - { + } else if(attacker->IsPet() && attacker->IsFamiliar()) { hasRuleDefined = true; Result = false; - } - else if(attacker->IsBot() && attacker->CastToBot()->GetBotOwner() && attacker->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) - { - if(target->IsBot() && target->GetOwner() && target->GetOwner()->CastToClient()->GetPVP()) - { - // my target is a bot and it's owner is pvp + } else if(attacker->IsBot() && attacker->CastToBot()->GetBotOwner() && attacker->CastToBot()->GetBotOwner()->CastToClient()->GetPVP()) { + if(target->IsBot() && target->GetOwner() && target->GetOwner()->CastToClient()->GetPVP()) { hasRuleDefined = true; - if(target->GetOwner() == attacker->GetOwner()) - { - // no attacking if my target's owner is my owner Result = false; - } else - { Result = true; - } - } - else if(target->IsClient() && target->CastToClient()->GetPVP()) - { - // my target is a player and it's pvp + } else if(target->IsClient() && target->CastToClient()->GetPVP()) { hasRuleDefined = true; - if(target == attacker->GetOwner()) - { - // my target cannot be my owner Result = false; - } else - { Result = true; - } - } - else if(target->IsNPC()) - { + } else if(target->IsNPC()) { hasRuleDefined = true; Result = true; - } - else if(!target->IsNPC()) - { + } else if(!target->IsNPC()) { hasRuleDefined = true; Result = false; } } } - return Result; } void Bot::EquipBot(std::string* errorMessage) { GetBotItems(errorMessage, m_inv); - const ItemInst* inst = 0; const Item_Struct* item = 0; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { @@ -7764,33 +6490,14 @@ void Bot::EquipBot(std::string* errorMessage) { return; } } - UpdateEquipmentLight(); } -//// This method is meant to be called by zone or client methods to clean up objects when a client camps, goes LD, zones out or something like that. -//void Bot::DestroyBotRaidObjects(Client* client) { -// if(client) { -// if(client->GetBotRaidID() > 0) { -// BotRaids* br = entity_list.GetBotRaidByMob(client); -// if(br) { -// br->RemoveRaidBots(); -// br = nullptr; -// } -// } -// -// //BotOrderCampAll(client); -// } -//} - -// Orders all the bots owned by the specified client bot owner to camp out of the game void Bot::BotOrderCampAll(Client* c) { if(c) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { + for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) (*botListItr)->Camp(); - } } } @@ -7798,11 +6505,9 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) { if(botOwner) { if(botOwner->IsClient()) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(botOwner->CastToClient()->CharacterID()); - if(!BotList.empty()) { for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot) { tempBot->SetTarget(0); tempBot->SetBotOwner(0); @@ -7815,20 +6520,12 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) { void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { if(guildOfficer && botToGuild) { - // Bots can be only guild member rank if(!botToGuild->IsInAGuild()) { - //they are not in this or any other guild, this is an invite if (!guild_mgr.CheckPermission(guildOfficer->GuildID(), guildOfficer->GuildRank(), GUILD_INVITE)) { guildOfficer->Message(13, "You dont have permission to invite."); return; } - - // Log.Out(Logs::Detail, Logs::Guilds, "Inviting %s (%d) into guild %s (%d)", botToGuild->GetName(), botToGuild->GetBotID(), guild_mgr.GetGuildName(client->GuildID()), client->GuildID()); - SetBotGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER); - - //Log.LogDebugType(Logs::Detail, Logs::Guilds, "Sending char refresh for BOT %s from guild %d to world", botToGuild->GetName(), guildOfficer->GuildID(); - ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct)); ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer; s->guild_id = guildOfficer->GuildID(); @@ -7836,9 +6533,7 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { s->char_id = botToGuild->GetBotID(); worldserver.SendPacket(pack); safe_delete(pack); - } else { - //they are in some other guild guildOfficer->Message(13, "Player is in a guild."); return; } @@ -7847,18 +6542,14 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) { bool Result = false; - if(guildOfficer && !botName.empty()) { Bot* botToUnGuild = entity_list.GetBotByBotName(botName); if(botToUnGuild) { SetBotGuildMembership(botToUnGuild->GetBotID(), 0, 0); Result = true; - } - else { + } else { uint32 botId = GetBotIDByBotName(botName); - if(botId > 0) { - // Bot is camped or in another zone SetBotGuildMembership(botId, 0, 0); Result = true; } @@ -7874,7 +6565,6 @@ bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) { safe_delete(outapp); } } - return Result; } @@ -7883,27 +6573,20 @@ void Bot::SetBotGuildMembership(uint32 botId, uint32 guildid, uint8 rank) { return; if(guildid > 0) { - std::string query = StringFormat("REPLACE INTO botguildmembers " - "SET char_id = %u, guild_id = %u, rank = %u;", - botId, guildid, rank); + std::string query = StringFormat("REPLACE INTO botguildmembers SET char_id = %u, guild_id = %u, rank = %u", botId, guildid, rank); auto results = database.QueryDatabase(query); return; } - std::string query = StringFormat("DELETE FROM botguildmembers WHERE char_id = %u;", botId); + std::string query = StringFormat("DELETE FROM botguildmembers WHERE char_id = %u", botId); auto results = database.QueryDatabase(query); } void Bot::LoadGuildMembership(uint32* guildId, uint8* guildRank, std::string* guildName) { - if(guildId == nullptr || guildRank == nullptr || guildName == nullptr) return; - std::string query = StringFormat("SELECT gm.guild_id, gm.rank, g.name " - "FROM vwGuildMembers AS gm JOIN guilds AS g " - "ON gm.guild_id = g.id " - "WHERE gm.char_id = %u AND gm.mobtype = 'B';", - GetBotID()); + std::string query = StringFormat("SELECT gm.guild_id, gm.rank, g.name FROM vwGuildMembers AS gm JOIN guilds AS g ON gm.guild_id = g.id WHERE gm.char_id = %u AND gm.mobtype = 'B'", GetBotID()); auto results = database.QueryDatabase(query); if(!results.Success() || results.RowCount() == 0) return; @@ -7915,56 +6598,44 @@ void Bot::LoadGuildMembership(uint32* guildId, uint8* guildRank, std::string* gu } int32 Bot::CalcMaxMana() { - switch(GetCasterClass()) - { + switch(GetCasterClass()) { case 'I': - case 'W': - { + case 'W': { max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement()); break; } - case 'N': - { + case 'N': { max_mana = 0; break; } - default: - { + default: { Log.Out(Logs::General, Logs::None, "Invalid Class '%c' in CalcMaxMana", GetCasterClass()); max_mana = 0; break; } } - if(cur_mana > max_mana) { + if(cur_mana > max_mana) cur_mana = max_mana; - } - else if(max_mana < 0) { + else if(max_mana < 0) max_mana = 0; - } return max_mana; } void Bot::SetAttackTimer() { - float haste_mod = GetHaste() * 0.01f; - - //default value for attack timer in case they have - //an invalid weapon equipped: + float haste_mod = (GetHaste() * 0.01f); attack_timer.SetAtTrigger(4000, true); - Timer* TimerToUse = nullptr; const Item_Struct* PrimaryWeapon = nullptr; - for (int i = MainRange; i <= MainSecondary; i++) { - //pick a timer if (i == MainPrimary) TimerToUse = &attack_timer; else if (i == MainRange) TimerToUse = &ranged_timer; else if (i == MainSecondary) TimerToUse = &attack_dw_timer; - else //invalid slot (hands will always hit this) + else continue; const Item_Struct* ItemToUse = nullptr; @@ -7972,60 +6643,36 @@ void Bot::SetAttackTimer() { if (ci) ItemToUse = ci->GetItem(); - //special offhand stuff if (i == MainSecondary) { - //if we have a 2H weapon in our main hand, no dual if (PrimaryWeapon != nullptr) { - if (PrimaryWeapon->ItemClass == ItemClassCommon - && (PrimaryWeapon->ItemType == ItemType2HSlash - || PrimaryWeapon->ItemType == ItemType2HBlunt - || PrimaryWeapon->ItemType == ItemType2HPiercing)) { + if (PrimaryWeapon->ItemClass == ItemClassCommon && (PrimaryWeapon->ItemType == ItemType2HSlash || PrimaryWeapon->ItemType == ItemType2HBlunt || PrimaryWeapon->ItemType == ItemType2HPiercing)) { attack_dw_timer.Disable(); continue; } } - //clients must have the skill to use it... if (!GetSkill(SkillDualWield)) { attack_dw_timer.Disable(); continue; } } - //see if we have a valid weapon if (ItemToUse != nullptr) { - //check type and damage/delay - if (ItemToUse->ItemClass != ItemClassCommon - || ItemToUse->Damage == 0 - || ItemToUse->Delay == 0) { - //no weapon + if (ItemToUse->ItemClass != ItemClassCommon || ItemToUse->Damage == 0 || ItemToUse->Delay == 0 || ((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing))) ItemToUse = nullptr; - } - // Check to see if skill is valid - else if ((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing)) { - //no weapon - ItemToUse = nullptr; - } } - int hhe = itembonuses.HundredHands + spellbonuses.HundredHands; + int hhe = (itembonuses.HundredHands + spellbonuses.HundredHands); int speed = 0; int delay = 36; - - //if we have no weapon.. if (ItemToUse == nullptr) { - //above checks ensure ranged weapons do not fall into here - // Work out if we're a monk if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) delay = GetMonkHandToHandDelay(); } else { - //we have a weapon, use its delay delay = ItemToUse->Delay; } - if (RuleB(Spells, Jun182014HundredHandsRevamp)) - speed = static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100); - else - speed = static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100); + + speed = (RuleB(Spells, Jun182014HundredHandsRevamp) ? static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100) : static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100)); TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); if(i == MainPrimary) @@ -8034,66 +6681,52 @@ void Bot::SetAttackTimer() { } int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { - if (spells[spell_id].targettype == ST_Self) return value; bool Critical = false; int32 value_BaseEffect = 0; - - value_BaseEffect = value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id)/100); - + value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100)); // Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40. if ( (spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40) - value -= (GetLevel() - 40) * 20; + value -= ((GetLevel() - 40) * 20); //This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch. if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm Touch - value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch + value -= (GetAA(aaUnholyTouch) * 450); //Unholy Touch int chance = RuleI(Spells, BaseCritChance); - chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance; + chance += (itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance); - if (chance > 0){ + if (chance > 0) { + int32 ratio = RuleI(Spells, BaseCritRatio); + if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) + chance = 100; - int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals. - - //Improved Harm Touch is a guaranteed crit if you have at least one level of SCF. - if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) - chance = 100; - - if (zone->random.Int(1,100) <= chance){ + if (zone->random.Int(1, 100) <= chance){ Critical = true; - ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease; - ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack; - } - - else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Int(1,100) <= RuleI(Spells, WizCritChance))) { - ratio = zone->random.Int(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. + ratio += (itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease); + ratio += (itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack); + } else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Int(1, 100) <= RuleI(Spells, WizCritChance))) { + ratio = zone->random.Int(1, 100); Critical = true; } - - ratio += RuleI(Spells, WizCritRatio); //Default is zero - - if (Critical){ - - value = value_BaseEffect*ratio/100; - - value += value_BaseEffect*GetBotFocusEffect(BotfocusImprovedDamage, spell_id)/100; - - value += int(value_BaseEffect*GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id)/100)*ratio/100; - + ratio += RuleI(Spells, WizCritRatio); + if (Critical) { + value = (value_BaseEffect * ratio / 100); + value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100); + value += (int(value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100) * ratio / 100); if (target) { - value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100; + value += (int(value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100) * ratio / 100); value -= target->GetFcDamageAmtIncoming(this, spell_id); } - value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id)*ratio/100; + value -= (GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id) * ratio / 100); value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100); entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), -value); @@ -8101,29 +6734,23 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { } } - value = value_BaseEffect; - - value += value_BaseEffect*GetBotFocusEffect(BotfocusImprovedDamage, spell_id)/100; - - value += value_BaseEffect*GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id)/100; - - if (target) { - value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100; + value = value_BaseEffect; + value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100); + value += (value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100); + if (target) { + value += (value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100); value -= target->GetFcDamageAmtIncoming(this, spell_id); - } + } - value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id); - - value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); + value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id); + value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); return value; } int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { - if (target == nullptr) target = this; @@ -8131,72 +6758,52 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { int32 chance = 0; int8 modifier = 1; bool Critical = false; - - value_BaseEffect = value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id)/100); - + value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100)); value = value_BaseEffect; - - value += int(value_BaseEffect*GetBotFocusEffect(BotfocusImprovedHeal, spell_id)/100); - - // Instant Heals + value += int(value_BaseEffect*GetBotFocusEffect(BotfocusImprovedHeal, spell_id) / 100); if(spells[spell_id].buffduration < 1) { - - chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance; - + chance += (itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance); chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id); - if (spellbonuses.CriticalHealDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - if(chance && (zone->random.Int(0,99) < chance)) { + if(chance && (zone->random.Int(0, 99) < chance)) { Critical = true; - modifier = 2; //At present time no critical heal amount modifier SPA exists. + modifier = 2; } value *= modifier; - value += GetBotFocusEffect(BotfocusFcHealAmtCrit, spell_id) * modifier; + value += (GetBotFocusEffect(BotfocusFcHealAmtCrit, spell_id) * modifier); value += GetBotFocusEffect(BotfocusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier; - - value += value*target->GetHealRate(spell_id, this)/100; + if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + value += (GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier); + value += (value * target->GetHealRate(spell_id, this) / 100); if (Critical) entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), value); return value; - } - - //Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value] - else { - - chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime; - + } else { + chance = (itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime); chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id); - if (spellbonuses.CriticalRegenDecay) chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); if(chance && (zone->random.Int(0,99) < chance)) return (value * 2); } - return value; } int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) { int32 cast_reducer = 0; cast_reducer += GetBotFocusEffect(BotfocusSpellHaste, spell_id); - uint8 botlevel = GetLevel(); uint8 botclass = GetClass(); - - if (botlevel >= 51 && casttime >= 3000 && !BeneficialSpell(spell_id) - && (botclass == SHADOWKNIGHT || botclass == RANGER - || botclass == PALADIN || botclass == BEASTLORD )) - cast_reducer += (GetLevel()-50)*3; + if (botlevel >= 51 && casttime >= 3000 && !BeneficialSpell(spell_id) && (botclass == SHADOWKNIGHT || botclass == RANGER || botclass == PALADIN || botclass == BEASTLORD )) + cast_reducer += ((GetLevel() - 50) * 3); if((casttime >= 4000) && BeneficialSpell(spell_id) && IsBuffSpell(spell_id)) { switch (GetAA(aaSpellCastingDeftness)) { @@ -8269,86 +6876,70 @@ int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) { if (cast_reducer > RuleI(Spells, MaxCastTimeReduction)) cast_reducer = RuleI(Spells, MaxCastTimeReduction); - casttime = (casttime*(100 - cast_reducer)/100); - + casttime = (casttime * (100 - cast_reducer) / 100); return casttime; } int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { - // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) - { - int32 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; - // Doesnt generate mana, so best case is a free spell + if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) { + int32 mana_back = (this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100); if(mana_back > cost) mana_back = cost; cost -= mana_back; } - // This formula was derived from the following resource: - // http://www.eqsummoners.com/eq1/specialization-library.html - // WildcardX float PercentManaReduction = 0; float SpecializeSkill = GetSpecializeSkillValue(spell_id); int SuccessChance = zone->random.Int(0, 100); - float bonus = 1.0; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - bonus += 0.05; - break; - case 2: - bonus += 0.15; - break; - case 3: - bonus += 0.30; - break; + switch(GetAA(aaSpellCastingMastery)) { + case 1: + bonus += 0.05; + break; + case 2: + bonus += 0.15; + break; + case 3: + bonus += 0.30; + break; } - bonus += 0.05 * GetAA(aaAdvancedSpellCastingMastery); + bonus += (0.05 * GetAA(aaAdvancedSpellCastingMastery)); - if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) - { - PercentManaReduction = 1 + 0.05 * SpecializeSkill; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; + if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) { + PercentManaReduction = (1 + 0.05 * SpecializeSkill); + switch(GetAA(aaSpellCastingMastery)) { + case 1: + PercentManaReduction += 2.5; + break; + case 2: + PercentManaReduction += 5.0; + break; + case 3: + PercentManaReduction += 10.0; + break; } - switch(GetAA(aaAdvancedSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; + switch(GetAA(aaAdvancedSpellCastingMastery)) { + case 1: + PercentManaReduction += 2.5; + break; + case 2: + PercentManaReduction += 5.0; + break; + case 3: + PercentManaReduction += 10.0; + break; } } int32 focus_redux = GetBotFocusEffect(BotfocusManaCost, spell_id); if(focus_redux > 0) - { PercentManaReduction += zone->random.Real(1, (double)focus_redux); - } cost -= (cost * (PercentManaReduction / 100)); - - // Gift of Mana - reduces spell cost to 1 mana if(focus_redux >= 100) { uint32 buff_max = GetMaxTotalSlots(); for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) { @@ -8371,17 +6962,15 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { float Bot::GetActSpellRange(uint16 spell_id, float range) { float extrange = 100; extrange += GetBotFocusEffect(BotfocusRange, spell_id); - return (range * extrange) / 100; + return ((range * extrange) / 100); } int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { int increase = 100; increase += GetBotFocusEffect(BotfocusSpellDuration, spell_id); - int tic_inc = 0; - tic_inc = GetBotFocusEffect(BotfocusSpellDurByTic, spell_id); + int tic_inc = 0; tic_inc = GetBotFocusEffect(BotfocusSpellDurByTic, spell_id); - if(IsBeneficialSpell(spell_id)) - { + if(IsBeneficialSpell(spell_id)) { switch (GetAA(aaSpellCastingReinforcement)) { case 1: increase += 5; @@ -8393,6 +6982,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { increase += 30; if (GetAA(aaSpellCastingReinforcementMastery) == 1) increase += 20; + break; } @@ -8400,52 +6990,43 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) { increase += 20; } - if(IsMezSpell(spell_id)) { + if(IsMezSpell(spell_id)) tic_inc += GetAA(aaMesmerizationMastery); - } return (((duration * increase) / 100) + tic_inc); } float Bot::GetAOERange(uint16 spell_id) { float range; - range = spells[spell_id].aoerange; - if(range == 0) //for TGB spells, they prolly do not have an aoe range - range = spells[spell_id].range; if(range == 0) - range = 10; //something.... + range = spells[spell_id].range; + + if(range == 0) + range = 10; if(IsBardSong(spell_id) && IsBeneficialSpell(spell_id)) { - //Live AA - Extended Notes, SionachiesCrescendo - float song_bonus = aabonuses.SongRange + spellbonuses.SongRange + itembonuses.SongRange; - range += range*song_bonus /100.0f; + float song_bonus = (aabonuses.SongRange + spellbonuses.SongRange + itembonuses.SongRange); + range += (range * song_bonus / 100.0f); } - range = GetActSpellRange(spell_id, range); - return range; } bool Bot::SpellEffect(Mob* caster, uint16 spell_id, float partial) { bool Result = false; - Result = Mob::SpellEffect(caster, spell_id, partial); - - // Franck-add: If healed/doted, a bot must show its new HP to its leader if(IsGrouped()) { Group *g = GetGroup(); if(g) { EQApplicationPacket hp_app; CreateHPPacket(&hp_app); for(int i=0; imembers[i] && g->members[i]->IsClient()) { + if(g->members[i] && g->members[i]->IsClient()) g->members[i]->CastToClient()->QueuePacket(&hp_app); - } } } } - return Result; } @@ -8456,26 +7037,26 @@ void Bot::DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster) { bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust, uint32 aa_id) { bool Result = false; - if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { - - Log.Out(Logs::Detail, Logs::Spells, "CastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item slot %d", - spells[spell_id].name, spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot); + Log.Out(Logs::Detail, Logs::Spells, "CastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item slot %d", spells[spell_id].name, spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot); if(casting_spell_id == spell_id) ZeroCastingVars(); if(GetClass() != BARD) { if(!IsValidSpell(spell_id) || casting_spell_id || delaytimer || spellend_timer.Enabled() || IsStunned() || IsFeared() || IsMezzed() || (IsSilenced() && !IsDiscipline(spell_id)) || (IsAmnesiad() && IsDiscipline(spell_id))) { - Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d", - IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() ); + Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d", IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() ); if(IsSilenced() && !IsDiscipline(spell_id)) Message_StringID(13, SILENCED_STRING); + if(IsAmnesiad() && IsDiscipline(spell_id)) + Message_StringID(13, MELEE_SILENCE); + if(casting_spell_id) AI_Event_SpellCastFinished(false, casting_spell_slot); - return(false); + + return false; } } @@ -8483,36 +7064,28 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t Message_StringID(13, SPELL_WOULDNT_HOLD); if(casting_spell_id) AI_Event_SpellCastFinished(false, casting_spell_slot); - return(false); + + return false; } - //cannot cast under deivne aura if(DivineAura()) { Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: cannot cast while Divine Aura is in effect."); InterruptSpell(173, 0x121, false); - return(false); + return false; } - - // check for fizzle - // note that CheckFizzle itself doesn't let NPCs fizzle, - // but this code allows for it. - if(slot < MAX_PP_MEMSPELL && !CheckFizzle(spell_id)) - { + + if(slot < MAX_PP_MEMSPELL && !CheckFizzle(spell_id)) { int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; InterruptSpell(fizzle_msg, 0x121, spell_id); uint32 use_mana = ((spells[spell_id].mana) / 4); Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: fizzled. %d mana has been consumed", use_mana); - - // fizzle 1/4 the mana away SetMana(GetMana() - use_mana); - return(false); + return false; } if (HasActiveSong()) { Log.Out(Logs::Detail, Logs::Spells, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong); - //Note: this does NOT tell the client - //_StopSong(); bardsong = 0; bardsong_target_id = 0; bardsong_slot = 0; @@ -8521,22 +7094,16 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t Result = DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, aa_id); } - return Result; } bool Bot::SpellOnTarget(uint16 spell_id, Mob* spelltar) { bool Result = false; - if(!IsValidSpell(spell_id)) return false; if(spelltar) { if(spelltar->IsBot() && (spells[spell_id].targettype == ST_GroupTeleport)) { - // So I made this check because teleporting a group of bots tended to crash the zone - // It seems several group spells also show up as ST_GroupTeleport for some - // reason so I now have to check by spell id. These appear to be Group v1 spells and - // Heal over Time spells. switch(spell_id) { // Paladin case 3577: // Wave of Life @@ -8607,50 +7174,39 @@ bool Bot::SpellOnTarget(uint16 spell_id, Mob* spelltar) { } } - //Franck-add: can't detrimental spell on bots and bots can't detriment on you or the others bots if(((IsDetrimentalSpell(spell_id) && spelltar->IsBot()) || (IsDetrimentalSpell(spell_id) && spelltar->IsClient())) && !IsResurrectionEffects(spell_id)) return false; if(spelltar->IsPet()) { - for(int i=0; iGetZoneID() == 202) && !(this == caster)) { Result = Mob::IsImmuneToSpell(spell_id, caster); - if(!Result) { if(caster->IsBot()) { if(spells[spell_id].targettype == ST_Undead) { if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Undead) && (GetBodyType() != BT_Vampire)) { - Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not an undead."); - return true; + Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not an undead."); + return true; } } if(spells[spell_id].targettype == ST_Summoned) { - if((GetBodyType() != BT_SummonedUndead) - && (GetBodyType() != BT_Summoned) - && (GetBodyType() != BT_Summoned2) - && (GetBodyType() != BT_Summoned3) - ) { - Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not a summoned creature."); - return true; + if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Summoned) && (GetBodyType() != BT_Summoned2) && (GetBodyType() != BT_Summoned3)) { + Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not a summoned creature."); + return true; } } } @@ -8664,30 +7220,21 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction) { bool Result = false; - SpellTargetType targetType = spells[spell_id].targettype; - - - // This is so PoK NPC Necro/Shd can create essence emeralds for pc's from perl scripts if(targetType == ST_GroupClientAndPet) { - if(((spell_id == 1768) && (zone->GetZoneID() == 202)) || (!IsDetrimentalSpell(spell_id))) { + if((spell_id == 1768 && zone->GetZoneID() == 202) || (!IsDetrimentalSpell(spell_id))) { CastAction = SingleTarget; return true; } } - Result = Mob::DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction); - return Result; } bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) { bool Result = false; - - if(GetClass() == BARD) { - // Bard bots casting time is interrupting thier melee + if(GetClass() == BARD) cast_time = 0; - } Result = Mob::DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, aa_id); @@ -8695,144 +7242,114 @@ bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast const SPDat_Spell_Struct &spell = spells[spell_id]; *oSpellWillFinish = Timer::GetCurrentTime() + ((spell.recast_time > 20000) ? 10000 : spell.recast_time); } - return Result; } -int32 Bot::GenerateBaseManaPoints() -{ - // Now, we need to calc the base mana. +int32 Bot::GenerateBaseManaPoints() { int32 bot_mana = 0; int32 WisInt = 0; int32 MindLesserFactor, MindFactor; int wisint_mana = 0; int base_mana = 0; int ConvertedWisInt = 0; - - switch(GetCasterClass()) - { + switch(GetCasterClass()) { case 'I': WisInt = INT; if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if(WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); - if(WisInt > 201) { + if(WisInt > 201) ConvertedWisInt -= ((WisInt - 201) * 5 / 4); - } } - else { + else ConvertedWisInt = WisInt; - } + if(GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); - } - else if(GetLevel() < 81) { + } else if(GetLevel() < 81) { wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100)); base_mana = (600 + ((GetLevel() - 40) * 30)); - } - else { + } else { wisint_mana = (9 * ConvertedWisInt); base_mana = (1800 + ((GetLevel() - 80) * 18)); } - bot_mana = base_mana + wisint_mana; - } - else { - if((( WisInt - 199 ) / 2) > 0) { - MindLesserFactor = ( WisInt - 199 ) / 2; - } - else { + bot_mana = (base_mana + wisint_mana); + } else { + if(((WisInt - 199) / 2) > 0) + MindLesserFactor = ((WisInt - 199) / 2); + else MindLesserFactor = 0; - } + MindFactor = WisInt - MindLesserFactor; - if(WisInt > 100) { + if(WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); - } - else { + else bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100); - } } break; - case 'W': WisInt = WIS; if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if(WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); - if(WisInt > 201) { + if(WisInt > 201) ConvertedWisInt -= ((WisInt - 201) * 5 / 4); - } - } - else { + } else ConvertedWisInt = WisInt; - } + if(GetLevel() < 41) { wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000); base_mana = (GetLevel() * 15); - } - else if(GetLevel() < 81) { + } else if(GetLevel() < 81) { wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100)); base_mana = (600 + ((GetLevel() - 40) * 30)); - } - else { + } else { wisint_mana = (9 * ConvertedWisInt); base_mana = (1800 + ((GetLevel() - 80) * 18)); } - bot_mana = base_mana + wisint_mana; - } - else { - if((( WisInt - 199 ) / 2) > 0) { - MindLesserFactor = ( WisInt - 199 ) / 2; - } - else { + bot_mana = (base_mana + wisint_mana); + } else { + if(((WisInt - 199) / 2) > 0) + MindLesserFactor = ((WisInt - 199) / 2); + else MindLesserFactor = 0; - } - MindFactor = WisInt - MindLesserFactor; - if(WisInt > 100) { + + MindFactor = (WisInt - MindLesserFactor); + if(WisInt > 100) bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40); - } - else { + else bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100); - } } break; - default: bot_mana = 0; break; } - max_mana = bot_mana; - return bot_mana; } -void Bot::GenerateSpecialAttacks() -{ - // Special Attacks - if(((GetClass() == MONK) || (GetClass() == WARRIOR) || (GetClass() == RANGER) || (GetClass() == BERSERKER)) && (GetLevel() >= 60)) { +void Bot::GenerateSpecialAttacks() { + if(((GetClass() == MONK) || (GetClass() == WARRIOR) || (GetClass() == RANGER) || (GetClass() == BERSERKER)) && (GetLevel() >= 60)) SetSpecialAbility(SPECATK_TRIPLE, 1); - } } bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { if(GetClass() == BARD) { - if(!ApplyNextBardPulse(bardsong, this, bardsong_slot)) { + if(!ApplyNextBardPulse(bardsong, this, bardsong_slot)) InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong); - } + stopLogic = true; } - return true; } bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { if(spellTarget) { if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, BotGroupBuffing)) { - //NPC *bot = this->CastToNPC(); bool noGroupSpell = false; uint16 thespell = spell_id; - for(int i=0; i < AIspells.size(); i++) { int j = BotGetSpells(i); int spelltype = BotGetSpellType(i); @@ -8841,11 +7358,8 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].targettype == ST_Self)); bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN)); bool slotequal = (slot == USE_ITEM_SPELL_SLOT); - - // if it's a targeted heal or escape spell or pet spell or it's self only buff or self buff weapon proc, we only want to cast it once if(spellequal || slotequal) { if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { - // Don't let the Shaman canni themselves to death if(((spells[thespell].effectid[0] == 0) && (spells[thespell].base[0] < 0)) && (spellTarget->GetHP() < ((spells[thespell].base[0] * (-1)) + 100))) { return false; @@ -8861,71 +7375,45 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 if(!noGroupSpell) { Group *g = GetGroup(); if(g) { - for(int i=0; imembers[i]) { - if((g->members[i]->GetClass() == NECROMANCER) && - (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune))) { - // don't cast this on necro's, their health to mana - // spell eats up the rune spell and it just keeps - // getting recast over and over + if((g->members[i]->GetClass() == NECROMANCER) && (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune))) { } else - { SpellOnTarget(thespell, g->members[i]); - } - if(g->members[i] && g->members[i]->GetPetID()) { + + if(g->members[i] && g->members[i]->GetPetID()) SpellOnTarget(thespell, g->members[i]->GetPet()); - } } } SetMana(GetMana() - (GetActSpellCost(thespell, spells[thespell].mana) * (g->GroupCount() - 1))); } } - stopLogic = true; } } - return true; } bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { bool isMainGroupMGB = false; - - //if(GetBotRaidID() > 0) { - // BotRaids *br = entity_list.GetBotRaidByMob(this); - // if(br) { - // for(int n=0; nBotRaidGroups[0] && (br->BotRaidGroups[0]->members[n] == this)) { - // if(GetLevel() >= 59) // MGB AA - // isMainGroupMGB = true; - // break; - // } - // } - // } - //} - if(isMainGroupMGB && (GetClass() != BARD)) { - Say("MGB %s", spells[spell_id].name); + BotGroupSay(this, "MGB %s", spells[spell_id].name); SpellOnTarget(spell_id, this); entity_list.AESpell(this, this, spell_id, true); - } - else { + } else { Group *g = GetGroup(); if(g) { - for(int i=0; imembers[i]) { SpellOnTarget(spell_id, g->members[i]); - if(g->members[i] && g->members[i]->GetPetID()) { + if(g->members[i] && g->members[i]->GetPetID()) SpellOnTarget(spell_id, g->members[i]->GetPet()); - } } } } } - stopLogic = true; - return true; } @@ -8936,7 +7424,6 @@ void Bot::CalcBonuses() { CalcSpellBonuses(&spellbonuses); CalcAABonuses(&aabonuses); SetAttackTimer(); - CalcATK(); CalcSTR(); CalcSTA(); @@ -8945,16 +7432,13 @@ void Bot::CalcBonuses() { CalcINT(); CalcWIS(); CalcCHA(); - CalcMR(); CalcFR(); CalcDR(); CalcPR(); CalcCR(); CalcCorrup(); - GenerateArmorClass(); - CalcMaxHP(); CalcMaxMana(); CalcMaxEndurance(); @@ -8966,17 +7450,14 @@ void Bot::CalcBonuses() { int32 Bot::CalcHPRegenCap(){ int level = GetLevel(); int32 hpregen_cap = 0; - hpregen_cap = RuleI(Character, ItemHealthRegenCap) + itembonuses.HeroicSTA/25; - - hpregen_cap += aabonuses.ItemHPRegenCap + spellbonuses.ItemHPRegenCap + itembonuses.ItemHPRegenCap; - + hpregen_cap = (RuleI(Character, ItemHealthRegenCap) + itembonuses.HeroicSTA / 25); + hpregen_cap += (aabonuses.ItemHPRegenCap + spellbonuses.ItemHPRegenCap + itembonuses.ItemHPRegenCap); return (hpregen_cap * RuleI(Character, HPRegenMultiplier) / 100); } int32 Bot::CalcManaRegenCap(){ int32 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap; - switch(GetCasterClass()) - { + switch(GetCasterClass()) { case 'I': cap += (itembonuses.HeroicINT / 25); break; @@ -8984,36 +7465,27 @@ int32 Bot::CalcManaRegenCap(){ cap += (itembonuses.HeroicWIS / 25); break; } - return (cap * RuleI(Character, ManaRegenMultiplier) / 100); } -// Return max stat value for level int32 Bot::GetMaxStat() { int level = GetLevel(); int32 base = 0; - - if (level < 61) { + if (level < 61) base = 255; - } - else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoF) { - base = 255 + 5 * (level - 60); - } - else if (level < 71) { - base = 255 + 5 * (level - 60); - } - else { + else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoF) + base = (255 + 5 * (level - 60)); + else if (level < 71) + base = (255 + 5 * (level - 60)); + else base = 330; - } - return(base); + return base; } int32 Bot::GetMaxResist() { int level = GetLevel(); - int32 base = 500; - if(level > 60) base += ((level - 60) * 5); @@ -9021,93 +7493,63 @@ int32 Bot::GetMaxResist() { } int32 Bot::GetMaxSTR() { - return GetMaxStat() - + itembonuses.STRCapMod - + spellbonuses.STRCapMod - + aabonuses.STRCapMod; + return (GetMaxStat() + itembonuses.STRCapMod + spellbonuses.STRCapMod + aabonuses.STRCapMod); } + int32 Bot::GetMaxSTA() { - return GetMaxStat() - + itembonuses.STACapMod - + spellbonuses.STACapMod - + aabonuses.STACapMod; + return (GetMaxStat() + itembonuses.STACapMod + spellbonuses.STACapMod + aabonuses.STACapMod); } + int32 Bot::GetMaxDEX() { - return GetMaxStat() - + itembonuses.DEXCapMod - + spellbonuses.DEXCapMod - + aabonuses.DEXCapMod; + return (GetMaxStat() + itembonuses.DEXCapMod + spellbonuses.DEXCapMod + aabonuses.DEXCapMod); } + int32 Bot::GetMaxAGI() { - return GetMaxStat() - + itembonuses.AGICapMod - + spellbonuses.AGICapMod - + aabonuses.AGICapMod; + return (GetMaxStat() + itembonuses.AGICapMod + spellbonuses.AGICapMod + aabonuses.AGICapMod); } + int32 Bot::GetMaxINT() { - return GetMaxStat() - + itembonuses.INTCapMod - + spellbonuses.INTCapMod - + aabonuses.INTCapMod; + return (GetMaxStat() + itembonuses.INTCapMod + spellbonuses.INTCapMod + aabonuses.INTCapMod); } + int32 Bot::GetMaxWIS() { - return GetMaxStat() - + itembonuses.WISCapMod - + spellbonuses.WISCapMod - + aabonuses.WISCapMod; + return (GetMaxStat() + itembonuses.WISCapMod + spellbonuses.WISCapMod + aabonuses.WISCapMod); } int32 Bot::GetMaxCHA() { - return GetMaxStat() - + itembonuses.CHACapMod - + spellbonuses.CHACapMod - + aabonuses.CHACapMod; + return (GetMaxStat() + itembonuses.CHACapMod + spellbonuses.CHACapMod + aabonuses.CHACapMod); } + int32 Bot::GetMaxMR() { - return GetMaxResist() - + itembonuses.MRCapMod - + spellbonuses.MRCapMod - + aabonuses.MRCapMod; + return (GetMaxResist() + itembonuses.MRCapMod + spellbonuses.MRCapMod + aabonuses.MRCapMod); } + int32 Bot::GetMaxPR() { - return GetMaxResist() - + itembonuses.PRCapMod - + spellbonuses.PRCapMod - + aabonuses.PRCapMod; + return (GetMaxResist() + itembonuses.PRCapMod + spellbonuses.PRCapMod + aabonuses.PRCapMod); } + int32 Bot::GetMaxDR() { - return GetMaxResist() - + itembonuses.DRCapMod - + spellbonuses.DRCapMod - + aabonuses.DRCapMod; + return (GetMaxResist() + itembonuses.DRCapMod + spellbonuses.DRCapMod + aabonuses.DRCapMod); } + int32 Bot::GetMaxCR() { - return GetMaxResist() - + itembonuses.CRCapMod - + spellbonuses.CRCapMod - + aabonuses.CRCapMod; + return (GetMaxResist() + itembonuses.CRCapMod + spellbonuses.CRCapMod + aabonuses.CRCapMod); } + int32 Bot::GetMaxFR() { - return GetMaxResist() - + itembonuses.FRCapMod - + spellbonuses.FRCapMod - + aabonuses.FRCapMod; + return (GetMaxResist() + itembonuses.FRCapMod + spellbonuses.FRCapMod + aabonuses.FRCapMod); } + int32 Bot::GetMaxCorrup() { - return GetMaxResist() - + itembonuses.CorrupCapMod - + spellbonuses.CorrupCapMod - + aabonuses.CorrupCapMod; + return (GetMaxResist() + itembonuses.CorrupCapMod + spellbonuses.CorrupCapMod + aabonuses.CorrupCapMod); } int32 Bot::CalcSTR() { - int32 val = STR + itembonuses.STR + spellbonuses.STR; - + int32 val = (STR + itembonuses.STR + spellbonuses.STR); int32 mod = aabonuses.STR; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - STR = val + mod; - + + STR = (val + mod); if(STR < 1) STR = 1; @@ -9115,18 +7557,16 @@ int32 Bot::CalcSTR() { if(STR > m) STR = m; - return(STR); + return STR; } int32 Bot::CalcSTA() { - int32 val = STA + itembonuses.STA + spellbonuses.STA; - + int32 val = (STA + itembonuses.STA + spellbonuses.STA); int32 mod = aabonuses.STA; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - STA = val + mod; - + + STA = (val + mod); if(STA < 1) STA = 1; @@ -9134,18 +7574,16 @@ int32 Bot::CalcSTA() { if(STA > m) STA = m; - return(STA); + return STA; } int32 Bot::CalcAGI() { - int32 val = AGI + itembonuses.AGI + spellbonuses.AGI; + int32 val = (AGI + itembonuses.AGI + spellbonuses.AGI); int32 mod = aabonuses.AGI; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - AGI = val + mod; - + AGI = (val + mod); if(AGI < 1) AGI = 1; @@ -9153,18 +7591,16 @@ int32 Bot::CalcAGI() { if(AGI > m) AGI = m; - return(AGI); + return AGI; } int32 Bot::CalcDEX() { - int32 val = DEX + itembonuses.DEX + spellbonuses.DEX; - + int32 val = (DEX + itembonuses.DEX + spellbonuses.DEX); int32 mod = aabonuses.DEX; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - DEX = val + mod; - + + DEX = (val + mod); if(DEX < 1) DEX = 1; @@ -9172,35 +7608,34 @@ int32 Bot::CalcDEX() { if(DEX > m) DEX = m; - return(DEX); + return DEX; } int32 Bot::CalcINT() { - int32 val = INT + itembonuses.INT + spellbonuses.INT; - + int32 val = (INT + itembonuses.INT + spellbonuses.INT); int32 mod = aabonuses.INT; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - INT = val + mod; + + INT = (val + mod); if(INT < 1) INT = 1; + int m = GetMaxINT(); if(INT > m) INT = m; - return(INT); + return INT; } int32 Bot::CalcWIS() { - int32 val = WIS + itembonuses.WIS + spellbonuses.WIS; - + int32 val = (WIS + itembonuses.WIS + spellbonuses.WIS); int32 mod = aabonuses.WIS; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - WIS = val + mod; + + WIS = (val + mod); if(WIS < 1) WIS = 1; @@ -9209,17 +7644,16 @@ int32 Bot::CalcWIS() { if(WIS > m) WIS = m; - return(WIS); + return WIS; } int32 Bot::CalcCHA() { - int32 val = CHA + itembonuses.CHA + spellbonuses.CHA; - + int32 val = (CHA + itembonuses.CHA + spellbonuses.CHA); int32 mod = aabonuses.CHA; - - if(val>255 && GetLevel() <= 60) + if(val > 255 && GetLevel() <= 60) val = 255; - CHA = val + mod; + + CHA = (val + mod); if(CHA < 1) CHA = 1; @@ -9228,18 +7662,13 @@ int32 Bot::CalcCHA() { if(CHA > m) CHA = m; - return(CHA); + return CHA; } -//The AA multipliers are set to be 5, but were 2 on WR -//The resistant discipline which I think should be here is implemented -//in Mob::ResistSpell -int32 Bot::CalcMR() -{ - MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR; - +int32 Bot::CalcMR() { + MR += (itembonuses.MR + spellbonuses.MR + aabonuses.MR); if(GetClass() == WARRIOR) - MR += GetLevel() / 2; + MR += (GetLevel() / 2); if(MR < 1) MR = 1; @@ -9247,21 +7676,19 @@ int32 Bot::CalcMR() if(MR > GetMaxMR()) MR = GetMaxMR(); - return(MR); + return MR; } -int32 Bot::CalcFR() -{ +int32 Bot::CalcFR() { int c = GetClass(); if(c == RANGER) { FR += 4; - int l = GetLevel(); if(l > 49) - FR += l - 49; + FR += (l - 49); } - FR += itembonuses.FR + spellbonuses.FR + aabonuses.FR; + FR += (itembonuses.FR + spellbonuses.FR + aabonuses.FR); if(FR < 1) FR = 1; @@ -9269,57 +7696,48 @@ int32 Bot::CalcFR() if(FR > GetMaxFR()) FR = GetMaxFR(); - return(FR); + return FR; } -int32 Bot::CalcDR() -{ +int32 Bot::CalcDR() { int c = GetClass(); if(c == PALADIN) { DR += 8; - int l = GetLevel(); if(l > 49) - DR += l - 49; - + DR += (l - 49); } else if(c == SHADOWKNIGHT) { DR += 4; - int l = GetLevel(); if(l > 49) - DR += l - 49; + DR += (l - 49); } - DR += itembonuses.DR + spellbonuses.DR + aabonuses.DR; - + DR += (itembonuses.DR + spellbonuses.DR + aabonuses.DR); if(DR < 1) DR = 1; if(DR > GetMaxDR()) DR = GetMaxDR(); - return(DR); + return DR; } -int32 Bot::CalcPR() -{ +int32 Bot::CalcPR() { int c = GetClass(); if(c == ROGUE) { PR += 8; - int l = GetLevel(); if(l > 49) - PR += l - 49; - + PR += (l - 49); } else if(c == SHADOWKNIGHT) { PR += 4; - int l = GetLevel(); if(l > 49) - PR += l - 49; + PR += (l - 49); } - PR += itembonuses.PR + spellbonuses.PR + aabonuses.PR; + PR += (itembonuses.PR + spellbonuses.PR + aabonuses.PR); if(PR < 1) PR = 1; @@ -9327,21 +7745,19 @@ int32 Bot::CalcPR() if(PR > GetMaxPR()) PR = GetMaxPR(); - return(PR); + return PR; } -int32 Bot::CalcCR() -{ +int32 Bot::CalcCR() { int c = GetClass(); if(c == RANGER) { CR += 4; - int l = GetLevel(); if(l > 49) - CR += l - 49; + CR += (l - 49); } - CR += itembonuses.CR + spellbonuses.CR + aabonuses.CR; + CR += (itembonuses.CR + spellbonuses.CR + aabonuses.CR); if(CR < 1) CR = 1; @@ -9349,39 +7765,28 @@ int32 Bot::CalcCR() if(CR > GetMaxCR()) CR = GetMaxCR(); - return(CR); + return CR; } -int32 Bot::CalcCorrup() -{ - Corrup = Corrup + itembonuses.Corrup + spellbonuses.Corrup + aabonuses.Corrup; - +int32 Bot::CalcCorrup() { + Corrup = (Corrup + itembonuses.Corrup + spellbonuses.Corrup + aabonuses.Corrup); if(Corrup > GetMaxCorrup()) Corrup = GetMaxCorrup(); - return(Corrup); + return Corrup; } int32 Bot::CalcATK() { - ATK = itembonuses.ATK + spellbonuses.ATK + aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); - return(ATK); + ATK = (itembonuses.ATK + spellbonuses.ATK + aabonuses.ATK + GroupLeadershipAAOffenseEnhancement()); + return ATK; } void Bot::CalcRestState() { - - // This method calculates rest state HP and mana regeneration. - // The bot must have been out of combat for RuleI(Character, RestRegenTimeToActivate) seconds, - // must be sitting down, and must not have any detrimental spells affecting them. - // if(!RuleI(Character, RestRegenPercent)) return; RestRegenHP = RestRegenMana = RestRegenEndurance = 0; - - if(IsEngaged() || !IsSitting()) - return; - - if(!rest_timer.Check(false)) + if(IsEngaged() || !IsSitting() || !rest_timer.Check(false)) return; uint32 buff_count = GetMaxTotalSlots(); @@ -9394,44 +7799,35 @@ void Bot::CalcRestState() { } RestRegenHP = (GetMaxHP() * RuleI(Character, RestRegenPercent) / 100); - RestRegenMana = (GetMaxMana() * RuleI(Character, RestRegenPercent) / 100); - if(RuleB(Character, RestRegenEndurance)) RestRegenEndurance = (GetMaxEndurance() * RuleI(Character, RestRegenPercent) / 100); } -int32 Bot::LevelRegen() -{ +int32 Bot::LevelRegen() { int level = GetLevel(); bool bonus = GetRaceBitmask(_baseRace) & RuleI(Character, BaseHPRegenBonusRaces); uint8 multiplier1 = bonus ? 2 : 1; int32 hp = 0; - - //these calculations should match up with the info from Monkly Business, which was last updated ~05/2008: http://www.monkly-business.net/index.php?pageid=abilities if (level < 51) { if (IsSitting()) { if (level < 20) - hp += 2 * multiplier1; + hp += (2 * multiplier1); else if (level < 50) - hp += 3 * multiplier1; - else //level == 50 - hp += 4 * multiplier1; - } - else //feigned or standing - hp += 1 * multiplier1; - } - //there may be an easier way to calculate this next part, but I don't know what it is - else { //level >= 51 + hp += (3 * multiplier1); + else + hp += (4 * multiplier1); + } else + hp += (1 * multiplier1); + } else { int32 tmp = 0; float multiplier2 = 1; if (level < 56) { tmp = 2; if (bonus) multiplier2 = 3; - } - else if (level < 60) { - tmp = 3; + } else if (level < 60) { + tmp = 3; if (bonus) multiplier2 = 3.34; } @@ -9439,56 +7835,44 @@ int32 Bot::LevelRegen() tmp = 4; if (bonus) multiplier2 = 3; - } - else if (level < 63) { + } else if (level < 63) { tmp = 5; if (bonus) multiplier2 = 2.8; - } - else if (level < 65) { + } else if (level < 65) { tmp = 6; if (bonus) multiplier2 = 2.67; - } - else { //level >= 65 + } else { tmp = 7; if (bonus) multiplier2 = 2.58; } - - hp += int32(float(tmp) * multiplier2); + hp += (int32(float(tmp) * multiplier2)); } - return hp; } int32 Bot::CalcHPRegen() { - int32 regen = LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen; - regen += aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration(); - - regen = (regen * RuleI(Character, HPRegenMultiplier)) / 100; + int32 regen = (LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen); + regen += (aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration()); + regen = ((regen * RuleI(Character, HPRegenMultiplier)) / 100); return regen; } -int32 Bot::CalcManaRegen() -{ +int32 Bot::CalcManaRegen() { uint8 level = GetLevel(); uint8 botclass = GetClass(); int32 regen = 0; - //this should be changed so we dont med while camping, etc... - if (IsSitting()) - { + if (IsSitting()) { BuffFadeBySitModifier(); if(botclass != WARRIOR && botclass != MONK && botclass != ROGUE && botclass != BERSERKER) { - regen = (((GetSkill(SkillMeditate) / 10) + (level - (level / 4))) / 4) + 4; - regen += spellbonuses.ManaRegen + itembonuses.ManaRegen; - } - else - regen = 2 + spellbonuses.ManaRegen + itembonuses.ManaRegen; - } - else { - regen = 2 + spellbonuses.ManaRegen + itembonuses.ManaRegen; - } + regen = ((((GetSkill(SkillMeditate) / 10) + (level - (level / 4))) / 4) + 4); + regen += (spellbonuses.ManaRegen + itembonuses.ManaRegen); + } else + regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen); + } else + regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen); if(GetCasterClass() == 'I') regen += (itembonuses.HeroicINT / 25); @@ -9498,37 +7882,18 @@ int32 Bot::CalcManaRegen() regen = 0; regen += aabonuses.ManaRegen; - - regen = (regen * RuleI(Character, ManaRegenMultiplier)) / 100; - + regen = ((regen * RuleI(Character, ManaRegenMultiplier)) / 100); float mana_regen_rate = RuleR(Bots, BotManaRegen); if(mana_regen_rate < 0.0f) mana_regen_rate = 0.0f; - regen = regen * mana_regen_rate; // 90% of people wouldnt guess that manaregen would decrease the larger the number they input, this makes more sense - + regen = (regen * mana_regen_rate); return regen; } -// This is for calculating Base HPs + STA bonus for SoD or later clients. uint32 Bot::GetClassHPFactor() { - - int factor; - - // Note: Base HP factor under level 41 is equal to factor / 12, and from level 41 to 80 is factor / 6. - // Base HP over level 80 is factor / 10 - // HP per STA point per level is factor / 30 for level 80+ - // HP per STA under level 40 is the level 80 HP Per STA / 120, and for over 40 it is / 60. - - switch(GetClass()) - { - case DRUID: - case ENCHANTER: - case NECROMANCER: - case MAGICIAN: - case WIZARD: - factor = 240; - break; + uint32 factor; + switch(GetClass()) { case BEASTLORD: case BERSERKER: case MONK: @@ -9560,46 +7925,36 @@ uint32 Bot::GetClassHPFactor() { int32 Bot::CalcMaxHP() { int32 bot_hp = 0; uint32 nd = 10000; - - bot_hp += GenerateBaseHitPoints() + itembonuses.HP; - - nd += aabonuses.MaxHP; //Natural Durability, Physical Enhancement, Planar Durability - bot_hp = (float)bot_hp * (float)nd / (float)10000; //this is to fix the HP-above-495k issue - bot_hp += spellbonuses.HP + aabonuses.HP; - + bot_hp += (GenerateBaseHitPoints() + itembonuses.HP); + nd += aabonuses.MaxHP; + bot_hp = ((float)bot_hp * (float)nd / (float)10000); + bot_hp += (spellbonuses.HP + aabonuses.HP); bot_hp += GroupLeadershipAAHealthEnhancement(); - - bot_hp += bot_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f); + bot_hp += (bot_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f)); max_hp = bot_hp; - if (cur_hp > max_hp) cur_hp = max_hp; int hp_perc_cap = spellbonuses.HPPercCap[0]; if(hp_perc_cap) { - int curHP_cap = (max_hp * hp_perc_cap) / 100; + int curHP_cap = ((max_hp * hp_perc_cap) / 100); if (cur_hp > curHP_cap || (spellbonuses.HPPercCap[1] && cur_hp > spellbonuses.HPPercCap[1])) cur_hp = curHP_cap; } - return max_hp; } -int32 Bot::CalcMaxEndurance() -{ - max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance; - - if (max_end < 0) { +int32 Bot::CalcMaxEndurance() { + max_end = (CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance); + if (max_end < 0) max_end = 0; - } - if (cur_end > max_end) { + if (cur_end > max_end) cur_end = max_end; - } int end_perc_cap = spellbonuses.EndPercCap[0]; if(end_perc_cap) { - int curEnd_cap = (max_end * end_perc_cap) / 100; + int curEnd_cap = ((max_end * end_perc_cap) / 100); if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[1] && cur_end > spellbonuses.EndPercCap[1])) cur_end = curEnd_cap; } @@ -9607,49 +7962,37 @@ int32 Bot::CalcMaxEndurance() return max_end; } -int32 Bot::CalcBaseEndurance() -{ +int32 Bot::CalcBaseEndurance() { int32 base_end = 0; int32 base_endurance = 0; int32 ConvertedStats = 0; int32 sta_end = 0; int Stats = 0; - if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { int HeroicStats = 0; - Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4); HeroicStats = ((GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4); - if (Stats > 100) { ConvertedStats = (((Stats - 100) * 5 / 2) + 100); - if (Stats > 201) { + if (Stats > 201) ConvertedStats -= ((Stats - 201) * 5 / 4); - } - } - else { + } else ConvertedStats = Stats; - } if (GetLevel() < 41) { sta_end = (GetLevel() * 75 * ConvertedStats / 1000); base_endurance = (GetLevel() * 15); - } - else if (GetLevel() < 81) { + } else if (GetLevel() < 81) { sta_end = ((3 * ConvertedStats) + ((GetLevel() - 40) * 15 * ConvertedStats / 100)); base_endurance = (600 + ((GetLevel() - 40) * 30)); - } - else { + } else { sta_end = (9 * ConvertedStats); base_endurance = (1800 + ((GetLevel() - 80) * 18)); } base_end = (base_endurance + sta_end + (HeroicStats * 10)); - } - else - { - Stats = GetSTR()+GetSTA()+GetDEX()+GetAGI(); - int LevelBase = GetLevel() * 15; - + } else { + Stats = (GetSTR()+GetSTA()+GetDEX()+GetAGI()); + int LevelBase = (GetLevel() * 15); int at_most_800 = Stats; if(at_most_800 > 800) at_most_800 = 800; @@ -9658,57 +8001,45 @@ int32 Bot::CalcBaseEndurance() int HalfBonus400to800 = 0; int Bonus800plus = 0; int HalfBonus800plus = 0; - - int BonusUpto800 = int( at_most_800 / 4 ) ; + int BonusUpto800 = int(at_most_800 / 4) ; if(Stats > 400) { - Bonus400to800 = int( (at_most_800 - 400) / 4 ); - HalfBonus400to800 = int( std::max( ( at_most_800 - 400 ), 0 ) / 8 ); - + Bonus400to800 = int((at_most_800 - 400) / 4); + HalfBonus400to800 = int(std::max((at_most_800 - 400), 0) / 8); if(Stats > 800) { - Bonus800plus = int( (Stats - 800) / 8 ) * 2; - HalfBonus800plus = int( (Stats - 800) / 16 ); + Bonus800plus = (int((Stats - 800) / 8) * 2); + HalfBonus800plus = int((Stats - 800) / 16); } } - int bonus_sum = BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus; - + int bonus_sum = (BonusUpto800 + Bonus400to800 + HalfBonus400to800 + Bonus800plus + HalfBonus800plus); base_end = LevelBase; - - //take all of the sums from above, then multiply by level*0.075 - base_end += ( bonus_sum * 3 * GetLevel() ) / 40; + base_end += ((bonus_sum * 3 * GetLevel()) / 40); } return base_end; } int32 Bot::CalcEnduranceRegen() { - int32 regen = int32(GetLevel() * 4 / 10) + 2; - regen += spellbonuses.EnduranceRegen + itembonuses.EnduranceRegen; - + int32 regen = (int32(GetLevel() * 4 / 10) + 2); + regen += (spellbonuses.EnduranceRegen + itembonuses.EnduranceRegen); return (regen * RuleI(Character, EnduranceRegenMultiplier) / 100); } int32 Bot::CalcEnduranceRegenCap() { - int cap = (RuleI(Character, ItemEnduranceRegenCap) + itembonuses.HeroicSTR/25 + itembonuses.HeroicDEX/25 + itembonuses.HeroicAGI/25 + itembonuses.HeroicSTA/25); - + int cap = (RuleI(Character, ItemEnduranceRegenCap) + itembonuses.HeroicSTR / 25 + itembonuses.HeroicDEX / 25 + itembonuses.HeroicAGI / 25 + itembonuses.HeroicSTA / 25); return (cap * RuleI(Character, EnduranceRegenMultiplier) / 100); } -void Bot::SetEndurance(int32 newEnd) -{ - /*Endurance can't be less than 0 or greater than max*/ +void Bot::SetEndurance(int32 newEnd) { if(newEnd < 0) newEnd = 0; - else if(newEnd > GetMaxEndurance()){ + else if(newEnd > GetMaxEndurance()) newEnd = GetMaxEndurance(); - } cur_end = newEnd; } void Bot::DoEnduranceUpkeep() { int upkeep_sum = 0; - - int cost_redux = spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction; - + int cost_redux = (spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction); uint32 buffs_i; uint32 buff_count = GetMaxTotalSlots(); for (buffs_i = 0; buffs_i < buff_count; buffs_i++) { @@ -9717,15 +8048,15 @@ void Bot::DoEnduranceUpkeep() { if(upkeep > 0) { if(cost_redux > 0) { if(upkeep <= cost_redux) - continue; //reduced to 0 + continue; + upkeep -= cost_redux; } - if((upkeep+upkeep_sum) > GetEndurance()) { - //they do not have enough to keep this one going. + + if((upkeep+upkeep_sum) > GetEndurance()) BuffFadeBySlot(buffs_i); - } else { + else upkeep_sum += upkeep; - } } } } @@ -9737,13 +8068,11 @@ void Bot::DoEnduranceUpkeep() { void Bot::Camp(bool databaseSave) { Sit(); - if(IsGrouped()) { + if(IsGrouped()) RemoveBotFromGroup(this, GetGroup()); - } - if(GetInHealRotation()) { + if(GetInHealRotation()) GetHealRotationLeader()->RemoveHealRotationMember(this); - } if(databaseSave) Save(); @@ -9752,9 +8081,8 @@ void Bot::Camp(bool databaseSave) { } void Bot::Zone() { - if(HasGroup()) { + if(HasGroup()) GetGroup()->MemberZoned(this); - } Save(); Depop(); @@ -9762,38 +8090,26 @@ void Bot::Zone() { bool Bot::IsArcheryRange(Mob *target) { bool result = false; - if(target) { - float range = GetBotArcheryRange() + 5.0; //Fudge it a little, client will let you hit something at 0 0 0 when you are at 205 0 0 - + float range = (GetBotArcheryRange() + 5.0); range *= range; - float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition()); - - float minRuleDistance = RuleI(Combat, MinRangedAttackDist) * RuleI(Combat, MinRangedAttackDist); - + float minRuleDistance = (RuleI(Combat, MinRangedAttackDist) * RuleI(Combat, MinRangedAttackDist)); if((targetDistance > range) || (targetDistance < minRuleDistance)) result = false; else result = true; } - return result; } bool Bot::IsBotCasterCombatRange(Mob *target) { bool result = false; - if(target) { float range = BotAISpellRange; - range *= range; - - // half the max so the bot doesn't always stop at max range to allow combat movement range *= .5; - float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition()); - if(targetDistance > range) result = false; else @@ -9806,36 +8122,28 @@ bool Bot::IsBotCasterCombatRange(Mob *target) { bool Bot::IsGroupPrimaryHealer() { bool result = false; uint8 botclass = GetClass(); - if(HasGroup()) { Group *g = GetGroup(); - - switch(botclass) - { - case CLERIC: - { + switch(botclass) { + case CLERIC: { result = true; break; } - case DRUID: - { + case DRUID: { result = GroupHasClericClass(g) ? false : true; break; } - case SHAMAN: - { + case SHAMAN: { result = (GroupHasClericClass(g) || GroupHasDruidClass(g)) ? false : true; break; } case PALADIN: case RANGER: - case BEASTLORD: - { + case BEASTLORD: { result = GroupHasPriestClass(g) ? false : true; break; } - default: - { + default: { result = false; break; } @@ -9848,29 +8156,22 @@ bool Bot::IsGroupPrimaryHealer() { bool Bot::IsGroupPrimarySlower() { bool result = false; uint8 botclass = GetClass(); - if(HasGroup()) { Group *g = GetGroup(); - - switch(botclass) - { - case SHAMAN: - { + switch(botclass) { + case SHAMAN: { result = true; break; } - case ENCHANTER: - { + case ENCHANTER: { result = GroupHasShamanClass(g) ? false : true; break; } - case BEASTLORD: - { + case BEASTLORD: { result = (GroupHasShamanClass(g) || GroupHasEnchanterClass(g)) ? false : true; break; } - default: - { + default: { result = false; break; } @@ -9893,14 +8194,9 @@ bool Bot::CanHeal() { botSpell = GetFirstBotSpellBySpellType(this, SpellType_Heal); - if(botSpell.SpellId != 0){ + if(botSpell.SpellId != 0) result = true; - } - - /*if(GetFirstBotSpellBySpellType(this, SpellType_Heal)){ - result = true; - }*/ - + return result; } @@ -9908,32 +8204,26 @@ bool Bot::CalculateNewPosition2(float x, float y, float z, float speed, bool che return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ); } -// Orders all bots in the specified group to follow their group leader. void Bot::BotGroupOrderFollow(Group* group, Client* client) { if(group && client) { Mob* groupLeader = group->GetLeader(); - if(groupLeader) { for(int i = 0; i< MAX_GROUP_MEMBERS; i++) { if(group->members[i] && group->members[i]->IsBot()) { Bot* botGroupMember = group->members[i]->CastToBot(); - if(botGroupMember && botGroupMember->GetBotOwnerCharacterID() == client->CharacterID()) { if(group->IsLeader(botGroupMember) && botGroupMember->GetBotOwner()) { botGroupMember->SetFollowID(botGroupMember->GetBotOwner()->GetID()); if(botGroupMember->GetBotOwner()) - botGroupMember->Say("Following %s.", botGroupMember->GetBotOwner()->GetName()); - } - else { + botGroupMember->BotGroupSay(botGroupMember, "Following %s.", botGroupMember->GetBotOwner()->GetName()); + } else { botGroupMember->SetFollowID(groupLeader->GetID()); - botGroupMember->Say("Following %s.", groupLeader->GetCleanName()); + botGroupMember->BotGroupSay(botGroupMember, "Following %s.", groupLeader->GetCleanName()); } botGroupMember->WipeHateList(); - - if(botGroupMember->HasPet() && botGroupMember->GetPet()) { + if(botGroupMember->HasPet() && botGroupMember->GetPet()) botGroupMember->GetPet()->WipeHateList(); - } } } } @@ -9941,42 +8231,33 @@ void Bot::BotGroupOrderFollow(Group* group, Client* client) { } } -// Orders all bots in the specified group to guard their current location. void Bot::BotGroupOrderGuard(Group* group, Client* client) { if(group && client) { for(int i = 0; i< MAX_GROUP_MEMBERS; i++) { if(group->members[i] && group->members[i]->IsBot()) { Bot* botGroupMember = group->members[i]->CastToBot(); - if(botGroupMember && botGroupMember->GetBotOwnerCharacterID() == client->CharacterID()) { botGroupMember->SetFollowID(0); - botGroupMember->Say("Guarding here."); - + botGroupMember->BotGroupSay(botGroupMember, "Guarding here."); botGroupMember->WipeHateList(); - - if(botGroupMember->HasPet() && botGroupMember->GetPet()) { + if(botGroupMember->HasPet() && botGroupMember->GetPet()) botGroupMember->GetPet()->WipeHateList(); - } } } } } } -// Orders all bots in the specified group to attack their group leader's target. void Bot::BotGroupOrderAttack(Group* group, Mob* target, Client* client) { if(group && target) { Mob* groupLeader = group->GetLeader(); - if(groupLeader) { for(int i=0; i < MAX_GROUP_MEMBERS; i++) { if(group->members[i] && group->members[i]->IsBot()) { Bot* botGroupMember = group->members[i]->CastToBot(); - if(botGroupMember->GetBotOwnerCharacterID() == client->CharacterID()) { botGroupMember->WipeHateList(); botGroupMember->AddToHateList(target, 1); - if(botGroupMember->HasPet() && botGroupMember->GetPet()) { botGroupMember->GetPet()->WipeHateList(); botGroupMember->GetPet()->AddToHateList(target, 1); @@ -9988,18 +8269,15 @@ void Bot::BotGroupOrderAttack(Group* group, Mob* target, Client* client) { } } -// Summons all bot group members to ther owners location. void Bot::BotGroupSummon(Group* group, Client* client) { if(group) { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(group->members[i] && group->members[i]->IsBot()) { Bot* botMember = group->members[i]->CastToBot(); - if(botMember->GetBotOwnerCharacterID() == client->CharacterID()) { botMember->SetTarget(botMember->GetBotOwner()); botMember->WipeHateList(); botMember->Warp(glm::vec3(botMember->GetBotOwner()->GetPosition())); - if(botMember->HasPet() && botMember->GetPet()) { botMember->GetPet()->SetTarget(botMember); botMember->GetPet()->WipeHateList(); @@ -10011,13 +8289,10 @@ void Bot::BotGroupSummon(Group* group, Client* client) { } } -// Finds a bot in the entitity list by bot owner character id and the bot first name Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { Bot* Result = 0; - if(c) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - if(!BotList.empty()) { for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { if(std::string((*botListItr)->GetCleanName()) == botName) { @@ -10027,11 +8302,9 @@ Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { } } } - return Result; } -// Processes a group invite from a Client for a Bot character. void Bot::ProcessBotGroupInvite(Client* c, std::string botName) { if(c) { Bot* invitedBot = GetBotByBotClientOwnerAndBotName(c, botName); @@ -10046,16 +8319,11 @@ void Bot::ProcessBotGroupInvite(Client* c, std::string botName) { database.SetGroupID(c->GetName(), g->GetID(), c->CharacterID()); database.SetGroupID(invitedBot->GetCleanName(), g->GetID(), invitedBot->GetBotID()); } - } - else { + } else { AddBotToGroup(invitedBot, c->GetGroup()); database.SetGroupID(invitedBot->GetCleanName(), c->GetGroup()->GetID(), invitedBot->GetBotID()); } - - /*if(c->GetBotRaidID() > 0) - invitedBot->SetBotRaidID(c->GetBotRaidID());*/ } - // TODO: if there is a bot but the bot is already in a group, do we send an group invitation cancel message back to the client? } } @@ -10185,8 +8453,8 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) { const Item_Struct* itemtmp = 0; - for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { - const ItemInst* item = GetBotItem(i); + for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { + const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); if(item) { AddItemBonuses(item, newbon); } @@ -10489,52 +8757,6 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, } } - // Add Item Faction Mods - //if (item->FactionMod1) - //{ - // if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) - // { - // AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - // } - // else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) - // { - // AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - // } - //} - //if (item->FactionMod2) - //{ - // if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) - // { - // AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - // } - // else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) - // { - // AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - // } - //} - //if (item->FactionMod3) - //{ - // if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) - // { - // AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - // } - // else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) - // { - // AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - // } - //} - //if (item->FactionMod4) - //{ - // if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) - // { - // AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - // } - // else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) - // { - // AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - // } - //} - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); @@ -10630,9 +8852,7 @@ void Bot::CalcBotStats(bool showtext) { } bool Bot::CheckLoreConflict(const Item_Struct* item) { - if (!item) - return false; - if (!(item->LoreFlag)) + if (!item || !(item->LoreFlag)) return false; if (item->LoreGroup == -1) // Standard lore items; look everywhere except the shared bank, return the result @@ -10668,19 +8888,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } if(!strcasecmp( sep->arg[1], "help") && !strcasecmp( sep->arg[2], "\0")){ - c->Message(0, "List of commands availables for bots :"); + c->Message(0, "List of commands availables for bots:"); c->Message(0, "#bot help - show this"); c->Message(0, "#bot create [name] [class (id)] [race (id)] [model (male/female)] - create a permanent bot. See #bot help create."); c->Message(0, "#bot help create - show all the race/class id. (make it easier to create bots)"); c->Message(0, "#bot delete - completely destroy forever the targeted bot and all its items."); - c->Message(0, "#bot list [all/class(1-16)] - list your bots all or by class. Classes: 1(Warrior), 2(Cleric), 3(Paladin), 4(Ranger), 5(Sk), 6(Druid), 7(Monk), 8(Bard), 9(Rogue), 10(Shaman), 11(Necro), 12(Wiz), 13(Mag), 14(Ench), 15(Beast), 16(Bersek)"); + c->Message(0, "#bot list [all/class(1-16)] - list your bots all or by class. Classes: 1(WAR), 2(CLR), 3(PAL), 4(RNG), 5(SHD), 6(DRU), 7(MNK), 8(BRD), 9(ROG), 10(SHM), 11(NEC), 12(WIZ), 13(MAG), 14(ENC), 15(BST), 16(BER)"); c->Message(0, "#bot spawn [bot name] - spawn a bot from it's name (use list to see all the bots). "); - c->Message(0, "#bot inventory list - show the inventory (and the slots IDs) of the targetted bot."); - c->Message(0, "#bot inventory remove [slotid] - remove the item at the given slot in the inventory of the targetted bot."); + c->Message(0, "#bot inventory list - show the inventory (and the slots IDs) of the targeted bot."); + c->Message(0, "#bot inventory remove [slotid] - remove the item at the given slot in the inventory of the targeted bot."); c->Message(0, "#bot update - you must type that command once you gain a level."); c->Message(0, "#bot summon - It will summon your targeted bot to you."); - c->Message(0, "#bot ai mez - If you're grouped with an enchanter, he will mez your target."); - c->Message(0, "#bot picklock - You must have a targeted rogue bot in your group and be right on the door."); + c->Message(0, "#bot ai mez - If you're grouped with an Enchanter, he will mez your target."); + c->Message(0, "#bot picklock - You must have a targeted Rogue bot in your group and be right on the door."); c->Message(0, "#bot cure [poison|disease|curse|blindness] Cleric has most options"); c->Message(0, "#bot bindme - You must have a Cleric in your group to get Bind Affinity cast on you."); c->Message(0, "#bot track - look at mobs in the zone (ranger has options)"); @@ -10702,7 +8922,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "#bot gate - you need a Druid or Wizard in your group)"); c->Message(0, "#bot archery - Toggle Archery Skilled bots between using a Bow or using Melee weapons."); c->Message(0, "#bot magepet [earth|water|air|fire|monster] - Select the pet type you want your Mage bot to use."); - c->Message(0, "#bot giveitem - Gives your targetted bot the item you have on your cursor."); + c->Message(0, "#bot giveitem - Gives your targeted bot the item you have on your cursor."); c->Message(0, "#bot augmentitem - Allows you to augment items for other classes. You must have the Augmentation Sealer window filled."); c->Message(0, "#bot camp - Tells your bot to camp out of the game."); c->Message(0, "#bot group help - Displays the commands available to manage any BOTs in your group."); @@ -10716,8 +8936,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "#bot groupmessages [on|off] [bot name|all] - Turns group messages on/off for named bot/all bots."); c->Message(0, "#bot defensive [bot name] - Causes warrior or knight bot to use defensive discipline / buff."); c->Message(0, "#bot healrotation help - Displays the commands available to manage BOT heal rotations."); - // TODO: - // c->Message(0, "#bot illusion - Enchanter Bot cast an illusion buff spell on you or your target."); c->Message(0, "#bot pull [] [target] - Bot Pulling Target NPC's"); c->Message(0, "#bot setinspectmessage - Copies your inspect message to a targeted bot that you own"); c->Message(0, "#bot bardoutofcombat [on|off] - Determines wheter bard bots use out of combat songs."); @@ -10727,29 +8945,23 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { // pull if(!strcasecmp(sep->arg[1], "pull")) { Mob *target = c->GetTarget(); - if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner()->IsBot())) - { + if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; } - if(c->IsGrouped()) - { + if(c->IsGrouped()) { bool haspuller = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot() && !strcasecmp(g->members[i]->GetName() , sep->arg[2])) - { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(g && g->members[i] && g->members[i]->IsBot() && !strcasecmp(g->members[i]->GetName() , sep->arg[2])) { haspuller = true; Mob *puller = g->members[i]; - if (puller->CastToBot()->IsArcheryRange(target)) - { - puller->Say("Trying to Pull %s \n", target->GetCleanName()); + if (puller->CastToBot()->IsArcheryRange(target)) { + puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Trying to Pull %s \n", target->GetCleanName()); puller->CastToBot()->BotRangedAttack(target); - } - else { - puller->Say("Out of Range %s \n", target->GetCleanName()); + } else { + puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Out of Range %s \n", target->GetCleanName()); } } } @@ -10768,7 +8980,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else { uint32 BotFollowDistance = atoi(sep->arg[2]); c->GetTarget()->SetFollowDistance(BotFollowDistance); - } return; @@ -10786,33 +8997,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 botid = c->GetTarget()->CastToBot()->GetBotID(); std::string errorMessage; - int setslot = atoi(sep->arg[2]); uint8 red = atoi(sep->arg[3]); uint8 green = atoi(sep->arg[4]); uint8 blue = atoi(sep->arg[5]); uint32 setcolor = (red << 16) | (green << 8) | blue; - std::string query = StringFormat("UPDATE botinventory SET color = %u " - "WHERE slotID = %i AND botID = %u", - setcolor, setslot, botid); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; + std::string query; + if (setslot == -1) { + int slots[] = { 2, 7, 9, 12, 17, 18, 19 }; + query = StringFormat("UPDATE botinventory SET color = %u WHERE slotID IN (2, 7, 9, 12, 17, 18, 19) AND botID = %u", setcolor, botid); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + + for (int i = 0; i < 7; i++) { + uint8 slotmaterial = Inventory::CalcMaterialFromSlot((uint8)slots[i]); + c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); + } + } else { + query = StringFormat("UPDATE botinventory SET color = %u WHERE slotID = %i AND botID = %u", setcolor, setslot, botid); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + + uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot); + c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); + } - uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot); - c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); } else { c->Message(15, "You must target a bot you own to do this."); } return; } - // Help for coloring bot armor - if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "armorcolor") ){ - //read from db - + + if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "armorcolor")){ c->Message(0, "-----------------#bot armorcolor help-----------------------------"); - c->Message(0, "Armor: 17(Chest/Robe), 7(Arms), 9(Bracer), 12(Hands), 18(Legs), 19(Boots), 2(Helm)"); + c->Message(0, "Armor: -1(All), 2(Helm), 7(Arms), 9(Bracer), 12(Hands), 17(Chest/Robe), 18(Legs), 19(Boots)"); c->Message(0, "------------------------------------------------------------------"); c->Message(0, "Color: [red] [green] [blue] (enter a number from 0-255 for each"); c->Message(0, "------------------------------------------------------------------"); @@ -10830,7 +9051,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "giveitem")) { if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) { - // Its a bot targetted and this client is the bots owner Bot* targetedBot = c->GetTarget()->CastToBot(); if(targetedBot) targetedBot->FinishTrade(c, BotTradeClientNoDropNoTrade); @@ -10844,17 +9064,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "camp")) { if(!strcasecmp(sep->arg[2], "all")) { - // Camp out all bots owned by this bot owner BotOrderCampAll(c); - } - else { - // Camp only the targetted bot + } else { if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner()->CastToClient() == c)) { Bot* targetedBot = c->GetTarget()->CastToBot(); if(targetedBot) targetedBot->Camp(); - } - else + } else c->Message(15, "You must target a bot you own to do this."); } @@ -10865,16 +9081,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->arg[2][0] == '\0' || sep->arg[3][0] == '\0' || sep->arg[4][0] == '\0' || sep->arg[5][0] == '\0' || sep->arg[6][0] != '\0') { c->Message(0, "Usage: #bot create [name] [class(id)] [race(id)] [gender (male/female)]"); return; - } - else if(strcasecmp(sep->arg[3],"1") && strcasecmp(sep->arg[3],"2") && strcasecmp(sep->arg[3],"3") && strcasecmp(sep->arg[3],"4") && strcasecmp(sep->arg[3],"5") && strcasecmp(sep->arg[3],"6") && strcasecmp(sep->arg[3],"7") && strcasecmp(sep->arg[3],"8") && strcasecmp(sep->arg[3],"9") && strcasecmp(sep->arg[3],"10") && strcasecmp(sep->arg[3],"11") && strcasecmp(sep->arg[3],"12") && strcasecmp(sep->arg[3],"13") && strcasecmp(sep->arg[3],"14") && strcasecmp(sep->arg[3],"15") && strcasecmp(sep->arg[3],"16")) { + } else if(strcasecmp(sep->arg[3],"1") && strcasecmp(sep->arg[3],"2") && strcasecmp(sep->arg[3],"3") && strcasecmp(sep->arg[3],"4") && strcasecmp(sep->arg[3],"5") && strcasecmp(sep->arg[3],"6") && strcasecmp(sep->arg[3],"7") && strcasecmp(sep->arg[3],"8") && strcasecmp(sep->arg[3],"9") && strcasecmp(sep->arg[3],"10") && strcasecmp(sep->arg[3],"11") && strcasecmp(sep->arg[3],"12") && strcasecmp(sep->arg[3],"13") && strcasecmp(sep->arg[3],"14") && strcasecmp(sep->arg[3],"15") && strcasecmp(sep->arg[3],"16")) { c->Message(0, "Usage: #bot create [name] [class(id)] [race(id)] [gender (male/female)]"); return; - } - else if(strcasecmp(sep->arg[4],"1") && strcasecmp(sep->arg[4],"2") && strcasecmp(sep->arg[4],"3") && strcasecmp(sep->arg[4],"4") && strcasecmp(sep->arg[4],"5") && strcasecmp(sep->arg[4],"6") && strcasecmp(sep->arg[4],"7") && strcasecmp(sep->arg[4],"8") && strcasecmp(sep->arg[4],"9") && strcasecmp(sep->arg[4],"10") && strcasecmp(sep->arg[4],"11") && strcasecmp(sep->arg[4],"12") && strcasecmp(sep->arg[4],"330") && strcasecmp(sep->arg[4],"128") && strcasecmp(sep->arg[4],"130") && strcasecmp(sep->arg[4],"522")) { + } else if(strcasecmp(sep->arg[4],"1") && strcasecmp(sep->arg[4],"2") && strcasecmp(sep->arg[4],"3") && strcasecmp(sep->arg[4],"4") && strcasecmp(sep->arg[4],"5") && strcasecmp(sep->arg[4],"6") && strcasecmp(sep->arg[4],"7") && strcasecmp(sep->arg[4],"8") && strcasecmp(sep->arg[4],"9") && strcasecmp(sep->arg[4],"10") && strcasecmp(sep->arg[4],"11") && strcasecmp(sep->arg[4],"12") && strcasecmp(sep->arg[4],"330") && strcasecmp(sep->arg[4],"128") && strcasecmp(sep->arg[4],"130") && strcasecmp(sep->arg[4],"522")) { c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender (male/female)]"); return; - } - else if(strcasecmp(sep->arg[5],"male") && strcasecmp(sep->arg[5],"female")) { + } else if(strcasecmp(sep->arg[5],"male") && strcasecmp(sep->arg[5],"female")) { c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender (male/female)]"); return; } @@ -10918,7 +9131,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Now that all validation is complete, we can save our newly created bot if(!NewBot->Save()) c->Message(0, "Unable to save %s as a bot.", NewBot->GetCleanName()); else @@ -10927,15 +9139,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else { // TODO: Log error message here } - - // Bot creation is complete return; } if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "create") ){ - c->Message(0, "Classes: 1(Warrior), 2(Cleric), 3(Paladin), 4(Ranger), 5(Sk), 6(Druid), 7(Monk), 8(Bard), 9(Rogue), 10(Shaman), 11(Necro), 12(Wiz), 13(Mag), 14(Ench), 15(Beast), 16(Bersek)"); + c->Message(0, "Classes: 1(WAR), 2(CLR), 3(PAL), 4(RNG), 5(SHD), 6(DRU), 7(MNK), 8(BRD), 9(ROG), 10(SHM), 11(NEC), 12(WIZ), 13(MAG), 14(ENC), 15(BST), 16(BER)"); c->Message(0, "------------------------------------------------------------------"); - c->Message(0, "Races: 1(Human), 2(Barb), 3(Erudit), 4(Wood elf), 5(High elf), 6(Dark elf), 7(Half elf), 8(Dwarf), 9(Troll), 10(Ogre), 11(Halfling), 12(Gnome), 128(Iksar), 130(Vah shir), 330(Froglok), 522(Drakkin)"); + c->Message(0, "Races: 1(Human), 2(Barbarian), 3(Erudite), 4(Wood Elf), 5(High Elf), 6(Dark Elf), 7(Half Elf), 8(Dwarf), 9(Troll), 10(Ogre), 11(Halfling), 12(Gnome), 128(Iksar), 130(Vah Shir), 330(Froglok), 522(Drakkin)"); c->Message(0, "------------------------------------------------------------------"); c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender(male/female)]"); c->Message(0, "Example: #bot create Sneaky 9 6 male"); @@ -10975,7 +9185,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "list")) { bool listAll = true; int iClass = atoi(sep->arg[2]); - if(iClass > 0 && iClass < 17) listAll = false; @@ -10993,8 +9202,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "Name: %s -- Class: %s -- Level: %u -- Race: %s", TempAvailableBotsList->BotName, ClassIdToString(TempAvailableBotsList->BotClass).c_str(), TempAvailableBotsList->BotLevel, RaceIdToString(TempAvailableBotsList->BotRace).c_str()); } - } - else { + } else { c->Message(0, "You have no bots created. Use the #bot create command to create a bot."); } } @@ -11002,34 +9210,25 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "mana")) { bool listAll = false; Bot* bot = 0; - if(sep->argnum == 2) { if(std::string(sep->arg[2]).compare("all") == 0) listAll = true; else { std::string botName = std::string(sep->arg[2]); - Bot* tempBot = entity_list.GetBotByBotName(botName); - - if(tempBot && tempBot->GetBotOwner() == c) { + if(tempBot && tempBot->GetBotOwner() == c) bot = tempBot; - } } - } - else { + } else { if(c->GetTarget() && c->GetTarget()->IsBot()) bot = c->GetTarget()->CastToBot(); } if(bot && !listAll) { - // Specific bot only if(bot->GetClass() != WARRIOR && bot->GetClass() != MONK && bot->GetClass() != BARD && bot->GetClass() != BERSERKER && bot->GetClass() != ROGUE) c->Message(0, "Name: %s -- Class: %s -- Mana: %3.1f%%", bot->GetCleanName(), ClassIdToString(bot->GetClass()).c_str(), bot->GetManaRatio()); - } - else { - // List all + } else { std::list spawnedBots = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - if(!spawnedBots.empty()) { for(std::list::iterator botsListItr = spawnedBots.begin(); botsListItr != spawnedBots.end(); ++botsListItr) { Bot* tempBot = *botsListItr; @@ -11038,12 +9237,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "Name: %s -- Class: %s -- Mana: %3.1f%%", tempBot->GetCleanName(), ClassIdToString(tempBot->GetClass()).c_str(), tempBot->GetManaRatio()); } } - } - else { + } else { c->Message(0, "You have no spawned bots in this zone."); } } - return; } @@ -11065,16 +9262,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - /*if(c->GetBotRaidID() > 0) { - BotRaids *br = entity_list.GetBotRaidByMob(c->CastToMob()); - if(br) { - if(br->GetBotRaidAggro()) { - c->Message(15, "You can't summon bots while you are engaged."); - return; - } - } - }*/ - if(c->IsGrouped()) { Group *g = entity_list.GetGroupByClient(c); for (int i=0; iSpawn(c, &TempErrorMessage); if(!TempErrorMessage.empty()) { @@ -11152,10 +9338,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - TempBot->CastToMob()->Say("I am ready for battle."); - } - else { - // We did not find a bot for the specified bot id from the database + TempBot->BotGroupSay(TempBot, "I am ready for battle."); + } else { c->Message(0, "BotID: %i not found", atoi(sep->arg[2])); } @@ -11204,18 +9388,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(c->GetTarget()->IsMob() && !c->GetTarget()->IsPet()) { Mob *b = c->GetTarget(); - if(b) - { - // Is our target "botable" ? + if(b) { if(!b->IsBot()){ c->Message(15, "You must target a bot!"); - } - else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) - { - b->Say("You can only summon your own bots."); - } - else - { + } else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) { + b->CastToBot()->BotGroupSay(b->CastToBot(), "You can only summon your own bots."); + } else { b->SetTarget(c->CastToMob()); b->Warp(glm::vec3(c->GetPosition())); } @@ -11236,9 +9414,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + const char* equipped[EmuConstants::EQUIPMENT_SIZE + 1] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", - "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo" }; + "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; const ItemInst* inst = nullptr; const Item_Struct* item = nullptr; @@ -11248,12 +9426,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { + for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { if((i == MainSecondary) && is2Hweapon) { continue; } - inst = b->CastToBot()->GetBotItem(i); + inst = b->CastToBot()->GetBotItem(i == 22 ? 9999 : i); if (inst) item = inst->GetItem(); else @@ -11264,28 +9442,23 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } if(item == nullptr) { - c->Message(15, "I need something for my %s (Item %i)", equipped[i], i); + c->Message(15, "I need something for my %s (Item %i)", equipped[i], (i == 22 ? 9999 : i)); continue; } if((i == MainPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { is2Hweapon = true; } - // I could not find a difference between the criteria positive code and the criteria negative code.. - // ..so, I deleted the check (old criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) - linker.SetItemInst(inst); item_link = linker.GenerateLink(); - c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], i); + c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], (i == 22 ? 9999 : i)); } - } - else { + } else { c->Message(15, "You must group your bot first."); } - } - else { + } else { c->Message(15, "You must target a bot first."); } return; @@ -11294,7 +9467,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "inventory") && !strcasecmp(sep->arg[2], "remove")) { if((c->GetTarget() == nullptr) || (sep->arg[3][0] == '\0') || !c->GetTarget()->IsBot()) { - c->Message(15, "Usage: #bot inventory remove [slotid] (You must have a bot targetted) "); + c->Message(15, "Usage: #bot inventory remove [slotid] (You must have a bot targeted) "); return; } else if(c->GetTarget()->IsBot() && c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) @@ -11303,13 +9476,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; int slotId = atoi(sep->arg[3]); - if(slotId > EmuConstants::EQUIPMENT_END || slotId < EmuConstants::EQUIPMENT_BEGIN) { - c->Message(15, "A bot has 21 slots in its inventory, please choose a slot between 0 and 21."); + if((slotId > EmuConstants::EQUIPMENT_END || slotId < EmuConstants::EQUIPMENT_BEGIN) && slotId != 9999) { + c->Message(15, "A bot has 22 slots in its inventory, please choose a slot between 0 and 21 or 9999."); return; } - const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + const char* equipped[EmuConstants::EQUIPMENT_SIZE + 1] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", - "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo" }; + "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; const Item_Struct* itm = nullptr; const ItemInst* itminst = c->GetTarget()->CastToBot()->GetBotItem(slotId); @@ -11326,16 +9499,14 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(itminst) { for (int m = AUG_BEGIN; m < EmuConstants::ITEM_COMMON_SIZE; ++m) { ItemInst *itma = itminst->GetAugment(m); - if(itma) - { - if(c->CheckLoreConflict(itma->GetItem())) { + if(itma) { + if(c->CheckLoreConflict(itma->GetItem())) failedLoreCheck = true; - } } } - if(c->CheckLoreConflict(itm)) { + + if(c->CheckLoreConflict(itm)) failedLoreCheck = true; - } } if(!failedLoreCheck) { if(itm) { @@ -11370,16 +9541,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { case MainFinger2: case MainChest: case MainWaist: - //case MainPowerSource: + case MainPowerSource: case MainAmmo: - gearbot->Say("My %s is now unequipped.", equipped[slotId]); + gearbot->BotGroupSay(gearbot, "My %s is now unequipped.", equipped[slotId]); break; case MainShoulders: case MainArms: case MainHands: case MainLegs: case MainFeet: - gearbot->Say("My %s are now unequipped.", equipped[slotId]); + gearbot->BotGroupSay(gearbot, "My %s are now unequipped.", equipped[slotId]); break; default: break; @@ -11403,16 +9574,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { case MainFinger2: case MainChest: case MainWaist: - //case MainPowerSource: + case MainPowerSource: case MainAmmo: - c->GetTarget()->Say("My %s is already unequipped.", equipped[slotId]); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "My %s is already unequipped.", equipped[slotId]); break; case MainShoulders: case MainArms: case MainHands: case MainLegs: case MainFeet: - c->GetTarget()->Say("My %s are already unequipped.", equipped[slotId]); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "My %s are already unequipped.", equipped[slotId]); break; default: break; @@ -11427,20 +9598,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(!strcasecmp(sep->arg[1], "update")) { - // Congdar: add IsEngaged check for exploit to keep bots alive by repeatedly using #bot update. if((c->GetTarget() != nullptr) && c->GetTarget()->IsBot()) { if(c->GetLevel() <= c->GetTarget()->GetLevel()) { c->Message(15, "This bot has already been updated."); return; } - if(c->IsGrouped()) - { + if(c->IsGrouped()) { Group *g = entity_list.GetGroupByClient(c); - for (int i=0; imembers[i] && g->members[i]->IsEngaged()) - { + for (int i=0; imembers[i] && g->members[i]->IsEngaged()) { c->Message(15, "You can't update bots while you are engaged."); return; } @@ -11449,20 +9616,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if((c->GetTarget()->CastToBot()->GetBotOwner() == c->CastToMob()) && !c->GetFeigned()) { Bot* bot = c->GetTarget()->CastToBot(); - //bot->SetLevel(c->GetLevel()); bot->SetPetChooser(false); bot->CalcBotStats(); - } - else { + } else { if(c->GetFeigned()) { c->Message(15, "You cannot update bots while feigned."); - } - else { + } else { c->Message(15, "You must target your bot first"); } } - } - else { + } else { c->Message(15, "You must target a bot first"); } @@ -11473,25 +9636,23 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "bindme")) { Mob *binder = nullptr; bool hasbinder = false; - if(c->IsGrouped()) - { + if(c->IsGrouped()) { Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) - { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) { hasbinder = true; binder = g->members[i]; } } - if(!hasbinder) { + + if(!hasbinder) c->Message(15, "You must have a Cleric in your group."); - } } } + if(hasbinder) { - binder->Say("Attempting to bind you %s.", c->GetName()); + binder->CastToBot()->BotGroupSay(binder->CastToBot(), "Attempting to bind you %s.", c->GetName()); binder->CastToNPC()->CastSpell(35, c->GetID(), 1, -1, -1); } return; @@ -11501,49 +9662,41 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "runeme")) { Mob *runeer = nullptr; bool hasruneer = false; - if(c->IsGrouped()) - { + if(c->IsGrouped()) { Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) - { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) { hasruneer = true; runeer = g->members[i]; } } - if(!hasruneer) { + + if(!hasruneer) c->Message(15, "You must have an Enchanter in your group."); - } } } + if(hasruneer) { if (c->GetLevel() <= 12) { - runeer->Say("I need to be level 13 or higher for this..."); - } - else if ((c->GetLevel() >= 13) && (c->GetLevel() <= 21)) { - runeer->Say("Casting Rune I..."); + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "I need to be level 13 or higher for this..."); + } else if ((c->GetLevel() >= 13) && (c->GetLevel() <= 21)) { + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune I..."); runeer->CastSpell(481, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() >= 22) && (c->GetLevel() <= 32)) { - runeer->Say("Casting Rune II..."); + } else if ((c->GetLevel() >= 22) && (c->GetLevel() <= 32)) { + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune II..."); runeer->CastSpell(482, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() >= 33) && (c->GetLevel() <= 39)) { - runeer->Say("Casting Rune III..."); + } else if ((c->GetLevel() >= 33) && (c->GetLevel() <= 39)) { + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune III..."); runeer->CastSpell(483, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() >= 40) && (c->GetLevel() <= 51)) { - runeer->Say("Casting Rune IV..."); + } else if ((c->GetLevel() >= 40) && (c->GetLevel() <= 51)) { + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune IV..."); runeer->CastSpell(484, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() >= 52) && (c->GetLevel() <= 60)) { - runeer->Say("Casting Rune V..."); + } else if ((c->GetLevel() >= 52) && (c->GetLevel() <= 60)) { + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune V..."); runeer->CastSpell(1689, c->GetID(), 1, -1, -1); - } - else if (c->GetLevel() >= 61){ - runeer->Say("Casting Rune of Zebuxoruk..."); + } else if (c->GetLevel() >= 61){ + runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune of Zebuxoruk..."); runeer->CastSpell(3343, c->GetID(), 1, -1, -1); } } @@ -11554,10 +9707,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "track") && c->IsGrouped()) { Mob *Tracker; uint32 TrackerClass = 0; - Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case RANGER: @@ -11565,14 +9717,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { TrackerClass = RANGER; break; case DRUID: - // Unless we have a ranger, druid is next best. if(TrackerClass != RANGER) { Tracker = g->members[i]; TrackerClass = DRUID; } break; case BARD: - // If we haven't found a tracker yet, use bard. if(TrackerClass == 0) { Tracker = g->members[i]; TrackerClass = BARD; @@ -11585,42 +9735,34 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } int Level = (c->GetLevel()); - int RangeR = (Level*80); //Ranger - int RangeD = (Level*30); //Druid - int RangeB = (Level*20); //Bard + int RangeR = (Level * 80); //Ranger + int RangeD = (Level * 30); //Druid + int RangeB = (Level * 20); //Bard switch(TrackerClass) { case RANGER: if(!strcasecmp(sep->arg[2], "all")) { - Tracker->Say("Tracking everything", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking everything", c->GetName()); entity_list.ShowSpawnWindow(c, RangeR, false); - } - else if(!strcasecmp(sep->arg[2], "rare")) { - Tracker->Say("Selective tracking", c->GetName()); + } else if(!strcasecmp(sep->arg[2], "rare")) { + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Selective tracking", c->GetName()); entity_list.ShowSpawnWindow(c, RangeR, true); - } - else if(!strcasecmp(sep->arg[2], "near")) { - Tracker->Say("Tracking mobs nearby", c->GetName()); + } else if(!strcasecmp(sep->arg[2], "near")) { + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking mobs nearby", c->GetName()); entity_list.ShowSpawnWindow(c, RangeD, false); - } - else - Tracker->Say("You want to [track all], [track near], or [track rare]?", c->GetName()); + } else + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "You want to [track all], [track near], or [track rare]?", c->GetName()); break; - case BARD: - if(TrackerClass != RANGER) - Tracker->Say("Tracking up", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up", c->GetName()); entity_list.ShowSpawnWindow(c, RangeB, false); break; - case DRUID: - if(TrackerClass = BARD) - Tracker->Say("Tracking up", c->GetName()); + Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up", c->GetName()); entity_list.ShowSpawnWindow(c, RangeD, false); break; - default: c->Message(15, "You must have a Ranger, Druid, or Bard in your group."); break; @@ -11634,7 +9776,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 CurerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case CLERIC: @@ -11646,13 +9788,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Curer = g->members[i]; CurerClass = SHAMAN; } + break; case DRUID: if (CurerClass == 0){ Curer = g->members[i]; CurerClass = DRUID; } break; - break; default: break; } @@ -11661,83 +9803,63 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(CurerClass) { case CLERIC: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 1)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(1, Curer->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 4)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 4)) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(2, Curer->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "curse") && (c->GetLevel() >= 8)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "curse") && (c->GetLevel() >= 8)) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(3, Curer->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 3)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 3)) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(4, Curer->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "curse") && (c->GetLevel() <= 8) + } else if (!strcasecmp(sep->arg[2], "curse") && (c->GetLevel() <= 8) || !strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() <= 3) || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 1)) { - Curer->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Curer->Say("Do you want [cure poison], [cure disease], [cure curse], or [cure blindness]?", c->GetName()); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); + } else + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], [cure curse], or [cure blindness]?", c->GetName()); break; - case SHAMAN: if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 2)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(1, Curer->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 1)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 1)) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(2, Curer->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "curse")) { - Curer->Say("I don't have that spell", sep->arg[2]); - } - else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 7)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "curse")) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 7)) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(4, Curer->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() <= 7) + } else if (!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() <= 7) || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 1) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 2)) { - Curer->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Curer->Say("Do you want [cure poison], [cure disease], or [cure blindness]?", c->GetName()); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]); + } else + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], [cure disease], or [cure blindness]?", c->GetName()); break; - case DRUID: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 5)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(1, Curer->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 4)) { - Curer->Say("Trying to cure us of %s.", sep->arg[2]); + } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 4)) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); Curer->CastToBot()->Bot_Command_Cure(2, Curer->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "curse")) { // Fire level 1 - Curer->Say("I don't have that spell", sep->arg[2]); - } - else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 13)) { - Curer->Say("I don't have that spell", sep->arg[2]); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) + } else if(!strcasecmp(sep->arg[2], "curse")) { // Fire level 1 + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 13)) { + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell", sep->arg[2]); + } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 5)) { - Curer->Say("I don't have the needed level yet", sep->arg[2]) ; - } - else - Curer->Say("Do you want [cure poison], or [cure disease]?", c->GetName()); - + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have the needed level yet", sep->arg[2]) ; + } else + Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want [cure poison], or [cure disease]?", c->GetName()); break; - default: c->Message(15, "You must have a Cleric, Shaman, or Druid in your group."); break; @@ -11746,300 +9868,240 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } //Mez - if(!strcasecmp(sep->arg[1], "ai") && !strcasecmp(sep->arg[2], "mez")) - { + if(!strcasecmp(sep->arg[1], "ai") && !strcasecmp(sep->arg[2], "mez")) { Mob *target = c->GetTarget(); - if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner()->IsBot())) - { + if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; } - if(c->IsGrouped()) - { + if(c->IsGrouped()) { bool hasmezzer = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) - { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) { hasmezzer = true; Mob *mezzer = g->members[i]; - mezzer->Say("Trying to mez %s \n", target->GetCleanName()); + mezzer->CastToBot()->BotGroupSay(mezzer->CastToBot(), "Trying to mesmerize %s.", target->GetCleanName()); mezzer->CastToBot()->MesmerizeTarget(target); } } - if(!hasmezzer) { + + if(!hasmezzer) c->Message(15, "You must have an Enchanter in your group."); - } } return; } //Lore (Identify item) if(!strcasecmp(sep->arg[1], "lore")) { - if(c->IsGrouped()) - { + if(c->IsGrouped()) { bool hascaster = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot()) { uint8 casterlevel = g->members[i]->GetLevel(); switch(g->members[i]->GetClass()) { case ENCHANTER: - if(casterlevel >= 15) { + if(casterlevel >= 15) hascaster = true; - } + break; case WIZARD: - if(casterlevel >= 14) { + if(casterlevel >= 14) hascaster = true; - } + break; case NECROMANCER: - if(casterlevel >= 17) { + if(casterlevel >= 17) hascaster = true; - } + break; case MAGICIAN: - if(casterlevel >= 13) { + if(casterlevel >= 13) hascaster = true; - } + break; default: break; } if(hascaster) { - g->members[i]->Say("Trying to Identify your item..."); + g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Trying to Identify your item..."); g->members[i]->CastSpell(305, c->GetID(), 1, -1, -1); break; } } } - if(!hascaster) { + + if(!hascaster) c->Message(15, "You don't see anyone in your group that can cast Identify."); - } - } - else { + } else c->Message(15, "You don't see anyone in your group that can cast Identify."); - } + return; } //Resurrect - if(!strcasecmp(sep->arg[1], "resurrectme")) - { + if(!strcasecmp(sep->arg[1], "resurrectme")) { Mob *target = c->GetTarget(); - if(target == nullptr || !target->IsCorpse()) - { - c->Message(15, "You must select a corpse"); + if(target == nullptr || !target->IsCorpse()) { + c->Message(15, "You must select a corpse!"); return; } - if(c->IsGrouped()) - { + if(c->IsGrouped()) { bool hasrezzer = false; Group *g = c->GetGroup(); - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) - { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) { hasrezzer = true; Mob *rezzer = g->members[i]; - rezzer->Say("Trying to rez %s", target->GetCleanName()); + rezzer->CastToBot()->BotGroupSay(rezzer->CastToBot(), "Trying to resurrect %s.", target->GetCleanName()); rezzer->CastToBot()->Bot_Command_RezzTarget(target); break; } } - if(!hasrezzer) { - c->Message(15, "You must have a Cleric in your group."); - } - } - else { - c->Message(15, "You must have a Cleric in your group."); - } + + if(!hasrezzer) + c->Message(15, "You must have a Cleric in your group!"); + } else + c->Message(15, "You must have a Cleric in your group!"); + return; } - if(!strcasecmp(sep->arg[1], "magepet")) - { - if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->GetClass() == MAGICIAN)) - { - if(c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) - { + if(!strcasecmp(sep->arg[1], "magepet")) { + if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->GetClass() == MAGICIAN)) { + if(c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) { int botlevel = c->GetTarget()->GetLevel(); c->GetTarget()->CastToBot()->SetPetChooser(true); - if(botlevel == 1) - { - c->GetTarget()->Say("I don't have any pets yet."); + if(botlevel == 1) { + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have any pets yet."); return; } - if(!strcasecmp(sep->arg[2], "water")) - { + + if(!strcasecmp(sep->arg[2], "water")) { c->GetTarget()->CastToBot()->SetPetChooserID(0); - } - else if(!strcasecmp(sep->arg[2], "fire")) - { - if(botlevel < 3) - { - c->GetTarget()->Say("I don't have that pet yet."); + } else if(!strcasecmp(sep->arg[2], "fire")) { + if(botlevel < 3) { + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; - } - else - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(1); - } - } - else if(!strcasecmp(sep->arg[2], "air")) - { - if(botlevel < 4) - { - c->GetTarget()->Say("I don't have that pet yet."); + } else if(!strcasecmp(sep->arg[2], "air")) { + if(botlevel < 4) { + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; - } - else - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(2); - } - } - else if(!strcasecmp(sep->arg[2], "earth")) - { - if(botlevel < 5) - { - c->GetTarget()->Say("I don't have that pet yet."); + } else if(!strcasecmp(sep->arg[2], "earth")) { + if(botlevel < 5) { + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; - } - else - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(3); - } - } - else if(!strcasecmp(sep->arg[2], "monster")) - { - if(botlevel < 30) - { - c->GetTarget()->Say("I don't have that pet yet."); + } else if(!strcasecmp(sep->arg[2], "monster")) { + if(botlevel < 30) { + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); return; - } - else - { + } else c->GetTarget()->CastToBot()->SetPetChooserID(4); - } } - if(c->GetTarget()->GetPet()) - { - // cast reclaim energy + + if(c->GetTarget()->GetPet()) { uint16 id = c->GetTarget()->GetPetID(); c->GetTarget()->SetPetID(0); c->GetTarget()->CastSpell(331, id); } } - } - else - { - c->Message(15, "You must target your Magician bot."); - } + } else + c->Message(15, "You must target your Magician bot!"); + return; } //Summon Corpse if(!strcasecmp(sep->arg[1], "corpse") && !strcasecmp(sep->arg[2], "summon")) { if(c->GetTarget() == nullptr) { - c->Message(15, "You must select player with his corpse in the zone."); + c->Message(15, "You must select player with his corpse in the zone!"); return; } + if(c->IsGrouped()) { bool hassummoner = false; Mob *t = c->GetTarget(); Group *g = c->GetGroup(); int summonerlevel = 0; - for(int i=0; imembers[i] && g->members[i]->IsBot() && ((g->members[i]->GetClass() == NECROMANCER)||(g->members[i]->GetClass() == SHADOWKNIGHT))) { hassummoner = true; summonerlevel = g->members[i]->GetLevel(); g->members[i]->InterruptSpell(); if(!t->IsClient()) { - g->members[i]->Say("You have to target a player with a corpse in the zone"); + g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "You have to target a player with a corpse in the zone!"); return; - } - else { + } else { g->members[i]->SetTarget(t); - if(summonerlevel < 12) { - g->members[i]->Say("I don't have that spell yet."); - } - else if((summonerlevel > 11) && (summonerlevel < 35)) { - g->members[i]->Say("Attempting to summon %s\'s corpse.", t->GetCleanName()); + g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "I don't have that spell yet."); + } else if((summonerlevel > 11) && (summonerlevel < 35)) { + g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Attempting to summon %s\'s corpse.", t->GetCleanName()); g->members[i]->CastSpell(2213, t->GetID(), 1, -1, -1); return; - } - else if((summonerlevel > 34) && (summonerlevel < 71)) { - g->members[i]->Say("Attempting to summon %s\'s corpse.", t->GetCleanName()); + } else if((summonerlevel > 34) && (summonerlevel < 71)) { + g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Attempting to summon %s\'s corpse.", t->GetCleanName()); g->members[i]->CastSpell(3, t->GetID(), 1, -1, -1); return; - } - else if(summonerlevel > 70) { - g->members[i]->Say("Attempting to summon %s\'s corpse.", t->GetCleanName()); + } else if(summonerlevel > 70) { + g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Attempting to summon %s\'s corpse.", t->GetCleanName()); g->members[i]->CastSpell(10042, t->GetID(), 1, -1, -1); return; } } } } - if (!hassummoner) { - c->Message(15, "You must have a Necromancer or Shadowknight in your group."); - } + + if (!hassummoner) + c->Message(15, "You must have a Necromancer or Shadow Knight in your group."); + return; } } //Pacify - if(!strcasecmp(sep->arg[1], "target") && !strcasecmp(sep->arg[2], "calm")) - { + if(!strcasecmp(sep->arg[1], "target") && !strcasecmp(sep->arg[2], "calm")) { Mob *target = c->GetTarget(); - - if(target == nullptr || target->IsClient() || target->IsBot() || target->IsPet() && target->GetOwner()->IsBot()) - c->Message(15, "You must select a monster"); + if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) + c->Message(15, "You must select a monster!"); else { if(c->IsGrouped()) { Group *g = c->GetGroup(); - - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) { Bot *pacer = g->members[i]->CastToBot(); - pacer->Say("Trying to pacify %s \n", target->GetCleanName()); - + pacer->BotGroupSay(pacer, "Trying to pacify %s.", target->GetCleanName()); if(pacer->Bot_Command_CalmTarget(target)) { if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate)) - //if(pacer->IsPacified(target)) c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); - return; - /*else - c->Message(0, "I failed to pacify %s.", target->GetCleanName());*/ - } - else + + return; + } else c->Message(0, "I failed to pacify %s.", target->GetCleanName()); } // seperated cleric and chanter so chanter is primary if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC) && (GroupHasEnchanterClass(g) == false)) { Bot *pacer = g->members[i]->CastToBot(); - pacer->Say("Trying to pacify %s \n", target->GetCleanName()); + pacer->BotGroupSay(pacer, "Trying to pacify %s.", target->GetCleanName()); if(pacer->Bot_Command_CalmTarget(target)) { if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate)) - //if(pacer->IsPacified(target)) c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); - return; - /*else - c->Message(0, "I failed to pacify %s.", target->GetCleanName());*/ - } - else + + return; + } else c->Message(0, "I failed to pacify %s.", target->GetCleanName()); } - /*else - c->Message(15, "You must have an Enchanter or Cleric in your group.");*/ } } } @@ -12048,20 +10110,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } //Charm - if(!strcasecmp(sep->arg[1], "charm")) - { + if(!strcasecmp(sep->arg[1], "charm")) { Mob *target = c->GetTarget(); - if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner()->IsBot())) - { - c->Message(15, "You must select a monster"); + if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { + c->Message(15, "You must select a monster!"); return; } + uint32 DBtype = c->GetTarget()->GetBodyType(); Mob *Charmer; uint32 CharmerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case ENCHANTER: @@ -12073,13 +10134,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Charmer = g->members[i]; CharmerClass = NECROMANCER; } + break; case DRUID: if (CharmerClass == 0){ Charmer = g->members[i]; CharmerClass = DRUID; } break; - break; default: break; } @@ -12088,42 +10149,33 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(CharmerClass) { case ENCHANTER: if (c->GetLevel() >= 11) { - Charmer->Say("Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (1,target); - } - else if (c->GetLevel() <= 10){ - Charmer->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Charmer->Say("Mob level is too high or can't be charmed", c->GetName()); + } else if (c->GetLevel() <= 10){ + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob level is too high or can't be charmed.", c->GetName()); break; - case NECROMANCER: if ((c->GetLevel() >= 18) && (DBtype == 3)) { - Charmer->Say("Trying to Charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (2,target); - } - else if (c->GetLevel() <= 17){ - Charmer->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Charmer->Say("Mob Is not undead...", c->GetName()); + } else if (c->GetLevel() <= 17){ + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not undead.", c->GetName()); break; - case DRUID: if ((c->GetLevel() >= 13) && (DBtype == 21)) { - Charmer->Say("Trying to charm %s \n", target->GetCleanName(), sep->arg[2]); + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName(), sep->arg[2]); Charmer->CastToBot()->Bot_Command_CharmTarget (3,target); - } - else if (c->GetLevel() <= 12){ - Charmer->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Charmer->Say("Mob is not an animal...", c->GetName()); + } else if (c->GetLevel() <= 12){ + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not an animal.", c->GetName()); break; - default: - c->Message(15, "You must have an Enchanter, Necromancer or Druid in your group."); + c->Message(15, "You must have an Enchanter, Necromancer, or Druid in your group."); break; } } @@ -12136,36 +10188,28 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { ((c->GetTarget()->GetClass() == NECROMANCER) || (c->GetTarget()->GetClass() == ENCHANTER) || (c->GetTarget()->GetClass() == DRUID))) { if(c->GetTarget()->CastToBot()->IsBotCharmer()) { c->GetTarget()->CastToBot()->SetBotCharmer(false); - c->GetTarget()->Say("Using a summoned pet."); - } - else { - if(c->GetTarget()->GetPet()) - { + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "Using a summoned pet."); + } else { + if(c->GetTarget()->GetPet()) { c->GetTarget()->GetPet()->Say_StringID(PET_GETLOST_STRING); - // c->GetTarget()->GetPet()->Kill(); c->GetTarget()->GetPet()->Depop(false); c->GetTarget()->SetPetID(0); } c->GetTarget()->CastToBot()->SetBotCharmer(true); - c->GetTarget()->Say("Available for Dire Charm command."); + c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "Available for Dire Charm command."); } - } - else { + } else c->Message(15, "You must target your Enchanter, Necromancer, or Druid bot."); - } - } - else { + } else c->Message(15, "You must target an Enchanter, Necromancer, or Druid bot."); - } + return; } //Dire Charm - if(!strcasecmp(sep->arg[1], "Dire") && !strcasecmp(sep->arg[2], "Charm")) - { + if(!strcasecmp(sep->arg[1], "Dire") && !strcasecmp(sep->arg[2], "Charm")) { Mob *target = c->GetTarget(); - if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner()->IsBot())) - { + if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { c->Message(15, "You must select a monster"); return; } @@ -12174,7 +10218,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 DirerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case ENCHANTER: @@ -12186,13 +10230,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Direr = g->members[i]; DirerClass = NECROMANCER; } + break; case DRUID: if (DirerClass == 0){ Direr = g->members[i]; DirerClass = DRUID; } break; - break; default: break; } @@ -12201,42 +10245,33 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(DirerClass) { case ENCHANTER: if (c->GetLevel() >= 55) { - Direr->Say("Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (1,target); - } - else if (c->GetLevel() <= 55){ - Direr->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Direr->Say("Mob level is too high or can't be charmed", c->GetName()); + } else if (c->GetLevel() <= 55){ + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob level is too high or can't be charmed.", c->GetName()); break; - case NECROMANCER: if ((c->GetLevel() >= 55) && (DBtype == 3)) { - Direr->Say("Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (2,target); - } - else if (c->GetLevel() <= 55){ - Direr->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Direr->Say("Mob Is not undead...", c->GetName()); + } else if (c->GetLevel() <= 55){ + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not undead.", c->GetName()); break; - case DRUID: if ((c->GetLevel() >= 55) && (DBtype == 21)) { - Direr->Say("Trying to dire charm %s \n", target->GetCleanName(), sep->arg[2]); + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName(), sep->arg[2]); Direr->CastToBot()->Bot_Command_DireTarget (3,target); - } - else if (c->GetLevel() <= 55){ - Direr->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Direr->Say("Mob is not an animal...", c->GetName()); + } else if (c->GetLevel() <= 55){ + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I don't have the required level yet.", sep->arg[2]); + } else + Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not an animal.", c->GetName()); break; - default: - c->Message(15, "You must have an Enchanter, Necromancer or Druid in your group."); + c->Message(15, "You must have an Enchanter, Necromancer, or Druid in your group."); break; } } @@ -12246,31 +10281,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "evac")) { Mob *evac = nullptr; bool hasevac = false; - if(c->IsGrouped()) - { + if(c->IsGrouped()) { Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == DRUID)) - || (g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == WIZARD))) - { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if((g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == DRUID)) || (g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == WIZARD))) { hasevac = true; evac = g->members[i]; } } - if(!hasevac) { + + if(!hasevac) c->Message(15, "You must have a Druid in your group."); - } } } + if((hasevac) && (c->GetLevel() >= 18)) { - evac->Say("Attempting to Evac you %s.", c->GetName()); + evac->CastToBot()->BotGroupSay(evac->CastToBot(), "Attempting to evacuate you, %s.", c->GetName()); evac->CastToClient()->CastSpell(2183, c->GetID(), 1, -1, -1); - } - else if((hasevac) && (c->GetLevel() <= 17)) { - evac->Say("I'm not level 18 yet.", c->GetName()); - } + } else if((hasevac) && (c->GetLevel() <= 17)) + evac->CastToBot()->BotGroupSay(evac->CastToBot(), "I'm not level 18 yet.", c->GetName()); + return; } @@ -12280,7 +10311,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 SowerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -12312,92 +10343,69 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(SowerClass) { case DRUID: - if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() >= 10) ) { - Sower->Say("Casting sow..."); + if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() >= 10)) { + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting sow..."); Sower->CastSpell(278, c->GetID(), 1, -1, -1); } - else if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() <= 10) ) { - Sower->Say("I'm not level 10 yet."); - } + else if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() <= 10)) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 10 yet."); else if ((!strcasecmp(sep->arg[2], "wolf")) && zone->CanCastOutdoor() && (c->GetLevel() >= 20)) { - Sower->Say("Casting group wolf..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting group wolf..."); Sower->CastSpell(428, c->GetID(), 1, -1, -1); } - else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 20)) { - Sower->Say("I'm not level 20 yet."); - } + else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 20)) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 20 yet."); else if ((!strcasecmp(sep->arg[2], "feral")) && (c->GetLevel() >= 50)) { - Sower->Say("Casting Feral Pack..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Feral Pack..."); Sower->CastSpell(4058, c->GetID(), 1, -1, -1); } - else if ((!strcasecmp(sep->arg[2], "feral")) && (c->GetLevel() <= 50)) { - Sower->Say("I'm not level 50 yet."); - } + else if ((!strcasecmp(sep->arg[2], "feral")) && (c->GetLevel() <= 50)) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 50 yet."); else if ((!strcasecmp(sep->arg[2], "shrew")) && (c->GetLevel() >= 35)) { - Sower->Say("Casting Pack Shrew..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Pack Shrew..."); Sower->CastSpell(4055, c->GetID(), 1, -1, -1); } - else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 35)) { - Sower->Say("I'm not level 35 yet."); - } - else if ((!zone->CanCastOutdoor()) && (!strcasecmp(sep->arg[2], "regular")) || - (!zone->CanCastOutdoor()) && (!strcasecmp(sep->arg[2], "wolf"))) { - Sower->Say("I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); - } - else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); - } - else if (zone->CanCastOutdoor()) { - Sower->Say("Do you want [sow regular] or [sow wolf]?", c->GetName()); - } - else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher,", c->GetName()); - } + else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 35)) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 35 yet."); + else if ((!zone->CanCastOutdoor()) && (!strcasecmp(sep->arg[2], "regular")) || (!zone->CanCastOutdoor()) && (!strcasecmp(sep->arg[2], "wolf"))) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); + else if (!zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); + else if (zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Do you want [sow regular] or [sow wolf]?"); + else if (!zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try [sow shrew] if you're 35 or higher, or [sow feral] if you're 50 or higher."); break; - case SHAMAN: - if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 9)) { - Sower->Say("Casting SoW..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Spirit of Wolf."); Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); } - else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors", c->GetName()); - } - else if (c->GetLevel() <= 9) { - Sower->Say("I'm not level 9 yet."); - } + else if (!zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors."); + else if (c->GetLevel() <= 9) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 9 yet."); break; - case RANGER: - if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 28)){ - Sower->Say("Casting SoW..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Spirit of Wolf."); Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); } - else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors", c->GetName()); - } - else if (c->GetLevel() <= 28) { - Sower->Say("I'm not level 28 yet."); - } + else if (!zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors."); + else if (c->GetLevel() <= 28) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 28 yet."); break; - case BEASTLORD: - if((zone->CanCastOutdoor()) && (c->GetLevel() >= 24)) { - Sower->Say("Casting SoW..."); + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Spirit of Wolf."); Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); } - else if (!zone->CanCastOutdoor()) { - Sower->Say("I can't cast this spell indoors", c->GetName()); - } - else if (c->GetLevel() <= 24) { - Sower->Say("I'm not level 24 yet."); - } + else if (!zone->CanCastOutdoor()) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors."); + else if (c->GetLevel() <= 24) + Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 24 yet."); break; - - default: c->Message(15, "You must have a Druid, Shaman, Ranger, or Beastlord in your group."); break; @@ -12411,12 +10419,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 ShrinkerClass = 0; Group *g = c->GetGroup(); Mob *target = c->GetTarget(); - if(target == nullptr || (!target->IsClient() && (c->GetTarget()->CastToBot()->GetBotOwner() != c))) c->Message(15, "You must select a player or bot you own"); else if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case SHAMAN: @@ -12436,27 +10443,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(ShrinkerClass) { case SHAMAN: - if (c->GetLevel() >= 15) { - Shrinker->Say("Casting Shrink..."); + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink."); Shrinker->CastToBot()->SpellOnTarget(345, target); } - else if (c->GetLevel() <= 14) { - Shrinker->Say("I'm not level 15 yet."); - } + else if (c->GetLevel() <= 14) + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "I'm not level 15 yet."); break; - case BEASTLORD: - if (c->GetLevel() >= 23) { - Shrinker->Say("Casting Shrink..."); + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink."); Shrinker->CastToBot()->SpellOnTarget(345, target); } - else if (c->GetLevel() <= 22) { - Shrinker->Say("I'm not level 23 yet."); - } + else if (c->GetLevel() <= 22) + Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "I'm not level 23 yet."); break; - default: c->Message(15, "You must have a Shaman or Beastlord in your group."); break; @@ -12470,7 +10471,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 GaterClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -12491,106 +10492,81 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { switch(GaterClass) { case DRUID: if ((!strcasecmp(sep->arg[2], "karana")) && (c->GetLevel() >= 25) ) { - Gater->Say("Casting Circle of Karana..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Karana."); Gater->CastSpell(550, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Circle of Commons..."); + } else if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Commons."); Gater->CastSpell(551, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->Say("Casting Circle of Toxxulia..."); + } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Toxxulia."); Gater->CastSpell(552, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "butcher")) && (c->GetLevel() >= 25)) { - Gater->Say("Casting Circle of Butcherblock..."); + } else if ((!strcasecmp(sep->arg[2], "butcher")) && (c->GetLevel() >= 25)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Butcherblock."); Gater->CastSpell(553, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "lava")) && (c->GetLevel() >= 30)) { - Gater->Say("Casting Circle of Lavastorm..."); + } else if ((!strcasecmp(sep->arg[2], "lava")) && (c->GetLevel() >= 30)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Lavastorm."); Gater->CastSpell(554, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Circle of Ro..."); + } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Ro."); Gater->CastSpell(555, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "feerrott")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Circle of feerrott..."); + } else if ((!strcasecmp(sep->arg[2], "feerrott")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Feerrott."); Gater->CastSpell(556, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "steamfont")) && (c->GetLevel() >= 31)) { - Gater->Say("Casting Circle of Steamfont..."); + } else if ((!strcasecmp(sep->arg[2], "steamfont")) && (c->GetLevel() >= 31)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Steamfont."); Gater->CastSpell(557, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "misty")) && (c->GetLevel() >= 36)) { - Gater->Say("Casting Circle of Misty..."); + } else if ((!strcasecmp(sep->arg[2], "misty")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Misty."); Gater->CastSpell(558, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 40)) { - Gater->Say("Casting Circle of Wakening Lands..."); + } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 40)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Wakening Lands."); Gater->CastSpell(1398, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Circle of Iceclad Ocean..."); + } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Iceclad Ocean."); Gater->CastSpell(1434, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->Say("Casting Circle of The Great Divide..."); + } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Great Divide."); Gater->CastSpell(1438, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 42)) { - Gater->Say("Casting Circle of Cobalt Scar..."); + } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 42)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Cobalt Scar."); Gater->CastSpell(1440, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 33)) { - Gater->Say("Casting Circle of The Combines..."); + } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 33)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Combines."); Gater->CastSpell(1517, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "surefall")) && (c->GetLevel() >= 26)) { - Gater->Say("Casting Circle of Surefall Glade..."); + } else if ((!strcasecmp(sep->arg[2], "surefall")) && (c->GetLevel() >= 26)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Surefall Glade."); Gater->CastSpell(2020, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->Say("Casting Circle of Grimling Forest..."); + } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Grimling Forest."); Gater->CastSpell(2419, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 33)) { - Gater->Say("Casting Circle of Twilight..."); + } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 33)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Twilight."); Gater->CastSpell(2424, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 37)) { - Gater->Say("Casting Circle of Dawnshroud..."); + } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 37)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Dawnshroud."); Gater->CastSpell(2429, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 26)) { - Gater->Say("Casting Circle of The Nexus..."); + } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 26)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of The Nexus."); Gater->CastSpell(2432, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 38)) { - Gater->Say("Casting Circle of Knowledge..."); + } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 38)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Knowledge."); Gater->CastSpell(3184, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 28)) { - Gater->Say("Casting Circle of Stonebrunt Mountains..."); + } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 28)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Stonebrunt Mountains."); Gater->CastSpell(3792, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->Say("Casting Circle of Bloodfields..."); + } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Bloodfields."); Gater->CastSpell(6184, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 39)) { - Gater->Say("Casting Wind of the South..."); + } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 39)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the South."); Gater->CastSpell(1737, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 44)) { - Gater->Say("Casting Wind of the North..."); + } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 44)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wind of the North."); Gater->CastSpell(1736, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "slaughter")) && (c->GetLevel() >= 64)) { - Gater->Say("Casting Circle of Slaughter..."); + } else if ((!strcasecmp(sep->arg[2], "slaughter")) && (c->GetLevel() >= 64)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Circle of Slaughter."); Gater->CastSpell(6179, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "karana") + } else if ((!strcasecmp(sep->arg[2], "karana") || !strcasecmp(sep->arg[2], "tox") || !strcasecmp(sep->arg[2], "butcher") && (c->GetLevel() <= 25)) || !strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 27) @@ -12615,112 +10591,84 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 38) || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 43) || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->Say("I don't have the needed level yet", sep->arg[2]); - } - else { - Gater->Say("With the proper level I can [gate] to [karana],[commons],[tox],[butcher],[lava],[ro],[feerrott],[steamfont],[misty],[wakening],[iceclad],[divide],[cobalt],[combines],[surefall],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire] or [wos].", c->GetName()); - } + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet."); + } else + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [karana], [commons], [tox], [butcher], [lava], [ro], [feerrott], [steamfont], [misty], [wakening], [iceclad], [divide], [cobalt], [combines], [surefall], [grimling], [twilight], [dawnshroud], [nexus], [pok], [stonebrunt], [bloodfields], [emerald], [skyfire] or [wos]."); break; - case WIZARD: - if ((!strcasecmp(sep->arg[2], "commons")) && (c->GetLevel() >= 35) ) { - Gater->Say("Casting Common Portal..."); + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Common Portal."); Gater->CastSpell(566, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "fay")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Fay Portal..."); + } else if ((!strcasecmp(sep->arg[2], "fay")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal."); Gater->CastSpell(563, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 37)) { - Gater->Say("Casting Ro Portal..."); + } else if ((!strcasecmp(sep->arg[2], "ro")) && (c->GetLevel() >= 37)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Ro Portal."); Gater->CastSpell(567, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { - Gater->Say("Casting Toxxula Portal..."); + } else if ((!strcasecmp(sep->arg[2], "tox")) && (c->GetLevel() >= 25)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Toxxulia Portal."); Gater->CastSpell(561, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nk")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting North Karana Portal..."); + } else if ((!strcasecmp(sep->arg[2], "nk")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting North Karana Portal."); Gater->CastSpell(562, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nek")) && (c->GetLevel() >= 32)) { - Gater->Say("Casting Nektulos Portal..."); + } else if ((!strcasecmp(sep->arg[2], "nek")) && (c->GetLevel() >= 32)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nektulos Portal."); Gater->CastSpell(564, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 43)) { - Gater->Say("Casting Wakening Lands Portal..."); + } else if ((!strcasecmp(sep->arg[2], "wakening")) && (c->GetLevel() >= 43)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wakening Lands Portal."); Gater->CastSpell(1399, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 33)) { - Gater->Say("Casting Iceclad Ocean Portal..."); + } else if ((!strcasecmp(sep->arg[2], "iceclad")) && (c->GetLevel() >= 33)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Iceclad Ocean Portal."); Gater->CastSpell(1418, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { - Gater->Say("Casting Great Divide Portal..."); + } else if ((!strcasecmp(sep->arg[2], "divide")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Great Divide Portal."); Gater->CastSpell(1423, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 43)) { - Gater->Say("Casting Cobalt Scar Portal..."); + } else if ((!strcasecmp(sep->arg[2], "cobalt")) && (c->GetLevel() >= 43)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Cobalt Scar Portal."); Gater->CastSpell(1425, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 34)) { - Gater->Say("Casting Combines Portal..."); + } else if ((!strcasecmp(sep->arg[2], "combines")) && (c->GetLevel() >= 34)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Combines Portal."); Gater->CastSpell(1516, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wk")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting West Karana Portal..."); + } else if ((!strcasecmp(sep->arg[2], "wk")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting West Karana Portal."); Gater->CastSpell(568, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Twilight Portal..."); + } else if ((!strcasecmp(sep->arg[2], "twilight")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Twilight Portal."); Gater->CastSpell(2425, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Dawnshroud Portal..."); + } else if ((!strcasecmp(sep->arg[2], "dawnshroud")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Dawnshroud Portal."); Gater->CastSpell(2430, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 29)) { - Gater->Say("Casting Nexus Portal..."); + } else if ((!strcasecmp(sep->arg[2], "nexus")) && (c->GetLevel() >= 29)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Nexus Portal."); Gater->CastSpell(2944, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Plane of Knowledge Portal..."); + } else if ((!strcasecmp(sep->arg[2], "pok")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Plane of Knowledge Portal."); Gater->CastSpell(3180, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wos")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Wall of Slaughter Portal..."); + } else if ((!strcasecmp(sep->arg[2], "wos")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Wall of Slaughter Portal."); Gater->CastSpell(6178, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { - Gater->Say("Casting Fay Portal..."); + } else if ((!strcasecmp(sep->arg[2], "grimling")) && (c->GetLevel() >= 29)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Fay Portal."); Gater->CastSpell(2420, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 37)) { - Gater->Say("Porting to Emerald Jungle..."); + } else if ((!strcasecmp(sep->arg[2], "emerald")) && (c->GetLevel() >= 37)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Emerald Jungle."); Gater->CastSpell(1739, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "hateplane")) && (c->GetLevel() >= 39)) { - Gater->Say("Porting to Hate Plane..."); + } else if ((!strcasecmp(sep->arg[2], "hateplane")) && (c->GetLevel() >= 39)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Hate Plane."); Gater->CastSpell(666, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "airplane")) && (c->GetLevel() >= 39)) { - Gater->Say("Porting to airplane..."); + } else if ((!strcasecmp(sep->arg[2], "airplane")) && (c->GetLevel() >= 39)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Airplane."); Gater->CastSpell(674, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 36)) { - Gater->Say("Porting to Skyfire..."); + } else if ((!strcasecmp(sep->arg[2], "skyfire")) && (c->GetLevel() >= 36)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Porting to Skyfire."); Gater->CastSpell(1738, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { - Gater->Say("Casting Bloodfields Portal..."); + } else if ((!strcasecmp(sep->arg[2], "bloodfields")) && (c->GetLevel() >= 55)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Bloodfields Portal."); Gater->CastSpell(6183, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 27)) { - Gater->Say("Casting Stonebrunt Portal..."); + } else if ((!strcasecmp(sep->arg[2], "stonebrunt")) && (c->GetLevel() >= 27)) { + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Casting Stonebrunt Portal."); Gater->CastSpell(3793, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 35)) + } else if ((!strcasecmp(sep->arg[2], "commons") && (c->GetLevel() <= 35)) || !strcasecmp(sep->arg[2], "fay") && (c->GetLevel() <= 27) || (!strcasecmp(sep->arg[2], "ro") && (c->GetLevel() <= 37)) || !strcasecmp(sep->arg[2], "tox") && (c->GetLevel() <= 25) @@ -12744,11 +10692,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { || !strcasecmp(sep->arg[2], "emerald") && (c->GetLevel() <= 36) || !strcasecmp(sep->arg[2], "skyfire") && (c->GetLevel() <= 36) || !strcasecmp(sep->arg[2], "wos") && (c->GetLevel() <= 64)) { - Gater->Say("I don't have the needed level yet", sep->arg[2]); - } - else { - Gater->Say("With the proper level I can [gate] to [commons],[fay],[ro],[tox],[nk],[wakening],[iceclad],[divide],[cobalt],[combines],[wk],[grimling],[twilight],[dawnshroud],[nexus],[pok],[stonebrunt],[bloodfields],[emerald],[skyfire],[hateplane],[airplane] or [wos].", c->GetName()); - } + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "I don't have the needed level yet."); + } else + Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can [gate] to [commons], [fay], [ro], [tox], [nk], [wakening], [iceclad], [divide], [cobalt], [combines], [wk], [grimling], [twilight], [dawnshroud], [nexus], [pok], [stonebrunt], [bloodfields], [emerald], [skyfire], [hateplane], [airplane] or [wos].", c->GetName()); break; default: c->Message(15, "You must have a Druid or Wizard in your group."); @@ -12763,7 +10709,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 EndurerClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -12801,48 +10747,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(EndurerClass) { case DRUID: - if (c->GetLevel() < 6) { - Endurer->Say("I'm not level 6 yet."); - } + if (c->GetLevel() < 6) + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 6 yet."); else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); break; } break; case SHAMAN: - if (c->GetLevel() < 12) { - Endurer->Say("I'm not level 12 yet."); - } + if (c->GetLevel() < 12) + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 12 yet."); else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case RANGER: - if (c->GetLevel() < 20) { - Endurer->Say("I'm not level 20 yet."); - } + if (c->GetLevel() < 20) + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 20 yet."); else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case ENCHANTER: - if (c->GetLevel() < 12) { - Endurer->Say("I'm not level 12 yet."); - } + if (c->GetLevel() < 12) + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 12 yet."); else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; case BEASTLORD: - if (c->GetLevel() < 25) { - Endurer->Say("I'm not level 25 yet."); - } + if (c->GetLevel() < 25) + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 25 yet."); else { - Endurer->Say("Casting Enduring Breath..."); + Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); Endurer->CastSpell(86, c->GetID(), 1, -1, -1); } break; @@ -12859,7 +10800,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 InviserClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case ENCHANTER: @@ -12898,137 +10839,111 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(InviserClass) { case ENCHANTER: - if ((c->GetLevel() <= 14) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("I'm not level 14 yet."); - } + if ((c->GetLevel() <= 14) && (!strcasecmp(sep->arg[2], "undead"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 14 yet."); else if ((!c->IsInvisible(c)) && (!c->invisible_undead) && (c->GetLevel() >= 14) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("Casting invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 4 yet."); - } + else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 4 yet."); else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("Casting invisibilty..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invisibilty."); Inviser->CastSpell(42, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 6) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("I'm not level 6 yet."); - } + else if ((c->GetLevel() <= 6) && (!strcasecmp(sep->arg[2], "see"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 6 yet."); else if ((c->GetLevel() >= 6) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); - } - else { - Inviser->Say("Do you want [invis undead], [invis live] or [invis see] ?", c->GetName()); - } + else if ((c->IsInvisible(c)) || (c->invisible_undead)) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); + else + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis undead], [invis live] or [invis see]?"); break; case MAGICIAN: - if (!strcasecmp(sep->arg[2], "undead")) { - Inviser->Say("I don't have that spell."); - } - else if ((c->GetLevel() <= 8) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 8 yet."); - } + if (!strcasecmp(sep->arg[2], "undead")) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); + else if ((c->GetLevel() <= 8) && (!strcasecmp(sep->arg[2], "live"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 8 yet."); else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 8) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("Casting invisibilty..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invisibilty."); Inviser->CastSpell(42, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("I'm not level 16 yet."); - } + else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "see"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 16 yet."); else if ((c->GetLevel() >= 16) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); - } - else { - Inviser->Say("Do you want [invis live] or [invis see] ?", c->GetName()); - } + else if ((c->IsInvisible(c)) || (c->invisible_undead)) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); + else + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis live] or [invis see]?"); break; case WIZARD: - if ((c->GetLevel() <= 39) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("I'm not level 39 yet."); - } + if ((c->GetLevel() <= 39) && (!strcasecmp(sep->arg[2], "undead"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 39 yet."); else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 39) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("Casting invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 16 yet."); - } + else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "live"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 16 yet."); else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 16) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("Casting invisibilty..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invisibilty."); Inviser->CastSpell(42, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("I'm not level 6 yet."); - } + else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "see"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 6 yet."); else if ((c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); - } - else { - Inviser->Say("Do you want [invis undead], [invis live] or [invis see] ?", c->GetName()); - } + else if ((c->IsInvisible(c)) || (c->invisible_undead)) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); + else + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis undead], [invis live] or [invis see]?"); break; case NECROMANCER: if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->Say("Casting invis undead..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting invis undead."); Inviser->CastSpell(235, c->GetID(), 1, -1, -1); } - else if (!strcasecmp(sep->arg[2], "see")) { - Inviser->Say("I don't have that spell..."); - } - else if (!strcasecmp(sep->arg[2], "live")) { - Inviser->Say("I don't have that spell..."); - } - else if ((c->IsInvisible(c))|| (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); - } - else { - Inviser->Say("I only have [invis undead]", c->GetName()); - } + else if (!strcasecmp(sep->arg[2], "see")) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); + else if (!strcasecmp(sep->arg[2], "live")) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); + else if ((c->IsInvisible(c))|| (c->invisible_undead)) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); + else + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I only have [invis undead]"); break; case DRUID: - if (!strcasecmp(sep->arg[2], "undead")) { - Inviser->Say("I don't have that spell..."); - } - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("I'm not level 4 yet."); - } + if (!strcasecmp(sep->arg[2], "undead")) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); + else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 4 yet."); else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 18) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->Say("Casting Superior Camouflage..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Superior Camouflage."); Inviser->CastSpell(34, c->GetID(), 1, -1, -1); - } - else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live")) && (zone->CanCastOutdoor())) { - Inviser->Say("Casting Camouflage..."); + } else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live")) && (zone->CanCastOutdoor())) { + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Camouflage..."); Inviser->CastSpell(247, c->GetID(), 1, -1, -1); } - else if ((c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live")) && (!zone->CanCastOutdoor())) { - Inviser->Say("I can't cast this spell indoors..."); - } - else if ((c->GetLevel() <= 13) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("I'm not level 13 yet."); - } + else if ((c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live")) && (!zone->CanCastOutdoor())) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this spell indoors."); + else if ((c->GetLevel() <= 13) && (!strcasecmp(sep->arg[2], "see"))) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 13 yet."); else if ((c->GetLevel() >= 13) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->Say("Casting see invisible..."); + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting see invisible."); Inviser->CastSpell(80, c->GetID(), 1, -1, -1); } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) { - Inviser->Say("I can't cast this if you're already invis-buffed..."); - } - else { - Inviser->Say("Do you want [invis live] or [invis see] ?", c->GetName()); - } + else if ((c->IsInvisible(c)) || (c->invisible_undead)) + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); + else + Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want [invis live] or [invis see]?"); break; default: c->Message(15, "You must have a Enchanter, Magician, Wizard, Druid, or Necromancer in your group."); @@ -13043,7 +10958,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 LeverClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case DRUID: @@ -13075,62 +10990,46 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(LeverClass) { case DRUID: - if (c->GetLevel() <= 14) { - Lever->Say("I'm not level 14 yet."); - } + if (c->GetLevel() <= 14) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 14 yet."); else if (zone->CanCastOutdoor()) { - Lever->Say("Casting Levitate..."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); Lever->CastSpell(261, c->GetID(), 1, -1, -1); break; } - else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); - } + else if (!zone->CanCastOutdoor()) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); break; - case SHAMAN: - if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 10)) { - Lever->Say("Casting Levitate..."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); } - else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); - } - else if (c->GetLevel() <= 10) { - Lever->Say("I'm not level 10 yet."); - } + else if (!zone->CanCastOutdoor()) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); + else if (c->GetLevel() <= 10) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 10 yet."); break; - case WIZARD: - - if((zone->CanCastOutdoor()) && (c->GetLevel() >= 22)){ - Lever->Say("Casting Levitate..."); + if((zone->CanCastOutdoor()) && (c->GetLevel() >= 22)) { + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); } - else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); - } - else if (c->GetLevel() <= 22) { - Lever->Say("I'm not level 22 yet."); - } + else if (!zone->CanCastOutdoor()) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); + else if (c->GetLevel() <= 22) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 22 yet."); break; - case ENCHANTER: - if((zone->CanCastOutdoor()) && (c->GetLevel() >= 15)) { - Lever->Say("Casting Levitate..."); + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); } - else if (!zone->CanCastOutdoor()) { - Lever->Say("I can't cast this spell indoors", c->GetName()); - } - else if (c->GetLevel() <= 15) { - Lever->Say("I'm not level 15 yet."); - } + else if (!zone->CanCastOutdoor()) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); + else if (c->GetLevel() <= 15) + Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 15 yet."); break; - - default: c->Message(15, "You must have a Druid, Shaman, Wizard, or Enchanter in your group."); break; @@ -13144,7 +11043,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint32 ResisterClass = 0; Group *g = c->GetGroup(); if(g) { - for(int i=0; imembers[i] && g->members[i]->IsBot()) { switch(g->members[i]->GetClass()) { case CLERIC: @@ -13156,13 +11055,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Resister = g->members[i]; ResisterClass = SHAMAN; } + break; case DRUID: if (ResisterClass == 0){ Resister = g->members[i]; ResisterClass = DRUID; } break; - break; default: break; } @@ -13170,104 +11069,81 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } switch(ResisterClass) { case CLERIC: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 6)) { - Resister->Say("Casting poison protection...", sep->arg[2]); + if(!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 6)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection."); Resister->CastToBot()->Bot_Command_Resist(1, Resister->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 11)) { - Resister->Say("Casting disease protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 11)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting disease protection."); Resister->CastToBot()->Bot_Command_Resist(2, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 8)) { - Resister->Say("Casting fire protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 8)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting fire protection."); Resister->CastToBot()->Bot_Command_Resist(3, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { - Resister->Say("Casting cold protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting cold protection."); Resister->CastToBot()->Bot_Command_Resist(4, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { - Resister->Say("Casting magic protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting magic protection."); Resister->CastToBot()->Bot_Command_Resist(5, Resister->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 16) + } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 16) || !strcasecmp(sep->arg[2], "cold") && (c->GetLevel() <= 13) || !strcasecmp(sep->arg[2], "fire") && (c->GetLevel() <= 8) || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 11) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 6)) { - Resister->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Resister->Say("Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the required level yet."); + } else + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); break; - case SHAMAN: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 20)) { - Resister->Say("Casting poison protection...", sep->arg[2]); + if(!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 20)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection."); Resister->CastToBot()->Bot_Command_Resist(12, Resister->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 8)) { - Resister->Say("Casting disease protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 8)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting disease protection."); Resister->CastToBot()->Bot_Command_Resist(13, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 5)) { - Resister->Say("Casting fire protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 5)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting fire protection."); Resister->CastToBot()->Bot_Command_Resist(14, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 1)) { - Resister->Say("Casting cold protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 1)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting cold protection."); Resister->CastToBot()->Bot_Command_Resist(15, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 19)) { - Resister->Say("Casting magic protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 19)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting magic protection."); Resister->CastToBot()->Bot_Command_Resist(16, Resister->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 19) + } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 19) || !strcasecmp(sep->arg[2], "cold") && (c->GetLevel() <= 1) || !strcasecmp(sep->arg[2], "fire") && (c->GetLevel() <= 5) || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 8) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 20)) { - Resister->Say("I don't have the needed level yet", sep->arg[2]); - } - else - Resister->Say("Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the needed level yet."); + } else + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); break; - case DRUID: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 19)) { - Resister->Say("Casting poison protection...", sep->arg[2]); + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting poison protection."); Resister->CastToBot()->Bot_Command_Resist(7, Resister->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 19)) { - Resister->Say("Casting disease protection...", sep->arg[2]); + } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 19)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting disease protection."); Resister->CastToBot()->Bot_Command_Resist(8, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "fire")) { // Fire level 1 - Resister->Say("Casting fire protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "fire")) { // Fire level 1 + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting fire protection."); Resister->CastToBot()->Bot_Command_Resist(9, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { - Resister->Say("Casting cold protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting cold protection."); Resister->CastToBot()->Bot_Command_Resist(10, Resister->GetLevel()); - } - else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { - Resister->Say("Casting magic protection...", sep->arg[2]); + } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting magic protection."); Resister->CastToBot()->Bot_Command_Resist(11, Resister->GetLevel()); - } - else if (!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 16) + } else if (!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 16) || !strcasecmp(sep->arg[2], "cold") && (c->GetLevel() <= 9) || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 19) || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 19)) { - Resister->Say("I don't have the needed level yet", sep->arg[2]) ; - } - else - Resister->Say("Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?", c->GetName()); - + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I don't have the required level yet.") ; + } else + Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want [resist poison], [resist disease], [resist fire], [resist cold], or [resist magic]?"); break; - default: c->Message(15, "You must have a Cleric, Shaman, or Druid in your group."); break; @@ -13275,52 +11151,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } - // debug commands - if(!strcasecmp(sep->arg[1], "debug") && !strcasecmp(sep->arg[2], "inventory")) { - Mob *target = c->GetTarget(); - - if(target && target->IsBot()) { - for(int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) { - c->Message(15,"Equiped slot: %i , item: %i \n", i, target->CastToBot()->GetEquipment(i)); - } - if(target->CastToBot()->GetEquipment(MaterialSecondary) > 0) - c->Message(15,"This bot has an item in off-hand."); - } - return; - } - - if(!strcasecmp(sep->arg[1], "debug") && !strcasecmp(sep->arg[2], "botcaracs")) - { - Mob *target = c->GetTarget(); - if(target && target->IsBot()) - { - if(target->CanThisClassDualWield()) - c->Message(15, "This class can dual wield."); - if(target->CanThisClassDoubleAttack()) - c->Message(15, "This class can double attack."); - } - if(target->GetPetID()) - c->Message(15, "I've a pet and its name is %s", target->GetPet()->GetCleanName() ); - return; - } - - if(!strcasecmp(sep->arg[1], "debug") && !strcasecmp(sep->arg[2], "spells")) - { - Mob *target = c->GetTarget(); - if(target && target->IsBot()) - { - for(int i=0; iCastToBot()->AIspells.size(); i++) - { - if(target->CastToBot()->BotGetSpells(i) != 0) - { - SPDat_Spell_Struct botspell = spells[target->CastToBot()->BotGetSpells(i)]; - c->Message(15, "(DEBUG) %s , Slot(%i), Spell (%s) Priority (%i) \n", target->GetCleanName(), i, botspell.name, target->CastToBot()->BotGetSpellPriority(i)); - } - } - } - return; - } - // #bot group ... if(!strcasecmp(sep->arg[1], "group") && !strcasecmp(sep->arg[2], "help")) { c->Message(0, "#bot group help - will show this help."); @@ -13328,7 +11158,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "#bot group follow "); c->Message(0, "#bot group guard "); c->Message(0, "#bot group attack "); - return; } @@ -13336,23 +11165,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[2], "follow")) { if(c->IsGrouped()) BotGroupOrderFollow(c->GetGroup(), c); - } - else if(!strcasecmp(sep->arg[2], "guard")) { + } else if(!strcasecmp(sep->arg[2], "guard")) { if(c->IsGrouped()) BotGroupOrderGuard(c->GetGroup(), c); - } - else if(!strcasecmp(sep->arg[2], "attack")) { - if(c->IsGrouped() && (c->GetTarget() != nullptr) && c->IsAttackAllowed(c->GetTarget())) { + } else if(!strcasecmp(sep->arg[2], "attack")) { + if(c->IsGrouped() && (c->GetTarget() != nullptr) && c->IsAttackAllowed(c->GetTarget())) BotGroupOrderAttack(c->GetGroup(), c->GetTarget(), c); - } else c->Message(15, "You must target a monster."); - } - else if(!strcasecmp(sep->arg[2], "summon")) { + } else if(!strcasecmp(sep->arg[2], "summon")) { if(c->IsGrouped()) BotGroupSummon(c->GetGroup(), c); } - return; } @@ -13379,10 +11203,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -13390,11 +11212,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(Bot::BotGroupCreate(botGroupLeader)) - botGroupLeader->Say("I am prepared to lead."); + botGroupLeader->BotGroupSay(botGroupLeader, "I am prepared to lead."); else - botGroupLeader->Say("I can not lead."); - } - else + botGroupLeader->BotGroupSay(botGroupLeader, "I cannot lead."); + } else c->Message(13, "You must target a spawned bot first."); return; @@ -13402,17 +11223,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "add")) { int argCount = 0; - argCount = sep->argnum; - std::string botGroupLeaderName; std::string botGroupMemberName; - if(argCount >= 3) botGroupMemberName = std::string(sep->arg[3]); Bot* botGroupMember = entity_list.GetBotByBotName(botGroupMemberName); - if(!botGroupMember) { if(botGroupMemberName.empty()) c->Message(13, "You must target a bot in this zone. Please try again."); @@ -13423,13 +11240,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Bot* botGroupLeader = 0; - if(argCount == 4) { botGroupLeaderName = std::string(sep->arg[4]); - botGroupLeader = entity_list.GetBotByBotName(botGroupLeaderName); - } - else if(c->GetTarget() && c->GetTarget()->IsBot()) + } else if(c->GetTarget() && c->GetTarget()->IsBot()) botGroupLeader = c->GetTarget()->CastToBot(); if(!botGroupLeader) { @@ -13453,41 +11267,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupMember) { if(!botGroupMember->HasGroup()) { - // invite if(Bot::AddBotToGroup(botGroupMember, g)) { database.SetGroupID(botGroupMember->GetName(), g->GetID(), botGroupMember->GetBotID()); - botGroupMember->Say("I have joined %s\'s group.", botGroupLeader->GetName()); - } - else { - botGroupMember->Say("I can not join %s\'s group.", botGroupLeader->GetName()); - } - } - else { - // "I am already in a group." + botGroupMember->BotGroupSay(botGroupMember, "I have joined %s\'s group.", botGroupLeader->GetName()); + } else + botGroupMember->BotGroupSay(botGroupMember, "I can not join %s\'s group.", botGroupLeader->GetName()); + } else { Group* tempGroup = botGroupMember->GetGroup(); if(tempGroup) - botGroupMember->Say("I can not join %s\'s group. I am already a member in %s\'s group.", botGroupLeader->GetName(), tempGroup->GetLeaderName()); + botGroupMember->BotGroupSay(botGroupMember, "I can not join %s\'s group. I am already a member in %s\'s group.", botGroupLeader->GetName(), tempGroup->GetLeaderName()); } - } - else { - // must target a bot message + } else c->Message(13, "You must target a spawned bot first."); - } - } - else { - // "My group is full." - botGroupLeader->Say("I have no more openings in my group, %s.", c->GetName()); - } - } - else { - // "I am not a group leader." + } else + botGroupLeader->BotGroupSay(botGroupMember, "I have no more openings in my group, %s.", c->GetName()); + } else { Group* tempGroup = botGroupLeader->GetGroup(); if(tempGroup) - botGroupLeader->Say("I can not lead anyone because I am a member in %s\'s group.", tempGroup->GetLeaderName()); + botGroupLeader->BotGroupSay(botGroupLeader, "I can not lead anyone because I am a member in %s\'s group.", tempGroup->GetLeaderName()); } } } - return; } @@ -13496,9 +11296,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { std::string targetName = std::string(sep->arg[3]); Bot* botGroupMember = 0; - if(!targetName.empty()) { + if(!targetName.empty()) botGroupMember = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupMember = targetMob->CastToBot(); @@ -13507,16 +11306,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupMember) { if(botGroupMember->HasGroup()) { Group* g = botGroupMember->GetGroup(); - if(Bot::RemoveBotFromGroup(botGroupMember, g)) - botGroupMember->Say("I am no longer in a group."); + botGroupMember->BotGroupSay(botGroupMember, "I am no longer in a group."); else - botGroupMember->Say("I can not leave %s\'s group.", g->GetLeaderName()); - } - else - botGroupMember->Say("I am not in a group."); - } - else + botGroupMember->BotGroupSay(botGroupMember, "I can not leave %s\'s group.", g->GetLeaderName()); + } else + botGroupMember->BotGroupSay(botGroupMember, "I am not in a group."); + } else c->Message(13, "You must target a spawned bot first."); return; @@ -13526,10 +11322,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -13538,21 +11332,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) { if(Bot::RemoveBotFromGroup(botGroupLeader, g)) - botGroupLeader->Say("I have disbanded my group, %s.", c->GetName()); + botGroupLeader->BotGroupSay(botGroupLeader, "I have disbanded my group, %s.", c->GetName()); else - botGroupLeader->Say("I was not able to disband my group, %s.", c->GetName()); - } - else { - botGroupLeader->Say("I can not disband my group, %s, because I am not the leader. %s is the leader of my group.", c->GetName(), g->GetLeaderName()); - } - } - else - botGroupLeader->Say("I am not a group leader, %s.", c->GetName()); - } - else + botGroupLeader->BotGroupSay(botGroupLeader, "I was not able to disband my group, %s.", c->GetName()); + } else + botGroupLeader->BotGroupSay(botGroupLeader, "I can not disband my group, %s, because I am not the leader. %s is the leader of my group.", c->GetName(), g->GetLeaderName()); + } else + botGroupLeader->BotGroupSay(botGroupLeader, "I am not a group leader, %s.", c->GetName()); + } else c->Message(13, "You must target a spawned bot group leader first."); return; @@ -13563,9 +11352,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -13574,12 +11362,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) BotGroupSummon(g, c); } - } - else if(c->HasGroup()) + } else if(c->HasGroup()) BotGroupSummon(c->GetGroup(), c); return; @@ -13589,10 +11375,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -13601,12 +11385,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) BotGroupOrderFollow(g, c); } - } - else if(c->HasGroup()) + } else if(c->HasGroup()) BotGroupOrderFollow(c->GetGroup(), c); return; @@ -13616,10 +11398,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* targetMob = c->GetTarget(); std::string targetName = std::string(sep->arg[3]); Bot* botGroupLeader = 0; - - if(!targetName.empty()) { + if(!targetName.empty()) botGroupLeader = entity_list.GetBotByBotName(targetName); - } else if(targetMob) { if(targetMob->IsBot()) botGroupLeader = targetMob->CastToBot(); @@ -13628,12 +11408,10 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupLeader) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) BotGroupOrderGuard(g, c); } - } - else if(c->HasGroup()) + } else if(c->HasGroup()) BotGroupOrderGuard(c->GetGroup(), c); return; @@ -13644,95 +11422,73 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Bot* botGroupLeader = 0; std::string botGroupLeaderName = std::string(sep->arg[3]); std::string targetName = std::string(sep->arg[4]); - if(!botGroupLeaderName.empty()) { botGroupLeader = entity_list.GetBotByBotName(botGroupLeaderName); - if(botGroupLeader) { - if(!targetName.empty()) { + if(!targetName.empty()) targetMob = entity_list.GetMob(targetName.c_str()); - } if(targetMob) { if(c->IsAttackAllowed(targetMob)) { if(botGroupLeader->HasGroup()) { Group* g = botGroupLeader->GetGroup(); - if(g) { if(g->IsLeader(botGroupLeader)) BotGroupOrderAttack(g, targetMob, c); } - } - else if(c->HasGroup()) + } else if(c->HasGroup()) BotGroupOrderAttack(c->GetGroup(), targetMob, c); - } - else + } else c->Message(13, "You must target a monster."); - } - else + } else c->Message(13, "You must target a monster."); - } - else + } else c->Message(13, "You must target a spawned bot group leader first."); } - return; } if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "list")) { std::list botGroupList = GetBotGroupListByBotOwnerCharacterId(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } if(!botGroupList.empty()) { - for(std::list::iterator botGroupListItr = botGroupList.begin(); botGroupListItr != botGroupList.end(); ++botGroupListItr) { + for(std::list::iterator botGroupListItr = botGroupList.begin(); botGroupListItr != botGroupList.end(); ++botGroupListItr) c->Message(0, "Bot Group Name: %s -- Bot Group Leader: %s", botGroupListItr->BotGroupName.c_str(), botGroupListItr->BotGroupLeaderName.c_str()); - } - } - else { + } else c->Message(0, "You have no bot groups created. Use the #bot botgroup save command to save bot groups."); - } return; } if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "load")) { - - // If client is grouped, check for aggro on each group member. Group *g = c->GetGroup(); if(g) { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - // Skip invalid group members. - if(!g->members[i]) { continue; } - - // Fail if current group member is client and has aggro - // OR has a popuplated hate list (assume bot). - if((g->members[i]->IsClient() && g->members[i]->CastToClient()->GetAggroCount()) - || g->members[i]->IsEngaged()) { + if(!g->members[i]) + continue; + + if((g->members[i]->IsClient() && g->members[i]->CastToClient()->GetAggroCount()) || g->members[i]->IsEngaged()) { c->Message(0, "You can't spawn bots while your group is engaged."); return; } } - } - // Fail if ungrouped client has aggro. - else { + } else { if(c->GetAggroCount() > 0) { c->Message(0, "You can't spawn bots while you are engaged."); return; } } - // Parse botgroup name. std::string botGroupName = std::string(sep->arg[3]); if(botGroupName.empty()) { c->Message(13, "Invalid botgroup name supplied."); return; } - // Get botgroup id. uint32 botGroupID = CanLoadBotGroup(c->CharacterID(), botGroupName, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -13743,59 +11499,43 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Get list of bots in specified group. std::list botGroup = LoadBotGroup(botGroupName, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - // Count of client's currently spawned bots. int spawnedBots = SpawnedBotCount(c->CharacterID(), &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - // BotQuest rule value in database is True. if(RuleB(Bots, BotQuest)) { - // Max number of allowed spawned bots for client. const int allowedBotsBQ = AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - // Fail if no bots allowed for client. if(allowedBotsBQ == 0) { c->Message(0, "You can't spawn any bots."); return; } - // Fail if maximum number of spawned bots allowed for client met or exceeded - // OR will be when bot group is spawned. - if(spawnedBots >= allowedBotsBQ - || spawnedBots + (int)botGroup.size() > allowedBotsBQ) { - c->Message(0, "You can't spawn more than %i bot(s). [Rule:BQ]", allowedBotsBQ); + if(spawnedBots >= allowedBotsBQ || spawnedBots + (int)botGroup.size() > allowedBotsBQ) { + c->Message(0, "You can't spawn more than %i bot(s).", allowedBotsBQ); return; } } - // Fail if maximum number of spawned bots allowed for client met or exceeded - // OR will be when bot group is spawned. const int allowedBotsSBC = RuleI(Bots, SpawnBotCount); - if(spawnedBots >= allowedBotsSBC - || spawnedBots + (int)botGroup.size() > allowedBotsSBC) { - c->Message(0, "You can't spawn more than %i bots. [Rule:SBC]", allowedBotsSBC); + if(spawnedBots >= allowedBotsSBC || spawnedBots + (int)botGroup.size() > allowedBotsSBC) { + c->Message(0, "You can't spawn more than %i bots.", allowedBotsSBC); return; } - // Passed all checks. Spawn requested bot group. - - // Get botgroup's leader's id. uint32 botGroupLeaderBotID = GetBotGroupLeaderIdByBotGroupName(botGroupName); - - // Load botgroup's leader. Bot *botGroupLeader = LoadBot(botGroupLeaderBotID, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -13808,7 +11548,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Spawn botgroup's leader. botGroupLeader->Spawn(c, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -13816,11 +11555,11 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Create botgroup. if(!BotGroupCreate(botGroupLeader)) { c->Message(13, "Unable to create botgroup."); return; } + Group *newBotGroup = botGroupLeader->GetGroup(); if(!newBotGroup) { c->Message(13, "Unable to find valid botgroup"); @@ -13828,23 +11567,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } for(auto botGroupItr = botGroup.begin(); botGroupItr != botGroup.end(); ++botGroupItr) { - // Don't try to re-spawn the botgroup's leader. - if(botGroupItr->BotID == botGroupLeader->GetBotID()) { continue; } + if(botGroupItr->BotID == botGroupLeader->GetBotID()) + continue; - // Load current botgroup member Bot *botGroupMember = LoadBot(botGroupItr->BotID, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); safe_delete(botGroupMember); return; } - // Skip invalid botgroup members. + if(!botGroupMember) { safe_delete(botGroupMember); continue; } - // Spawn current botgroup member. botGroupMember->Spawn(c, &TempErrorMessage); if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); @@ -13852,19 +11589,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - // Add current botgroup member to botgroup. AddBotToGroup(botGroupMember, newBotGroup); } - return; } if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "delete")) { std::string botGroupName = std::string(sep->arg[3]); - if(!botGroupName.empty()) { uint32 botGroupId = CanLoadBotGroup(c->CharacterID(), botGroupName, &TempErrorMessage); - if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; @@ -13872,24 +11605,20 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(botGroupId > 0) { DeleteBotGroup(botGroupName, &TempErrorMessage); - if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } } } - return; } if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "save")) { std::string botGroupName = std::string(sep->arg[3]); - if(!botGroupName.empty()) { if(!DoesBotGroupNameExist(botGroupName)) { Bot* groupLeader = 0; - if(c->GetTarget() && c->GetTarget()->IsBot()) groupLeader = c->GetTarget()->CastToBot(); else @@ -13898,23 +11627,17 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(groupLeader) { if(groupLeader->HasGroup() && groupLeader->GetGroup()->IsLeader(groupLeader)) { SaveBotGroup(groupLeader->GetGroup(), botGroupName, &TempErrorMessage); - - if(!TempErrorMessage.empty()) { + if(!TempErrorMessage.empty()) c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - } else c->Message(0, "%s's bot group has been saved as %s.", groupLeader->GetName(), botGroupName.c_str()); - } - else + } else c->Message(0, "You must target a bot group leader only."); - } - else + } else c->Message(0, "You must target a bot that is in the same zone as you."); - } - else + } else c->Message(0, "The bot group name already exists. Please choose another name to save your bot group as."); } - return; } @@ -13933,22 +11656,23 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { uint8 BeardColor = target->GetBeardColor(); uint8 EyeColor1 = target->GetEyeColor1(); uint8 EyeColor2 = target->GetEyeColor2(); - uint8 LuclinFace = target->GetLuclinFace(); uint8 Beard = target->GetBeard(); uint32 DrakkinHeritage = target->GetDrakkinHeritage(); uint32 DrakkinTattoo = target->GetDrakkinTattoo(); uint32 DrakkinDetails = target->GetDrakkinDetails(); float Size = target->GetSize(); - if (!strcasecmp(sep->arg[1], "hair")) HairStyle = atoi(sep->arg[2]); + if (!strcasecmp(sep->arg[1], "haircolor")) HairColor = atoi(sep->arg[2]); + if (!strcasecmp(sep->arg[1], "beard") || !strcasecmp(sep->arg[1], "beardcolor")) { if (!Gender || Race == 8) { if (!strcasecmp(sep->arg[1], "beard")) Beard = atoi(sep->arg[2]); + if (!strcasecmp(sep->arg[1], "beardcolor")) BeardColor = atoi(sep->arg[2]); } else { @@ -13956,6 +11680,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } } + if (!strcasecmp(sep->arg[1], "face")) LuclinFace = atoi(sep->arg[2]); @@ -13963,46 +11688,42 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { EyeColor1 = EyeColor2 = atoi(sep->arg[2]); c->Message(0, "Eye Values = 0 - 11"); } + if(!strcasecmp(sep->arg[1], "heritage") || !strcasecmp(sep->arg[1], "tattoo") || !strcasecmp(sep->arg[1], "details")) { if(Race == 522) { if(!strcasecmp(sep->arg[1], "heritage")) { DrakkinHeritage = atoi(sep->arg[2]); c->Message(0, "Heritage Values = 0 - 6"); } + if(!strcasecmp(sep->arg[1], "tattoo")) { DrakkinTattoo = atoi(sep->arg[2]); c->Message(0, "Tattoo Values = 0 - 7"); } + if(!strcasecmp(sep->arg[1], "details")) { DrakkinDetails = atoi(sep->arg[2]); c->Message(0, "Details Values = 0 - 7"); } - } - else { + } else { c->Message(0, "Drakkin only."); return; } } - target->SendIllusionPacket(Race, Gender, Texture, HelmTexture, HairColor, BeardColor, - EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, - DrakkinHeritage, DrakkinTattoo, DrakkinDetails, Size); - + target->SendIllusionPacket(Race, Gender, Texture, HelmTexture, HairColor, BeardColor, EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, DrakkinHeritage, DrakkinTattoo, DrakkinDetails, Size); if(target->CastToBot()->Save()) c->Message(0, "%s saved.", target->GetCleanName()); else c->Message(13, "%s save failed!", target->GetCleanName()); - c->Message(0,"Feature changed."); - } else { + c->Message(0, "Feature changed."); + } else c->Message(0, "You must own the bot to make changes."); - } - } else { + } else c->Message(0, "Requires a value."); - } - } else { - c->Message(0,"A bot needs to be targetted."); - } + } else + c->Message(0, "A bot needs to be targeted."); return; } @@ -14021,7 +11742,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Bot *targetedBot = nullptr; - if(c->GetTarget() != nullptr) { if (c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) targetedBot = c->GetTarget()->CastToBot(); @@ -14035,26 +11755,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(taunt) { if(!targetedBot->taunting) - targetedBot->Say("I am now taunting."); - } - else { + targetedBot->BotGroupSay(targetedBot, "I am now taunting."); + } else { if(targetedBot->taunting) - targetedBot->Say("I am no longer taunting."); + targetedBot->BotGroupSay(targetedBot, "I am no longer taunting."); } targetedBot->SetTaunting(taunt); - } - else + } else c->Message(13, "You must select a bot with the taunt skill."); - } - else { + } else { c->Message(13, "You must target a spawned bot."); } } - } - else { + } else c->Message(0, "Usage #bot taunt [on|off]"); - } return; } @@ -14063,7 +11778,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3){ Bot* tempBot = nullptr; std::string botName = std::string(sep->arg[2]); - if(!botName.empty()) tempBot = entity_list.GetBotByBotName(botName); else @@ -14072,23 +11786,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(tempBot) { std::string stanceName; BotStanceType botStance; - if (tempBot->GetBotOwner() != c) { c->Message(13, "You must target a bot that you own."); return; } - if(!strcasecmp(sep->arg[3], "list")) { + if(!strcasecmp(sep->arg[3], "list")) botStance = tempBot->GetBotStance(); - } else { int stance = atoi(sep->arg[3]); - if(stance >= MaxStances || stance < 0){ c->Message(0, "Usage #bot stance [name] [stance (id)] (Passive = 0, Balanced = 1, Efficient = 2, Reactive = 3, Aggressive = 4, Burn = 5, BurnAE = 6)"); return; - } - else { + } else { botStance = (BotStanceType)stance; if(botStance != tempBot->GetBotStance()) { tempBot->SetBotStance(botStance); @@ -14133,20 +11843,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } } c->Message(0, "Stance for %s: %s.", tempBot->GetCleanName(), stanceName.c_str()); - } - else { + } else c->Message(13, "You must name a valid bot."); - } - } - else { + } else c->Message(0, "Usage #bot stance [name] [stance (id)] (Passive = 0, Balanced = 1, Efficient = 2, Reactive = 3, Aggressive = 4, Burn = 5, BurnAE = 6)"); - } + return; } if(!strcasecmp(sep->arg[1], "groupmessages")) { bool groupMessages = false; - if(sep->arg[2] && sep->arg[3]){ if(!strcasecmp(sep->arg[2], "on")) groupMessages = true; @@ -14158,10 +11864,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Bot* tempBot; - if(!strcasecmp(sep->arg[3], "all")) { std::list spawnedBots = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - if(!spawnedBots.empty()) { for(std::list::iterator botsListItr = spawnedBots.begin(); botsListItr != spawnedBots.end(); ++botsListItr) { Bot* tempBot = *botsListItr; @@ -14169,16 +11873,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { tempBot->SetGroupMessagesOn(groupMessages); } } - } - else { + } else c->Message(0, "You have no spawned bots in this zone."); - } c->Message(0, "Group messages now %s for all bots.", groupMessages?"on":"off"); - } - else { + } else { std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) tempBot = entity_list.GetBotByBotName(botName); else { @@ -14191,25 +11891,21 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(13, "You must target a bot that you own."); return; } - tempBot->SetGroupMessagesOn(groupMessages); c->Message(0, "Group messages now %s.", groupMessages?"on":"off"); - } - else { + } else { c->Message(13, "You must name a valid bot."); } } - } - else { + } else c->Message(0, "Usage #bot groupmessages [on|off] [bot name|all]"); - } + return; } if(!strcasecmp(sep->arg[1], "defensive")) { Bot* tempBot; std::string botName = std::string(sep->arg[2]); - if(!botName.empty()) tempBot = entity_list.GetBotByBotName(botName); else { @@ -14220,7 +11916,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(tempBot) { uint8 botlevel = tempBot->GetLevel(); uint32 defensiveSpellID = 0; - if (tempBot->GetBotOwner() != c) { c->Message(13, "You must target a bot that you own."); return; @@ -14237,7 +11932,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(botlevel >= 52) defensiveSpellID = 4503; //Evasive discipline else - c->Message(0, "Error: warrior must be level 52+"); + c->Message(0, "Warrior must be level 52 or higher."); break; case PALADIN: if(botlevel >= 73) @@ -14249,7 +11944,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(botlevel >= 56) defensiveSpellID = 7004; //Guard of Piety else - c->Message(0, "Error: paladin must be level 56+"); + c->Message(0, "Paladin must be level 56 or higher."); break; case SHADOWKNIGHT: if(botlevel >= 73) @@ -14261,20 +11956,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { else if(botlevel >= 56) defensiveSpellID = 7005; //Ichor guard else - c->Message(0, "Error: shadowknight must be level 56+"); + c->Message(0, "Shadow Knight must be level 56 or higher."); break; default: - c->Message(0, "Error: you must select a warrior or knight"); + c->Message(0, "You must select a Warrior, Paladin, or Shadow Knight."); break; } - if(defensiveSpellID > 0) { + if(defensiveSpellID > 0) tempBot->UseDiscipline(defensiveSpellID, tempBot->GetID()); - } - } - else { + } else c->Message(13, "You must name a valid bot."); - } + return; } @@ -14292,16 +11985,13 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "#bot healrotation start "); c->Message(0, "#bot healrotation stop "); c->Message(0, "#bot healrotation list "); - return; } if(!strcasecmp(sep->arg[2], "create")) { - if(sep->argnum == 5 || sep->argnum == 6) { //allows for target or not + if(sep->argnum == 5 || sep->argnum == 6) { Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14313,14 +12003,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* target = nullptr; uint32 timer; bool fastHeals = false; - if (!sep->IsNumber(4)) { c->Message(0, "Usage #bot healrotation create [target]."); return; } timer = (uint32)(atof(sep->arg[4]) * 1000); - if (leaderBot->GetBotOwner() != c) { c->Message(13, "You must target a bot that you own."); return; @@ -14331,7 +12019,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //get percentage heals if(!strcasecmp(sep->arg[5], "fasthealson")) fastHeals = true; else if(strcasecmp(sep->arg[5], "fasthealsoff")) { @@ -14340,10 +12027,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(!leaderBot->GetInHealRotation()) { - //check for target if(sep->argnum == 6) { std::string targetName = std::string(sep->arg[6]); - if(!targetName.empty()) target = entity_list.GetMob(targetName.c_str()); else { @@ -14356,23 +12041,18 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } } - - //create rotation leaderBot->CreateHealRotation(target, timer); leaderBot->SetHealRotationUseFastHeals(fastHeals); c->Message(0, "Bot heal rotation created successfully."); - } - else { + } else { c->Message(13, "That bot is already in a heal rotation."); return; } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "Usage #bot healrotation create [target]."); return; } @@ -14382,7 +12062,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 4) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14393,7 +12072,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(leaderBot) { Bot* healer; std::string healerName = std::string(sep->arg[4]); - if (leaderBot->GetBotOwner() != c) { c->Message(13, "You must target a bot that you own."); return; @@ -14417,21 +12095,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //add to rotation - if(leaderBot->AddHealRotationMember(healer)) { + if(leaderBot->AddHealRotationMember(healer)) c->Message(0, "Bot heal rotation member added successfully."); - } - else { - c->Message(13, "Unable to add bot to rotation. "); - } + else + c->Message(13, "Unable to add bot to rotation."); } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation addmember "); return; } @@ -14457,7 +12130,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Bot* healer; std::string healerName = std::string(sep->arg[4]); - if(!healerName.empty()) healer = entity_list.GetBotByBotName(healerName); else { @@ -14471,25 +12143,19 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //remove from rotation - if(leaderBot->RemoveHealRotationMember(healer)) { + if(leaderBot->RemoveHealRotationMember(healer)) c->Message(0, "Bot heal rotation member removed successfully."); - } - else { - c->Message(13, "Unable to remove bot from rotation. "); - } - } - else { + else + c->Message(13, "Unable to remove bot from rotation."); + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation removemember "); return; } @@ -14499,7 +12165,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3 || sep->argnum == 4) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14515,35 +12180,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* target = nullptr; std::string targetName = std::string(sep->arg[4]); - if(!targetName.empty()) target = entity_list.GetMob(targetName.c_str()); else { - if(c->GetTarget() != nullptr) { + if(c->GetTarget() != nullptr) target = c->GetTarget(); - } } if(target) { - //add target - if(leaderBot->AddHealRotationTarget(target)) { + if(leaderBot->AddHealRotationTarget(target)) c->Message(0, "Bot heal rotation target added successfully."); - } - else { - c->Message(13, "Unable to add rotation target. "); - } - } - else { + else + c->Message(13, "Unable to add rotation target."); + } else { c->Message(13, "Invalid target."); return; } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation addtarget [bot healrotation target name to add] "); return; } @@ -14553,7 +12210,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 4) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14569,7 +12225,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { Mob* target; std::string targetName = std::string(sep->arg[4]); - if(!targetName.empty()) target = entity_list.GetMob(targetName.c_str()); else { @@ -14578,21 +12233,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } if(target) { - //add to rotation - if(leaderBot->RemoveHealRotationTarget(target)) { + if(leaderBot->RemoveHealRotationTarget(target)) c->Message(0, "Bot heal rotation target removed successfully."); - } - else { - c->Message(13, "Unable to remove rotation target. "); - } + else + c->Message(13, "Unable to remove rotation target."); } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation removetarget "); return; } @@ -14602,36 +12252,27 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3) { if(!strcasecmp(sep->arg[3], "all")) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { Bot* leaderBot = *botListItr; if(leaderBot->GetInHealRotation() && leaderBot->GetHealRotationLeader() == leaderBot) { - //start all heal rotations std::list rotationMemberList; int index = 0; - rotationMemberList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator rotationMemberItr = rotationMemberList.begin(); rotationMemberItr != rotationMemberList.end(); ++rotationMemberItr) { Bot* tempBot = *rotationMemberItr; - if(tempBot) { tempBot->SetHealRotationActive(true); tempBot->SetHealRotationNextHealTime(Timer::GetCurrentTime() + index * leaderBot->GetHealRotationTimer() * 1000); tempBot->SetHasHealedThisCycle(false); } - index++; } - c->Message(0, "Bot heal rotation started successfully."); } } - } - else { + } else { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14648,28 +12289,22 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot) { tempBot->SetHealRotationActive(true); tempBot->SetHealRotationNextHealTime(Timer::GetCurrentTime() + index * leaderBot->GetHealRotationTimer() * 1000); tempBot->SetHasHealedThisCycle(false); } - index++; } - c->Message(0, "Bot heal rotation started successfully."); - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } } - } - else { + } else { c->Message(0, "#bot healrotation start "); return; } @@ -14679,32 +12314,24 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3) { if(!strcasecmp(sep->arg[3], "all")) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { Bot* leaderBot = *botListItr; if(leaderBot->GetInHealRotation() && leaderBot->GetHealRotationLeader() == leaderBot) { - //start all heal rotations std::list rotationMemberList; - rotationMemberList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator rotationMemberItr = rotationMemberList.begin(); rotationMemberItr != rotationMemberList.end(); ++rotationMemberItr) { Bot* tempBot = *rotationMemberItr; - if(tempBot) { tempBot->SetHealRotationActive(false); tempBot->SetHasHealedThisCycle(false); } } - c->Message(0, "Bot heal rotation started successfully."); } } - } - else { + } else { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14720,10 +12347,8 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) { tempBot->SetHealRotationActive(false); tempBot->SetHasHealedThisCycle(false); @@ -14731,14 +12356,12 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } c->Message(0, "Bot heal rotation stopped successfully."); - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } } - } - else { + } else { c->Message(0, "#bot healrotation stop "); return; } @@ -14749,21 +12372,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { bool showAll = false; Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!strcasecmp(sep->arg[3], "all")) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot->GetInHealRotation() && tempBot->GetHealRotationLeader() == tempBot) { - //list leaders and number of bots per rotation + if(tempBot->GetInHealRotation() && tempBot->GetHealRotationLeader() == tempBot) c->Message(0, "Bot Heal Rotation- Leader: %s, Number of Members: %i, Timer: %1.1f", tempBot->GetCleanName(), tempBot->GetNumHealRotationMembers(), (float)(tempBot->GetHealRotationTimer()/1000)); - } } - } - else { + } else { std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14779,43 +12396,31 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } botList = GetBotsInHealRotation(leaderBot); - - //list leader and number of members c->Message(0, "Bot Heal Rotation- Leader: %s", leaderBot->GetCleanName()); c->Message(0, "Bot Heal Rotation- Timer: %1.1f", ((float)leaderBot->GetHealRotationTimer()/1000.0f)); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) { - //list rotation members + if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) c->Message(0, "Bot Heal Rotation- Member: %s", tempBot->GetCleanName()); - } } - for(int i=0; iGetHealRotationTarget(i)) { Mob* tempTarget = leaderBot->GetHealRotationTarget(i); - if(tempTarget) { std::string targetInfo = ""; - targetInfo += tempTarget->GetHPRatio() < 0 ? "(dead) " : ""; targetInfo += tempTarget->GetZoneID() != leaderBot->GetZoneID() ? "(not in zone) " : ""; - - //list targets c->Message(0, "Bot Heal Rotation- Target: %s %s", tempTarget->GetCleanName(), targetInfo.c_str()); } } } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } } - } - else { + } else { c->Message(0, "#bot healrotation list "); return; } @@ -14825,7 +12430,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14841,20 +12445,16 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) tempBot->ClearHealRotationTargets(); } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation cleartargets "); return; } @@ -14864,7 +12464,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(sep->argnum == 3) { Bot* leaderBot; std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) leaderBot = entity_list.GetBotByBotName(botName); else { @@ -14880,7 +12479,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; } - //get percentage heals & target if(!strcasecmp(sep->arg[4], "on")) fastHeals = true; else if(strcasecmp(sep->arg[4], "off")) { @@ -14889,36 +12487,22 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) tempBot->SetHealRotationUseFastHeals(fastHeals); } - } - else { + } else { c->Message(13, "You must name a valid bot."); return; } - } - else { + } else { c->Message(0, "#bot healrotation fastheals "); return; } } - - if(!strcasecmp(sep->arg[2], "load")) { - } - - if(!strcasecmp(sep->arg[2], "save")) { - } - - if(!strcasecmp(sep->arg[2], "delete")) { - } } - // #bot setinspectmessage if(!strcasecmp(sep->arg[1], "setinspectmessage")) { if(!strcasecmp(sep->arg[2], "help")) { c->Message(0, "[Titanium clients:]"); @@ -14932,20 +12516,15 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { c->Message(0, "- Close the self-inspect window to update the server"); c->Message(0, "- Target a bot that you own and wish to update"); c->Message(0, "- type #bot setinspectmessage to set the bot's message"); - } - else { + } else { Mob *target = c->GetTarget(); - if(target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { const InspectMessage_Struct& playermessage = c->GetInspectMessage(); InspectMessage_Struct& botmessage = target->CastToBot()->GetInspectMessage(); - memcpy(&botmessage, &playermessage, sizeof(InspectMessage_Struct)); database.SetBotInspectMessage(target->CastToBot()->GetBotID(), &botmessage); - c->Message(0, "Bot %s's inspect message now reflects your inspect message.", target->GetName()); - } - else { + } else { c->Message(0, "Your target must be a bot that you own."); } } @@ -14953,7 +12532,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if(!strcasecmp(sep->arg[1], "bardoutofcombat")) { bool useOutOfCombatSongs = false; - if(sep->arg[2] && sep->arg[3]){ if(!strcasecmp(sep->arg[2], "on")) useOutOfCombatSongs = true; @@ -14965,45 +12543,53 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { } Mob *target = c->GetTarget(); - if(target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { Bot* bardBot = target->CastToBot(); - if(bardBot) { bardBot->SetBardUseOutOfCombatSongs(useOutOfCombatSongs); c->Message(0, "Bard use of out of combat songs updated."); } - } - else { + } else c->Message(0, "Your target must be a bot that you own."); - } - } - else { + } else c->Message(0, "Usage #bot bardoutofcombat [on|off]"); - } + return; + } + + if(!strcasecmp(sep->arg[1], "showhelm")) { + bool showhelm = true; + if (sep->arg[2]) { + if (!strcasecmp(sep->arg[2], "on")) + showhelm = true; + else if (!strcasecmp(sep->arg[2], "off")) + showhelm = false; + else { + c->Message(0, "Usage #bot showhelm [on|off]"); + return; + } + + Mob *target = c->GetTarget(); + if (target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { + Bot* b = target->CastToBot(); + if (b) { + b->SetShowHelm(showhelm); + c->Message(0, "Your bot will %s show their helmet.", (showhelm ? "now" : "no longer")); + } + } + } else + c->Message(0, "Usage #bot showhelm [on|off]"); + return; } } -// franck: EQoffline -// This function has been reworked for the caster bots, when engaged. -// Healers bots must heal thoses who loose HP. bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { - if((iSpellTypes&SpellTypes_Detrimental) != 0) { - //according to live, you can buff and heal through walls... - //now with PCs, this only applies if you can TARGET the target, but - // according to Rogean, Live NPCs will just cast through walls/floors, no problem.. - // - // This check was put in to address an idle-mob CPU issue Log.Out(Logs::General, Logs::Error, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); - return(false); + return false; } - if(!caster) - return false; - - if(!caster->AI_HasSpells()) + if(!caster || !caster->AI_HasSpells()) return false; if (iChance < 100) { @@ -15015,30 +12601,22 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl uint8 botCasterClass = caster->GetClass(); if( iSpellTypes == SpellType_Heal ) { - // Changed so heal based on health percentage is different for hybrids if( botCasterClass == CLERIC || botCasterClass == DRUID || botCasterClass == SHAMAN) { - //If AI_EngagedCastCheck() said to the healer that he had to heal - - // check in group if(caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(g->members[i] && !g->members[i]->qglobal) { if(g->members[i]->IsClient() && g->members[i]->GetHPRatio() < 90) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < 95) { + } else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < 95) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < 80) { + } else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < 80) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetHPRatio() < 70) { + } else if(g->members[i]->GetHPRatio() < 70) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; } @@ -15054,26 +12632,13 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } - - // TODO: raid heals } - // Changed so heal based on health percentage is different for hybrids if( botCasterClass == PALADIN || botCasterClass == BEASTLORD || botCasterClass == RANGER) { - //If AI_EngagedCastCheck() said to the healer that he had to heal - - // check in group if(caster->HasGroup()) { Group *g = caster->GetGroup(); - float hpRatioToHeal = 25.0f; - - switch(caster->GetBotStance()) - { - case BotStanceAggressive: - case BotStanceEfficient: - hpRatioToHeal = 25.0f; - break; + switch(caster->GetBotStance()) { case BotStanceReactive: case BotStanceBalanced: hpRatioToHeal = 50.0f; @@ -15082,6 +12647,8 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl case BotStanceBurnAE: hpRatioToHeal = 20.0f; break; + case BotStanceAggressive: + case BotStanceEfficient: default: hpRatioToHeal = 25.0f; break; @@ -15093,16 +12660,13 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl if(g->members[i]->IsClient() && g->members[i]->GetHPRatio() < hpRatioToHeal) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < hpRatioToHeal) { + } else if((g->members[i]->GetClass() == WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) && g->members[i]->GetHPRatio() < hpRatioToHeal) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < hpRatioToHeal) { + } else if(g->members[i]->GetClass() == ENCHANTER && g->members[i]->GetHPRatio() < hpRatioToHeal) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; - } - else if(g->members[i]->GetHPRatio() < hpRatioToHeal/2) { + } else if(g->members[i]->GetHPRatio() < hpRatioToHeal/2) { if(caster->AICastSpell(g->members[i], 100, SpellType_Heal)) return true; } @@ -15118,15 +12682,11 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } - - // TODO: raid heals } } - //Ok for the buffs.. if( iSpellTypes == SpellType_Buff) { - uint8 chanceToCast = caster->IsEngaged()?caster->GetChanceToCastBySpellType(SpellType_Buff):100; - // Let's try to make Bard working... + uint8 chanceToCast = caster->IsEngaged() ? caster->GetChanceToCastBySpellType(SpellType_Buff) : 100; if(botCasterClass == BARD) { if(caster->AICastSpell(caster, chanceToCast, SpellType_Buff)) return true; @@ -15136,29 +12696,22 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl if(caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { - for( int i = 0; i < MAX_GROUP_MEMBERS; i++) { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(g->members[i]) { - if(caster->AICastSpell(g->members[i], chanceToCast, SpellType_Buff)) - return true; - - if(caster->AICastSpell(g->members[i]->GetPet(), chanceToCast, SpellType_Buff)) + if(caster->AICastSpell(g->members[i], chanceToCast, SpellType_Buff) || caster->AICastSpell(g->members[i]->GetPet(), chanceToCast, SpellType_Buff)) return true; } } } } - - // TODO: raid buffs } if( iSpellTypes == SpellType_Cure) { if(caster->HasGroup()) { Group *g = caster->GetGroup(); - if(g) { - for( int i = 0; i < MAX_GROUP_MEMBERS; i++) { + for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { if(g->members[i] && caster->GetNeedsCured(g->members[i])) { if(caster->AICastSpell(g->members[i], caster->GetChanceToCastBySpellType(SpellType_Cure), SpellType_Cure)) return true; @@ -15173,157 +12726,128 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } - - // TODO: raid buffs } - return false; } Mob* EntityList::GetMobByBotID(uint32 botID) { Mob* Result = 0; - if(botID > 0) { auto it = mob_list.begin(); - - for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { - if(!it->second) continue; + for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { + if(!it->second) + continue; + if(it->second->IsBot() && it->second->CastToBot()->GetBotID() == botID) { Result = it->second; break; } } } - return Result; } Bot* EntityList::GetBotByBotID(uint32 botID) { Bot* Result = 0; - if(botID > 0) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotID() == botID) { Result = tempBot; break; } } } - return Result; } Bot* EntityList::GetBotByBotName(std::string botName) { Bot* Result = 0; - if(!botName.empty()) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && std::string(tempBot->GetName()) == botName) { Result = tempBot; break; } } } - return Result; } void EntityList::AddBot(Bot *newBot, bool SendSpawnPacket, bool dontqueue) { if(newBot) { newBot->SetID(GetFreeID()); - if(SendSpawnPacket) { if(dontqueue) { - // Send immediately EQApplicationPacket* outapp = new EQApplicationPacket(); newBot->CreateSpawnPacket(outapp); outapp->priority = 6; QueueClients(newBot, outapp, true); safe_delete(outapp); - } - else { - // Queue the packet + } else { NewSpawn_Struct* ns = new NewSpawn_Struct; memset(ns, 0, sizeof(NewSpawn_Struct)); newBot->FillSpawnStruct(ns, newBot); AddToSpawnQueue(newBot->GetID(), &ns); safe_delete(ns); } - parse->EventNPC(EVENT_SPAWN, newBot, nullptr, "", 0); } - bot_list.push_back(newBot); - mob_list.insert(std::pair(newBot->GetID(), newBot)); } } std::list EntityList::GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID) { std::list Result; - if(botOwnerCharacterID > 0) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == botOwnerCharacterID) Result.push_back(tempBot); } } - return Result; } -void EntityList::BotPickLock(Bot* rogue) -{ +void EntityList::BotPickLock(Bot* rogue) { for (auto it = door_list.begin(); it != door_list.end(); ++it) { Doors *cdoor = it->second; if(!cdoor || cdoor->IsDoorOpen()) continue; - auto diff = rogue->GetPosition() - cdoor->GetPosition(); - - float curdist = diff.x * diff.x + diff.y * diff.y; - - if((diff.z * diff.z >= 10) || (curdist > 130)) + auto diff = (rogue->GetPosition() - cdoor->GetPosition()); + float curdist = ((diff.x * diff.x) + (diff.y * diff.y)); + if(((diff.z * diff.z) >= 10) || curdist > 130) continue; - // All rogue items with lock pick bonuses are hands or primary const ItemInst* item1 = rogue->GetBotItem(MainHands); const ItemInst* item2 = rogue->GetBotItem(MainPrimary); - float bonus1 = 0.0f; float bonus2 = 0.0f; float skill = rogue->GetSkill(SkillPickLock); - - if(item1) // Hand slot item + if(item1) if(item1->GetItem()->SkillModType == SkillPickLock) - bonus1 = skill * (((float)item1->GetItem()->SkillModValue) / 100.0f); + bonus1 = (skill * (((float)item1->GetItem()->SkillModValue) / 100.0f)); - if(item2) // Primary slot item + if(item2) if(item2->GetItem()->SkillModType == SkillPickLock) - bonus2 = skill * (((float)item2->GetItem()->SkillModValue) / 100.0f); + bonus2 = (skill * (((float)item2->GetItem()->SkillModValue) / 100.0f)); - if((skill+bonus1+bonus2) >= cdoor->GetLockpick()) + if((skill + bonus1 + bonus2) >= cdoor->GetLockpick()) cdoor->ForceOpen(rogue); else - rogue->Say("I am not skilled enough for this lock."); + rogue->BotGroupSay(rogue, "I am not skilled enough for this lock."); } } bool EntityList::RemoveBot(uint16 entityID) { bool Result = false; - if(entityID > 0) { - for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) - { + for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetID() == entityID) { bot_list.erase(botListItr); Result = true; @@ -15331,23 +12855,17 @@ bool EntityList::RemoveBot(uint16 entityID) { } } } - return Result; } void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { - const char *WindowTitle = "Bot Tracking Window"; - std::string WindowText; int LastCon = -1; int CurrentCon = 0; Mob* curMob = nullptr; - uint32 array_counter = 0; - auto it = mob_list.begin(); - for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { curMob = it->second; if (curMob && DistanceNoZ(curMob->GetPosition(), client->GetPosition()) <= Distance) { @@ -15386,36 +12904,34 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { "stone_","lava_","_","" }; unsigned int MyArraySize; - for ( MyArraySize = 0; true; MyArraySize++) { //Find empty string & get size - if (!(*(MyArray[MyArraySize]))) break; //Checks for null char in 1st pos + for ( MyArraySize = 0; true; MyArraySize++) { + if (!(*(MyArray[MyArraySize]))) + break; }; if (NamedOnly) { bool ContinueFlag = false; - const char *CurEntityName = cur_entity->GetName(); //Call function once + const char *CurEntityName = cur_entity->GetName(); for (int Index = 0; Index < MyArraySize; Index++) { if (!strncasecmp(CurEntityName, MyArray[Index], strlen(MyArray[Index])) || (Extras)) { ContinueFlag = true; - break; //From Index for + break; }; }; - if (ContinueFlag) continue; //Moved here or would apply to Index for + if (ContinueFlag) + continue; }; CurrentCon = client->GetLevelCon(cur_entity->GetLevel()); if(CurrentCon != LastCon) { - if(LastCon != -1) WindowText += ""; LastCon = CurrentCon; - switch(CurrentCon) { - case CON_GREEN: { WindowText += ""; break; } - case CON_LIGHTBLUE: { WindowText += ""; break; @@ -15424,7 +12940,6 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { WindowText += ""; break; } - case CON_YELLOW: { WindowText += ""; break; @@ -15439,66 +12954,50 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { } } } - WindowText += cur_entity->GetCleanName(); WindowText += "
"; - if(strlen(WindowText.c_str()) > 4000) { - // Popup window is limited to 4096 characters. - WindowText += "


List truncated ... too many mobs to display"; + WindowText += "


List truncated... too many mobs to display"; break; } } } } WindowText += "
"; - client->SendPopupToClient(WindowTitle, WindowText.c_str()); - return; } uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { uint8 needHealed = 0; Group *g; - if(this->HasGroup()) { g = this->GetGroup(); - if(g) { for( int i = 0; imembers[i] && !g->members[i]->qglobal) { - if(g->members[i]->GetHPRatio() <= hpr) needHealed++; if(includePets) { - if(g->members[i]->GetPet() && g->members[i]->GetPet()->GetHPRatio() <= hpr) { + if(g->members[i]->GetPet() && g->members[i]->GetPet()->GetHPRatio() <= hpr) needHealed++; - } } } } } } - return needHealed; } -uint32 Bot::GetEquipmentColor(uint8 material_slot) const -{ - //Bot tints +uint32 Bot::GetEquipmentColor(uint8 material_slot) const { int16 slotid = 0; uint32 botid = this->GetBotID(); - - //Translate code slot # to DB slot # slotid = Inventory::CalcSlotFromMaterial(material_slot); if (slotid == INVALID_INDEX) return 0; - //read from db - std::string query = StringFormat("SELECT color FROM botinventory " - "WHERE BotID = %u AND SlotID = %u", botid, slotid); + std::string query = StringFormat("SELECT color FROM botinventory WHERE BotID = %u AND SlotID = %u", botid, slotid); auto results = database.QueryDatabase(query); if (!results.Success() || results.RowCount() != 1) return 0; @@ -15507,21 +13006,16 @@ uint32 Bot::GetEquipmentColor(uint8 material_slot) const return atoul(row[0]); } -int Bot::GetRawACNoShield(int &shield_ac) -{ +int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; ItemInst* inst = GetBotItem(MainSecondary); - if(inst) - { - if(inst->GetItem()->ItemType == ItemTypeShield) - { + if(inst) { + if(inst->GetItem()->ItemType == ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) - { - if(inst->GetAugment(i)) - { + for (uint8 i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + if(inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; } @@ -15532,38 +13026,32 @@ int Bot::GetRawACNoShield(int &shield_ac) } uint32 Bot::CalcCurrentWeight() { - const Item_Struct* TempItem = 0; ItemInst* inst; uint32 Total = 0; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { - TempItem = inst->GetItem(); - if (TempItem) - Total += TempItem->Weight; + TempItem = inst->GetItem(); + if (TempItem) + Total += TempItem->Weight; } } - float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat; - + float Packrat = ((float)spellbonuses.Packrat + (float)aabonuses.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 - + Total = (uint32)((float)Total * (1.0f - ((Packrat * 1.0f) / 100.0f))); + return Total; } -int Bot::GroupLeadershipAAHealthEnhancement() -{ +int Bot::GroupLeadershipAAHealthEnhancement() { Group *g = GetGroup(); if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAHealthEnhancement)) - { + switch(g->GetLeadershipAA(groupAAHealthEnhancement)) { case 0: return 0; case 1: @@ -15573,19 +13061,15 @@ int Bot::GroupLeadershipAAHealthEnhancement() case 3: return 100; } - return 0; } -int Bot::GroupLeadershipAAManaEnhancement() -{ +int Bot::GroupLeadershipAAManaEnhancement() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAManaEnhancement)) - { + switch(g->GetLeadershipAA(groupAAManaEnhancement)) { case 0: return 0; case 1: @@ -15595,19 +13079,15 @@ int Bot::GroupLeadershipAAManaEnhancement() case 3: return 100; } - return 0; } -int Bot::GroupLeadershipAAHealthRegeneration() -{ +int Bot::GroupLeadershipAAHealthRegeneration() { Group *g = GetGroup(); - if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAHealthRegeneration)) - { + switch(g->GetLeadershipAA(groupAAHealthRegeneration)) { case 0: return 0; case 1: @@ -15621,15 +13101,13 @@ int Bot::GroupLeadershipAAHealthRegeneration() return 0; } -int Bot::GroupLeadershipAAOffenseEnhancement() -{ +int Bot::GroupLeadershipAAOffenseEnhancement() { Group *g = GetGroup(); if(!g || (g->GroupCount() < 3)) return 0; - switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) - { + switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) { case 0: return 0; case 1: @@ -15648,23 +13126,16 @@ int Bot::GroupLeadershipAAOffenseEnhancement() bool Bot::GetNeedsCured(Mob *tar) { bool needCured = false; - if(tar) { if(tar->FindType(SE_PoisonCounter) || tar->FindType(SE_DiseaseCounter) || tar->FindType(SE_CurseCounter) || tar->FindType(SE_CorruptionCounter)) { uint32 buff_count = GetMaxTotalSlots(); int buffsWithCounters = 0; needCured = true; - for (unsigned int j = 0; j < buff_count; j++) { if(tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { if(CalculateCounters(tar->GetBuffs()[j].spellid) > 0) { buffsWithCounters++; - if(buffsWithCounters == 1 && (tar->GetBuffs()[j].ticsremaining < 2 || (int32)((tar->GetBuffs()[j].ticsremaining * 6) / tar->GetBuffs()[j].counters) < 2)) { - // Spell has ticks remaining but may have too many counters to cure in the time remaining; - // We should try to just wait it out. Could spend entire time trying to cure spell instead of healing, buffing, etc. - // Since this is the first buff with counters, don't try to cure. Cure spell will be wasted, as cure will try to - // remove counters from the first buff that has counters remaining. needCured = false; break; } @@ -15673,27 +13144,23 @@ bool Bot::GetNeedsCured(Mob *tar) { } } } - return needCured; } bool Bot::HasOrMayGetAggro() { bool mayGetAggro = false; - if(GetTarget() && GetTarget()->GetHateTop()) { Mob *topHate = GetTarget()->GetHateTop(); - if(topHate == this) - mayGetAggro = true; //I currently have aggro + mayGetAggro = true; else { uint32 myHateAmt = GetTarget()->GetHateAmount(this); uint32 topHateAmt = GetTarget()->GetHateAmount(topHate); - if(myHateAmt > 0 && topHateAmt > 0 && (uint8)((myHateAmt/topHateAmt)*100) > 90) //I have 90% as much hate as top, next action may give me aggro + if(myHateAmt > 0 && topHateAmt > 0 && (uint8)((myHateAmt / topHateAmt) * 100) > 90) mayGetAggro = true; } } - return mayGetAggro; } @@ -15701,115 +13168,56 @@ void Bot::SetHasBeenSummoned(bool wasSummoned) { _hasBeenSummoned = wasSummoned; if(!wasSummoned) m_PreSummonLocation = glm::vec3(); - } void Bot::SetDefaultBotStance() { - BotStanceType defaultStance; - - switch(GetClass()) - { - case DRUID: - case CLERIC: - case SHAMAN: - case ENCHANTER: - case NECROMANCER: - case MAGICIAN: - case WIZARD: - case BEASTLORD: - case BERSERKER: - case MONK: - case ROGUE: - case BARD: - case SHADOWKNIGHT: - case PALADIN: - case RANGER: - defaultStance = BotStanceBalanced; - break; - case WARRIOR: - defaultStance = BotStanceAggressive; - break; - default: - defaultStance = BotStanceBalanced; - break; - } + BotStanceType defaultStance = BotStanceBalanced; + if (GetClass() == WARRIOR) + defaultStance = BotStanceAggressive; + _baseBotStance = BotStancePassive; _botStance = defaultStance; } -void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) -{ - +void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) { char buf[1000]; va_list ap; - va_start(ap, msg); vsnprintf(buf, 1000, msg, ap); va_end(ap); - if(speaker->HasGroup()) { Group *g = speaker->GetGroup(); - if(g) g->GroupMessage(speaker->CastToMob(), 0, 100, buf); - } + } else + speaker->Say("%s", buf); } bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { - //make sure we have the spell... - int r; - /*for(r = 0; r < MAX_PP_DISCIPLINES; r++) { - if(m_pp.disciplines.values[r] == spell_id) - break; - } - if(r == MAX_PP_DISCIPLINES) - return(false); //not found. - - //Check the disc timer - pTimerType DiscTimer = pTimerDisciplineReuseStart + spells[spell_id].EndurTimerIndex; - if(!p_timers.Expired(&database, DiscTimer)) { - uint32 remain = p_timers.GetRemainingTime(DiscTimer); - //Message_StringID(0, DISCIPLINE_CANUSEIN, ConvertArray((remain)/60,val1), ConvertArray(remain%60,val2)); - Message(0, "You can use this discipline in %d minutes %d seconds.", ((remain)/60), (remain%60)); - return(false); - }*/ - - //make sure we can use it.. if(!IsValidSpell(spell_id)) { - Say("Not a valid spell"); - return(false); + BotGroupSay(this, "Not a valid spell."); + return false; } - //can we use the spell? const SPDat_Spell_Struct &spell = spells[spell_id]; uint8 level_to_use = spell.classes[GetClass() - 1]; - if(level_to_use == 255) { - return(false); + if(level_to_use == 255 || level_to_use > GetLevel()) { + return false; } - if(level_to_use > GetLevel()) { - return(false); - } - - if(GetEndurance() > spell.EndurCost) { + if(GetEndurance() > spell.EndurCost) SetEndurance(GetEndurance() - spell.EndurCost); - } else { - return(false); - } + else + return false; - if(spell.recast_time > 0) - { + if(spell.recast_time > 0) { if(CheckDisciplineRecastTimers(this, spells[spell_id].EndurTimerIndex)) { - - //CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); - if(spells[spell_id].EndurTimerIndex > 0 && spells[spell_id].EndurTimerIndex < MAX_DISCIPLINE_TIMERS) { + if(spells[spell_id].EndurTimerIndex > 0 && spells[spell_id].EndurTimerIndex < MAX_DISCIPLINE_TIMERS) SetDisciplineRecastTimer(spells[spell_id].EndurTimerIndex, spell.recast_time); - } - } - else { - uint32 remain = GetDisciplineRemainingTime(this, spells[spell_id].EndurTimerIndex) / 1000; - GetOwner()->Message(0, "%s can use this discipline in %d minutes %d seconds.", GetCleanName(), ((remain)/60), (remain%60)); - return(false); + } else { + uint32 remain = (GetDisciplineRemainingTime(this, spells[spell_id].EndurTimerIndex) / 1000); + GetOwner()->Message(0, "%s can use this discipline in %d minutes %d seconds.", GetCleanName(), (remain / 60), (remain % 60)); + return false; } } @@ -15817,8 +13225,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { InterruptSpell(); CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); - - return(true); + return true; } void Bot::CreateHealRotation( Mob* target, uint32 timer ) { @@ -15830,7 +13237,6 @@ void Bot::CreateHealRotation( Mob* target, uint32 timer ) { SetPrevHealRotationMember(this); SetHealRotationTimer(timer); SetHasHealedThisCycle(false); - if(target) AddHealRotationTarget(target); } @@ -15839,13 +13245,11 @@ bool Bot::AddHealRotationMember( Bot* healer ) { if(healer) { if(GetNumHealRotationMembers() > 0 && GetNumHealRotationMembers() < MaxHealRotationMembers) { Bot* tempBot = GetPrevHealRotationMember(); - if(tempBot) { - //add new healer to rotation at end of list - for(int i=0; i<3; i++){ + for(int i = 0; i < 3; i++){ healer->ClearHealRotationMembers(); healer->ClearHealRotationTargets(); - healer->AddHealRotationTarget(entity_list.GetMob(_healRotationTargets[i])); // add all targets.. + healer->AddHealRotationTarget(entity_list.GetMob(_healRotationTargets[i])); } healer->SetHealRotationTimer(tempBot->GetHealRotationTimer()); healer->SetHealRotationLeader(this); @@ -15854,27 +13258,18 @@ bool Bot::AddHealRotationMember( Bot* healer ) { healer->SetInHealRotation(true); healer->SetHasHealedThisCycle(false); healer->SetHealRotationUseFastHeals(tempBot->GetHealRotationUseFastHeals()); - - //set previous rotation member's next member to new member tempBot->SetNextHealRotationMember(healer); - - //update leader's previous member (end of list) to new member and update rotation data SetPrevHealRotationMember(healer); - std::list botList = GetBotsInHealRotation(this); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot) tempBot->SetNumHealRotationMembers(GetNumHealRotationMembers()+1); } - return true; } } } - return false; } @@ -15883,15 +13278,11 @@ bool Bot::RemoveHealRotationMember( Bot* healer ) { Bot* leader = healer->GetHealRotationLeader(); Bot* prevBot = healer->GetPrevHealRotationMember(); Bot* nextBot = healer->GetNextHealRotationMember(); - if(healer == this) { - if(nextBot != this) { - //get new leader + if(nextBot != this) leader = nextBot; - } } - //remove healer from list healer->SetHealRotationTimer(0); healer->ClearHealRotationMembers(); healer->ClearHealRotationTargets(); @@ -15899,34 +13290,22 @@ bool Bot::RemoveHealRotationMember( Bot* healer ) { healer->SetHasHealedThisCycle(false); healer->SetHealRotationActive(false); healer->SetInHealRotation(false); - if(prevBot && nextBot && GetNumHealRotationMembers() > 1) { - //set previous rotation member's next member to new member prevBot->SetNextHealRotationMember(nextBot); - - //set previous rotation member's next member to new member nextBot->SetPrevHealRotationMember(prevBot); } - //update rotation data std::list botList = GetBotsInHealRotation(leader); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot) { - tempBot->SetNumHealRotationMembers(GetNumHealRotationMembers()-1); - - if(tempBot->GetHealRotationLeader() != leader) { - // change leader if leader is being removed + tempBot->SetNumHealRotationMembers(GetNumHealRotationMembers() - 1); + if(tempBot->GetHealRotationLeader() != leader) tempBot->SetHealRotationLeader(leader); - } } } - return true; } - return false; } @@ -15945,67 +13324,56 @@ void Bot::SetPrevHealRotationMember( Bot* healer ) { Bot* Bot::GetHealRotationLeader( ) { if(_healRotationLeader) return entity_list.GetBotByBotID(_healRotationLeader); + return 0; } Bot* Bot::GetNextHealRotationMember( ) { if(_healRotationMemberNext) return entity_list.GetBotByBotID(_healRotationMemberNext); + return 0; } Bot* Bot::GetPrevHealRotationMember( ) { if(_healRotationMemberNext) return entity_list.GetBotByBotID(_healRotationMemberPrev); + return 0; } bool Bot::AddHealRotationTarget( Mob* target ) { if(target) { - for (int i = 0; i < MaxHealRotationTargets; ++i) { if(_healRotationTargets[i] > 0) { Mob* tempTarget = entity_list.GetMob(_healRotationTargets[i]); - if(!tempTarget) { _healRotationTargets[i] = 0; - } - else if(!strcasecmp(tempTarget->GetCleanName(), target->GetCleanName())) { - //check to see if target's ID is incorrect (could have zoned, died, etc) - if(tempTarget->GetID() != target->GetID()) { + } else if(!strcasecmp(tempTarget->GetCleanName(), target->GetCleanName())) { + if(tempTarget->GetID() != target->GetID()) _healRotationTargets[i] = target->GetID(); - } - //target already in list + return false; } } - if (_healRotationTargets[i] == 0) - { + if (_healRotationTargets[i] == 0) { std::list botList = GetBotsInHealRotation(this); - _healRotationTargets[i] = target->GetID(); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - - if(tempBot && tempBot != this) { - //add target to all members + if(tempBot && tempBot != this) tempBot->AddHealRotationTarget(target, i); - } } - return true; } } } - return false; } bool Bot::AddHealRotationTarget( Mob *target, int index ) { if (target && index < MaxHealRotationTargets) { - //add target to list of targets at specified index _healRotationTargets[index] = target->GetID(); return true; } @@ -16016,37 +13384,30 @@ bool Bot::RemoveHealRotationTarget( Mob* target ) { int index = 0; bool removed = false; if(target) { - //notify all heal rotation members to remove target - for(int i=0; iGetID()) { std::list botList = GetBotsInHealRotation(this); _healRotationTargets[i] = 0; index = i; removed = true; - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { Bot* tempBot = *botListItr; - if(tempBot) tempBot->RemoveHealRotationTarget(i); } } } } - return removed; } bool Bot::RemoveHealRotationTarget( int index ) { if(index >= 0) { - //clear rotation target at index _healRotationTargets[index] = 0; - if(index < MaxHealRotationTargets) { - for(int i=index; i 0) { - - //get first target in list target = entity_list.GetMob(_healRotationTargets[i]); - if(target) { - //check if valid target - if(target->GetZoneID() == GetZoneID() - && !(target->GetAppearance() == eaDead - && !(target->IsClient() && target->CastToClient()->GetFeigned()))) { - + if(target->GetZoneID() == GetZoneID() && !(target->GetAppearance() == eaDead && !(target->IsClient() && target->CastToClient()->GetFeigned()))) { count++; - - //get first valid target - if(!first) { + if(!first) first = target; - } - //check to see if target is group main tank - //(target first, in case top target has died and was rez'd - - //we don't want to heal them then) if(!tank) { Group* g = target->GetGroup(); - if(g && !strcasecmp(g->GetMainTankName(), target->GetCleanName())) { + if(g && !strcasecmp(g->GetMainTankName(), target->GetCleanName())) tank = target; - } } } - } - else { - //if not valid target, remove from list + } else { if(removeIndex == 0) removeIndex = i; } } } - if (removeIndex > 0) { - RemoveHealRotationTarget( removeIndex ); - } + if (removeIndex > 0) + RemoveHealRotationTarget(removeIndex); if(tank) return tank; @@ -16123,35 +13465,27 @@ Mob* Bot::GetHealRotationTarget( ) { Mob* Bot::GetHealRotationTarget( uint8 index ) { Mob* target = nullptr; - - if(_healRotationTargets[index] > 0) { - //get target at specified index + if(_healRotationTargets[index] > 0) target = entity_list.GetMob(_healRotationTargets[index]); - } return target; } std::list Bot::GetBotsInHealRotation(Bot* rotationLeader) { std::list Result; - if(rotationLeader != nullptr) { Result.push_back(rotationLeader); Bot* rotationMember = rotationLeader->GetNextHealRotationMember(); - while(rotationMember && rotationMember != rotationLeader) { Result.push_back(rotationMember); rotationMember = rotationMember->GetNextHealRotationMember(); } } - return Result; } void Bot::NotifyNextHealRotationMember(bool notifyNow) { - //check if we need to notify to start now, or after timer uint32 nextHealTime = notifyNow ? Timer::GetCurrentTime() : Timer::GetCurrentTime() + GetHealRotationTimer(); - Bot* nextMember = GetNextHealRotationMember(); if(nextMember && nextMember != this) { nextMember->SetHealRotationNextHealTime(nextHealTime); @@ -16162,11 +13496,9 @@ void Bot::NotifyNextHealRotationMember(bool notifyNow) { void Bot::BotHealRotationsClear(Client* c) { if(c) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { Bot* tempBot = *botListItr; if(tempBot->GetInHealRotation()) { - //clear all heal rotation data for bots in a heal rotation tempBot->SetInHealRotation(false); tempBot->SetHealRotationActive(false); tempBot->SetHasHealedThisCycle(false); diff --git a/zone/bot.h b/zone/bot.h index 6103fa7f2..86a1ef895 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -465,6 +465,7 @@ public: uint32 GetHealRotationNextHealTime() { return _healRotationNextHeal; } uint32 GetHealRotationTimer () { return _healRotationTimer; } bool GetBardUseOutOfCombatSongs() { return _bardUseOutOfCombatSongs;} + bool GetShowHelm() { return _showhelm; } inline virtual int32 GetAC() const { return AC; } inline virtual int32 GetSTR() const { return STR; } inline virtual int32 GetSTA() const { return STA; } @@ -548,6 +549,7 @@ public: void SetHealRotationTimer( uint32 timer ) { _healRotationTimer = timer; } void SetNumHealRotationMembers( uint8 numMembers ) { _numHealRotationMembers = numMembers; } void SetBardUseOutOfCombatSongs(bool useOutOfCombatSongs) { _bardUseOutOfCombatSongs = useOutOfCombatSongs;} + void SetShowHelm(bool showhelm) { _showhelm = showhelm; } // Class Destructors virtual ~Bot(); @@ -620,6 +622,7 @@ private: std::map botAAs; InspectMessage_Struct _botInspectMessage; bool _bardUseOutOfCombatSongs; + bool _showhelm; // Private "base stats" Members int32 _baseMR; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index fb6714087..57c41be8b 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1105,7 +1105,7 @@ void Mob::AI_Process() { } #ifdef BOTS - if (IsPet() && GetOwner()->IsBot() && target == GetOwner()) + if (IsPet() && GetOwner() && GetOwner()->IsBot() && target == GetOwner()) { // this blocks all pet attacks against owner..bot pet test (copied above check) RemoveFromHateList(this); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 0021350a4..bd8000e63 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -615,11 +615,11 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if(primaryweapondamage > 0){ if(level > 25){ - max_hit = (((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level-25)/3) + 1; + max_hit = (((((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level-25)/3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; } else{ - max_hit = (((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1;; + max_hit = (((((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; }