Compare commits

...

79 Commits

Author SHA1 Message Date
Paul Coene 75391d96f4 [Release] 22.13.1 (#3406)
* Update version.h for /target Emergency release 22.13.1

* Update CHANGELOG.md for 22.13.1 release

* Update package.json for 22.13.1 emergency patch release

* Update CHANGELOG.md using tool as instructed
2023-06-13 17:50:33 -04:00
Paul Coene 81b07a5aa0 [Targeting] Revert #3383 (#3405) 2023-06-13 15:48:35 -05:00
Alex King 774aa99b29 [Release] 22.13.0 (#3404)
* [Release] 22.13.0

* Update CHANGELOG.md
2023-06-12 20:56:43 -04:00
Alex King 756e835144 [Quest API/Cleanup] Add several spell methods to Perl/Lua (#3379)
* [Quest API/Cleanup] Add several spell methods to Perl/Lua

- Add `quest::CalculateCorruptionCounters(spell_id)`.
- Add `quest::CalculateCounters(spell_id)`.
- Add `quest::CalculateCurseCounters(spell_id)`.
- Add `quest::CalculateDiseaseCounters(spell_id)`.
- Add `quest::CalculatePoisonCounters(spell_id)`.
- Add `quest::GetSpellEffectDescriptionNumber(spell_id)`.
- Add `quest::GetSpellEffectIndex(spell_id, effect_id)`.
- Add `quest::GetSpellFuriousBash(spell_id)`.
- Add `quest::GetSpellMinimumLevel(spell_id)`.
- Add `quest::GetSpellNimbusEffect(spell_id)`.
- Add `quest::GetSpellPartialMagicRuneAmount(spell_id)`.
- Add `quest::GetSpellPartialMagicRuneReduction(spell_id)`.
- Add `quest::GetSpellPartialMeleeRuneAmount(spell_id)`.
- Add `quest::GetSpellPartialMeleeRuneReduction(spell_id)`.
- Add `quest::GetSpellProcLimitTimer(spell_id)`.
- Add `quest::GetSpellResistType(spell_id)`.
- Add `quest::GetSpellResurrectionSicknessCheck(spell_id_one, spell_id_two)`.
- Add `quest::GetSpellTargetType(spell_id)`.
- Add `quest::GetSpellTriggerSpellID(spell_id)`.
- Add `quest::GetSpellViralMaximumSpreadTime(spell_id)`.
- Add `quest::GetSpellViralMinimumSpreadTime(spell_id)`.
- Add `quest::GetSpellViralSpreadRange(spell_id)`.
- Add `quest::IsAEDurationSpell(spell_id)`.
- Add `quest::IsAENukeSpell(spell_id)`.
- Add `quest::IsAERainNukeSpell(spell_id)`.
- Add `quest::IsAllianceSpell(spell_id)`.
- Add `quest::IsBardOnlyStackEffect(effect_id)`.
- Add `quest::IsBardSong(spell_id)`.
- Add `quest::IsBlankSpellEffect(spell_id, effect_index)`.
- Add `quest::IsBlindSpell(spell_id)`.
- Add `quest::IsBuffSpell(spell_id)`.
- Add `quest::IsCastNotStandingSpell(spell_id)`.
- Add `quest::IsCastOnFadeDurationSpell(spell_id)`.
- Add `quest::IsCastRestrictedSpell(spell_id)`.
- Add `quest::IsCastTimeReductionSpell(spell_id)`.
- Add `quest::IsCastWhileInvisibleSpell(spell_id)`.
- Add `quest::IsCharmSpell(spell_id)`.
- Add `quest::IsCombatSkill(spell_id)`.
- Add `quest::IsCompleteHealDurationSpell(spell_id)`.
- Add `quest::IsCompleteHealSpell(spell_id)`.
- Add `quest::IsCureSpell(spell_id)`.
- Add `quest::IsDamageSpell(spell_id)`.
- Add `quest::IsDeathSaveSpell(spell_id)`.
- Add `quest::IsDebuffSpell(spell_id)`.
- Add `quest::IsDetrimentalSpell(spell_id)`.
- Add `quest::IsDiscipline(spell_id)`.
- Add `quest::IsDisciplineBuff(spell_id)`.
- Add `quest::IsDiseaseCounterSpell(spell_id)`.
- Add `quest::IsDistanceModifierSpell(spell_id)`.
- Add `quest::IsEffectIgnoredInStacking(effect_id)`.
- Add `quest::IsFastHealSpell(spell_id)`.
- Add `quest::IsFearSpell(spell_id)`.
- Add `quest::IsFocusLimit(effect_id)`.
- Add `quest::IsFullDeathSaveSpell(spell_id)`.
- Add `quest::IsGateSpell(spell_id)`.
- Add `quest::IsImprovedDamageSpell(spell_id)`.
- Add `quest::IsImprovedHealingSpell(spell_id)`.
- Add `quest::IsIncreaseDurationSpell(spell_id)`.
- Add `quest::IsIncreaseRangeSpell(spell_id)`.
- Add `quest::IsInstrumentModifierAppliedToSpellEffect(spell_id, effect_id)`.
- Add `quest::IsInvisibleSpell(spell_id)`.
- Add `quest::IsInvulnerabilitySpell(spell_id)`.
- Add `quest::IsLDoNObjectSpell(spell_id)`.
- Add `quest::IsLifetapSpell(spell_id)`.
- Add `quest::IsMagicRuneSpell(spell_id)`.
- Add `quest::IsManaCostReductionSpell(spell_id)`.
- Add `quest::IsManaTapSpell(spell_id)`.
- Add `quest::IsMesmerizeSpell(spell_id)`.
- Add `quest::IsNoDetrimentalSpellAggroSpell(spell_id)`.
- Add `quest::IsPBAENukeSpell(spell_id)`.
- Add `quest::IsPartialDeathSaveSpell(spell_id)`.
- Add `quest::IsPartialResistableSpell(spell_id)`.
- Add `quest::IsPercentalHealSpell(spell_id)`.
- Add `quest::IsPersistDeathSpell(spell_id)`.
- Add `quest::IsPetSpell(spell_id)`.
- Add `quest::IsPoisonCounterSpell(spell_id)`.
- Add `quest::IsPulsingBardSong(spell_id)`.
- Add `quest::IsPureNukeSpell(spell_id)`.
- Add `quest::IsRegularGroupHealSpell(spell_id)`.
- Add `quest::IsRegularSingleTargetHealSpell(spell_id)`.
- Add `quest::IsResistDebuffSpell(spell_id)`.
- Add `quest::IsResistableSpell(spell_id)`.
- Add `quest::IsRestAllowedSpell(spell_id)`.
- Add `quest::IsResurrectionEffects(spell_id)`.
- Add `quest::IsRuneSpell(spell_id)`.
- Add `quest::IsRunning(spell_id)`.
- Add `quest::IsSacrificeSpell(spell_id)`.
- Add `quest::IsSelfConversionSpell(spell_id)`.
- Add `quest::IsShadowStepSpell(spell_id)`.
- Add `quest::IsShortDurationBuff(spell_id)`.
- Add `quest::IsSpellUsableInThisZoneType(spell_id)`.
- Add `quest::IsSpellUsableInThisZoneType(spell_id, zone_type)`.
- Add `quest::IsStackableDOT(spell_id)`.
- Add `quest::IsStunSpell(spell_id)`.
- Add `quest::IsSuccorSpell(spell_id)`.
- Add `quest::IsSummonItemSpell(spell_id)`.
- Add `quest::IsSummonPCSpell(spell_id)`.
- Add `quest::IsSummonPetSpell(spell_id)`.
- Add `quest::IsSummonSkeletonSpell(spell_id)`.
- Add `quest::IsSummonSpell(spell_id)`.
- Add `quest::IsSuspendableSpell(spell_id)`.
- Add `quest::IsTargetRequiredForSpell(spell_id)`.
- Add `quest::IsTargetableAESpell(spell_id)`.
- Add `quest::IsTeleportSpell(spell_id)`.
- Add `quest::IsTranslocateSpell(spell_id)`.
- Add `quest::IsValidSpell(spell_id)`.
- Add `quest::IsVeryFastHealSpell(spell_id)`.
- Add `quest::IsVirusSpell(spell_id)`.

- Add `eq.calculate_corruption_counters(spell_id)`.
- Add `eq.calculate_counters(spell_id)`.
- Add `eq.calculate_curse_counters(spell_id)`.
- Add `eq.calculate_disease_counters(spell_id)`.
- Add `eq.calculate_poison_counters(spell_id)`.
- Add `eq.get_spell_effect_description_number(spell_id)`.
- Add `eq.get_spell_effect_index(spell_id, effect_id)`.
- Add `eq.get_spell_furious_bash(spell_id)`.
- Add `eq.get_spell_level(spell_id, class_id)`.
- Add `eq.get_spell_minimum_level(spell_id)`.
- Add `eq.get_spell_nimbus_effect(spell_id)`.
- Add `eq.get_spell_partial_magic_rune_amount(spell_id)`.
- Add `eq.get_spell_partial_magic_rune_reduction(spell_id)`.
- Add `eq.get_spell_partial_melee_rune_amount(spell_id)`.
- Add `eq.get_spell_partial_melee_rune_reduction(spell_id)`.
- Add `eq.get_spell_proc_limit_timer(spell_id)`.
- Add `eq.get_spell_resist_type(spell_id)`.
- Add `eq.get_spell_resurrection_sickness_check(spell_id_one, spell_id_two)`.
- Add `eq.get_spell_target_type(spell_id)`.
- Add `eq.get_spell_trigger_spell_id(spell_id)`.
- Add `eq.get_spell_viral_maximum_spread_time(spell_id)`.
- Add `eq.get_spell_viral_minimum_spread_time(spell_id)`.
- Add `eq.get_spell_viral_spread_range(spell_id)`.
- Add `eq.is_ae_duration_spell(spell_id)`.
- Add `eq.is_ae_nuke_spell(spell_id)`.
- Add `eq.is_ae_rain_nuke_spell(spell_id)`.
- Add `eq.is_alliance_spell(spell_id)`.
- Add `eq.is_bard_only_stack_effect(spell_id)`.
- Add `eq.is_bard_song(spell_id)`.
- Add `eq.is_beneficial_spell(spell_id)`.
- Add `eq.is_blank_spell_effect(spell_id)`.
- Add `eq.is_blind_spell(spell_id)`.
- Add `eq.is_buff_spell(spell_id)`.
- Add `eq.is_cast_not_standing_spell(spell_id)`.
- Add `eq.is_cast_on_fade_duration_spell(spell_id)`.
- Add `eq.is_cast_restricted_spell(spell_id)`.
- Add `eq.is_cast_time_reduction_spell(spell_id)`.
- Add `eq.is_cast_while_invisible_spell(spell_id)`.
- Add `eq.is_charm_spell(spell_id)`.
- Add `eq.is_combat_skill(spell_id)`.
- Add `eq.is_complete_heal_duration_spell(spell_id)`.
- Add `eq.is_complete_heal_spell(spell_id)`.
- Add `eq.is_cure_spell(spell_id)`.
- Add `eq.is_damage_spell(spell_id)`.
- Add `eq.is_death_save_spell(spell_id)`.
- Add `eq.is_debuff_spell(spell_id)`.
- Add `eq.is_detrimental_spell(spell_id)`.
- Add `eq.is_discipline(spell_id)`.
- Add `eq.is_discipline_buff(spell_id)`.
- Add `eq.is_disease_counter_spell(spell_id)`.
- Add `eq.is_distance_modifier_spell(spell_id)`.
- Add `eq.is_effect_ignored_in_stacking(effect_id)`.
- Add `eq.is_effect_in_spell(spell_id, effect_id)`.
- Add `eq.is_fast_heal_spell(spell_id)`.
- Add `eq.is_fear_spell(spell_id)`.
- Add `eq.is_focus_limit(effect_id)`.
- Add `eq.is_full_death_save_spell(spell_id)`.
- Add `eq.is_gate_spell(spell_id)`.
- Add `eq.is_group_complete_heal_spell(spell_id)`.
- Add `eq.is_group_heal_over_time_spell(spell_id)`.
- Add `eq.is_group_only_spell(spell_id)`.
- Add `eq.is_group_spell(spell_id)`.
- Add `eq.is_harmony_spell(spell_id)`.
- Add `eq.is_haste_spell(spell_id)`.
- Add `eq.is_heal_over_time_spell(spell_id)`.
- Add `eq.is_health_spell(spell_id)`.
- Add `eq.is_illusion_spell(spell_id)`.
- Add `eq.is_improved_damage_spell(spell_id)`.
- Add `eq.is_improved_healing_spell(spell_id)`.
- Add `eq.is_increase_duration_spell(spell_id)`.
- Add `eq.is_increase_range_spell(spell_id)`.
- Add `eq.is_instrument_modifier_applied_to_spell_effect(spell_id, effect_id)`.
- Add `eq.is_invisible_spell(spell_id)`.
- Add `eq.is_invulnerability_spell(spell_id)`.
- Add `eq.is_ldon_object_spell(spell_id)`.
- Add `eq.is_lifetap_spell(spell_id)`.
- Add `eq.is_magic_rune_spell(spell_id)`.
- Add `eq.is_mana_cost_reduction_spell(spell_id)`.
- Add `eq.is_mana_tap_spell(spell_id)`.
- Add `eq.is_mesmerize_spell(spell_id)`.
- Add `eq.is_no_detrimental_spell_aggro_spell(spell_id)`.
- Add `eq.is_partial_death_save_spell(spell_id)`.
- Add `eq.is_partial_resistable_spell(spell_id)`.
- Add `eq.is_pbae_nuke_spell(spell_id)`.
- Add `eq.is_percental_heal_spell(spell_id)`.
- Add `eq.is_persist_death_spell(spell_id)`.
- Add `eq.is_pet_spell(spell_id)`.
- Add `eq.is_poison_counter_spell(spell_id)`.
- Add `eq.is_pulsing_bard_song(spell_id)`.
- Add `eq.is_pure_nuke_spell(spell_id)`.
- Add `eq.is_regular_group_heal_spell(spell_id)`.
- Add `eq.is_regular_single_target_heal_spell(spell_id)`.
- Add `eq.is_resist_debuff_spell(spell_id)`.
- Add `eq.is_resistable_spell(spell_id)`.
- Add `eq.is_rest_allowed_spell(spell_id)`.
- Add `eq.is_resurrection_effects(spell_id)`.
- Add `eq.is_rune_spell(spell_id)`.
- Add `eq.is_sacrifice_spell(spell_id)`.
- Add `eq.is_self_conversion_spell(spell_id)`.
- Add `eq.is_shadow_step_spell(spell_id)`.
- Add `eq.is_short_duration_buff(spell_id)`.
- Add `eq.is_spell_usable_in_this_zone_type(spell_id)`.
- Add `eq.is_spell_usable_in_this_zone_type(spell_id, zone_type)`.
- Add `eq.is_stackable_dot(spell_id)`.
- Add `eq.is_stun_spell(spell_id)`.
- Add `eq.is_succor_spell(spell_id)`.
- Add `eq.is_summon_item_spell(spell_id)`.
- Add `eq.is_summon_pc_spell(spell_id)`.
- Add `eq.is_summon_pet_spell(spell_id)`.
- Add `eq.is_summon_skeleton_spell(spell_id)`.
- Add `eq.is_summon_spell(spell_id)`.
- Add `eq.is_suspendable_spell(spell_id)`.
- Add `eq.is_target_required_for_spell(spell_id)`.
- Add `eq.is_targetable_ae_spell(spell_id)`.
- Add `eq.is_teleport_spell(spell_id)`.
- Add `eq.is_tgb_compatible_spell(spell_id)`.
- Add `eq.is_translocate_spell(spell_id)`.
- Add `eq.is_valid_spell(spell_id)`.
- Add `eq.is_very_fast_heal_spell(spell_id)`.
- Add `eq.is_virus_spell(spell_id)`.

- A lot of cleanup in the logic and naming of these methods was done.
- Missing GM restricted spells like Guide spells and GM Health buffs were added as defines.
- Good effect values were added as defines.
- Resurrection effects non-stacking value was added as a define.
- Max fast heal casting time and max very fast heal casting time were added as defines.
- `SE_Display` was uncommented so we could use it instead of the magic number `425`.
- `IsEvacSpell(spell_id)` was removed as it was unnecessary since `IsSuccorSpell(spell_id)` checks for `SE_Succor` as well.
- `GetMorphTrigger(spell_id)` was removed as it was unused.
- `GroupOnlySpell(spell_id)` was removed as it was unnecessary since `IsGroupOnlySpell(spell_id)` exists.
- `CanUseSpell(spell_id)` was removed as it was unnecessary since `GetSpellLevel(spell_id, class_id)` exists.
- `BeneficialSpell(spell_id)` was removed as it was unnecessary since `IsBeneficialSpell(spell_id)` exists.

* Update spell_effects.cpp

* Update spdat.cpp
2023-06-12 20:27:22 -04:00
Alex King c5c575b028 [Quest API] Add GetEXPForLevel() to Perl/Lua (#3403)
# Perl
- Add `$client->GetEXPForLevel(check_level)`.

# Lua
- Add `client:GetEXPForLevel(check_level)`.

# Notes
- This allows operators to see the required experience for a level based on the client provided, this takes race/class modifiers into account as well if enabled.
2023-06-12 19:18:39 -05:00
Alex King 152e99444c [Cleanup] Remove GetClientCount() from zone/entity.cpp and zone/entity.h (#3392)
* [Cleanup] Remove GetClientCount() from zone/entity.cpp and zone/entity.h

# Notes
- This is unused.

* Update entity.cpp
2023-06-12 19:18:17 -05:00
Alex King 795df5c597 [Cleanup] Remove CountTempPets() from zone/entity.cpp and zone/entity.h (#3390)
* [Cleanup] Remove CountTempPets() from zone/entity.cpp and zone/entity.h

# Notes
- This is unused.

* Update entity.h
2023-06-12 19:17:53 -05:00
Alex King 18eff726d0 [Commands] Assign #opcode to a #reload alias (#3401)
* [Commands] Assign #opcode to a #reload alias

# Notes
- Can use `#reload opcodes

* Add ServerOP_ReloadOpcodes
2023-06-12 18:42:39 -04:00
Alex King f06a37a009 [Cleanup] Add GMFind_Struct to packet structures (#3402)
* [Cleanup] Add GMFind_Struct to packet structures

# Notes
- X and Y were swapped in GMSummon_Struct so it displayed XYZ incorrectly in /find, adding its own struct fixes this.

* Update eq_packet_structs.h

* Update eq_packet_structs.h
2023-06-12 18:35:04 -04:00
Paul Coene ae53efc52c [Targeting] /tar <bad target> should not untarget existing target (#3383)
* [Targeting] /tar <bad target> should not untarget existing target

* Forgot string Id file.

* removed unneeded this->
2023-06-12 16:40:09 -05:00
Alex King 548eb65e1d [Cleanup] Remove InteractiveChat() and TakenAction() from zone/npc.h (#3382)
# Notes
- These are unimplemented and unused.
2023-06-12 15:14:34 -05:00
Alex King fede8760d4 [Cleanup] Remove CheckCoordLosNoZLeaps() from zone/entity.cpp and zone/entity.h (#3384)
# Notes
- This is unused.
2023-06-12 15:13:03 -05:00
Alex King 6faa202b57 [Cleanup] Remove pDBAsyncWorkID from zone/entity.h (#3385)
# Notes
- This is unused.
2023-06-12 15:12:47 -05:00
Alex King c406710623 [Cleanup] Remove GetClient(ip, port) from zone/entity.h (#3386)
# Notes
- This is unused.
2023-06-12 15:12:22 -05:00
Alex King 662c4012db [Cleanup] Remove GetGroupByBot(), GetRaidByMob(), and GetRaidByLeaderName() from zone/entity.cpp and zone/entity.h (#3387)
# Notes
- These are unused.
2023-06-12 15:12:00 -05:00
Alex King 849e7b910d [Cleanup] Remove SendAATimer() from zone/entity.h (#3388)
# Notes
- This is unused.
2023-06-12 15:11:32 -05:00
Alex King 8e33755f02 [Cleanup] Remove RemoveMob() and RemoveRaid() from zone/entity.cpp and zone/entity.h (#3389)
# Notes
- These are unused.
2023-06-12 15:11:17 -05:00
Alex King dfaa929778 [Cleanup] Remove GateAllClients() from zone/entity.cpp and zone/entity.h (#3391)
# Notes
- This is unused.
2023-06-12 15:10:36 -05:00
Alex King 306b06745f [Cleanup] Remove LimitCheckBoth() from zone/entity.cpp and zone/entity.h (#3393)
# Notes
- This is unused.
2023-06-12 15:05:39 -05:00
Alex King 108fc82ee0 [Cleanup] Remove Evade() from zone/entity.cpp and zone/entity.h (#3394)
# Notes
- This is unused.
2023-06-12 15:05:23 -05:00
Alex King 577f61b082 [Cleanup] Remove WriteEntityIDs() from zone/entity.cpp and zone/entity.h (#3395)
# Notes
- This is unused.
2023-06-12 15:05:09 -05:00
Alex King a01cf0718d [Cleanup] Remove struct DynamicZoneSafeReturn from zone/entity.h (#3396)
# Notes
- This is unused.
2023-06-12 15:04:54 -05:00
Alex King 90412ba61b [Cleanup] Remove struct TradeEntity from zone/common.h (#3397)
# Notes
- This is unused.
2023-06-12 15:04:38 -05:00
Alex King 5cbc380c62 [Cleanup] Remove CHECK_LOS_STEP from zone/common.h (#3398)
# Notes
- This is unused.
2023-06-12 15:04:25 -05:00
Alex King 6c289a7c71 [Cleanup] Remove _BECOMENPCPET() and _NPCPET() from zone/common.h (#3399)
# Notes
- These are unused.
2023-06-12 15:04:09 -05:00
Alex King 57335b188f [Cleanup] Remove SPECIALIZE_MANA_REDUCE from zone/common.h (#3400)
# Notes
- This is unused.
2023-06-12 15:03:55 -05:00
Alex King 056e429100 [Cleanup] Remove NPC::AddCash() from npc.cpp/npc.h (#3380)
# Notes
- This is unused.
2023-06-09 11:50:52 -04:00
Paul Coene f548aeddb2 [Logging] Fixed statements that logged incorrect data (#3381) 2023-06-07 08:26:04 -04:00
Paul Coene 4ff9faa4e6 [Illusions] RandomizeFeatures and SetGender were killing db texture (#3376)
* [Illusions] RandomizeFeatures and SetGender were killing db texture

* Found actual source of the problem.
2023-06-06 08:30:41 -04:00
Alex King 17fc350d46 [Quest API] Add SendChannelMessage() to Perl/Lua (#3378)
* [Quest API] Add SendChannelMessage() to Perl/Lua

# Perl
- Add `quest::send_channel_message(channel_number, guild_id, language_id, language_skill, message)`.
- Add `quest::send_channel_message(from, channel_number, guild_id, language_id, language_skill, message)`.
- Add `quest::send_channel_message(from, to, channel_number, guild_id, language_id, language_skill, message)`.

# Lua
- Add `eq.send_channel_message(channel_number, guild_id, language_id, language_skill, message)`.
- Add `eq.send_channel_message(from, channel_number, guild_id, language_id, language_skill, message)`.
- Add `eq.send_channel_message(from, to, channel_number, guild_id, language_id, language_skill, message)`.

# Notes
- This allows operators to send channel messages from scripts like a broadcast or tell.

* Update zoneserver.cpp

* Update lua_general.cpp

* Update questmgr.h
2023-06-03 19:06:40 -05:00
Chris Miles b18bc66b42 [Release] 22.12.0 (#3377) 2023-05-30 00:10:44 -05:00
Alex King 324bfd448e [Commands] Add entity variable command (#3345)
* [Commands] Add entity variable commands

# Commands
- Add `#clearentityvariables` to clear all entity variables from yourself or your target.
- Add `#deleteentityvariable [Variable Name]` to delete an entity variable from yourself or your target.
- Add `#setentityvariable [Variable Name] [Variable Value]` to set an entity variable for yourself or your target.
- Add `#viewentityvariables [Search Criteria]` to view your or your target's entity variables.

# Notes
- `#setentityvariable` can use multi-word names/values by using double quotes like `#setentityvariable "Test Variable" "Test Value"`.
- `#viewentityvariable` does not require a search criteria, not using one shows all entity variables on yourself or your target.

* Update viewentityvariables.cpp

* Unnecessary parameter.

* Consolidate commands.

* Update entityvariable.cpp

* Update command.cpp

* Proper arguments.
2023-05-25 19:49:09 -04:00
Alex King 75560ee830 [Performance] Character tribute is now bulk saved (#3340)
* [Performance] Character tribute is now bulk saved

This pull request combines individual `character_tribute` queries during `Save()` into one.

This pull request also adds a primary key of `id` to `character_tribute` and renames the pre-existing `id` column to `character_id`, this allows us to use repositories for this table.

* Update zonedb.cpp

* Update zonedb.cpp
2023-05-25 19:21:18 -04:00
Alex King 50db7637aa [Quest API] Add Memorize and Scribe Spell Events to Perl/Lua (#3363)
* [Quest API] Add Memorize and Scribe Spell Events to Perl/Lua

# Perl
- Add `EVENT_MEMORIZE_SPELL`.
- Add `EVENT_UNMEMORIZE_SPELL`.
- Add `EVENT_SCRIBE_SPELL`.
- Add `EVENT_UNSCRIBE_SPELL`.

# Lua
- Add `event_memorize_spell`.
- Add `event_unmemorize_spell`.
- Add `event_scribe_spell`.
- Add `event_unscribe_spell`.

# Notes
- Allows operators to perform events on memorization, unmemorization, scribe, or unscribe.
- Cleaned up target description messages for `#unscribespell`.

* Update client.cpp
2023-05-25 18:18:14 -05:00
Alex King 67fdc75df3 [Commands] Cleanup #setanim (#3350)
# Notes
- Make use of constants instead of hard-coded strings.
2023-05-25 18:04:09 -05:00
Chris Miles 9993022418 [Pets] Fix saving inconsistencies with pets (#3375) 2023-05-25 11:33:34 -04:00
Alex King bd95ed44fd [Cleanup] Remove GetMaxRank() from aa_ability.cpp/aa_ability.h (#3347)
# Notes
- This is unused.
2023-05-24 22:44:53 -05:00
Alex King 65fd323eab [Cleanup] Remove LoadSpawn2() and PopulateZoneSpawnListClose() from spawn2.cpp/zonedb.h (#3344)
# Notes
- These are unused.
2023-05-24 22:42:20 -05:00
Aeadoin 290c58741e [Bug Fix] Fix issue with Group Pointers/Member roles (#3374)
* [Bug Fix] Fix issue with Group Corruption

* cleanup

* Fix for Group Roles

* Fix for Group Roles
2023-05-24 22:40:59 -05:00
Alex King 39d0772a01 [Cleanup] Remove IsRaid() from raids.h (#3361)
# Notes
- This is unused.
2023-05-24 22:40:32 -05:00
Alex King 622fe50479 [Cleanup] Remove numMembers from raids.h (#3362)
# Notes
- This is unused.
2023-05-24 22:40:20 -05:00
Alex King f41a219309 [Cleanup] Remove CalcPetHp from spdat.h (#3364)
# Notes
- This is unused.
2023-05-24 22:37:04 -05:00
Alex King 23bc3c7fd6 [Cleanup] Remove Z_AGGRO from spdat.h (#3365)
# Notes
- This is unused.
2023-05-24 22:36:52 -05:00
Alex King 3144ac1a28 [Cleanup] Cleanup #setskill and #setskillall Commands (#3367)
# Notes
- No need to cap at 400 for max skill.
- When setting skill/skills, if we go over cap, set to cap.
2023-05-24 22:36:38 -05:00
Alex King a5106420e8 [Commands] Add #findcurrency Command (#3368)
* [Commands] Add #findcurrency Command

# Notes
- Allows you to find alternate currencies by item ID or name.
- Has a saylink for summoning a stack of the currency if the GM can use the `#summonitem` command.

* Update findcurrency.cpp

* Update findcurrency.cpp
2023-05-24 22:30:06 -05:00
Alex King 5a42c4f667 [Quest API] Add zone data methods to Perl/Lua (#3342)
# Perl
- Add `quest::GetZoneSafeX(zone_id)`.
- Add `quest::GetZoneSafeX(zone_id, version)`.
- Add `quest::GetZoneSafeY(zone_id)`.
- Add `quest::GetZoneSafeY(zone_id, version)`.
- Add `quest::GetZoneSafeZ(zone_id)`.
- Add `quest::GetZoneSafeZ(zone_id, version)`.
- Add `quest::GetZoneSafeHeading(zone_id)`.
- Add `quest::GetZoneSafeHeading(zone_id, version)`.
- Add `quest::GetZoneMinimumLevel(zone_id)`.
- Add `quest::GetZoneMinimumLevel(zone_id, version)`.
- Add `quest::GetZoneMaximumLevel(zone_id)`.
- Add `quest::GetZoneMaximumLevel(zone_id, version)`.
- Add `quest::GetZoneMinimumStatus(zone_id)`.
- Add `quest::GetZoneMinimumStatus(zone_id, version)`.
- Add `quest::GetZoneTimeZone(zone_id)`.
- Add `quest::GetZoneTimeZone(zone_id, version)`.
- Add `quest::GetZoneMaximumPlayers(zone_id)`.
- Add `quest::GetZoneMaximumPlayers(zone_id, version)`.
- Add `quest::GetZoneRuleSet(zone_id)`.
- Add `quest::GetZoneRuleSet(zone_id, version)`.
- Add `quest::GetZoneNote(zone_id)`.
- Add `quest::GetZoneNote(zone_id, version)`.
- Add `quest::GetZoneUnderworld(zone_id)`.
- Add `quest::GetZoneUnderworld(zone_id, version)`.
- Add `quest::GetZoneMinimumClip(zone_id)`.
- Add `quest::GetZoneMinimumClip(zone_id, version)`.
- Add `quest::GetZoneMaximumClip(zone_id)`.
- Add `quest::GetZoneMaximumClip(zone_id, version)`.
- Add `quest::GetZoneFogMinimumClip(zone_id)`.
- Add `quest::GetZoneFogMinimumClip(zone_id, slot)`.
- Add `quest::GetZoneFogMinimumClip(zone_id, slot, version)`.
- Add `quest::GetZoneFogMaximumClip(zone_id)`.
- Add `quest::GetZoneFogMaximumClip(zone_id, slot)`.
- Add `quest::GetZoneFogMaximumClip(zone_id, slot, version)`.
- Add `quest::GetZoneFogRed(zone_id)`.
- Add `quest::GetZoneFogRed(zone_id, slot)`.
- Add `quest::GetZoneFogRed(zone_id, slot, version)`.
- Add `quest::GetZoneFogGreen(zone_id)`.
- Add `quest::GetZoneFogGreen(zone_id, slot)`.
- Add `quest::GetZoneFogGreen(zone_id, slot, version)`.
- Add `quest::GetZoneFogBlue(zone_id)`.
- Add `quest::GetZoneFogBlue(zone_id, slot)`.
- Add `quest::GetZoneFogBlue(zone_id, slot, version)`.
- Add `quest::GetZoneSky(zone_id)`.
- Add `quest::GetZoneSky(zone_id, version)`.
- Add `quest::GetZoneZType(zone_id)`.
- Add `quest::GetZoneZType(zone_id, version)`.
- Add `quest::GetZoneExperienceMultiplier(zone_id)`.
- Add `quest::GetZoneExperienceMultiplier(zone_id, version)`.
- Add `quest::GetZoneWalkSpeed(zone_id)`.
- Add `quest::GetZoneWalkSpeed(zone_id, version)`.
- Add `quest::GetZoneTimeType(zone_id)`.
- Add `quest::GetZoneTimeType(zone_id, version)`.
- Add `quest::GetZoneFogDensity(zone_id)`.
- Add `quest::GetZoneFogDensity(zone_id, version)`.
- Add `quest::GetZoneFlagNeeded(zone_id)`.
- Add `quest::GetZoneFlagNeeded(zone_id, version)`.
- Add `quest::GetZoneCanBind(zone_id)`.
- Add `quest::GetZoneCanBind(zone_id, version)`.
- Add `quest::GetZoneCanCombat(zone_id)`.
- Add `quest::GetZoneCanCombat(zone_id, version)`.
- Add `quest::GetZoneCanLevitate(zone_id)`.
- Add `quest::GetZoneCanLevitate(zone_id, version)`.
- Add `quest::GetZoneCastOutdoor(zone_id)`.
- Add `quest::GetZoneCastOutdoor(zone_id, version)`.
- Add `quest::GetZoneHotzone(zone_id)`.
- Add `quest::GetZoneHotzone(zone_id, version)`.
- Add `quest::GetZoneInstanceType(zone_id)`.
- Add `quest::GetZoneInstanceType(zone_id, version)`.
- Add `quest::GetZoneShutdownDelay(zone_id)`.
- Add `quest::GetZoneShutdownDelay(zone_id, version)`.
- Add `quest::GetZonePEQZone(zone_id)`.
- Add `quest::GetZonePEQZone(zone_id, version)`.
- Add `quest::GetZoneExpansion(zone_id)`.
- Add `quest::GetZoneExpansion(zone_id, version)`.
- Add `quest::GetZoneBypassExpansionCheck(zone_id)`.
- Add `quest::GetZoneBypassExpansionCheck(zone_id, version)`.
- Add `quest::GetZoneSuspendBuffs(zone_id)`.
- Add `quest::GetZoneSuspendBuffs(zone_id, version)`.
- Add `quest::GetZoneRainChance(zone_id)`.
- Add `quest::GetZoneRainChance(zone_id, slot)`.
- Add `quest::GetZoneRainChance(zone_id, slot, version)`.
- Add `quest::GetZoneRainDuration(zone_id)`.
- Add `quest::GetZoneRainDuration(zone_id, slot)`.
- Add `quest::GetZoneRainDuration(zone_id, slot, version)`.
- Add `quest::GetZoneSnowChance(zone_id)`.
- Add `quest::GetZoneSnowChance(zone_id, slot)`.
- Add `quest::GetZoneSnowChance(zone_id, slot, version)`.
- Add `quest::GetZoneSnowDuration(zone_id)`.
- Add `quest::GetZoneSnowDuration(zone_id, slot)`.
- Add `quest::GetZoneSnowDuration(zone_id, slot, version)`.
- Add `quest::GetZoneGravity(zone_id)`.
- Add `quest::GetZoneGravity(zone_id, version)`.
- Add `quest::GetZoneType(zone_id)`.
- Add `quest::GetZoneType(zone_id, version)`.
- Add `quest::GetZoneSkyLock(zone_id)`.
- Add `quest::GetZoneSkyLock(zone_id, version)`.
- Add `quest::GetZoneFastRegenHP(zone_id)`.
- Add `quest::GetZoneFastRegenHP(zone_id, version)`.
- Add `quest::GetZoneFastRegenMana(zone_id)`.
- Add `quest::GetZoneFastRegenMana(zone_id, version)`.
- Add `quest::GetZoneFastRegenEndurance(zone_id)`.
- Add `quest::GetZoneFastRegenEndurance(zone_id, version)`.
- Add `quest::GetZoneNPCMaximumAggroDistance(zone_id)`.
- Add `quest::GetZoneNPCMaximumAggroDistance(zone_id, version)`.
- Add `quest::GetZoneMaximumMovementUpdateRange(zone_id)`.
- Add `quest::GetZoneMaximumMovementUpdateRange(zone_id, version)`.
- Add `quest::GetZoneMinimumExpansion(zone_id)`.
- Add `quest::GetZoneMinimumExpansion(zone_id, version)`.
- Add `quest::GetZoneMaximumExpansion(zone_id)`.
- Add `quest::GetZoneMaximumExpansion(zone_id, version)`.
- Add `quest::GetZoneContentFlags(zone_id)`.
- Add `quest::GetZoneContentFlags(zone_id, version)`.
- Add `quest::GetZoneContentFlagsDisabled(zone_id)`.
- Add `quest::GetZoneContentFlagsDisabled(zone_id, version)`.
- Add `quest::GetZoneUnderworldTeleportIndex(zone_id)`.
- Add `quest::GetZoneUnderworldTeleportIndex(zone_id, version)`.
- Add `quest::GetZoneLavaDamage(zone_id)`.
- Add `quest::GetZoneLavaDamage(zone_id, version)`.
- Add `quest::GetZoneMinimumLavaDamage(zone_id)`.
- Add `quest::GetZoneMinimumLavaDamage(zone_id, version)`.

# Lua
- Add `eq.get_zone_safe_x(zone_id)`.
- Add `eq.get_zone_safe_x(zone_id, version)`.
- Add `eq.get_zone_safe_y(zone_id)`.
- Add `eq.get_zone_safe_y(zone_id, version)`.
- Add `eq.get_zone_safe_z(zone_id)`.
- Add `eq.get_zone_safe_z(zone_id, version)`.
- Add `eq.get_zone_safe_heading(zone_id)`.
- Add `eq.get_zone_safe_heading(zone_id, version)`.
- Add `eq.get_zone_minimum_level(zone_id)`.
- Add `eq.get_zone_minimum_level(zone_id, version)`.
- Add `eq.get_zone_maximum_level(zone_id)`.
- Add `eq.get_zone_maximum_level(zone_id, version)`.
- Add `eq.get_zone_minimum_status(zone_id)`.
- Add `eq.get_zone_minimum_status(zone_id, version)`.
- Add `eq.get_zone_time_zone(zone_id)`.
- Add `eq.get_zone_time_zone(zone_id, version)`.
- Add `eq.get_zone_maximum_players(zone_id)`.
- Add `eq.get_zone_maximum_players(zone_id, version)`.
- Add `eq.get_zone_rule_set(zone_id)`.
- Add `eq.get_zone_rule_set(zone_id, version)`.
- Add `eq.get_zone_note(zone_id)`.
- Add `eq.get_zone_note(zone_id, version)`.
- Add `eq.get_zone_underworld(zone_id)`.
- Add `eq.get_zone_underworld(zone_id, version)`.
- Add `eq.get_zone_minimum_clip(zone_id)`.
- Add `eq.get_zone_minimum_clip(zone_id, version)`.
- Add `eq.get_zone_maximum_clip(zone_id)`.
- Add `eq.get_zone_maximum_clip(zone_id, version)`.
- Add `eq.get_zone_fog_minimum_clip(zone_id)`.
- Add `eq.get_zone_fog_minimum_clip(zone_id, slot)`.
- Add `eq.get_zone_fog_minimum_clip(zone_id, slot, version)`.
- Add `eq.get_zone_fog_maximum_clip(zone_id)`.
- Add `eq.get_zone_fog_maximum_clip(zone_id, slot)`.
- Add `eq.get_zone_fog_maximum_clip(zone_id, slot, version)`.
- Add `eq.get_zone_fog_red(zone_id)`.
- Add `eq.get_zone_fog_red(zone_id, slot)`.
- Add `eq.get_zone_fog_red(zone_id, slot, version)`.
- Add `eq.get_zone_fog_green(zone_id)`.
- Add `eq.get_zone_fog_green(zone_id, slot)`.
- Add `eq.get_zone_fog_green(zone_id, slot, version)`.
- Add `eq.get_zone_fog_blue(zone_id)`.
- Add `eq.get_zone_fog_blue(zone_id, slot)`.
- Add `eq.get_zone_fog_blue(zone_id, slot, version)`.
- Add `eq.get_zone_sky(zone_id)`.
- Add `eq.get_zone_sky(zone_id, version)`.
- Add `eq.get_zone_ztype(zone_id)`.
- Add `eq.get_zone_ztype(zone_id, version)`.
- Add `eq.get_zone_experience_multiplier(zone_id)`.
- Add `eq.get_zone_experience_multiplier(zone_id, version)`.
- Add `eq.get_zone_walk_speed(zone_id)`.
- Add `eq.get_zone_walk_speed(zone_id, version)`.
- Add `eq.get_zone_time_type(zone_id)`.
- Add `eq.get_zone_time_type(zone_id, version)`.
- Add `eq.get_zone_fog_density(zone_id)`.
- Add `eq.get_zone_fog_density(zone_id, version)`.
- Add `eq.get_zone_flag_needed(zone_id)`.
- Add `eq.get_zone_flag_needed(zone_id, version)`.
- Add `eq.get_zone_can_bind(zone_id)`.
- Add `eq.get_zone_can_bind(zone_id, version)`.
- Add `eq.get_zone_can_combat(zone_id)`.
- Add `eq.get_zone_can_combat(zone_id, version)`.
- Add `eq.get_zone_can_levitate(zone_id)`.
- Add `eq.get_zone_can_levitate(zone_id, version)`.
- Add `eq.get_zone_cast_outdoor(zone_id)`.
- Add `eq.get_zone_cast_outdoor(zone_id, version)`.
- Add `eq.get_zone_hotzone(zone_id)`.
- Add `eq.get_zone_hotzone(zone_id, version)`.
- Add `eq.get_zone_instance_type(zone_id)`.
- Add `eq.get_zone_instance_type(zone_id, version)`.
- Add `eq.get_zone_shutdown_delay(zone_id)`.
- Add `eq.get_zone_shutdown_delay(zone_id, version)`.
- Add `eq.get_zone_peqzone(zone_id)`.
- Add `eq.get_zone_peqzone(zone_id, version)`.
- Add `eq.get_zone_expansion(zone_id)`.
- Add `eq.get_zone_expansion(zone_id, version)`.
- Add `eq.get_zone_bypass_expansion_check(zone_id)`.
- Add `eq.get_zone_bypass_expansion_check(zone_id, version)`.
- Add `eq.get_zone_suspend_buffs(zone_id)`.
- Add `eq.get_zone_suspend_buffs(zone_id, version)`.
- Add `eq.get_zone_rain_chance(zone_id)`.
- Add `eq.get_zone_rain_chance(zone_id, slot)`.
- Add `eq.get_zone_rain_chance(zone_id, slot, version)`.
- Add `eq.get_zone_rain_duration(zone_id)`.
- Add `eq.get_zone_rain_duration(zone_id, slot)`.
- Add `eq.get_zone_rain_duration(zone_id, slot, version)`.
- Add `eq.get_zone_snow_chance(zone_id)`.
- Add `eq.get_zone_snow_chance(zone_id, slot)`.
- Add `eq.get_zone_snow_chance(zone_id, slot, version)`.
- Add `eq.get_zone_snow_duration(zone_id)`.
- Add `eq.get_zone_snow_duration(zone_id, slot)`.
- Add `eq.get_zone_snow_duration(zone_id, slot, version)`.
- Add `eq.get_zone_gravity(zone_id)`.
- Add `eq.get_zone_gravity(zone_id, version)`.
- Add `eq.get_zone_type(zone_id)`.
- Add `eq.get_zone_type(zone_id, version)`.
- Add `eq.get_zone_sky_lock(zone_id)`.
- Add `eq.get_zone_sky_lock(zone_id, version)`.
- Add `eq.get_zone_fast_regen_hp(zone_id)`.
- Add `eq.get_zone_fast_regen_hp(zone_id, version)`.
- Add `eq.get_zone_fast_regen_mana(zone_id)`.
- Add `eq.get_zone_fast_regen_mana(zone_id, version)`.
- Add `eq.get_zone_fast_regen_endurance(zone_id)`.
- Add `eq.get_zone_fast_regen_endurance(zone_id, version)`.
- Add `eq.get_zone_npc_maximum_aggro_distance(zone_id)`.
- Add `eq.get_zone_npc_maximum_aggro_distance(zone_id, version)`.
- Add `eq.get_zone_maximum_movement_update_range(zone_id)`.
- Add `eq.get_zone_maximum_movement_update_range(zone_id, version)`.
- Add `eq.get_zone_minimum_expansion(zone_id)`.
- Add `eq.get_zone_minimum_expansion(zone_id, version)`.
- Add `eq.get_zone_maximum_expansion(zone_id)`.
- Add `eq.get_zone_maximum_expansion(zone_id, version)`.
- Add `eq.get_zone_content_flags(zone_id)`.
- Add `eq.get_zone_content_flags(zone_id, version)`.
- Add `eq.get_zone_content_flags_disabled(zone_id)`.
- Add `eq.get_zone_content_flags_disabled(zone_id, version)`.
- Add `eq.get_zone_underworld_teleport_index(zone_id)`.
- Add `eq.get_zone_underworld_teleport_index(zone_id, version)`.
- Add `eq.get_zone_lava_damage(zone_id)`.
- Add `eq.get_zone_lava_damage(zone_id, version)`.
- Add `eq.get_zone_minimum_lava_damage(zone_id)`.
- Add `eq.get_zone_minimum_lava_damage(zone_id, version)`.

# Notes
- These methods add support for reading every value that the `zone` table contains, allowing operators to get any information about a specific zone and version they could need.
2023-05-24 17:59:18 -04:00
Alex King a3107cc54d [Bug Fix] Fix duplicate messages in #npcedit (#3372)
# Notes
- `#npcedit special_attacks` and `#npcedit special_abilities` send duplicate messages since the `d` variable wasn't being set and a message was being sent instead, meaning a message was sent inside the condition as well as a blank message at the bottom of the command.
2023-05-21 18:56:51 -04:00
Alex King f0152cef66 [Rules] Add World:MaximumQuestErrors Rule (#3349)
* [Rules] Add World:MaximumQuestErrors Rule

# Notes
- Allows operators to display more than 30 errors with #questerrors if they want.

* Update quest_interface.h
2023-05-21 18:48:30 -04:00
Alex King 21755a9f9e [Bug Fix] Fix typos in #zheader (#3370)
# Notes
- Argument 2 and 3 were being used when it should have been arguments 1 and 2.
2023-05-21 18:48:22 -04:00
Alex King b329515a07 [Quest API] Cleanup The Darkened Sea Quest Methods Names (#3369)
# Notes
- These were spelled incorrectly.
2023-05-21 18:48:15 -04:00
Alex King ff4b117cfa [Cleanup] Fix #spawn command NPCs having 0 health (#3371)
# Notes
- NPCs when spawned with this command have 0 health by default, requiring operators to manually edit their health if they're using this NPC as an NPC in their hub.
2023-05-21 18:48:08 -04:00
Paul Coene e305ba852b [Bug Fix] NPC Armor Upgrade to a slot not handled correctly (#3366)
* [NPC Armor - Bug] NPC upgardes in armor not correct

* Revert "[NPC Armor - Bug] NPC upgardes in armor not correct"

This reverts commit d5a68654a7.

* [NPC item bonuses] Upgrades not processed correctly

* Update loottables.cpp

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-05-19 22:28:01 -04:00
RekkasGit b8c91cf4f9 [Bug Fix] Mob scaling issue with min dmg set to zero while max dmg is not (#3351)
* fix for mob scaling issue with min dmg set to zero while max dmg is not.

* Cleanup

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-05-19 22:11:11 -04:00
Alex King cd82bd8472 [Cleanup] Remove DumpMerchantList() from zone.cpp/zone.h (#3343)
# Notes
- This is unused.
2023-05-17 09:02:14 -04:00
Alex King 20bed20f47 [Cleanup] Delete message.h (#3348)
# Notes
- This is unsued.
2023-05-17 09:00:38 -04:00
Alex King c93054421f [Cleanup] Remove CountNPC() and QueueManaged() from entity.cpp/entity.h (#3346)
# Notes
- These are unused.
2023-05-17 08:58:50 -04:00
Alex King b7a1fc6644 [Cleanup] Remove IsEntityInFrenzyMode() from hate_list.cpp/hate_list.h (#3352)
# Notes
- This is unused.
2023-05-17 08:58:27 -04:00
Alex King 6bfb8fca2e [Cleanup] Remove GetEscapingEntOnHateList() from hate_list.cpp/hate_list.h (#3353)
# Notes
- This is unused.
2023-05-17 08:58:13 -04:00
Alex King 9d6a7ad743 [Cleanup] Remove SetGraveyard() from zone.cpp/zone.h (#3354)
# Notes
- This is unused.
2023-05-17 08:58:02 -04:00
Alex King 076b88be9a [Cleanup] Remove TypeToSkill() from tradeskills.cpp/object.h (#3355)
# Notes
- This is unused.
2023-05-17 08:57:51 -04:00
Alex King 84a779c4df [Cleanup] Remove SetTradeCash() from trading.cpp/common.h (#3356)
# Notes
- This is unused.
2023-05-17 08:57:09 -04:00
Alex King 3fb479e612 [Cleanup] Remove TraderUpdate() from trading.cpp/client.h (#3357)
# Notes
- This is unused.
2023-05-17 08:56:42 -04:00
Alex King c1f4ee0e65 [Cleanup] Remove GetDamageReceived() and GetHealReceived() from combat_record.cpp/combat_record.h (#3358)
# Notes
- These are unused.
2023-05-17 08:56:09 -04:00
RekkasGit 32f7dc3d1b [Quest API] Add GetHateListClosest(), GetHateListClosestBot(), GetHateListClosestClient(), and GetHateListClosestNPC() methods/overloads to Perl/Lua (#3359)
* Add HateListClosestClient available for scripting.

* Add other methods.

* Use pre-existing constants.

* Typos

* Update mob.h

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-05-15 21:23:19 -04:00
RekkasGit fa55fd1664 [Bug Fix] Fix Heroic INT/WIS Bonuses (#3341)
* fix for heroic int/wis for hybrids

* Update classes.cpp

* Update classes.cpp

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-05-15 10:52:53 -04:00
Chris Miles c44c0d4efa [Performance] Character buffs now save in bulk (#3336)
* [Performance] Character buffs now save in bulk

* Only insert if we have buffs to insert

* Swap for .empty()
2023-05-09 13:28:34 -05:00
Chris Miles 50c63b95db [Performance] Character pet bulk saving (#3337)
* [Performance] Character pet bulk saving

* Update zonedb.cpp
2023-05-09 13:27:17 -05:00
Chris Miles 612029de6e [Performance] Character bind is now bulk saved (#3338)
* [Performance] Character bind is now bulk saved

* Fix bind heading
2023-05-09 13:22:57 -05:00
Chris Miles dbc6346fe8 [Performance] Mail key is now cached during player load (#3339)
* [Performance] Mail key is now cached during player load

* More refactoring
2023-05-09 13:22:43 -05:00
nytmyr 93a4153a4b [Rules] ResurrectionEffectBlock to prevent/allow/move buffs. (#3288)
* [Rules] ResurrectionEffectsBlock to prevent/allow/move buffs.

This removes the rule ResurrectionEffectsBlock (Bool) and creates ResurrectionEffectsBlock (Int)

Default = 2

Setting to 0 = Functions as it did before any blocking changes, Focus of Spirit and Strength buffs can overwrite Resurrection Effects.

Setting to 1 = Blocks all buffs that could overwrite Resurrection Effects.

Setting to 2 = Allows all buffs that would overwrite Resurrection Effects to land, however they will be moved to a new buff slot if one is available to allow both the beneficial buff to land and detrimental effects of Resurrection Effects to stay in effect until the duration is expired.

* Update logging

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-05-08 08:32:21 -05:00
Akkadius 434f270f68 Revert "[Bug Fix] ReloadQuests() on Zone::Init() to avoid cached global quests/plugins (#3333)"
This reverts commit 8c23eee42a.
2023-05-07 23:33:43 -05:00
Alex King 5ba33b88bd [Cleanup] Set GetAugmentType() to int again (#3335)
# Notes
- Augment type can be `-1` for all augment types.
2023-05-07 21:40:45 -04:00
Alex King ce1de9997b [Quest API] Add GetPet() to Perl (#3309)
# Perl
- Add `$mob->GetPet()`.

# Notes
- This exists in Lua, but not Perl.
2023-05-07 19:13:26 -05:00
Chris Miles 8814ab26cd [Hotfix] Fix mob item bonus calc (#3334) 2023-05-07 18:23:22 -05:00
Alex King 8c23eee42a [Bug Fix] ReloadQuests() on Zone::Init() to avoid cached global quests/plugins (#3333)
# Notes
- Before this, quests/plugins would be cached in an old state, so you'd have to either enter the zone and `#reload quest` or `#reload world` to get them to update.
2023-05-07 14:41:57 -04:00
Alex King 5475615448 [Bug Fix] #augmentitem bypasses augment restrictions (#3332)
* [Bug Fix] #augmentitem bypasses augment restrictions

# Notes
- `Object::HandleAugmentation` did not properly check for `augrestrict` values. This allowed augment restrictions to be bypassed with `#augmentitem` or anything else that uses this method.
- `Client::SummonItem` already properly checked these, so I just broke it out into a `Client::IsAugmentRestricted()` method.

* Update item_instance.h
2023-05-07 11:40:04 -04:00
Chris Miles 4a5559022f [Memory Leak] Fix large memory leak introduced in CalcItemBonuses (#3331) 2023-05-07 09:47:03 -04:00
Paul Coene 5be2041085 [Messages] Remove duplicate heal message for healing yourself (#3329) 2023-05-03 16:50:54 -04:00
Jasdac 9f4d60ec36 [Feature] Intoxication setter/getter for source, getter for Perl/Lua (#3330)
* Add setter and getter methods for intoxication
Add GetIntoxication functions for perl and Lua

* Remove trailing tab

* Use clamp instead of min/max
2023-05-03 16:19:53 -04:00
108 changed files with 7711 additions and 2211 deletions
+133
View File
@@ -1,3 +1,136 @@
## [22.13.1] - 06/13/2023
### Targeting
* Revert #3383 ([#3405](https://github.com/EQEmu/Server/pull/3405)) @noudess 2023-06-13
## [22.13.0] - 06/12/2023
### Code
* Add GMFind_Struct to packet structures ([#3402](https://github.com/EQEmu/Server/pull/3402)) @Kinglykrab 2023-06-12
* Remove CHECK_LOS_STEP from zone/common.h ([#3398](https://github.com/EQEmu/Server/pull/3398)) @Kinglykrab 2023-06-12
* Remove CheckCoordLosNoZLeaps() from zone/entity.cpp and zone/entity.h ([#3384](https://github.com/EQEmu/Server/pull/3384)) @Kinglykrab 2023-06-12
* Remove CountTempPets() from zone/entity.cpp and zone/entity.h ([#3390](https://github.com/EQEmu/Server/pull/3390)) @Kinglykrab 2023-06-12
* Remove Evade() from zone/entity.cpp and zone/entity.h ([#3394](https://github.com/EQEmu/Server/pull/3394)) @Kinglykrab 2023-06-12
* Remove GateAllClients() from zone/entity.cpp and zone/entity.h ([#3391](https://github.com/EQEmu/Server/pull/3391)) @Kinglykrab 2023-06-12
* Remove GetClient(ip, port) from zone/entity.h ([#3386](https://github.com/EQEmu/Server/pull/3386)) @Kinglykrab 2023-06-12
* Remove GetClientCount() from zone/entity.cpp and zone/entity.h ([#3392](https://github.com/EQEmu/Server/pull/3392)) @Kinglykrab 2023-06-12
* Remove GetGroupByBot(), GetRaidByMob(), and GetRaidByLeaderName() from zone/entity.cpp and zone/entity.h ([#3387](https://github.com/EQEmu/Server/pull/3387)) @Kinglykrab 2023-06-12
* Remove InteractiveChat() and TakenAction() from zone/npc.h ([#3382](https://github.com/EQEmu/Server/pull/3382)) @Kinglykrab 2023-06-12
* Remove LimitCheckBoth() from zone/entity.cpp and zone/entity.h ([#3393](https://github.com/EQEmu/Server/pull/3393)) @Kinglykrab 2023-06-12
* Remove NPC::AddCash() from npc.cpp/npc.h ([#3380](https://github.com/EQEmu/Server/pull/3380)) @Kinglykrab 2023-06-09
* Remove RemoveMob() and RemoveRaid() from zone/entity.cpp and zone/entity.h ([#3389](https://github.com/EQEmu/Server/pull/3389)) @Kinglykrab 2023-06-12
* Remove SPECIALIZE_MANA_REDUCE from zone/common.h ([#3400](https://github.com/EQEmu/Server/pull/3400)) @Kinglykrab 2023-06-12
* Remove SendAATimer() from zone/entity.h ([#3388](https://github.com/EQEmu/Server/pull/3388)) @Kinglykrab 2023-06-12
* Remove WriteEntityIDs() from zone/entity.cpp and zone/entity.h ([#3395](https://github.com/EQEmu/Server/pull/3395)) @Kinglykrab 2023-06-12
* Remove _BECOMENPCPET() and _NPCPET() from zone/common.h ([#3399](https://github.com/EQEmu/Server/pull/3399)) @Kinglykrab 2023-06-12
* Remove pDBAsyncWorkID from zone/entity.h ([#3385](https://github.com/EQEmu/Server/pull/3385)) @Kinglykrab 2023-06-12
* Remove struct DynamicZoneSafeReturn from zone/entity.h ([#3396](https://github.com/EQEmu/Server/pull/3396)) @Kinglykrab 2023-06-12
* Remove struct TradeEntity from zone/common.h ([#3397](https://github.com/EQEmu/Server/pull/3397)) @Kinglykrab 2023-06-12
### Commands
* Assign #opcode to a #reload alias ([#3401](https://github.com/EQEmu/Server/pull/3401)) @Kinglykrab 2023-06-12
### Illusions
* RandomizeFeatures and SetGender were killing db texture ([#3376](https://github.com/EQEmu/Server/pull/3376)) @noudess 2023-06-06
### Logging
* Fixed statements that logged incorrect data ([#3381](https://github.com/EQEmu/Server/pull/3381)) @noudess 2023-06-07
### Quest API
* Add GetEXPForLevel() to Perl/Lua ([#3403](https://github.com/EQEmu/Server/pull/3403)) @Kinglykrab 2023-06-12
* Add SendChannelMessage() to Perl/Lua ([#3378](https://github.com/EQEmu/Server/pull/3378)) @Kinglykrab 2023-06-04
* Add several spell methods to Perl/Lua ([#3379](https://github.com/EQEmu/Server/pull/3379)) @Kinglykrab 2023-06-12
### Targeting
* /tar <bad target> should not untarget existing target ([#3383](https://github.com/EQEmu/Server/pull/3383)) @noudess 2023-06-12
## [22.12.0] - 05/29/2023
### Code
* Cleanup #setskill and #setskillall Commands ([#3367](https://github.com/EQEmu/Server/pull/3367)) @Kinglykrab 2023-05-25
* Delete message.h ([#3348](https://github.com/EQEmu/Server/pull/3348)) @Kinglykrab 2023-05-17
* Fix #spawn command NPCs having 0 health ([#3371](https://github.com/EQEmu/Server/pull/3371)) @Kinglykrab 2023-05-21
* Remove CalcPetHp from spdat.h ([#3364](https://github.com/EQEmu/Server/pull/3364)) @Kinglykrab 2023-05-25
* Remove CountNPC() and QueueManaged() from entity.cpp/entity.h ([#3346](https://github.com/EQEmu/Server/pull/3346)) @Kinglykrab 2023-05-17
* Remove DumpMerchantList() from zone.cpp/zone.h ([#3343](https://github.com/EQEmu/Server/pull/3343)) @Kinglykrab 2023-05-17
* Remove GetDamageReceived() and GetHealReceived() from combat_record.cpp/combat_record.h ([#3358](https://github.com/EQEmu/Server/pull/3358)) @Kinglykrab 2023-05-17
* Remove GetEscapingEntOnHateList() from hate_list.cpp/hate_list.h ([#3353](https://github.com/EQEmu/Server/pull/3353)) @Kinglykrab 2023-05-17
* Remove GetMaxRank() from aa_ability.cpp/aa_ability.h ([#3347](https://github.com/EQEmu/Server/pull/3347)) @Kinglykrab 2023-05-25
* Remove IsEntityInFrenzyMode() from hate_list.cpp/hate_list.h ([#3352](https://github.com/EQEmu/Server/pull/3352)) @Kinglykrab 2023-05-17
* Remove IsRaid() from raids.h ([#3361](https://github.com/EQEmu/Server/pull/3361)) @Kinglykrab 2023-05-25
* Remove LoadSpawn2() and PopulateZoneSpawnListClose() from spawn2.cpp/zonedb.h ([#3344](https://github.com/EQEmu/Server/pull/3344)) @Kinglykrab 2023-05-25
* Remove SetGraveyard() from zone.cpp/zone.h ([#3354](https://github.com/EQEmu/Server/pull/3354)) @Kinglykrab 2023-05-17
* Remove SetTradeCash() from trading.cpp/common.h ([#3356](https://github.com/EQEmu/Server/pull/3356)) @Kinglykrab 2023-05-17
* Remove TraderUpdate() from trading.cpp/client.h ([#3357](https://github.com/EQEmu/Server/pull/3357)) @Kinglykrab 2023-05-17
* Remove TypeToSkill() from tradeskills.cpp/object.h ([#3355](https://github.com/EQEmu/Server/pull/3355)) @Kinglykrab 2023-05-17
* Remove Z_AGGRO from spdat.h ([#3365](https://github.com/EQEmu/Server/pull/3365)) @Kinglykrab 2023-05-25
* Remove numMembers from raids.h ([#3362](https://github.com/EQEmu/Server/pull/3362)) @Kinglykrab 2023-05-25
* Set GetAugmentType() to int again ([#3335](https://github.com/EQEmu/Server/pull/3335)) @Kinglykrab 2023-05-08
### Commands
* Add #findcurrency Command ([#3368](https://github.com/EQEmu/Server/pull/3368)) @Kinglykrab 2023-05-25
* Add entity variable command ([#3345](https://github.com/EQEmu/Server/pull/3345)) @Kinglykrab 2023-05-25
* Cleanup #setanim ([#3350](https://github.com/EQEmu/Server/pull/3350)) @Kinglykrab 2023-05-25
### Feature
* Intoxication setter/getter for source, getter for Perl/Lua ([#3330](https://github.com/EQEmu/Server/pull/3330)) @JasXSL 2023-05-03
### Fixes
* #augmentitem bypasses augment restrictions ([#3332](https://github.com/EQEmu/Server/pull/3332)) @Kinglykrab 2023-05-07
* Fix Heroic INT/WIS Bonuses ([#3341](https://github.com/EQEmu/Server/pull/3341)) @RekkasGit 2023-05-15
* Fix duplicate messages in #npcedit ([#3372](https://github.com/EQEmu/Server/pull/3372)) @Kinglykrab 2023-05-21
* Fix issue with Group Pointers/Member roles ([#3374](https://github.com/EQEmu/Server/pull/3374)) @Aeadoin 2023-05-25
* Fix mob item bonus calc ([#3334](https://github.com/EQEmu/Server/pull/3334)) @Akkadius 2023-05-07
* Fix typos in #zheader ([#3370](https://github.com/EQEmu/Server/pull/3370)) @Kinglykrab 2023-05-21
* Mob scaling issue with min dmg set to zero while max dmg is not ([#3351](https://github.com/EQEmu/Server/pull/3351)) @RekkasGit 2023-05-20
* NPC Armor Upgrade to a slot not handled correctly ([#3366](https://github.com/EQEmu/Server/pull/3366)) @noudess 2023-05-20
* ReloadQuests() on Zone::Init() to avoid cached global quests/plugins ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Kinglykrab 2023-05-07
* Revert " ReloadQuests() on Zone::Init() to avoid cached global quests/plugins " ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Akkadius 2023-05-08
### Memory Leak
* Fix large memory leak introduced in CalcItemBonuses ([#3331](https://github.com/EQEmu/Server/pull/3331)) @Akkadius 2023-05-07
### Messages
* Remove duplicate heal message for healing yourself ([#3329](https://github.com/EQEmu/Server/pull/3329)) @noudess 2023-05-03
### Performance
* Character bind is now bulk saved ([#3338](https://github.com/EQEmu/Server/pull/3338)) @Akkadius 2023-05-09
* Character buffs now save in bulk ([#3336](https://github.com/EQEmu/Server/pull/3336)) @Akkadius 2023-05-09
* Character pet bulk saving ([#3337](https://github.com/EQEmu/Server/pull/3337)) @Akkadius 2023-05-09
* Character tribute is now bulk saved ([#3340](https://github.com/EQEmu/Server/pull/3340)) @Kinglykrab 2023-05-25
* Mail key is now cached during player load ([#3339](https://github.com/EQEmu/Server/pull/3339)) @Akkadius 2023-05-09
### Pets
* Fix saving inconsistencies with pets ([#3375](https://github.com/EQEmu/Server/pull/3375)) @Akkadius 2023-05-25
### Quest API
* Add GetHateListClosest(), GetHateListClosestBot(), GetHateListClosestClient(), and GetHateListClosestNPC() methods/overloads to Perl/Lua ([#3359](https://github.com/EQEmu/Server/pull/3359)) @RekkasGit 2023-05-16
* Add GetPet() to Perl ([#3309](https://github.com/EQEmu/Server/pull/3309)) @Kinglykrab 2023-05-08
* Add Memorize and Scribe Spell Events to Perl/Lua ([#3363](https://github.com/EQEmu/Server/pull/3363)) @Kinglykrab 2023-05-25
* Add zone data methods to Perl/Lua ([#3342](https://github.com/EQEmu/Server/pull/3342)) @Kinglykrab 2023-05-24
* Cleanup The Darkened Sea Quest Methods Names ([#3369](https://github.com/EQEmu/Server/pull/3369)) @Kinglykrab 2023-05-21
### Rules
* Add World:MaximumQuestErrors Rule ([#3349](https://github.com/EQEmu/Server/pull/3349)) @Kinglykrab 2023-05-21
* ResurrectionEffectBlock to prevent/allow/move buffs. ([#3288](https://github.com/EQEmu/Server/pull/3288)) @nytmyr 2023-05-08
## [22.11.0] - 04/29/2023 ## [22.11.0] - 04/29/2023
### Code ### Code
+29
View File
@@ -630,6 +630,20 @@ bool IsINTCasterClass(uint8 class_id)
} }
} }
bool IsHeroicINTCasterClass(uint8 class_id)
{
switch (class_id) {
case NECROMANCER:
case WIZARD:
case MAGICIAN:
case ENCHANTER:
case SHADOWKNIGHT:
return true;
default:
return false;
}
}
bool IsWISCasterClass(uint8 class_id) bool IsWISCasterClass(uint8 class_id)
{ {
switch (class_id) { switch (class_id) {
@@ -642,6 +656,21 @@ bool IsWISCasterClass(uint8 class_id)
} }
} }
bool IsHeroicWISCasterClass(uint8 class_id)
{
switch (class_id) {
case CLERIC:
case DRUID:
case SHAMAN:
case PALADIN:
case BEASTLORD:
case RANGER:
return true;
default:
return false;
}
}
bool IsPlateClass(uint8 class_id) bool IsPlateClass(uint8 class_id)
{ {
switch (class_id) { switch (class_id) {
+2 -1
View File
@@ -140,7 +140,8 @@ bool IsHybridClass(uint8 class_id);
bool IsCasterClass(uint8 class_id); bool IsCasterClass(uint8 class_id);
bool IsINTCasterClass(uint8 class_id); bool IsINTCasterClass(uint8 class_id);
bool IsWISCasterClass(uint8 class_id); bool IsWISCasterClass(uint8 class_id);
bool IsHeroicINTCasterClass(uint8 class_id);
bool IsHeroicWISCasterClass(uint8 class_id);
bool IsPlateClass(uint8 class_id); bool IsPlateClass(uint8 class_id);
bool IsChainClass(uint8 class_id); bool IsChainClass(uint8 class_id);
bool IsLeatherClass(uint8 class_id); bool IsLeatherClass(uint8 class_id);
+1 -1
View File
@@ -68,7 +68,7 @@ namespace DatabaseSchema {
{"character_spells", "id"}, {"character_spells", "id"},
{"character_task_timers", "character_id"}, {"character_task_timers", "character_id"},
{"character_tasks", "charid"}, {"character_tasks", "charid"},
{"character_tribute", "id"}, {"character_tribute", "character_id"},
{"completed_tasks", "charid"}, {"completed_tasks", "charid"},
{"data_buckets", "id"}, {"data_buckets", "id"},
{"faction_values", "char_id"}, {"faction_values", "char_id"},
+7
View File
@@ -1045,4 +1045,11 @@ enum ResurrectionActions
Accept Accept
}; };
enum ScribeSpellActions
{
Scribe,
Memorize,
Unmemorize
};
#endif /*COMMON_EQ_CONSTANTS_H*/ #endif /*COMMON_EQ_CONSTANTS_H*/
+11
View File
@@ -1793,6 +1793,17 @@ struct GMSummon_Struct {
/*104*/ uint32 unknown2; // E0 E0 56 00 /*104*/ uint32 unknown2; // E0 E0 56 00
}; };
struct GMFind_Struct {
char charname[64];
char gmname[64];
uint32 success;
uint32 zoneID;
float x;
float y;
float z;
uint32 unknown2;
};
struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet
/* 0*/ char charname[64]; /* 0*/ char charname[64];
+2 -1
View File
@@ -108,7 +108,8 @@ namespace EQ
bool AvailableWearSlot(uint32 aug_wear_slots) const; bool AvailableWearSlot(uint32 aug_wear_slots) const;
int8 AvailableAugmentSlot(int32 augment_type) const; int8 AvailableAugmentSlot(int32 augment_type) const;
bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const; bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const;
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); } inline int GetAugmentType() const { return m_item ? m_item->AugType : 0; }
inline uint32 GetAugmentRestriction() const { return m_item ? m_item->AugRestrict : 0; }
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); } inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); }
@@ -0,0 +1,354 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
#define EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseCharacterTributeRepository {
public:
struct CharacterTribute {
int32_t id;
uint32_t character_id;
uint8_t tier;
uint32_t tribute;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"character_id",
"tier",
"tribute",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"character_id",
"tier",
"tribute",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("character_tribute");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static CharacterTribute NewEntity()
{
CharacterTribute e{};
e.id = 0;
e.character_id = 0;
e.tier = 0;
e.tribute = 0;
return e;
}
static CharacterTribute GetCharacterTribute(
const std::vector<CharacterTribute> &character_tributes,
int character_tribute_id
)
{
for (auto &character_tribute : character_tributes) {
if (character_tribute.id == character_tribute_id) {
return character_tribute;
}
}
return NewEntity();
}
static CharacterTribute FindOne(
Database& db,
int character_tribute_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
character_tribute_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
CharacterTribute e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int character_tribute_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
character_tribute_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const CharacterTribute &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.character_id));
v.push_back(columns[2] + " = " + std::to_string(e.tier));
v.push_back(columns[3] + " = " + std::to_string(e.tribute));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static CharacterTribute InsertOne(
Database& db,
CharacterTribute e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.tier));
v.push_back(std::to_string(e.tribute));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<CharacterTribute> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.tier));
v.push_back(std::to_string(e.tribute));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<CharacterTribute> All(Database& db)
{
std::vector<CharacterTribute> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterTribute e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<CharacterTribute> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<CharacterTribute> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterTribute e{};
e.id = static_cast<int32_t>(atoi(row[0]));
e.character_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.tier = static_cast<uint8_t>(strtoul(row[2], nullptr, 10));
e.tribute = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
};
#endif //EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H
@@ -0,0 +1,50 @@
#ifndef EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H
#define EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_character_tribute_repository.h"
class CharacterTributeRepository: public BaseCharacterTributeRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* CharacterTributeRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* CharacterTributeRepository::GetWhereNeverExpires()
* CharacterTributeRepository::GetWhereXAndY()
* CharacterTributeRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H
+2 -1
View File
@@ -297,6 +297,7 @@ RULE_BOOL(World, StartZoneSameAsBindOnCreation, true, "Should the start zone alw
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for characters that are online at login") RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for characters that are online at login")
RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)") RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt") RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Zone) RULE_CATEGORY(Zone)
@@ -444,7 +445,7 @@ RULE_BOOL(Spells, IllusionsAlwaysPersist, false, "Allows Illusions to persist be
RULE_BOOL(Spells, UseItemCastMessage, false, "Enable to use the \"item begins to glow\" messages when casting from an item.") RULE_BOOL(Spells, UseItemCastMessage, false, "Enable to use the \"item begins to glow\" messages when casting from an item.")
RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type") RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type")
RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true") RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true")
RULE_BOOL(Spells, ResurrectionEffectsBlock, true, "If enabled, resurrection effects cannot be overwritten.") RULE_INT(Spells, ResurrectionEffectBlock, 2, "0 = allow overwrites/rule disabled. If set to 1 = Block all buffs that would overwrite Resurrection Effects. If set to 2 = Will not overwrite Resurrection Effects, instead moves new buff to an empty slot if available. Default is 2.")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Combat) RULE_CATEGORY(Combat)
+13 -12
View File
@@ -235,18 +235,19 @@
#define ServerOP_ReloadMerchants 0x4109 #define ServerOP_ReloadMerchants 0x4109
#define ServerOP_ReloadNPCEmotes 0x4110 #define ServerOP_ReloadNPCEmotes 0x4110
#define ServerOP_ReloadObjects 0x4111 #define ServerOP_ReloadObjects 0x4111
#define ServerOP_ReloadPerlExportSettings 0x4112 #define ServerOP_ReloadOpcodes 0x4112
#define ServerOP_ReloadRules 0x4113 #define ServerOP_ReloadPerlExportSettings 0x4113
#define ServerOP_ReloadStaticZoneData 0x4114 #define ServerOP_ReloadRules 0x4114
#define ServerOP_ReloadTasks 0x4115 #define ServerOP_ReloadStaticZoneData 0x4115
#define ServerOP_ReloadTitles 0x4116 #define ServerOP_ReloadTasks 0x4116
#define ServerOP_ReloadTraps 0x4117 #define ServerOP_ReloadTitles 0x4117
#define ServerOP_ReloadVariables 0x4118 #define ServerOP_ReloadTraps 0x4118
#define ServerOP_ReloadVeteranRewards 0x4119 #define ServerOP_ReloadVariables 0x4119
#define ServerOP_ReloadWorld 0x4120 #define ServerOP_ReloadVeteranRewards 0x4120
#define ServerOP_ReloadZonePoints 0x4121 #define ServerOP_ReloadWorld 0x4121
#define ServerOP_ReloadDzTemplates 0x4122 #define ServerOP_ReloadZonePoints 0x4122
#define ServerOP_ReloadZoneData 0x4123 #define ServerOP_ReloadDzTemplates 0x4123
#define ServerOP_ReloadZoneData 0x4124
#define ServerOP_CZDialogueWindow 0x4500 #define ServerOP_CZDialogueWindow 0x4500
#define ServerOP_CZLDoNUpdate 0x4501 #define ServerOP_CZLDoNUpdate 0x4501
+31 -32
View File
@@ -133,55 +133,54 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
{ {
char MailKeyString[17]; char mail_key[17];
if (RuleB(Chat, EnableMailKeyIPVerification) == true)
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
else
sprintf(MailKeyString, "%08X", MailKey);
const std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
MailKeyString, CharID);
const auto results = QueryDatabase(query);
if (!results.Success())
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, MailKeyString, results.ErrorMessage().c_str());
if (RuleB(Chat, EnableMailKeyIPVerification) == true) {
sprintf(mail_key, "%08X%08X", IPAddress, MailKey);
}
else {
sprintf(mail_key, "%08X", MailKey);
} }
std::string SharedDatabase::GetMailKey(int CharID, bool key_only) const std::string query = StringFormat(
{ "UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID); mail_key, CharID
auto results = QueryDatabase(query); );
const auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, mail_key, results.ErrorMessage().c_str());
}
}
Log(Logs::Detail, Logs::MySQLError, "Error retrieving mailkey from database: %s", results.ErrorMessage().c_str()); SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id)
return std::string(); {
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", character_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return MailKeys{};
} }
if (!results.RowCount()) { if (!results.RowCount()) {
Log(Logs::General,
Log(Logs::General, Logs::ClientLogin, "Error: Mailkey for character id [%i] does not exist or could not be found", CharID); Logs::ClientLogin,
return std::string(); "Error: Mailkey for character id [%i] does not exist or could not be found",
character_id
);
return MailKeys{};
} }
auto &row = results.begin(); auto &row = results.begin();
if (row != results.end()) { if (row != results.end()) {
std::string mail_key = row[0]; std::string mail_key = row[0];
if (mail_key.length() > 8 && key_only) { return MailKeys{
return mail_key.substr(8); .mail_key = mail_key.substr(8),
.mail_key_full = mail_key
};
} }
else {
return mail_key;
}
}
else {
Log(Logs::General, Logs::MySQLError, "Internal MySQL error in SharedDatabase::GetMailKey(int, bool)"); return MailKeys{};
return std::string();
}
} }
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQ::ItemInstance*>::const_iterator &start, std::list<EQ::ItemInstance*>::const_iterator &end) bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQ::ItemInstance*>::const_iterator &start, std::list<EQ::ItemInstance*>::const_iterator &end)
+5 -1
View File
@@ -81,7 +81,11 @@ public:
bool SetGMInvul(uint32 account_id, bool gminvul); bool SetGMInvul(uint32 account_id, bool gminvul);
bool SetGMFlymode(uint32 account_id, uint8 flymode); bool SetGMFlymode(uint32 account_id, uint8 flymode);
void SetMailKey(int CharID, int IPAddress, int MailKey); void SetMailKey(int CharID, int IPAddress, int MailKey);
std::string GetMailKey(int CharID, bool key_only = false); struct MailKeys {
std::string mail_key;
std::string mail_key_full;
};
MailKeys GetMailKey(int character_id);
bool SaveCursor( bool SaveCursor(
uint32 char_id, uint32 char_id,
std::list<EQ::ItemInstance *>::const_iterator &start, std::list<EQ::ItemInstance *>::const_iterator &start,
+1011 -534
View File
File diff suppressed because it is too large Load Diff
+101 -60
View File
@@ -171,6 +171,37 @@
#define SPELL_ILLUSION_MALE 1732 #define SPELL_ILLUSION_MALE 1732
#define SPELL_UNSUMMON_SELF 892 #define SPELL_UNSUMMON_SELF 892
#define SPELL_ANCIENT_LIFEBANE 2115 #define SPELL_ANCIENT_LIFEBANE 2115
#define SPELL_GMHP25K 6817
#define SPELL_GMHP50K 6818
#define SPELL_GMHP100K 6819
#define SPELL_GMHP225K 6820
#define SPELL_GMHP475K 6821
#define SPELL_GMHP925K 6822
#define SPELL_GMHP2M 6823
#define SPELL_GMHP3M 6824
#define SPELL_GMHP5M 39851
#define SPELL_GUIDE_ACTING_ONE 778
#define SPELL_GUIDE_ALLIANCE_ONE 810
#define SPELL_GUIDE_CANCEL_MAGIC_ONE 811
#define SPELL_GUIDE_JOURNEY_ONE 813
#define SPELL_GUIDE_VISION_ONE 814
#define SPELL_GUIDE_HEALTH_ONE 815
#define SPELL_GUIDE_INVULNERABILITY_ONE 816
#define SPELL_GUIDE_BOLT_ONE 817
#define SPELL_GUIDE_MEMORY_BLUR_ONE 818
#define SPELL_GUIDE_ACTING_TWO 1209
#define SPELL_GUIDE_CANCEL_MAGIC_TWO 1211
#define SPELL_GUIDE_JOURNEY_TWO 1212
#define SPELL_GUIDE_VISION_TWO 1213
#define SPELL_GUIDE_HEALTH_TWO 1214
#define SPELL_GUIDE_INVULNERABILITY_TWO 1215
#define SPELL_GUIDE_BOLT_TWO 1216
#define SPELL_GUIDE_MEMORY_BLUR_TWO 1217
#define SPELL_GUIDE_ALLIANCE_TWO 1219
#define SPELL_GUIDE_EVACUATION 3921
#define SPELL_GUIDE_LEVITATION 39852
#define SPELL_GUIDE_SPELL_HASTE 39853
#define SPELL_GUIDE_HASTE 39854
//spellgroup ids //spellgroup ids
#define SPELLGROUP_FRENZIED_BURNOUT 2754 #define SPELLGROUP_FRENZIED_BURNOUT 2754
@@ -201,8 +232,22 @@
#define INSTRUMENT_LUTE 13011 #define INSTRUMENT_LUTE 13011
#define INSTRUMENT_HORN 13012 #define INSTRUMENT_HORN 13012
//option types for the rule Spells:ResurrectionEffectBlock
#define RES_EFFECTS_CANNOT_STACK -1
#define NO_RES_EFFECTS_BLOCK 0
#define RES_EFFECTS_BLOCK 1
#define RES_EFFECTS_BLOCK_WITH_BUFFS 2
#define MOVE_NEW_SLOT 2
const int Z_AGGRO=10; #define PARTIAL_DEATH_SAVE 1
#define FULL_DEATH_SAVE 2
#define MAX_FAST_HEAL_CASTING_TIME 2000
#define MAX_VERY_FAST_HEAL_CASTING_TIME 1000
#define DETRIMENTAL_EFFECT 0
#define BENEFICIAL_EFFECT 1
#define BENEFICIAL_EFFECT_GROUP_ONLY 2
const uint32 MobAISpellRange=100; // max range of buffs const uint32 MobAISpellRange=100; // max range of buffs
@@ -1160,7 +1205,7 @@ typedef enum {
#define SE_LimitUseMin 422 // implemented, @Ff Minium amount of numhits for a spell to be focused, base: numhit amt #define SE_LimitUseMin 422 // implemented, @Ff Minium amount of numhits for a spell to be focused, base: numhit amt
#define SE_LimitUseType 423 // implemented, @Ff Focus will only affect if has this numhits type, base: numhit type #define SE_LimitUseType 423 // implemented, @Ff Focus will only affect if has this numhits type, base: numhit type
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace #define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626) #define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window #define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_SkillProcAttempt 427 // implemented - chance to proc when using a skill(ie taunt) #define SE_SkillProcAttempt 427 // implemented - chance to proc when using a skill(ie taunt)
#define SE_LimitToSkill 428 // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none #define SE_LimitToSkill 428 // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none
@@ -1443,7 +1488,7 @@ extern int32 SPDAT_RECORDS;
bool IsTargetableAESpell(uint16 spell_id); bool IsTargetableAESpell(uint16 spell_id);
bool IsSacrificeSpell(uint16 spell_id); bool IsSacrificeSpell(uint16 spell_id);
bool IsLifetapSpell(uint16 spell_id); bool IsLifetapSpell(uint16 spell_id);
bool IsMezSpell(uint16 spell_id); bool IsMesmerizeSpell(uint16 spell_id);
bool IsStunSpell(uint16 spell_id); bool IsStunSpell(uint16 spell_id);
bool IsSlowSpell(uint16 spell_id); bool IsSlowSpell(uint16 spell_id);
bool IsHasteSpell(uint16 spell_id); bool IsHasteSpell(uint16 spell_id);
@@ -1452,22 +1497,23 @@ bool IsPercentalHealSpell(uint16 spell_id);
bool IsGroupOnlySpell(uint16 spell_id); bool IsGroupOnlySpell(uint16 spell_id);
bool IsBeneficialSpell(uint16 spell_id); bool IsBeneficialSpell(uint16 spell_id);
bool IsDetrimentalSpell(uint16 spell_id); bool IsDetrimentalSpell(uint16 spell_id);
bool IsInvisSpell(uint16 spell_id); bool IsInvisibleSpell(uint16 spell_id);
bool IsInvulnerabilitySpell(uint16 spell_id); bool IsInvulnerabilitySpell(uint16 spell_id);
bool IsCHDurationSpell(uint16 spell_id); bool IsCompleteHealDurationSpell(uint16 spell_id);
bool IsPoisonCounterSpell(uint16 spell_id); bool IsPoisonCounterSpell(uint16 spell_id);
bool IsDiseaseCounterSpell(uint16 spell_id); bool IsDiseaseCounterSpell(uint16 spell_id);
bool IsSummonItemSpell(uint16 spell_id); bool IsSummonItemSpell(uint16 spell_id);
bool IsSummonSkeletonSpell(uint16 spell_id); bool IsSummonSkeletonSpell(uint16 spell_id);
bool IsSummonPetSpell(uint16 spell_id); bool IsSummonPetSpell(uint16 spell_id);
bool IsSummonPCSpell(uint16 spell_id); bool IsSummonPCSpell(uint16 spell_id);
bool IsPetSpell(uint16 spell_id);
bool IsCharmSpell(uint16 spell_id); bool IsCharmSpell(uint16 spell_id);
bool IsBlindSpell(uint16 spell_id); bool IsBlindSpell(uint16 spell_id);
bool IsEffectHitpointsSpell(uint16 spell_id); bool IsHealthSpell(uint16 spell_id);
bool IsReduceCastTimeSpell(uint16 spell_id); bool IsCastTimeReductionSpell(uint16 spell_id);
bool IsIncreaseDurationSpell(uint16 spell_id); bool IsIncreaseDurationSpell(uint16 spell_id);
bool IsReduceManaSpell(uint16 spell_id); bool IsManaCostReductionSpell(uint16 spell_id);
bool IsExtRangeSpell(uint16 spell_id); bool IsIncreaseRangeSpell(uint16 spell_id);
bool IsImprovedHealingSpell(uint16 spell_id); bool IsImprovedHealingSpell(uint16 spell_id);
bool IsImprovedDamageSpell(uint16 spell_id); bool IsImprovedDamageSpell(uint16 spell_id);
bool IsAEDurationSpell(uint16 spell_id); bool IsAEDurationSpell(uint16 spell_id);
@@ -1475,26 +1521,22 @@ bool IsPureNukeSpell(uint16 spell_id);
bool IsAENukeSpell(uint16 spell_id); bool IsAENukeSpell(uint16 spell_id);
bool IsPBAENukeSpell(uint16 spell_id); bool IsPBAENukeSpell(uint16 spell_id);
bool IsAERainNukeSpell(uint16 spell_id); bool IsAERainNukeSpell(uint16 spell_id);
bool IsPartialCapableSpell(uint16 spell_id); bool IsPartialResistableSpell(uint16 spell_id);
bool IsResistableSpell(uint16 spell_id); bool IsResistableSpell(uint16 spell_id);
bool IsGroupSpell(uint16 spell_id); bool IsGroupSpell(uint16 spell_id);
bool IsTGBCompatibleSpell(uint16 spell_id); bool IsTGBCompatibleSpell(uint16 spell_id);
bool IsBardSong(uint16 spell_id); bool IsBardSong(uint16 spell_id);
bool IsEffectInSpell(uint16 spellid, int effect); bool IsEffectInSpell(uint16 spell_id, int effect_id);
uint16 GetTriggerSpellID(uint16 spell_id, uint32 effect); uint16 GetSpellTriggerSpellID(uint16 spell_id, int effect_id);
bool IsBlankSpellEffect(uint16 spellid, int effect_index); bool IsBlankSpellEffect(uint16 spell_id, int effect_index);
bool IsValidSpell(uint32 spellid); bool IsValidSpell(uint32 spell_id);
bool IsSummonSpell(uint16 spellid); bool IsSummonSpell(uint16 spell_id);
bool IsEvacSpell(uint16 spellid); bool IsDamageSpell(uint16 spell_id);
bool IsDamageSpell(uint16 spellid); bool IsFearSpell(uint16 spell_id);
bool IsFearSpell(uint16 spellid); bool IsCureSpell(uint16 spell_id);
bool IsCureSpell(uint16 spellid); int GetSpellEffectIndex(uint16 spell_id, int effect_id);
bool BeneficialSpell(uint16 spell_id); uint8 GetSpellMinimumLevel(uint16 spell_id);
bool GroupOnlySpell(uint16 spell_id); uint8 GetSpellLevel(uint16 spell_id, uint8 class_id);
int GetSpellEffectIndex(uint16 spell_id, int effect);
int CanUseSpell(uint16 spellid, int classa, int level);
int GetMinLevel(uint16 spell_id);
int GetSpellLevel(uint16 spell_id, int classa);
int CalcBuffDuration_formula(int level, int formula, int duration); int CalcBuffDuration_formula(int level, int formula, int duration);
int32 CalculatePoisonCounters(uint16 spell_id); int32 CalculatePoisonCounters(uint16 spell_id);
int32 CalculateDiseaseCounters(uint16 spell_id); int32 CalculateDiseaseCounters(uint16 spell_id);
@@ -1505,10 +1547,11 @@ bool IsDisciplineBuff(uint16 spell_id);
bool IsDiscipline(uint16 spell_id); bool IsDiscipline(uint16 spell_id);
bool IsCombatSkill(uint16 spell_id); bool IsCombatSkill(uint16 spell_id);
bool IsResurrectionEffects(uint16 spell_id); bool IsResurrectionEffects(uint16 spell_id);
int8 GetSpellResurrectionSicknessCheck(uint16 spell_id_one, uint16 spell_id_two);
bool IsRuneSpell(uint16 spell_id); bool IsRuneSpell(uint16 spell_id);
bool IsMagicRuneSpell(uint16 spell_id); bool IsMagicRuneSpell(uint16 spell_id);
bool IsManaTapSpell(uint16 spell_id); bool IsManaTapSpell(uint16 spell_id);
bool IsAllianceSpellLine(uint16 spell_id); bool IsAllianceSpell(uint16 spell_id);
bool IsDeathSaveSpell(uint16 spell_id); bool IsDeathSaveSpell(uint16 spell_id);
bool IsFullDeathSaveSpell(uint16 spell_id); bool IsFullDeathSaveSpell(uint16 spell_id);
bool IsPartialDeathSaveSpell(uint16 spell_id); bool IsPartialDeathSaveSpell(uint16 spell_id);
@@ -1517,10 +1560,10 @@ bool IsSuccorSpell(uint16 spell_id);
bool IsTeleportSpell(uint16 spell_id); bool IsTeleportSpell(uint16 spell_id);
bool IsTranslocateSpell(uint16 spell_id); bool IsTranslocateSpell(uint16 spell_id);
bool IsGateSpell(uint16 spell_id); bool IsGateSpell(uint16 spell_id);
bool IsPlayerIllusionSpell(uint16 spell_id); // seveian 2008-09-23 bool IsIllusionSpell(uint16 spell_id);
bool IsLDoNObjectSpell(uint16 spell_id); bool IsLDoNObjectSpell(uint16 spell_id);
int32 GetSpellResistType(uint16 spell_id); int GetSpellResistType(uint16 spell_id);
int32 GetSpellTargetType(uint16 spell_id); int GetSpellTargetType(uint16 spell_id);
bool IsHealOverTimeSpell(uint16 spell_id); bool IsHealOverTimeSpell(uint16 spell_id);
bool IsCompleteHealSpell(uint16 spell_id); bool IsCompleteHealSpell(uint16 spell_id);
bool IsFastHealSpell(uint16 spell_id); bool IsFastHealSpell(uint16 spell_id);
@@ -1535,38 +1578,36 @@ bool IsSelfConversionSpell(uint16 spell_id);
bool IsBuffSpell(uint16 spell_id); bool IsBuffSpell(uint16 spell_id);
bool IsPersistDeathSpell(uint16 spell_id); bool IsPersistDeathSpell(uint16 spell_id);
bool IsSuspendableSpell(uint16 spell_id); bool IsSuspendableSpell(uint16 spell_id);
uint32 GetMorphTrigger(uint32 spell_id); bool IsCastOnFadeDurationSpell(uint16 spell_id);
bool IsCastonFadeDurationSpell(uint16 spell_id); bool IsDistanceModifierSpell(uint16 spell_id);
bool IsPowerDistModSpell(uint16 spell_id); int GetSpellPartialMeleeRuneReduction(uint16 spell_id);
uint32 GetPartialMeleeRuneReduction(uint32 spell_id); int GetSpellPartialMagicRuneReduction(uint16 spell_id);
uint32 GetPartialMagicRuneReduction(uint32 spell_id); int GetSpellPartialMeleeRuneAmount(uint16 spell_id);
uint32 GetPartialMeleeRuneAmount(uint32 spell_id); int GetSpellPartialMagicRuneAmount(uint16 spell_id);
uint32 GetPartialMagicRuneAmount(uint32 spell_id); bool IsNoDetrimentalSpellAggroSpell(uint16 spell_id);
bool NoDetrimentalSpellAggro(uint16 spell_id); bool IsStackableDOT(uint16 spell_id);
bool IsStackableDot(uint16 spell_id); bool IsBardOnlyStackEffect(int effect_id);
bool IsBardOnlyStackEffect(int effect); bool IsCastWhileInvisibleSpell(uint16 spell_id);
bool IsCastWhileInvis(uint16 spell_id); bool IsEffectIgnoredInStacking(int effect_id);
bool IsEffectIgnoredInStacking(int spa); bool IsFocusLimit(int effect_id);
bool IsFocusLimit(int spa); bool IsTargetRequiredForSpell(uint16 spell_id);
bool SpellRequiresTarget(int target_type); bool IsVirusSpell(uint16 spell_id);
bool IsVirusSpell(int32 spell_id); int GetSpellViralMinimumSpreadTime(uint16 spell_id);
int GetViralMinSpreadTime(int32 spell_id); int GetSpellViralMaximumSpreadTime(uint16 spell_id);
int GetViralMaxSpreadTime(int32 spell_id); int GetSpellViralSpreadRange(uint16 spell_id);
int GetViralSpreadRange(int32 spell_id); bool IsInstrumentModifierAppliedToSpellEffect(uint16 spell_id, int effect_id);
bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect); bool IsPulsingBardSong(uint16 spell_id);
bool IsPulsingBardSong(int32 spell_id); int GetSpellProcLimitTimer(uint16 spell_id, int proc_type);
uint32 GetProcLimitTimer(int32 spell_id, int proc_type); bool IsCastNotStandingSpell(uint16 spell_id);
bool IgnoreCastingRestriction(int32 spell_id); int GetSpellEffectDescriptionNumber(uint16 spell_id);
int CalcPetHp(int levelb, int classb, int STA = 75); DmgShieldType GetDamageShieldType(uint16 spell_id, int damage_shield_type = 0);
int GetSpellEffectDescNum(uint16 spell_id); bool IsRestAllowedSpell(uint16 spell_id);
DmgShieldType GetDamageShieldType(uint16 spell_id, int32 DSType = 0); int GetSpellNimbusEffect(uint16 spell_id);
bool DetrimentalSpellAllowsRest(uint16 spell_id); int GetSpellFuriousBash(uint16 spell_id);
uint32 GetNimbusEffect(uint16 spell_id);
int32 GetFuriousBash(uint16 spell_id);
bool IsShortDurationBuff(uint16 spell_id); bool IsShortDurationBuff(uint16 spell_id);
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type); bool IsSpellUsableInThisZoneType(uint16 spell_id, uint8 zone_type);
const char *GetSpellName(uint16 spell_id); const char *GetSpellName(uint16 spell_id);
int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot = 0); int GetSpellStatValue(uint16 spell_id, const char* stat_identifier, uint8 slot = 0);
bool CastRestrictedSpell(int spellid); bool IsCastRestrictedSpell(uint16 spell_id);
#endif #endif
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables // Build variables
// these get injected during the build pipeline // these get injected during the build pipeline
#define CURRENT_VERSION "22.11.0-dev" // always append -dev to the current version for custom-builds #define CURRENT_VERSION "22.13.1-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0" #define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__ #define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__ #define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9227 #define CURRENT_BINARY_DATABASE_VERSION 9228
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039
File diff suppressed because it is too large Load Diff
+58
View File
@@ -24,6 +24,8 @@
#include "../common/repositories/zone_repository.h" #include "../common/repositories/zone_repository.h"
#include "../common/repositories/base/base_content_flags_repository.h" #include "../common/repositories/base/base_content_flags_repository.h"
#include <glm/vec4.hpp>
class ZoneStore { class ZoneStore {
public: public:
ZoneStore(); ZoneStore();
@@ -43,6 +45,62 @@ public:
const char *GetZoneName(uint32 zone_id, bool error_unknown = false); const char *GetZoneName(uint32 zone_id, bool error_unknown = false);
const char *GetZoneLongName(uint32 zone_id, bool error_unknown = false); const char *GetZoneLongName(uint32 zone_id, bool error_unknown = false);
ZoneRepository::Zone *GetZoneWithFallback(uint32 zone_id, int version = 0); ZoneRepository::Zone *GetZoneWithFallback(uint32 zone_id, int version = 0);
glm::vec4 GetZoneSafeCoordinates(uint32 zone_id, int version = 0);
float GetZoneGraveyardID(uint32 zone_id, int version = 0);
uint8 GetZoneMinimumLevel(uint32 zone_id, int version = 0);
uint8 GetZoneMaximumLevel(uint32 zone_id, int version = 0);
uint8 GetZoneMinimumStatus(uint32 zone_id, int version = 0);
int GetZoneTimeZone(uint32 zone_id, int version = 0);
int GetZoneMaximumPlayers(uint32 zone_id, int version = 0);
uint32 GetZoneRuleSet(uint32 zone_id, int version = 0);
const std::string& GetZoneNote(uint32 zone_id, int version = 0);
float GetZoneUnderworld(uint32 zone_id, int version = 0);
float GetZoneMinimumClip(uint32 zone_id, int version = 0);
float GetZoneMaximumClip(uint32 zone_id, int version = 0);
float GetZoneFogMinimumClip(uint32 zone_id, uint8 slot = 0, int version = 0);
float GetZoneFogMaximumClip(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneFogRed(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneFogGreen(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneFogBlue(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneSky(uint32 zone_id, int version = 0);
uint8 GetZoneZType(uint32 zone_id, int version = 0);
float GetZoneExperienceMultiplier(uint32 zone_id, int version = 0);
float GetZoneWalkSpeed(uint32 zone_id, int version = 0);
uint8 GetZoneTimeType(uint32 zone_id, int version = 0);
float GetZoneFogDensity(uint32 zone_id, int version = 0);
const std::string& GetZoneFlagNeeded(uint32 zone_id, int version = 0);
int8 GetZoneCanBind(uint32 zone_id, int version = 0);
int8 GetZoneCanCombat(uint32 zone_id, int version = 0);
int8 GetZoneCanLevitate(uint32 zone_id, int version = 0);
int8 GetZoneCastOutdoor(uint32 zone_id, int version = 0);
uint8 GetZoneHotzone(uint32 zone_id, int version = 0);
uint8 GetZoneInstanceType(uint32 zone_id, int version = 0);
uint64 GetZoneShutdownDelay(uint32 zone_id, int version = 0);
int8 GetZonePEQZone(uint32 zone_id, int version = 0);
int8 GetZoneExpansion(uint32 zone_id, int version = 0);
int8 GetZoneBypassExpansionCheck(uint32 zone_id, int version = 0);
uint8 GetZoneSuspendBuffs(uint32 zone_id, int version = 0);
int GetZoneRainChance(uint32 zone_id, uint8 slot = 0, int version = 0);
int GetZoneRainDuration(uint32 zone_id, uint8 slot = 0, int version = 0);
int GetZoneSnowChance(uint32 zone_id, uint8 slot = 0, int version = 0);
int GetZoneSnowDuration(uint32 zone_id, uint8 slot = 0, int version = 0);
float GetZoneGravity(uint32 zone_id, int version = 0);
int GetZoneType(uint32 zone_id, int version = 0);
int8 GetZoneSkyLock(uint32 zone_id, int version = 0);
int GetZoneFastRegenHP(uint32 zone_id, int version = 0);
int GetZoneFastRegenMana(uint32 zone_id, int version = 0);
int GetZoneFastRegenEndurance(uint32 zone_id, int version = 0);
int GetZoneNPCMaximumAggroDistance(uint32 zone_id, int version = 0);
uint32 GetZoneMaximumMovementUpdateRange(uint32 zone_id, int version = 0);
int8 GetZoneMinimumExpansion(uint32 zone_id, int version = 0);
int8 GetZoneMaximumExpansion(uint32 zone_id, int version = 0);
const std::string& GetZoneContentFlags(uint32 zone_id, int version = 0);
const std::string& GetZoneContentFlagsDisabled(uint32 zone_id, int version = 0);
int GetZoneUnderworldTeleportIndex(uint32 zone_id, int version = 0);
int GetZoneLavaDamage(uint32 zone_id, int version = 0);
int GetZoneMinimumLavaDamage(uint32 zone_id, int version = 0);
private: private:
std::vector<ZoneRepository::Zone> m_zones; std::vector<ZoneRepository::Zone> m_zones;
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "eqemu-server", "name": "eqemu-server",
"version": "22.11.0", "version": "22.13.1",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/EQEmu/Server.git" "url": "https://github.com/EQEmu/Server.git"
+1
View File
@@ -481,6 +481,7 @@
9225|2023_01_21_bots_raid_members.sql|SHOW COLUMNS FROM `raid_members` LIKE 'bot_id'|empty| 9225|2023_01_21_bots_raid_members.sql|SHOW COLUMNS FROM `raid_members` LIKE 'bot_id'|empty|
9226|2023_03_17_corpse_fields.sql|SHOW COLUMNS FROM `character_corpse_items` LIKE 'custom_data'|empty| 9226|2023_03_17_corpse_fields.sql|SHOW COLUMNS FROM `character_corpse_items` LIKE 'custom_data'|empty|
9227|2023_03_24_npc_scale_global_base_verify.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'heroic_strikethrough'|not_empty| 9227|2023_03_24_npc_scale_global_base_verify.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'heroic_strikethrough'|not_empty|
9228|2023_05_08_character_tribute_primary_key.sql|SHOW COLUMNS FROM `character_tribute` LIKE 'character_id'|empty|
# Upgrade conditions: # Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not # This won't be needed after this system is implemented, but it is used database that are not
@@ -0,0 +1,4 @@
ALTER TABLE `character_tribute`
CHANGE COLUMN `id` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
+5 -5
View File
@@ -361,7 +361,7 @@ void ConsoleTell(
auto join_args = args; auto join_args = args;
join_args.erase(join_args.begin(), join_args.begin() + 1); join_args.erase(join_args.begin(), join_args.begin() + 1);
zoneserver_list.SendChannelMessage(tmpname, to.c_str(), 7, 0, Strings::Join(join_args, " ").c_str()); zoneserver_list.SendChannelMessage(tmpname, to.c_str(), ChatChannel_Tell, 0, Strings::Join(join_args, " ").c_str());
} }
/** /**
@@ -382,7 +382,7 @@ void ConsoleBroadcast(
char tmpname[64]; char tmpname[64];
tmpname[0] = '*'; tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str()); strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, Strings::Join(args, " ").c_str()); zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_Broadcast, 0, Strings::Join(args, " ").c_str());
} }
/** /**
@@ -403,7 +403,7 @@ void ConsoleGMSay(
char tmpname[64]; char tmpname[64];
tmpname[0] = '*'; tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str()); strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, Strings::Join(args, " ").c_str()); zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_GMSAY, 0, Strings::Join(args, " ").c_str());
} }
/** /**
@@ -457,7 +457,7 @@ void ConsoleOOC(
char tmpname[64]; char tmpname[64];
tmpname[0] = '*'; tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str()); strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, Strings::Join(args, " ").c_str()); zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_OOC, 0, Strings::Join(args, " ").c_str());
} }
/** /**
@@ -478,7 +478,7 @@ void ConsoleAuction(
char tmpname[64]; char tmpname[64];
tmpname[0] = '*'; tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str()); strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, Strings::Join(args, " ").c_str()); zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_Auction, 0, Strings::Join(args, " ").c_str());
} }
/** /**
+1
View File
@@ -146,6 +146,7 @@ std::vector<Reload> reload_types = {
Reload{.command = "merchants", .opcode = ServerOP_ReloadMerchants, .desc = "Merchants"}, Reload{.command = "merchants", .opcode = ServerOP_ReloadMerchants, .desc = "Merchants"},
Reload{.command = "npc_emotes", .opcode = ServerOP_ReloadNPCEmotes, .desc = "NPC Emotes"}, Reload{.command = "npc_emotes", .opcode = ServerOP_ReloadNPCEmotes, .desc = "NPC Emotes"},
Reload{.command = "objects", .opcode = ServerOP_ReloadObjects, .desc = "Objects"}, Reload{.command = "objects", .opcode = ServerOP_ReloadObjects, .desc = "Objects"},
Reload{.command = "opcodes", .opcode = ServerOP_ReloadOpcodes, .desc = "Opcodes"},
Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"}, Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"},
Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"}, Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"},
Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"}, Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"},
+5
View File
@@ -45,6 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/content/world_content_service.h" #include "../common/content/world_content_service.h"
#include "../common/repositories/player_event_logs_repository.h" #include "../common/repositories/player_event_logs_repository.h"
#include "../common/events/player_event_logs.h" #include "../common/events/player_event_logs.h"
#include "../common/patches/patches.h"
extern ClientList client_list; extern ClientList client_list;
extern GroupLFPList LFPGroupList; extern GroupLFPList LFPGroupList;
@@ -1296,6 +1297,10 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
QSLink.SendPacket(pack); QSLink.SendPacket(pack);
break; break;
} }
case ServerOP_ReloadOpcodes: {
ReloadAllPatches();
break;
}
case ServerOP_CZDialogueWindow: case ServerOP_CZDialogueWindow:
case ServerOP_CZLDoNUpdate: case ServerOP_CZLDoNUpdate:
case ServerOP_CZMarquee: case ServerOP_CZMarquee:
-1
View File
@@ -228,7 +228,6 @@ SET(zone_headers
lua_stat_bonuses.h lua_stat_bonuses.h
map.h map.h
masterentity.h masterentity.h
message.h
merc.h merc.h
mob.h mob.h
mob_movement_manager.h mob_movement_manager.h
+2 -2
View File
@@ -1320,7 +1320,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
timer_duration = 0; timer_duration = 0;
} }
if (!IsCastWhileInvis(rank->spell)) if (!IsCastWhileInvisibleSpell(rank->spell))
CommonBreakInvisible(); CommonBreakInvisible();
if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) { if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) {
@@ -1333,7 +1333,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
target_id = GetPetID(); target_id = GetPetID();
// extra handling for cast_not_standing spells // extra handling for cast_not_standing spells
if (!IgnoreCastingRestriction(rank->spell)) { if (!IsCastNotStandingSpell(rank->spell)) {
if (GetAppearance() == eaSitting) // we need to stand! if (GetAppearance() == eaSitting) // we need to stand!
SetAppearance(eaStanding, false); SetAppearance(eaStanding, false);
-12
View File
@@ -21,18 +21,6 @@
#include "masterentity.h" #include "masterentity.h"
#include "aa_ability.h" #include "aa_ability.h"
AA::Rank *AA::Ability::GetMaxRank() {
if(!first)
return nullptr;
Rank *current = first;
while(current->next) {
current = current->next;
}
return current;
}
AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) { AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) {
if(current_level == 0) if(current_level == 0)
return nullptr; return nullptr;
-1
View File
@@ -37,7 +37,6 @@ public:
Ability() { } Ability() { }
~Ability() { } ~Ability() { }
Rank *GetMaxRank();
Rank *GetRankByPointsSpent(int current_level); Rank *GetRankByPointsSpent(int current_level);
int GetMaxLevel(Mob *who); int GetMaxLevel(Mob *who);
+1 -1
View File
@@ -1161,7 +1161,7 @@ bool Mob::CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarge
//offensive spell aggro //offensive spell aggro
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
{ {
if (NoDetrimentalSpellAggro(spell_id)) if (IsNoDetrimentalSpellAggroSpell(spell_id))
return 0; return 0;
int32 AggroAmount = 0; int32 AggroAmount = 0;
+15 -7
View File
@@ -160,7 +160,7 @@ int Mob::compute_tohit(EQ::skills::SkillType skillinuse)
if (IsNPC()) if (IsNPC())
tohit += CastToNPC()->GetAccuracyRating(); tohit += CastToNPC()->GetAccuracyRating();
if (IsClient()) { if (IsClient()) {
double reduction = CastToClient()->m_pp.intoxication / 2.0; double reduction = CastToClient()->GetIntoxication() / 2.0;
if (reduction > 20.0) { if (reduction > 20.0) {
reduction = std::min((110 - reduction) / 100.0, 1.0); reduction = std::min((110 - reduction) / 100.0, 1.0);
tohit = reduction * static_cast<double>(tohit); tohit = reduction * static_cast<double>(tohit);
@@ -256,7 +256,7 @@ int Mob::compute_defense()
defense += CastToNPC()->GetAvoidanceRating(); defense += CastToNPC()->GetAvoidanceRating();
if (IsClient()) { if (IsClient()) {
double reduction = CastToClient()->m_pp.intoxication / 2.0; double reduction = CastToClient()->GetIntoxication() / 2.0;
if (reduction > 20.0) { if (reduction > 20.0) {
reduction = std::min((110 - reduction) / 100.0, 1.0); reduction = std::min((110 - reduction) / 100.0, 1.0);
defense = reduction * static_cast<double>(defense); defense = reduction * static_cast<double>(defense);
@@ -2958,7 +2958,7 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient())
return; return;
if (IsValidSpell(spell_id) && NoDetrimentalSpellAggro(spell_id)) if (IsValidSpell(spell_id) && IsNoDetrimentalSpellAggroSpell(spell_id))
return; return;
if (other == myowner) if (other == myowner)
@@ -4447,11 +4447,19 @@ void Mob::HealDamage(uint64 amount, Mob* caster, uint16 spell_id)
} }
} }
else { // normal heals else { // normal heals
FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage, // Message to caster
YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); if (caster->IsClient()) {
caster->FilteredMessageString(caster, Chat::NonMelee,
FilterSpellDamage, YOU_HEAL, GetCleanName(),
itoa(acthealed));
}
caster->FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage, // Message to target
YOU_HEAL, GetCleanName(), itoa(acthealed)); if (IsClient() && caster != this) {
FilteredMessageString(caster, Chat::NonMelee,
FilterSpellDamage, YOU_HEALED, caster->GetCleanName(),
itoa(acthealed));
}
} }
} else if ( } else if (
CastToClient()->GetFilter(FilterHealOverTime) != FilterShowSelfOnly || CastToClient()->GetFilter(FilterHealOverTime) != FilterShowSelfOnly ||
+9 -20
View File
@@ -146,18 +146,7 @@ void Mob::CalcItemBonuses(StatBonuses* b) {
int16 i; int16 i;
for (i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_SKILL_END; i++) { for (i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_SKILL_END; i++) {
const EQ::ItemInstance* inst = nullptr; const EQ::ItemInstance* inst = GetInv().GetItem(i);
if (IsOfClientBotMerc()) {
inst = GetInv().GetItem(i);
} else {
const auto* item = CastToNPC()->GetItem(i);
if (!item) {
continue;
}
inst = database.CreateItem(item->item_id);
}
if (!inst) { if (!inst) {
continue; continue;
} }
@@ -5959,26 +5948,26 @@ void Mob::CalcHeroicBonuses(StatBonuses* newbon)
void Mob::SetHeroicWisBonuses(StatBonuses* n) void Mob::SetHeroicWisBonuses(StatBonuses* n)
{ {
n->heroic_max_mana += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) * 10 : 0; n->heroic_max_mana += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) * 10 : 0;
n->heroic_mana_regen += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 : 0; n->heroic_mana_regen += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 : 0;
n->HealAmt += GetHeroicWIS() * RuleR(Character, HeroicWisdomIncreaseHealAmtMultiplier); n->HealAmt += GetHeroicWIS() * RuleR(Character, HeroicWisdomIncreaseHealAmtMultiplier);
if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) { if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) {
n->heroic_max_mana += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisMaxMana) * 10 : 0; n->heroic_max_mana += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisMaxMana) * 10 : 0;
n->heroic_mana_regen += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisManaRegen) / 25 : 0; n->heroic_mana_regen += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisManaRegen) / 25 : 0;
n->HealAmt += GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisHealAmt); n->HealAmt += GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisHealAmt);
} }
} }
void Mob::SetHeroicIntBonuses(StatBonuses* n) void Mob::SetHeroicIntBonuses(StatBonuses* n)
{ {
n->heroic_max_mana += IsINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10 : 0; n->heroic_max_mana += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10 : 0;
n->heroic_mana_regen += IsINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25 : 0; n->heroic_mana_regen += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25 : 0;
n->SpellDmg += GetHeroicINT() * RuleR(Character, HeroicIntelligenceIncreaseSpellDmgMultiplier); n->SpellDmg += GetHeroicINT() * RuleR(Character, HeroicIntelligenceIncreaseSpellDmgMultiplier);
if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) { if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) {
n->heroic_max_mana += IsINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntMaxMana) * 10 : 0; n->heroic_max_mana += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntMaxMana) * 10 : 0;
n->heroic_mana_regen += IsINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntManaRegen) / 25 : 0; n->heroic_mana_regen += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntManaRegen) / 25 : 0;
n->SpellDmg += GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntSpellDmg); n->SpellDmg += GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntSpellDmg);
} }
} }
+4 -4
View File
@@ -259,7 +259,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
const SPDat_Spell_Struct& spell = spells[buffs[j1].spellid]; const SPDat_Spell_Struct& spell = spells[buffs[j1].spellid];
if (int NimbusEffect = GetNimbusEffect(buffs[j1].spellid); NimbusEffect && !IsNimbusEffectActive(NimbusEffect)) { if (int NimbusEffect = GetSpellNimbusEffect(buffs[j1].spellid); NimbusEffect && !IsNimbusEffectActive(NimbusEffect)) {
SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true); SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true);
} }
@@ -4890,7 +4890,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max
if (botweapon->ItemType == EQ::item::ItemTypeShield) if (botweapon->ItemType == EQ::item::ItemTypeShield)
hate += botweapon->AC; hate += botweapon->AC;
hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); hate = (hate * (100 + GetSpellFuriousBash(botweapon->Focus.Effect)) / 100);
} }
} }
@@ -5536,7 +5536,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) {
increase += 20; increase += 20;
} }
if (IsMezSpell(spell_id)) if (IsMesmerizeSpell(spell_id))
tic_inc += GetAA(aaMesmerizationMastery); tic_inc += GetAA(aaMesmerizationMastery);
return (((duration * increase) / 100) + tic_inc); return (((duration * increase) / 100) + tic_inc);
@@ -6326,7 +6326,7 @@ void Bot::CalcRestState() {
for (unsigned int j = 0; j < buff_count; j++) { for (unsigned int j = 0; j < buff_count; j++) {
if (IsValidSpell(buffs[j].spellid)) { if (IsValidSpell(buffs[j].spellid)) {
if (IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0)) if (IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
if (!DetrimentalSpellAllowsRest(buffs[j].spellid)) if (!IsRestAllowedSpell(buffs[j].spellid))
return; return;
} }
} }
+10 -10
View File
@@ -110,7 +110,7 @@ bool Bot::BotCastSong(Mob* tar, uint8 botLevel) {
continue; continue;
if (!CheckSpellRecastTimers(this, iter.SpellIndex)) if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue; continue;
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue; continue;
switch (spells[iter.SpellId].target_type) { switch (spells[iter.SpellId].target_type) {
case ST_AEBard: case ST_AEBard:
@@ -144,7 +144,7 @@ bool Bot::BotCastCombatSong(Mob* tar, uint8 botLevel) {
continue; continue;
if (!CheckSpellRecastTimers(this, iter.SpellIndex)) if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue; continue;
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue; continue;
switch (spells[iter.SpellId].target_type) { switch (spells[iter.SpellId].target_type) {
case ST_AEBard: case ST_AEBard:
@@ -176,7 +176,7 @@ bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpel
continue; continue;
if (!CheckSpellRecastTimers(this, iter.SpellIndex)) if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue; continue;
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue; continue;
if (spells[iter.SpellId].target_type != ST_Target) if (spells[iter.SpellId].target_type != ST_Target)
continue; continue;
@@ -316,7 +316,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
continue; continue;
} }
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) { if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType())) {
continue; continue;
} }
@@ -582,7 +582,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
if ( if (
((IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) || ((IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) && (IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) &&
(botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType())) (botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
) { ) {
continue; continue;
} }
@@ -892,7 +892,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
(IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) || (IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor()) (IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())
) && ) &&
(botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType())) (botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
) { ) {
continue; continue;
} }
@@ -1902,7 +1902,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEff
continue; continue;
} }
if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) { if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetSpellTriggerSpellID(botSpellList[i].spellid, spellEffect)) {
BotSpell botSpell; BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i; botSpell.SpellIndex = i;
@@ -1940,7 +1940,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
if ( if (
( (
IsEffectInSpell(botSpellList[i].spellid, spellEffect) || IsEffectInSpell(botSpellList[i].spellid, spellEffect) ||
GetTriggerSpellID(botSpellList[i].spellid, spellEffect) GetSpellTriggerSpellID(botSpellList[i].spellid, spellEffect)
) && ) &&
spells[botSpellList[i].spellid].target_type == targetType spells[botSpellList[i].spellid].target_type == targetType
) { ) {
@@ -2313,7 +2313,7 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* botCaster) {
for (std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { for (std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if ( if (
IsMezSpell(botSpellListItr->SpellId) && IsMesmerizeSpell(botSpellListItr->SpellId) &&
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
@@ -2388,7 +2388,7 @@ BotSpell Bot::GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster) {
Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) { Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) {
Mob* result = 0; Mob* result = 0;
if (botCaster && IsMezSpell(botSpell.SpellId)) { if (botCaster && IsMesmerizeSpell(botSpell.SpellId)) {
std::list<NPC*> npc_list; std::list<NPC*> npc_list;
entity_list.GetNPCList(npc_list); entity_list.GetNPCList(npc_list);
+76 -14
View File
@@ -656,10 +656,10 @@ bool Client::Save(uint8 iCommitNow) {
/* Save Character Currency */ /* Save Character Currency */
database.SaveCharacterCurrency(CharacterID(), &m_pp); database.SaveCharacterCurrency(CharacterID(), &m_pp);
/* Save Current Bind Points */ // save character binds
for (int i = 0; i < 5; i++) // this may not need to be called in Save() but it's here for now
if (m_pp.binds[i].zone_id) // to maintain the current behavior
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i); database.SaveCharacterBinds(this);
/* Save Character Buffs */ /* Save Character Buffs */
database.SaveBuffs(this); database.SaveBuffs(this);
@@ -713,7 +713,7 @@ bool Client::Save(uint8 iCommitNow) {
p_timers.Store(&database); p_timers.Store(&database);
database.SaveCharacterTribute(CharacterID(), &m_pp); database.SaveCharacterTribute(this);
SaveTaskState(); /* Save Character Task */ SaveTaskState(); /* Save Character Task */
LogFood("Client::Save - hunger_level: [{}] thirst_level: [{}]", m_pp.hunger_level, m_pp.thirst_level); LogFood("Client::Save - hunger_level: [{}] thirst_level: [{}]", m_pp.hunger_level, m_pp.thirst_level);
@@ -908,8 +908,8 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
} }
// Garble the message based on drunkness // Garble the message based on drunkness
if (m_pp.intoxication > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) { if (GetIntoxication() > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) {
GarbleMessage(message, (int)(m_pp.intoxication / 3)); GarbleMessage(message, (int)(GetIntoxication() / 3));
language = 0; // No need for language when drunk language = 0; // No need for language when drunk
lang_skill = 100; lang_skill = 100;
} }
@@ -1062,7 +1062,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
if(!global_channel_timer.Check()) if(!global_channel_timer.Check())
{ {
if(strlen(targetname) == 0) if(strlen(targetname) == 0)
ChannelMessageReceived(7, language, lang_skill, message, "discard"); //Fast typer or spammer?? ChannelMessageReceived(ChatChannel_Tell, language, lang_skill, message, "discard"); //Fast typer or spammer??
else else
return; return;
} }
@@ -2783,18 +2783,64 @@ void Client::GMKill() {
safe_delete(outapp); safe_delete(outapp);
} }
void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing, uint32 reduction){ void Client::MemorizeSpell(uint32 slot, uint32 spell_id, uint32 scribing, uint32 reduction){
if (slot < 0 || slot >= EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize) if (
!EQ::ValueWithin(
slot,
0,
(EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize - 1)
)
) {
return; return;
if ((spellid < 3 || spellid > EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellIdMax) && spellid != 0xFFFFFFFF) }
if (
!EQ::ValueWithin(
spell_id,
3,
EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellIdMax
) &&
spell_id != UINT32_MAX
) {
return; return;
}
auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct)); auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct));
MemorizeSpell_Struct* mss=(MemorizeSpell_Struct*)outapp->pBuffer;
auto* mss = (MemorizeSpell_Struct*) outapp->pBuffer;
mss->scribing = scribing; mss->scribing = scribing;
mss->slot = slot; mss->slot = slot;
mss->spell_id=spellid; mss->spell_id = spell_id;
mss->reduction = reduction; mss->reduction = reduction;
outapp->priority = 5; outapp->priority = 5;
if (
parse->PlayerHasQuestSub(EVENT_SCRIBE_SPELL) ||
parse->PlayerHasQuestSub(EVENT_MEMORIZE_SPELL) ||
parse->PlayerHasQuestSub(EVENT_UNMEMORIZE_SPELL)
) {
const auto export_string = fmt::format("{} {}", slot, spell_id);
if (
scribing == ScribeSpellActions::Memorize &&
parse->PlayerHasQuestSub(EVENT_MEMORIZE_SPELL)
) {
parse->EventPlayer(EVENT_MEMORIZE_SPELL, this, export_string, 0);
} else if (
scribing == ScribeSpellActions::Unmemorize &&
parse->PlayerHasQuestSub(EVENT_UNMEMORIZE_SPELL)
) {
parse->EventPlayer(EVENT_UNMEMORIZE_SPELL, this, export_string, 0);
} else if (
scribing == ScribeSpellActions::Scribe &&
parse->PlayerHasQuestSub(EVENT_SCRIBE_SPELL)
) {
parse->EventPlayer(EVENT_SCRIBE_SPELL, this, export_string, 0);
}
}
QueuePacket(outapp); QueuePacket(outapp);
safe_delete(outapp); safe_delete(outapp);
} }
@@ -8340,6 +8386,11 @@ void Client::SetThirst(int32 in_thirst)
safe_delete(outapp); safe_delete(outapp);
} }
void Client::SetIntoxication(int32 in_intoxication)
{
m_pp.intoxication = EQ::Clamp(in_intoxication, 0, 200);
}
void Client::SetConsumption(int32 in_hunger, int32 in_thirst) void Client::SetConsumption(int32 in_hunger, int32 in_thirst)
{ {
EQApplicationPacket *outapp = nullptr; EQApplicationPacket *outapp = nullptr;
@@ -9425,6 +9476,7 @@ void Client::ShowDevToolsMenu()
menu_reload_five += Saylink::Silent("#reload merchants", "Merchants"); menu_reload_five += Saylink::Silent("#reload merchants", "Merchants");
menu_reload_five += " | " + Saylink::Silent("#reload npc_emotes", "NPC Emotes"); menu_reload_five += " | " + Saylink::Silent("#reload npc_emotes", "NPC Emotes");
menu_reload_five += " | " + Saylink::Silent("#reload objects", "Objects"); menu_reload_five += " | " + Saylink::Silent("#reload objects", "Objects");
menu_reload_five += " | " + Saylink::Silent("#reload opcodes", "Opcodes");
menu_reload_six += Saylink::Silent("#reload perl_export", "Perl Event Export Settings"); menu_reload_six += Saylink::Silent("#reload perl_export", "Perl Event Export Settings");
menu_reload_six += " | " + Saylink::Silent("#reload quest", "Quests"); menu_reload_six += " | " + Saylink::Silent("#reload quest", "Quests");
@@ -11233,7 +11285,7 @@ void Client::ReconnectUCS()
{ {
EQApplicationPacket *outapp = nullptr; EQApplicationPacket *outapp = nullptr;
std::string buffer; std::string buffer;
std::string mail_key = database.GetMailKey(CharacterID(), true); std::string mail_key = m_mail_key;
EQ::versions::UCSVersion connection_type = EQ::versions::ucsUnknown; EQ::versions::UCSVersion connection_type = EQ::versions::ucsUnknown;
// chat server packet // chat server packet
@@ -11432,6 +11484,16 @@ void Client::SendReloadCommandMessages() {
).c_str() ).c_str()
); );
auto opcodes_link = Saylink::Silent("#reload opcodes");
Message(
Chat::White,
fmt::format(
"Usage: {} - Reloads Opcodes globally",
opcodes_link
).c_str()
);
auto perl_export_link = Saylink::Silent("#reload perl_export"); auto perl_export_link = Saylink::Silent("#reload perl_export");
Message( Message(
+14 -3
View File
@@ -67,6 +67,7 @@ namespace EQ
#include "task_client_state.h" #include "task_client_state.h"
#include "cheat_manager.h" #include "cheat_manager.h"
#include "../common/events/player_events.h" #include "../common/events/player_events.h"
#include "../common/data_verification.h"
#ifdef _WINDOWS #ifdef _WINDOWS
// since windows defines these within windef.h (which windows.h include) // since windows defines these within windef.h (which windows.h include)
@@ -306,7 +307,6 @@ public:
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0); void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0);
void TradeRequestFailed(const EQApplicationPacket* app); void TradeRequestFailed(const EQApplicationPacket* app);
void BuyTraderItem(TraderBuy_Struct* tbs,Client* trader,const EQApplicationPacket* app); void BuyTraderItem(TraderBuy_Struct* tbs,Client* trader,const EQApplicationPacket* app);
void TraderUpdate(uint16 slot_id,uint32 trader_id);
void FinishTrade(Mob* with, bool finalizer = false, void* event_entry = nullptr, std::list<void*>* event_details = nullptr); void FinishTrade(Mob* with, bool finalizer = false, void* event_entry = nullptr, std::list<void*>* event_details = nullptr);
void SendZonePoints(); void SendZonePoints();
@@ -932,7 +932,7 @@ public:
inline uint32 GetAAPercent() const { return m_epp.perAA; } inline uint32 GetAAPercent() const { return m_epp.perAA; }
void SetAATitle(std::string title); void SetAATitle(std::string title);
void SetTitleSuffix(std::string suffix); void SetTitleSuffix(std::string suffix);
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing, uint32 reduction = 0); void MemorizeSpell(uint32 slot, uint32 spell_id, uint32 scribing, uint32 reduction = 0);
// Item methods // Item methods
void UseAugmentContainer(int container_slot); void UseAugmentContainer(int container_slot);
@@ -966,6 +966,8 @@ public:
void DropItem(int16 slot_id, bool recurse = true); void DropItem(int16 slot_id, bool recurse = true);
void DropItemQS(EQ::ItemInstance* inst, bool pickup); void DropItemQS(EQ::ItemInstance* inst, bool pickup);
bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction);
int GetItemLinkHash(const EQ::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field int GetItemLinkHash(const EQ::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field
void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false); void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false);
@@ -993,6 +995,7 @@ public:
void SetThirst(int32 in_thirst); void SetThirst(int32 in_thirst);
void SetConsumption(int32 in_hunger, int32 in_thirst); void SetConsumption(int32 in_hunger, int32 in_thirst);
bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; } bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; }
int32 GetIntoxication() const { return m_pp.intoxication; }
bool CheckTradeLoreConflict(Client* other); bool CheckTradeLoreConflict(Client* other);
bool CheckTradeNonDroppable(); bool CheckTradeNonDroppable();
@@ -1582,6 +1585,7 @@ public:
void SetEnvironmentDamageModifier(int32 val) { environment_damage_modifier = val; } void SetEnvironmentDamageModifier(int32 val) { environment_damage_modifier = val; }
inline bool GetInvulnerableEnvironmentDamage() const { return invulnerable_environment_damage; } inline bool GetInvulnerableEnvironmentDamage() const { return invulnerable_environment_damage; }
void SetInvulnerableEnvironmentDamage(bool val) { invulnerable_environment_damage = val; } void SetInvulnerableEnvironmentDamage(bool val) { invulnerable_environment_damage = val; }
void SetIntoxication(int32 in_intoxication);
void ShowNumHits(); // work around function for numhits not showing on buffs void ShowNumHits(); // work around function for numhits not showing on buffs
@@ -1637,6 +1641,7 @@ public:
PlayerEvent::PlayerEvent GetPlayerEvent(); PlayerEvent::PlayerEvent GetPlayerEvent();
void RecordKilledNPCEvent(NPC *n); void RecordKilledNPCEvent(NPC *n);
uint32 GetEXPForLevel(uint16 check_level);
protected: protected:
friend class Mob; friend class Mob;
void CalcEdibleBonuses(StatBonuses* newbon); void CalcEdibleBonuses(StatBonuses* newbon);
@@ -1812,7 +1817,6 @@ private:
bool temp_pvp; bool temp_pvp;
void NPCSpawn(const Seperator* sep); void NPCSpawn(const Seperator* sep);
uint32 GetEXPForLevel(uint16 level);
void SendLogoutPackets(); void SendLogoutPackets();
void SendZoneInPackets(); void SendZoneInPackets();
@@ -2033,6 +2037,13 @@ private:
bool CanTradeFVNoDropItem(); bool CanTradeFVNoDropItem();
void SendMobPositions(); void SendMobPositions();
void PlayerTradeEventLog(Trade *t, Trade *t2); void PlayerTradeEventLog(Trade *t, Trade *t2);
// full and partial mail key cache
std::string m_mail_key_full;
std::string m_mail_key;
public:
const std::string &GetMailKeyFull() const;
const std::string &GetMailKey() const;
}; };
#endif #endif
+6 -6
View File
@@ -797,10 +797,10 @@ uint32 Client::CalcCurrentWeight()
int32 Client::CalcAlcoholPhysicalEffect() int32 Client::CalcAlcoholPhysicalEffect()
{ {
if (m_pp.intoxication <= 55) { if (GetIntoxication() <= 55) {
return 0; return 0;
} }
return (m_pp.intoxication - 40) / 16; return (GetIntoxication() - 40) / 16;
} }
int32 Client::CalcSTR() int32 Client::CalcSTR()
@@ -878,8 +878,8 @@ int32 Client::CalcINT()
int32 val = m_pp.INT + itembonuses.INT + spellbonuses.INT; int32 val = m_pp.INT + itembonuses.INT + spellbonuses.INT;
int32 mod = aabonuses.INT; int32 mod = aabonuses.INT;
INT = val + mod; INT = val + mod;
if (m_pp.intoxication) { if (GetIntoxication()) {
int32 AlcINT = INT - (int32)((float)m_pp.intoxication / 200.0f * (float)INT) - 1; int32 AlcINT = INT - (int32)((float)GetIntoxication() / 200.0f * (float)INT) - 1;
if ((AlcINT < (int)(0.2 * INT))) { if ((AlcINT < (int)(0.2 * INT))) {
INT = (int)(0.2f * (float)INT); INT = (int)(0.2f * (float)INT);
} }
@@ -902,8 +902,8 @@ int32 Client::CalcWIS()
int32 val = m_pp.WIS + itembonuses.WIS + spellbonuses.WIS; int32 val = m_pp.WIS + itembonuses.WIS + spellbonuses.WIS;
int32 mod = aabonuses.WIS; int32 mod = aabonuses.WIS;
WIS = val + mod; WIS = val + mod;
if (m_pp.intoxication) { if (GetIntoxication()) {
int32 AlcWIS = WIS - (int32)((float)m_pp.intoxication / 200.0f * (float)WIS) - 1; int32 AlcWIS = WIS - (int32)((float)GetIntoxication() / 200.0f * (float)WIS) - 1;
if ((AlcWIS < (int)(0.2 * WIS))) { if ((AlcWIS < (int)(0.2 * WIS))) {
WIS = (int)(0.2f * (float)WIS); WIS = (int)(0.2f * (float)WIS);
} }
+36 -30
View File
@@ -656,7 +656,7 @@ void Client::CompleteConnect()
const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid]; const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid];
int NimbusEffect = GetNimbusEffect(buffs[j1].spellid); int NimbusEffect = GetSpellNimbusEffect(buffs[j1].spellid);
if (NimbusEffect) { if (NimbusEffect) {
if (!IsNimbusEffectActive(NimbusEffect)) if (!IsNimbusEffectActive(NimbusEffect))
SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true); SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true);
@@ -721,17 +721,17 @@ void Client::CompleteConnect()
case SE_AddMeleeProc: case SE_AddMeleeProc:
case SE_WeaponProc: case SE_WeaponProc:
{ {
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC)); AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
break; break;
} }
case SE_DefensiveProc: case SE_DefensiveProc:
{ {
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC)); AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
break; break;
} }
case SE_RangedProc: case SE_RangedProc:
{ {
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC)); AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
break; break;
} }
} }
@@ -1265,7 +1265,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */ database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */ database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */
database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */ database.LoadCharacterTribute(this); /* Load CharacterTribute */
// this pattern is strange
// this is remnants of the old way of doing things
auto mail_keys = database.GetMailKey(CharacterID());
m_mail_key_full = mail_keys.mail_key_full;
m_mail_key = mail_keys.mail_key;
/* Load AdventureStats */ /* Load AdventureStats */
AdventureStats_Struct as; AdventureStats_Struct as;
@@ -1309,7 +1315,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/* If we can maintain intoxication across zones, check for it */ /* If we can maintain intoxication across zones, check for it */
if (!RuleB(Character, MaintainIntoxicationAcrossZones)) if (!RuleB(Character, MaintainIntoxicationAcrossZones))
m_pp.intoxication = 0; SetIntoxication(0);
strcpy(name, m_pp.name); strcpy(name, m_pp.name);
strcpy(lastname, m_pp.last_name); strcpy(lastname, m_pp.last_name);
@@ -1508,8 +1514,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
} }
if (group) { if (group) {
// If the group leader is not set, pull the group leader infomrmation from the database.
if (!group->GetLeader()) {
char ln[64]; char ln[64];
char MainTankName[64]; char MainTankName[64];
char AssistName[64]; char AssistName[64];
@@ -1520,9 +1524,14 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
GroupLeadershipAA_Struct GLAA; GroupLeadershipAA_Struct GLAA;
memset(ln, 0, 64); memset(ln, 0, 64);
database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA); database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA);
group->LearnMembers();
if (!group->GetLeader()) {
Client *c = entity_list.GetClientByName(ln); Client *c = entity_list.GetClientByName(ln);
if (c) if (c) {
group->SetLeader(c); group->SetLeader(c);
}
}
group->SetMainTank(MainTankName); group->SetMainTank(MainTankName);
group->SetMainAssist(AssistName); group->SetMainAssist(AssistName);
@@ -1530,8 +1539,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
group->SetNPCMarker(NPCMarkerName); group->SetNPCMarker(NPCMarkerName);
group->SetGroupAAs(&GLAA); group->SetGroupAAs(&GLAA);
group->SetGroupMentor(mentor_percent, mentoree_name); group->SetGroupMentor(mentor_percent, mentoree_name);
}
group->LearnMembers();
JoinGroupXTargets(group); JoinGroupXTargets(group);
group->UpdatePlayer(this); group->UpdatePlayer(this);
LFG = false; LFG = false;
@@ -5568,10 +5575,8 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app)
if (IntoxicationIncrease < 0) if (IntoxicationIncrease < 0)
IntoxicationIncrease = 1; IntoxicationIncrease = 1;
m_pp.intoxication += IntoxicationIncrease; SetIntoxication(GetIntoxication()+IntoxicationIncrease);
if (m_pp.intoxication > 200)
m_pp.intoxication = 200;
} }
DeleteItemInInventory(alc->from_slot, 1); DeleteItemInInventory(alc->from_slot, 1);
@@ -6466,26 +6471,27 @@ void Client::Handle_OP_GMFind(const EQApplicationPacket *app)
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"});
return; return;
} }
if (app->size != sizeof(GMSummon_Struct)) {
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMSummon_Struct)); if (app->size != sizeof(GMFind_Struct)) {
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMFind_Struct));
return; return;
} }
//Break down incoming //Break down incoming
GMSummon_Struct* request = (GMSummon_Struct*)app->pBuffer; auto* request = (GMFind_Struct*) app->pBuffer;
//Create a new outgoing //Create a new outgoing
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMSummon_Struct)); auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMFind_Struct));
GMSummon_Struct* foundplayer = (GMSummon_Struct*)outapp->pBuffer; auto* foundplayer = (GMFind_Struct*) outapp->pBuffer;
//Copy the constants //Copy the constants
strcpy(foundplayer->charname, request->charname); strcpy(foundplayer->charname, request->charname);
strcpy(foundplayer->gmname, request->gmname); strcpy(foundplayer->gmname, request->gmname);
//Check if the NPC exits intrazone... //Check if the NPC exits intrazone...
Mob* gt = entity_list.GetMob(request->charname); auto* gt = entity_list.GetMob(request->charname);
if (gt != 0) { if (gt) {
foundplayer->success = 1; foundplayer->success = 1;
foundplayer->x = (int32)gt->GetX(); foundplayer->x = gt->GetX();
foundplayer->y = (int32)gt->GetY(); foundplayer->y = gt->GetY();
foundplayer->z = gt->GetZ();
foundplayer->z = (int32)gt->GetZ();
foundplayer->zoneID = zone->GetZoneID(); foundplayer->zoneID = zone->GetZoneID();
} }
//Send the packet... //Send the packet...
@@ -9227,7 +9233,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
return; return;
} }
if (i == 0) { if (i == 0) {
if (!IsCastWhileInvis(item->Click.Effect)) { if (!IsCastWhileInvisibleSpell(item->Click.Effect)) {
CommonBreakInvisible(); // client can't do this for us :( CommonBreakInvisible(); // client can't do this for us :(
} }
if (GetClass() == BARD){ if (GetClass() == BARD){
@@ -9299,7 +9305,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
} }
if (i == 0) { if (i == 0) {
if (!IsCastWhileInvis(augitem->Click.Effect)) { if (!IsCastWhileInvisibleSpell(augitem->Click.Effect)) {
CommonBreakInvisible(); // client can't do this for us :( CommonBreakInvisible(); // client can't do this for us :(
} }
if (GetClass() == BARD) { if (GetClass() == BARD) {
@@ -11464,7 +11470,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY)) { if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY)) {
response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY); response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY);
if (!response.empty()) { if (!response.empty()) {
ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true); ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
} }
} }
break; break;
@@ -11473,7 +11479,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY)) { if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY)) {
response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY); response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY);
if (!response.empty()) { if (!response.empty()) {
ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true); ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
} }
} }
break; break;
@@ -11679,7 +11685,7 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app)
EQApplicationPacket* outapp = nullptr; EQApplicationPacket* outapp = nullptr;
std::string buffer; std::string buffer;
std::string MailKey = database.GetMailKey(CharacterID(), true); std::string MailKey = GetMailKey();
EQ::versions::UCSVersion ConnectionType = EQ::versions::ucsUnknown; EQ::versions::UCSVersion ConnectionType = EQ::versions::ucsUnknown;
// chat server packet // chat server packet
+4 -4
View File
@@ -518,9 +518,9 @@ bool Client::Process() {
Save(0); Save(0);
} }
if (m_pp.intoxication > 0) if (GetIntoxication() > 0)
{ {
--m_pp.intoxication; SetIntoxication(GetIntoxication()-1);
CalcBonuses(); CalcBonuses();
} }
@@ -1035,7 +1035,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
BuffFadeNonPersistDeath(); BuffFadeNonPersistDeath();
} }
int SpellEffectDescNum = GetSpellEffectDescNum(SpellID); int SpellEffectDescNum = GetSpellEffectDescriptionNumber(SpellID);
// Rez spells with Rez effects have this DescNum (first is Titanium, second is 6.2 Client) // Rez spells with Rez effects have this DescNum (first is Titanium, second is 6.2 Client)
if(RuleB(Character, UseResurrectionSickness) && SpellEffectDescNum == 82 || SpellEffectDescNum == 39067) { if(RuleB(Character, UseResurrectionSickness) && SpellEffectDescNum == 82 || SpellEffectDescNum == 39067) {
SetHP(GetMaxHP() / 5); SetHP(GetMaxHP() / 5);
@@ -1968,7 +1968,7 @@ void Client::CalcRestState()
for (unsigned int j = 0; j < buff_count; j++) { for (unsigned int j = 0; j < buff_count; j++) {
if(IsValidSpell(buffs[j].spellid)) { if(IsValidSpell(buffs[j].spellid)) {
if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0)) if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
if(!DetrimentalSpellAllowsRest(buffs[j].spellid)) if(!IsRestAllowedSpell(buffs[j].spellid))
return; return;
} }
} }
-10
View File
@@ -71,13 +71,3 @@ float CombatRecord::GetHealedReceivedPerSecond() const
double time_in_combat = TimeInCombat(); double time_in_combat = TimeInCombat();
return time_in_combat > 0 ? (m_heal_received / time_in_combat) : m_heal_received; return time_in_combat > 0 ? (m_heal_received / time_in_combat) : m_heal_received;
} }
int64 CombatRecord::GetDamageReceived() const
{
return m_damage_received;
}
int64 CombatRecord::GetHealReceived() const
{
return m_heal_received;
}
-2
View File
@@ -12,8 +12,6 @@ public:
bool InCombat() const; bool InCombat() const;
void ProcessHPEvent(int64 hp, int64 current_hp); void ProcessHPEvent(int64 hp, int64 current_hp);
double TimeInCombat() const; double TimeInCombat() const;
int64 GetDamageReceived() const;
int64 GetHealReceived() const;
float GetDamageReceivedPerSecond() const; float GetDamageReceivedPerSecond() const;
float GetHealedReceivedPerSecond() const; float GetHealedReceivedPerSecond() const;
private: private:
+5 -2
View File
@@ -131,6 +131,7 @@ int command_init(void)
command_add("emptyinventory", "Clears your or your target's entire inventory (Equipment, General, Bank, and Shared Bank)", AccountStatus::GMImpossible, command_emptyinventory) || command_add("emptyinventory", "Clears your or your target's entire inventory (Equipment, General, Bank, and Shared Bank)", AccountStatus::GMImpossible, command_emptyinventory) ||
command_add("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) || command_add("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) ||
command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) || command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) ||
command_add("entityvariable", "[clear|delete|set|view] - Modify entity variables for yourself or your target", AccountStatus::GMAdmin, command_entityvariable) ||
command_add("exptoggle", "[Toggle] - Toggle your or your target's experience gain.", AccountStatus::QuestTroupe, command_exptoggle) || command_add("exptoggle", "[Toggle] - Toggle your or your target's experience gain.", AccountStatus::QuestTroupe, command_exptoggle) ||
command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) || command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) ||
command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) || command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) ||
@@ -140,6 +141,7 @@ int command_init(void)
command_add("findaliases", "[Search Criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) || command_add("findaliases", "[Search Criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) ||
command_add("findcharacter", "[Search Criteria] - Search for a character", AccountStatus::Guide, command_findcharacter) || command_add("findcharacter", "[Search Criteria] - Search for a character", AccountStatus::Guide, command_findcharacter) ||
command_add("findclass", "[Search Criteria] - Search for a class", AccountStatus::Guide, command_findclass) || command_add("findclass", "[Search Criteria] - Search for a class", AccountStatus::Guide, command_findclass) ||
command_add("findcurrency", "[Search Criteria] - Search for an alternate currency", AccountStatus::Guide, command_findcurrency) ||
command_add("findfaction", "[Search Criteria] - Search for a faction", AccountStatus::Guide, command_findfaction) || command_add("findfaction", "[Search Criteria] - Search for a faction", AccountStatus::Guide, command_findfaction) ||
command_add("findnpctype", "[Search Criteria] - Search database NPC types", AccountStatus::GMAdmin, command_findnpctype) || command_add("findnpctype", "[Search Criteria] - Search database NPC types", AccountStatus::GMAdmin, command_findnpctype) ||
command_add("findrace", "[Search Criteria] - Search for a race", AccountStatus::Guide, command_findrace) || command_add("findrace", "[Search Criteria] - Search for a race", AccountStatus::Guide, command_findrace) ||
@@ -230,7 +232,7 @@ int command_init(void)
command_add("nukeitem", "[Item ID] - Removes the specified Item ID from you or your player target's inventory", AccountStatus::GMLeadAdmin, command_nukeitem) || command_add("nukeitem", "[Item ID] - Removes the specified Item ID from you or your player target's inventory", AccountStatus::GMLeadAdmin, command_nukeitem) ||
command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", AccountStatus::GMAdmin, command_object) || command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", AccountStatus::GMAdmin, command_object) ||
command_add("oocmute", "[0|1] - Enable or Disable Server OOC", AccountStatus::GMMgmt, command_oocmute) || command_add("oocmute", "[0|1] - Enable or Disable Server OOC", AccountStatus::GMMgmt, command_oocmute) ||
command_add("opcode", "Reloads all server patches", AccountStatus::GMImpossible, command_opcode) || command_add("opcode", "Reloads all opcodes from server patch files", AccountStatus::GMMgmt, command_reload) ||
command_add("path", "view and edit pathing", AccountStatus::GMMgmt, command_path) || command_add("path", "view and edit pathing", AccountStatus::GMMgmt, command_path) ||
command_add("peekinv", "[equip/gen/cursor/poss/limbo/curlim/trib/bank/shbank/allbank/trade/world/all] - Print out contents of your player target's inventory", AccountStatus::GMAdmin, command_peekinv) || command_add("peekinv", "[equip/gen/cursor/poss/limbo/curlim/trib/bank/shbank/allbank/trade/world/all] - Print out contents of your player target's inventory", AccountStatus::GMAdmin, command_peekinv) ||
command_add("peqzone", "[Zone ID|Zone Short Name] - Teleports you to the specified zone if you meet the requirements.", AccountStatus::Player, command_peqzone) || command_add("peqzone", "[Zone ID|Zone Short Name] - Teleports you to the specified zone if you meet the requirements.", AccountStatus::Player, command_peqzone) ||
@@ -976,12 +978,14 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/emptyinventory.cpp" #include "gm_commands/emptyinventory.cpp"
#include "gm_commands/enablerecipe.cpp" #include "gm_commands/enablerecipe.cpp"
#include "gm_commands/endurance.cpp" #include "gm_commands/endurance.cpp"
#include "gm_commands/entityvariable.cpp"
#include "gm_commands/exptoggle.cpp" #include "gm_commands/exptoggle.cpp"
#include "gm_commands/faction.cpp" #include "gm_commands/faction.cpp"
#include "gm_commands/feature.cpp" #include "gm_commands/feature.cpp"
#include "gm_commands/findaa.cpp" #include "gm_commands/findaa.cpp"
#include "gm_commands/findcharacter.cpp" #include "gm_commands/findcharacter.cpp"
#include "gm_commands/findclass.cpp" #include "gm_commands/findclass.cpp"
#include "gm_commands/findcurrency.cpp"
#include "gm_commands/findfaction.cpp" #include "gm_commands/findfaction.cpp"
#include "gm_commands/findnpctype.cpp" #include "gm_commands/findnpctype.cpp"
#include "gm_commands/findrace.cpp" #include "gm_commands/findrace.cpp"
@@ -1069,7 +1073,6 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/nukeitem.cpp" #include "gm_commands/nukeitem.cpp"
#include "gm_commands/object.cpp" #include "gm_commands/object.cpp"
#include "gm_commands/oocmute.cpp" #include "gm_commands/oocmute.cpp"
#include "gm_commands/opcode.cpp"
#include "gm_commands/path.cpp" #include "gm_commands/path.cpp"
#include "gm_commands/peekinv.cpp" #include "gm_commands/peekinv.cpp"
#include "gm_commands/peqzone.cpp" #include "gm_commands/peqzone.cpp"
+2 -1
View File
@@ -82,6 +82,7 @@ void command_emoteview(Client *c, const Seperator *sep);
void command_emptyinventory(Client *c, const Seperator *sep); void command_emptyinventory(Client *c, const Seperator *sep);
void command_enablerecipe(Client *c, const Seperator *sep); void command_enablerecipe(Client *c, const Seperator *sep);
void command_endurance(Client *c, const Seperator *sep); void command_endurance(Client *c, const Seperator *sep);
void command_entityvariable(Client *c, const Seperator *sep);
void command_exptoggle(Client *c, const Seperator *sep); void command_exptoggle(Client *c, const Seperator *sep);
void command_faction(Client *c, const Seperator *sep); void command_faction(Client *c, const Seperator *sep);
void command_faction_association(Client *c, const Seperator *sep); void command_faction_association(Client *c, const Seperator *sep);
@@ -90,6 +91,7 @@ void command_findaa(Client *c, const Seperator *sep);
void command_findaliases(Client *c, const Seperator *sep); void command_findaliases(Client *c, const Seperator *sep);
void command_findcharacter(Client *c, const Seperator *sep); void command_findcharacter(Client *c, const Seperator *sep);
void command_findclass(Client *c, const Seperator *sep); void command_findclass(Client *c, const Seperator *sep);
void command_findcurrency(Client *c, const Seperator *sep);
void command_findfaction(Client *c, const Seperator *sep); void command_findfaction(Client *c, const Seperator *sep);
void command_findnpctype(Client *c, const Seperator *sep); void command_findnpctype(Client *c, const Seperator *sep);
void command_findrace(Client *c, const Seperator *sep); void command_findrace(Client *c, const Seperator *sep);
@@ -180,7 +182,6 @@ void command_nukebuffs(Client *c, const Seperator *sep);
void command_nukeitem(Client *c, const Seperator *sep); void command_nukeitem(Client *c, const Seperator *sep);
void command_object(Client *c, const Seperator *sep); void command_object(Client *c, const Seperator *sep);
void command_oocmute(Client *c, const Seperator *sep); void command_oocmute(Client *c, const Seperator *sep);
void command_opcode(Client *c, const Seperator *sep);
#ifdef PACKET_PROFILER #ifdef PACKET_PROFILER
void command_packetprofile(Client *c, const Seperator *sep); void command_packetprofile(Client *c, const Seperator *sep);
-6
View File
@@ -14,13 +14,10 @@
#define _CLIENTCORPSE(x) (x && x->IsCorpse() && x->CastToCorpse()->IsPlayerCorpse() && !x->CastToCorpse()->IsBecomeNPCCorpse()) #define _CLIENTCORPSE(x) (x && x->IsCorpse() && x->CastToCorpse()->IsPlayerCorpse() && !x->CastToCorpse()->IsBecomeNPCCorpse())
#define _NPCCORPSE(x) (x && x->IsCorpse() && (x->CastToCorpse()->IsNPCCorpse() || x->CastToCorpse()->IsBecomeNPCCorpse())) #define _NPCCORPSE(x) (x && x->IsCorpse() && (x->CastToCorpse()->IsNPCCorpse() || x->CastToCorpse()->IsBecomeNPCCorpse()))
#define _CLIENTPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient()) #define _CLIENTPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient())
#define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC())
#define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC())
//LOS Parameters: //LOS Parameters:
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from #define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
#define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS #define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS
#define CHECK_LOS_STEP 1.0f
#define ARCHETYPE_HYBRID 1 #define ARCHETYPE_HYBRID 1
#define ARCHETYPE_CASTER 2 #define ARCHETYPE_CASTER 2
@@ -44,7 +41,6 @@
//Spell specialization parameters, not sure of a better place for them //Spell specialization parameters, not sure of a better place for them
#define SPECIALIZE_FIZZLE 11 //% fizzle chance reduce at 200 specialized #define SPECIALIZE_FIZZLE 11 //% fizzle chance reduce at 200 specialized
#define SPECIALIZE_MANA_REDUCE 12 //% mana cost reduction at 200 specialized
//these are large right now because the x,y,z coords of the zone //these are large right now because the x,y,z coords of the zone
//lines do not make a lot of sense //lines do not make a lot of sense
@@ -232,7 +228,6 @@ enum GravityBehavior {
LevitateWhileRunning LevitateWhileRunning
}; };
struct TradeEntity;
class Trade; class Trade;
enum TradeState { enum TradeState {
TradeNone, TradeNone,
@@ -846,7 +841,6 @@ public:
virtual ~Trade(); virtual ~Trade();
void Reset(); void Reset();
void SetTradeCash(uint32 in_pp, uint32 in_gp, uint32 in_sp, uint32 in_cp);
// Initiate a trade with another mob // Initiate a trade with another mob
// Also puts other mob into trader mode with this mob // Also puts other mob into trader mode with this mob
+3 -3
View File
@@ -623,13 +623,13 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
if (!alt_mode) { // original function if (!alt_mode) { // original function
if (!m_is_open) { if (!m_is_open) {
if (!m_disable_timer) { if (!m_disable_timer) {
LogDoorsDetail("door_id [{}] starting timer", md->doorid); LogDoorsDetail("door_id [{}] starting timer", m_door_id);
m_close_timer.Start(); m_close_timer.Start();
} }
m_is_open = true; m_is_open = true;
} }
else { else {
LogDoorsDetail("door_id [{}] disable timer", md->doorid); LogDoorsDetail("door_id [{}] disable timer", m_door_id);
m_close_timer.Disable(); m_close_timer.Disable();
if (!m_disable_timer) { if (!m_disable_timer) {
m_is_open = false; m_is_open = false;
@@ -638,7 +638,7 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
} }
else { // alternative function else { // alternative function
if (!m_disable_timer) { if (!m_disable_timer) {
LogDoorsDetail("door_id [{}] alt starting timer", md->doorid); LogDoorsDetail("door_id [{}] alt starting timer", m_door_id);
m_close_timer.Start(); m_close_timer.Start();
} }
m_is_open = true; m_is_open = true;
+3 -3
View File
@@ -810,9 +810,9 @@ void Client::SendDisciplineUpdate() {
bool Client::UseDiscipline(uint32 spell_id, uint32 target) { bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
// Dont let client waste a reuse timer if they can't use the disc // Dont let client waste a reuse timer if they can't use the disc
if ((IsStunned() && !IgnoreCastingRestriction(spell_id))|| if ((IsStunned() && !IsCastNotStandingSpell(spell_id))||
IsFeared() || IsFeared() ||
(IsMezzed() && !IgnoreCastingRestriction(spell_id)) || (IsMezzed() && !IsCastNotStandingSpell(spell_id)) ||
IsAmnesiad() || IsAmnesiad() ||
IsPet()) IsPet())
{ {
@@ -837,7 +837,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
return false; return false;
} }
if (DivineAura() && !IgnoreCastingRestriction(spell_id)) { if (DivineAura() && !IsCastNotStandingSpell(spell_id)) {
return false; return false;
} }
+17
View File
@@ -179,6 +179,10 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_ITEM_CLICK_CAST_CLIENT", "EVENT_ITEM_CLICK_CAST_CLIENT",
"EVENT_DESTROY_ITEM_CLIENT", "EVENT_DESTROY_ITEM_CLIENT",
"EVENT_DROP_ITEM_CLIENT", "EVENT_DROP_ITEM_CLIENT",
"EVENT_MEMORIZE_SPELL",
"EVENT_UNMEMORIZE_SPELL",
"EVENT_SCRIBE_SPELL",
"EVENT_UNSCRIBE_SPELL",
// Add new events before these or Lua crashes // Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT", "EVENT_SPELL_EFFECT_BOT",
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT" "EVENT_SPELL_EFFECT_BUFF_TIC_BOT"
@@ -2160,6 +2164,19 @@ void PerlembParser::ExportEventVariables(
break; break;
} }
case EVENT_MEMORIZE_SPELL:
case EVENT_UNMEMORIZE_SPELL:
case EVENT_SCRIBE_SPELL:
case EVENT_UNSCRIBE_SPELL: {
Seperator sep(data);
ExportVar(package_name.c_str(), "slot_id", sep.arg[0]);
ExportVar(package_name.c_str(), "spell_id", sep.arg[1]);
if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[1]))) {
ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[1])]);
}
break;
}
default: { default: {
break; break;
} }
+1462 -17
View File
File diff suppressed because it is too large Load Diff
-228
View File
@@ -1756,21 +1756,6 @@ void EntityList::QueueClients(
} }
} }
void EntityList::QueueManaged(Mob *sender, const EQApplicationPacket *app,
bool ignore_sender, bool ackreq)
{
auto it = client_list.begin();
while (it != client_list.end()) {
Client *ent = it->second;
if ((!ignore_sender || ent != sender))
ent->QueuePacket(app, ackreq, Client::CLIENT_CONNECTED);
++it;
}
}
void EntityList::QueueClientsStatus(Mob *sender, const EQApplicationPacket *app, void EntityList::QueueClientsStatus(Mob *sender, const EQApplicationPacket *app,
bool ignore_sender, uint8 minstatus, uint8 maxstatus) bool ignore_sender, uint8 minstatus, uint8 maxstatus)
{ {
@@ -2180,21 +2165,6 @@ Group *EntityList::GetGroupByClient(Client *client)
return nullptr; return nullptr;
} }
Raid *EntityList::GetRaidByLeaderName(const char *leader)
{
std::list<Raid *>::iterator iterator;
iterator = raid_list.begin();
while (iterator != raid_list.end()) {
if ((*iterator)->GetLeader() && strcmp((*iterator)->GetLeader()->GetName(), leader) == 0) {
return *iterator;
}
++iterator;
}
return nullptr;
}
Raid *EntityList::GetRaidByID(uint32 id) Raid *EntityList::GetRaidByID(uint32 id)
{ {
std::list<Raid *>::iterator iterator; std::list<Raid *>::iterator iterator;
@@ -2274,26 +2244,6 @@ Raid* EntityList::GetRaidByBot(const Bot* bot)
return nullptr; return nullptr;
} }
Raid *EntityList::GetRaidByMob(Mob *mob)
{
std::list<Raid *>::iterator iterator;
iterator = raid_list.begin();
while (iterator != raid_list.end()) {
for(int x = 0; x < MAX_RAID_MEMBERS; x++) {
// TODO: Implement support for Mob objects in Raid class
/*if((*iterator)->members[x].member){
if((*iterator)->members[x].member == mob)
return *iterator;
}*/
}
++iterator;
}
return nullptr;
}
Client *EntityList::GetClientByAccID(uint32 accid) Client *EntityList::GetClientByAccID(uint32 accid)
{ {
auto it = client_list.begin(); auto it = client_list.begin();
@@ -2833,31 +2783,6 @@ bool EntityList::RemoveMob(uint16 delete_id)
return false; return false;
} }
/**
* @param delete_mob
* @return
*/
bool EntityList::RemoveMob(Mob *delete_mob)
{
if (delete_mob == 0) {
return true;
}
auto it = mob_list.begin();
while (it != mob_list.end()) {
if (it->second == delete_mob) {
safe_delete(it->second);
if (!corpse_list.count(it->first)) {
free_ids.push(it->first);
}
mob_list.erase(it);
return true;
}
++it;
}
return false;
}
/** /**
* @param delete_id * @param delete_id
* @return * @return
@@ -3109,18 +3034,6 @@ bool EntityList::RemoveGroup(uint32 delete_id)
return true; return true;
} }
bool EntityList::RemoveRaid(uint32 delete_id)
{
auto it = std::find_if(raid_list.begin(), raid_list.end(),
[delete_id](const Raid *a) { return a->GetID() == delete_id; });
if (it == raid_list.end())
return false;
auto raid = *it;
raid_list.erase(it);
safe_delete(raid);
return true;
}
void EntityList::Clear() void EntityList::Clear()
{ {
RemoveAllClients(); RemoveAllClients();
@@ -3205,21 +3118,6 @@ void EntityList::Process()
CheckSpawnQueue(); CheckSpawnQueue();
} }
void EntityList::CountNPC(uint32 *NPCCount, uint32 *NPCLootCount, uint32 *gmspawntype_count)
{
*NPCCount = 0;
*NPCLootCount = 0;
auto it = npc_list.begin();
while (it != npc_list.end()) {
(*NPCCount)++;
(*NPCLootCount) += it->second->CountLoot();
if (it->second->GetNPCTypeID() == 0)
(*gmspawntype_count)++;
++it;
}
}
void EntityList::Depop(bool StartSpawnTimer) void EntityList::Depop(bool StartSpawnTimer)
{ {
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) { for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
@@ -3554,15 +3452,6 @@ void EntityList::ClearClientPetitionQueue()
return; return;
} }
void EntityList::WriteEntityIDs()
{
auto it = mob_list.begin();
while (it != mob_list.end()) {
std::cout << "ID: " << it->first << " Name: " << it->second->GetName() << std::endl;
++it;
}
}
BulkZoneSpawnPacket::BulkZoneSpawnPacket(Client *iSendTo, uint32 iMaxSpawnsPerPacket) BulkZoneSpawnPacket::BulkZoneSpawnPacket(Client *iSendTo, uint32 iMaxSpawnsPerPacket)
{ {
data = nullptr; data = nullptr;
@@ -3631,24 +3520,6 @@ void EntityList::HalveAggro(Mob *who)
} }
} }
void EntityList::Evade(Mob *who)
{
uint32 flatval = who->GetLevel() * 13;
int amt = 0;
auto it = npc_list.begin();
while (it != npc_list.end()) {
if (it->second->CastToNPC()->CheckAggro(who)) {
amt = it->second->CastToNPC()->GetHateAmount(who);
amt -= flatval;
if (amt > 0)
it->second->CastToNPC()->SetHateAmountOnEnt(who, amt);
else
it->second->CastToNPC()->SetHateAmountOnEnt(who, 0);
}
++it;
}
}
//removes "targ" from all hate lists, including feigned, in the zone //removes "targ" from all hate lists, including feigned, in the zone
void EntityList::ClearAggro(Mob* targ) void EntityList::ClearAggro(Mob* targ)
{ {
@@ -4388,35 +4259,6 @@ bool EntityList::LimitCheckGroup(uint32 spawngroup_id, int count)
return true; return true;
} }
//check limits on an npc type in a given spawn group, and
//checks limits on the entire zone in one pass.
//returns true if neither limit has been reached
bool EntityList::LimitCheckBoth(uint32 npc_type, uint32 spawngroup_id, int group_count, int type_count)
{
if (group_count < 1 && type_count < 1)
return true;
std::map<uint16, SpawnLimitRecord>::iterator cur,end;
cur = npc_limit_list.begin();
end = npc_limit_list.end();
for (; cur != end; ++cur) {
if (cur->second.npc_type == npc_type) {
type_count--;
if (type_count == 0) {
return false;
}
}
if (cur->second.spawngroup_id == spawngroup_id) {
group_count--;
if (group_count == 0) {
return false;
}
}
}
return true;
}
bool EntityList::LimitCheckName(const char *npc_name) bool EntityList::LimitCheckName(const char *npc_name)
{ {
auto it = npc_list.begin(); auto it = npc_list.begin();
@@ -4463,25 +4305,6 @@ void EntityList::DestroyTempPets(Mob *owner)
} }
} }
int16 EntityList::CountTempPets(Mob *owner)
{
int16 count = 0;
auto it = npc_list.begin();
while (it != npc_list.end()) {
NPC* n = it->second;
if (n->GetSwarmInfo()) {
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
count++;
}
}
++it;
}
owner->SetTempPetCount(count);
return count;
}
void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy) void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
{ {
if (!other || !owner) if (!other || !owner)
@@ -4534,32 +4357,6 @@ void EntityList::AddTempPetsToHateListOnOwnerDamage(Mob *owner, Mob* attacker, i
} }
} }
bool Entity::CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z,
float trg_x, float trg_y, float trg_z, float perwalk)
{
if (zone->zonemap == nullptr)
return true;
glm::vec3 myloc;
glm::vec3 oloc;
glm::vec3 hit;
myloc.x = cur_x;
myloc.y = cur_y;
myloc.z = cur_z+5;
oloc.x = trg_x;
oloc.y = trg_y;
oloc.z = trg_z+5;
if (myloc.x == oloc.x && myloc.y == oloc.y && myloc.z == oloc.z)
return true;
if (!zone->zonemap->LineIntersectsZoneNoZLeaps(myloc,oloc,perwalk,&hit))
return true;
return false;
}
void EntityList::QuestJournalledSayClose( void EntityList::QuestJournalledSayClose(
Mob *sender, float dist, const char *mobname, const char *message, Mob *sender, float dist, const char *mobname, const char *message,
Journal::Options &opts Journal::Options &opts
@@ -5201,17 +4998,6 @@ uint32 EntityList::CheckNPCsClose(Mob *center)
return count; return count;
} }
void EntityList::GateAllClients()
{
auto it = client_list.begin();
while (it != client_list.end()) {
Client *c = it->second;
if (c)
c->GoToBind();
++it;
}
}
void EntityList::SignalAllClients(int signal_id) void EntityList::SignalAllClients(int signal_id)
{ {
for (const auto& c : client_list) { for (const auto& c : client_list) {
@@ -5221,20 +5007,6 @@ void EntityList::SignalAllClients(int signal_id)
} }
} }
uint16 EntityList::GetClientCount(){
uint16 ClientCount = 0;
std::list<Client*> client_list;
entity_list.GetClientList(client_list);
auto iter = client_list.begin();
while (iter != client_list.end()) {
Client *entry = (*iter);
entry->GetCleanName();
ClientCount++;
iter++;
}
return ClientCount;
}
void EntityList::GetMobList(std::list<Mob *> &m_list) void EntityList::GetMobList(std::list<Mob *> &m_list)
{ {
m_list.clear(); m_list.clear();
-19
View File
@@ -50,7 +50,6 @@ class Raid;
class Spawn2; class Spawn2;
class Trap; class Trap;
struct DynamicZoneSafeReturn;
struct GuildBankItemUpdate_Struct; struct GuildBankItemUpdate_Struct;
struct NewSpawn_Struct; struct NewSpawn_Struct;
struct QGlobal; struct QGlobal;
@@ -115,7 +114,6 @@ public:
inline const time_t& GetSpawnTimeStamp() const { return spawn_timestamp; } inline const time_t& GetSpawnTimeStamp() const { return spawn_timestamp; }
virtual const char* GetName() { return ""; } virtual const char* GetName() { return ""; }
bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1);
Bot* CastToBot(); Bot* CastToBot();
const Bot* CastToBot() const; const Bot* CastToBot() const;
@@ -129,7 +127,6 @@ protected:
initial_id = set_id; initial_id = set_id;
} }
} }
uint32 pDBAsyncWorkID;
private: private:
uint16 id; uint16 id;
uint16 initial_id; uint16 initial_id;
@@ -186,7 +183,6 @@ public:
Client *GetClientByCharID(uint32 iCharID); Client *GetClientByCharID(uint32 iCharID);
Client *GetClientByWID(uint32 iWID); Client *GetClientByWID(uint32 iWID);
Client *GetClientByLSID(uint32 iLSID); Client *GetClientByLSID(uint32 iLSID);
Client *GetClient(uint32 ip, uint16 port);
Bot* GetRandomBot(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Bot* exclude_bot = nullptr); Bot* GetRandomBot(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Bot* exclude_bot = nullptr);
Client* GetRandomClient(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Client* exclude_client = nullptr); Client* GetRandomClient(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Client* exclude_client = nullptr);
@@ -194,15 +190,12 @@ public:
Mob* GetRandomMob(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Mob* exclude_mob = nullptr); Mob* GetRandomMob(const glm::vec3& location = glm::vec3(0.f), float distance = 0, Mob* exclude_mob = nullptr);
Group* GetGroupByMob(Mob* mob); Group* GetGroupByMob(Mob* mob);
Group* GetGroupByMobName(const char* name); Group* GetGroupByMobName(const char* name);
Group* GetGroupByBot(Bot* bot);
bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2); bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2);
Group *GetGroupByClient(Client* client); Group *GetGroupByClient(Client* client);
Group *GetGroupByID(uint32 id); Group *GetGroupByID(uint32 id);
Group *GetGroupByLeaderName(const char* leader); Group *GetGroupByLeaderName(const char* leader);
Raid *GetRaidByMob(Mob* mob);
Raid *GetRaidByClient(Client* client); Raid *GetRaidByClient(Client* client);
Raid *GetRaidByID(uint32 id); Raid *GetRaidByID(uint32 id);
Raid *GetRaidByLeaderName(const char *leader);
Raid* GetRaidByBotName(const char* name); Raid* GetRaidByBotName(const char* name);
Raid* GetRaidByBot(const Bot* bot); Raid* GetRaidByBot(const Bot* bot);
@@ -268,7 +261,6 @@ public:
void ClearAreas(); void ClearAreas();
void ReloadMerchants(); void ReloadMerchants();
void ProcessProximitySay(const char *message, Client *c, uint8 language = 0); void ProcessProximitySay(const char *message, Client *c, uint8 language = 0);
void SendAATimer(uint32 charid,UseAA_Struct* uaa);
Doors *FindDoor(uint8 door_id); Doors *FindDoor(uint8 door_id);
Object *FindObject(uint32 object_id); Object *FindObject(uint32 object_id);
Object* FindNearbyObject(float x, float y, float z, float radius); Object* FindNearbyObject(float x, float y, float z, float radius);
@@ -291,13 +283,11 @@ public:
void AddProximity(NPC *proximity_for); void AddProximity(NPC *proximity_for);
void Clear(); void Clear();
bool RemoveMob(uint16 delete_id); bool RemoveMob(uint16 delete_id);
bool RemoveMob(Mob* delete_mob);
bool RemoveClient(uint16 delete_id); bool RemoveClient(uint16 delete_id);
bool RemoveClient(Client* delete_client); bool RemoveClient(Client* delete_client);
bool RemoveNPC(uint16 delete_id); bool RemoveNPC(uint16 delete_id);
bool RemoveMerc(uint16 delete_id); bool RemoveMerc(uint16 delete_id);
bool RemoveGroup(uint32 delete_id); bool RemoveGroup(uint32 delete_id);
bool RemoveRaid(uint32 delete_id);
bool RemoveCorpse(uint16 delete_id); bool RemoveCorpse(uint16 delete_id);
bool RemoveDoor(uint16 delete_id); bool RemoveDoor(uint16 delete_id);
bool RemoveTrap(uint16 delete_id); bool RemoveTrap(uint16 delete_id);
@@ -321,7 +311,6 @@ public:
void RemoveAllRaids(); void RemoveAllRaids();
void RemoveAllEncounters(); void RemoveAllEncounters();
void DestroyTempPets(Mob *owner); void DestroyTempPets(Mob *owner);
int16 CountTempPets(Mob *owner);
void AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy = false); void AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy = false);
void AddTempPetsToHateListOnOwnerDamage(Mob *owner, Mob* attacker, int32 spell_id); void AddTempPetsToHateListOnOwnerDamage(Mob *owner, Mob* attacker, int32 spell_id);
Entity *GetEntityMob(uint16 id); Entity *GetEntityMob(uint16 id);
@@ -428,7 +417,6 @@ public:
void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, EQ::versions::ClientVersionBitmask client_version_bits = EQ::versions::ClientVersionBitmask::maskAllClients); void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, EQ::versions::ClientVersionBitmask client_version_bits = EQ::versions::ClientVersionBitmask::maskAllClients);
void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app); void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true);
void AEAttack( void AEAttack(
Mob *attacker, Mob *attacker,
@@ -455,13 +443,11 @@ public:
Trap* FindNearbyTrap(Mob* searcher, float max_dist, float &curdist, bool detected = false); Trap* FindNearbyTrap(Mob* searcher, float max_dist, float &curdist, bool detected = false);
void AddHealAggro(Mob* target, Mob* caster, uint16 hate); void AddHealAggro(Mob* target, Mob* caster, uint16 hate);
Mob* FindDefenseNPC(uint32 npcid);
void OpenDoorsNear(Mob* opener); void OpenDoorsNear(Mob* opener);
void UpdateWho(bool iSendFullUpdate = false); void UpdateWho(bool iSendFullUpdate = false);
char* MakeNameUnique(char* name); char* MakeNameUnique(char* name);
static char* RemoveNumbers(char* name); static char* RemoveNumbers(char* name);
void SignalMobsByNPCID(uint32 npc_type, int signal_id); void SignalMobsByNPCID(uint32 npc_type, int signal_id);
void CountNPC(uint32* NPCCount, uint32* NPCLootCount, uint32* gmspawntype_count);
void RemoveEntity(uint16 id); void RemoveEntity(uint16 id);
void SendPetitionToAdmins(Petition* pet); void SendPetitionToAdmins(Petition* pet);
void SendPetitionToAdmins(); void SendPetitionToAdmins();
@@ -472,10 +458,8 @@ public:
uint32 DeleteNPCCorpses(); uint32 DeleteNPCCorpses();
uint32 DeletePlayerCorpses(); uint32 DeletePlayerCorpses();
void CorpseFix(Client* c); void CorpseFix(Client* c);
void WriteEntityIDs();
void HalveAggro(Mob* who); void HalveAggro(Mob* who);
void DoubleAggro(Mob* who); void DoubleAggro(Mob* who);
void Evade(Mob *who);
void UpdateHoTT(Mob* target); void UpdateHoTT(Mob* target);
void Process(); void Process();
@@ -496,7 +480,6 @@ public:
void LimitRemoveNPC(NPC *npc); void LimitRemoveNPC(NPC *npc);
bool LimitCheckType(uint32 npc_type, int count); bool LimitCheckType(uint32 npc_type, int count);
bool LimitCheckGroup(uint32 spawngroup_id, int count); bool LimitCheckGroup(uint32 spawngroup_id, int count);
bool LimitCheckBoth(uint32 npc_type, uint32 spawngroup_id, int group_count, int type_count);
bool LimitCheckName(const char* npc_name); bool LimitCheckName(const char* npc_name);
int GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con); int GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con);
@@ -521,7 +504,6 @@ public:
void ZoneWho(Client *c, Who_All_Struct* Who); void ZoneWho(Client *c, Who_All_Struct* Who);
void UnMarkNPC(uint16 ID); void UnMarkNPC(uint16 ID);
void GateAllClients();
void SignalAllClients(int signal_id); void SignalAllClients(int signal_id);
void UpdateQGlobal(uint32 qid, QGlobal newGlobal); void UpdateQGlobal(uint32 qid, QGlobal newGlobal);
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID); void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
@@ -531,7 +513,6 @@ public:
void GateAllClientsToSafeReturn(); void GateAllClientsToSafeReturn();
uint16 GetClientCount();
void GetMobList(std::list<Mob*> &m_list); void GetMobList(std::list<Mob*> &m_list);
void GetNPCList(std::list<NPC*> &n_list); void GetNPCList(std::list<NPC*> &n_list);
void GetMercList(std::list<Merc*> &n_list); void GetMercList(std::list<Merc*> &n_list);
+4
View File
@@ -124,6 +124,10 @@ typedef enum {
EVENT_ITEM_CLICK_CAST_CLIENT, EVENT_ITEM_CLICK_CAST_CLIENT,
EVENT_DESTROY_ITEM_CLIENT, EVENT_DESTROY_ITEM_CLIENT,
EVENT_DROP_ITEM_CLIENT, EVENT_DROP_ITEM_CLIENT,
EVENT_MEMORIZE_SPELL,
EVENT_UNMEMORIZE_SPELL,
EVENT_SCRIBE_SPELL,
EVENT_UNSCRIBE_SPELL,
// Add new events before these or Lua crashes // Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BOT,
EVENT_SPELL_EFFECT_BUFF_TIC_BOT, EVENT_SPELL_EFFECT_BUFF_TIC_BOT,
+2 -2
View File
@@ -62,7 +62,7 @@ void command_appearanceeffects(Client *c, const Seperator *sep)
"Appearance Effect ID {} in slot ID {} has been set for {}.", "Appearance Effect ID {} in slot ID {} has been set for {}.",
effect_id, effect_id,
slot_id, slot_id,
c->GetTargetDescription(t, TargetDescriptionType::LCSelf) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
} else if (is_remove) { } else if (is_remove) {
@@ -90,7 +90,7 @@ void command_appearanceeffects(Client *c, const Seperator *sep)
Chat::White, Chat::White,
fmt::format( fmt::format(
"Appearance Effects have been removed for {}.", "Appearance Effects have been removed for {}.",
c->GetTargetDescription(t, TargetDescriptionType::LCSelf) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
} else if (is_view) { } else if (is_view) {
+1 -1
View File
@@ -21,7 +21,7 @@ void command_castspell(Client *c, const Seperator *sep)
else { else {
uint16 spell_id = Strings::ToUnsignedInt(sep->arg[1]); uint16 spell_id = Strings::ToUnsignedInt(sep->arg[1]);
if (CastRestrictedSpell(spell_id) && c->Admin() < commandCastSpecials) { if (IsCastRestrictedSpell(spell_id) && c->Admin() < commandCastSpecials) {
c->Message(Chat::Red, "Unable to cast spell."); c->Message(Chat::Red, "Unable to cast spell.");
} }
else if (spell_id >= SPDAT_RECORDS) { else if (spell_id >= SPDAT_RECORDS) {
+190
View File
@@ -0,0 +1,190 @@
#include "../client.h"
void command_entityvariable(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #entityvariable clear - Clear all entity variables on yourself or your target");
c->Message(Chat::White, "Usage: #entityvariable delete [Variable Name] - Delete an entity variable from yourself or your target");
c->Message(Chat::White, "Usage: #entityvariable set [Variable Name] [Variable Value] - Set an entity variable for yourself or your target");
c->Message(Chat::White, "Usage: #entityvariable view [Variable Name] - View an entity variable on yourself or your target");
c->Message(Chat::White, "Note: You can have spaces in variable names and values by wrapping in double quotes like this");
c->Message(Chat::White, "Example: #entityvariable set \"Test Variable\" \"Test Value\"");
c->Message(Chat::White, "Note: Variable Value is optional and can be set to empty by not providing a value");
return;
}
const bool is_clear = !strcasecmp(sep->arg[1], "clear");
const bool is_delete = !strcasecmp(sep->arg[1], "delete");
const bool is_set = !strcasecmp(sep->arg[1], "set");
const bool is_view = !strcasecmp(sep->arg[1], "view");
if (
!is_clear &&
!is_delete &&
!is_set &&
!is_view
) {
c->Message(Chat::White, "Usage: #entityvariable clear - Clear all entity variables on yourself or your target");
c->Message(Chat::White, "Usage: #entityvariable delete [Variable Name] - Delete an entity variable from yourself or your target");
c->Message(Chat::White, "Usage: #entityvariable set [Variable Name] [Variable Value] - Set an entity variable for yourself or your target");
c->Message(Chat::White, "Usage: #entityvariable view [Variable Name] - View an entity variable on yourself or your target");
c->Message(Chat::White, "Note: You can have spaces in variable names and values by wrapping in double quotes like this");
c->Message(Chat::White, "Example: #entityvariable set \"Test Variable\" \"Test Value\"");
c->Message(Chat::White, "Note: Variable Value is optional and can be set to empty by not providing a value");
return;
}
Mob* t = c;
if (c->GetTarget()) {
t = c->GetTarget();
}
if (is_clear) {
const auto cleared = t->ClearEntityVariables();
if (!cleared) {
c->Message(
Chat::White,
fmt::format(
"{} {} not have any entity variables to clear.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "do" : "does"
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Cleared all entity variables for {}.",
c->GetTargetDescription(t)
).c_str()
);
} else if (is_delete) {
const std::string variable_name = sep->argplus[2];
if (!t->EntityVariableExists(variable_name)) {
c->Message(
Chat::White,
fmt::format(
"{} {} not have an entity variable named '{}'.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "do" : "does",
variable_name
).c_str()
);
return;
}
t->DeleteEntityVariable(variable_name);
c->Message(
Chat::White,
fmt::format(
"Deleted an entity variable named '{}' from {}.",
variable_name,
c->GetTargetDescription(t)
).c_str()
);
return;
} else if (is_set) {
const std::string variable_name = sep->arg[2];
const std::string variable_value = sep->arg[3];
t->SetEntityVariable(variable_name, variable_value);
c->Message(
Chat::White,
fmt::format(
"Set an entity variable named '{}' to a value of '{}' for {}.",
variable_name,
variable_value,
c->GetTargetDescription(t)
).c_str()
);
} else if (is_view) {
const auto &l = t->GetEntityVariables();
uint32 variable_count = 0;
uint32 variable_number = 1;
const std::string search_criteria = arguments ? sep->argplus[2] : "";
for (const auto &e: l) {
if (
search_criteria.empty() ||
Strings::Contains(Strings::ToLower(e), Strings::ToLower(search_criteria))
) {
c->Message(
Chat::White,
fmt::format(
"Variable {} | Name: {} Value: {} | {}",
variable_number,
e,
t->GetEntityVariable(e),
Saylink::Silent(
fmt::format(
"#entityvariable delete {}",
e
),
"Delete"
)
).c_str()
);
variable_count++;
variable_number++;
}
}
if (!variable_count) {
c->Message(
Chat::White,
fmt::format(
"{} {} no entity variables{}.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
(
!search_criteria.empty() ?
fmt::format(
" matching '{}'",
search_criteria
) :
""
)
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"{} {} {} entity variable{}{}, would you like to {} all of {} entity variables?",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
variable_count,
variable_count != 1 ? "s" : "",
(
!search_criteria.empty() ?
fmt::format(
" matching '{}'",
search_criteria
) :
""
),
Saylink::Silent(
"#entityvariable clear",
"clear"
),
c == t ? "your" : "their"
).c_str()
);
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ void command_exptoggle(Client *c, const Seperator *sep)
Chat::White, Chat::White,
fmt::format( fmt::format(
"Experience gain for {} is now {}abled.", "Experience gain for {} is now {}abled.",
c->GetTargetDescription(t, TargetDescriptionType::LCSelf), c->GetTargetDescription(t),
is_exp_enabled ? "en" : "dis" is_exp_enabled ? "en" : "dis"
).c_str() ).c_str()
); );
+134
View File
@@ -0,0 +1,134 @@
#include "../client.h"
void command_findcurrency(Client *c, const Seperator *sep)
{
const auto arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #findcurrency [Search Criteria]");
return;
}
const auto can_summon_items = c->Admin() >= GetCommandStatus(c, "summonitem");
if (sep->IsNumber(1)) {
const auto item_id = Strings::ToUnsignedInt(sep->arg[1]);
const auto currency_id = zone->GetCurrencyID(item_id);
if (!currency_id) {
c->Message(
Chat::White,
fmt::format(
"There is no currency with an item ID of {}.",
item_id
).c_str()
);
return;
}
const auto item_data = database.GetItem(item_id);
if (!item_data) {
c->Message(
Chat::White,
fmt::format(
"Item ID {} does not exist.",
item_id
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Currency {} | {} ({}){}",
currency_id,
database.CreateItemLink(item_id),
item_id,
(
can_summon_items ?
fmt::format(
" | {}",
Saylink::Silent(
fmt::format(
"#summonitem {} {}",
item_id,
item_data->StackSize
),
"Summon"
)
) :
""
)
).c_str()
);
return;
}
const std::string search_criteria = sep->argplus[1];
uint32 found_count = 0;
for (const auto& e : zone->AlternateCurrencies) {
const auto item_data = database.GetItem(e.item_id);
if (!item_data) {
continue;
}
const std::string item_name = Strings::ToLower(item_data->Name);
if (Strings::Contains(item_name, Strings::ToLower(search_criteria))) {
c->Message(
Chat::White,
fmt::format(
"Currency {} | {} ({}){}",
e.id,
database.CreateItemLink(e.item_id),
e.item_id,
(
can_summon_items ?
fmt::format(
" | {}",
Saylink::Silent(
fmt::format(
"#summonitem {} {}",
e.item_id,
item_data->StackSize
),
"Summon"
)
) :
""
)
).c_str()
);
found_count++;
}
}
if (!found_count) {
c->Message(
Chat::White,
fmt::format(
"No currencies were found matching '{}'.",
search_criteria
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"{} currenc{} found matching '{}'.",
found_count,
found_count != 1 ? "ies were" : "y was",
search_criteria
).c_str()
);
}
+2 -8
View File
@@ -420,24 +420,18 @@ void command_npcedit(Client *c, const Seperator *sep)
} else if (!strcasecmp(sep->arg[1], "special_attacks")) { } else if (!strcasecmp(sep->arg[1], "special_attacks")) {
std::string special_attacks = sep->argplus[2]; std::string special_attacks = sep->argplus[2];
n.npcspecialattks = special_attacks; n.npcspecialattks = special_attacks;
c->Message( d = fmt::format(
Chat::Yellow,
fmt::format(
"{} is now using the following Special Attacks '{}'.", "{} is now using the following Special Attacks '{}'.",
npc_id_string, npc_id_string,
special_attacks special_attacks
).c_str()
); );
} else if (!strcasecmp(sep->arg[1], "special_abilities")) { } else if (!strcasecmp(sep->arg[1], "special_abilities")) {
std::string special_abilities = sep->argplus[2]; std::string special_abilities = sep->argplus[2];
n.special_abilities = special_abilities; n.special_abilities = special_abilities;
c->Message( d = fmt::format(
Chat::Yellow,
fmt::format(
"{} is now using the following Special Abilities '{}'.", "{} is now using the following Special Abilities '{}'.",
npc_id_string, npc_id_string,
special_abilities special_abilities
).c_str()
); );
} else if (!strcasecmp(sep->arg[1], "aggroradius")) { } else if (!strcasecmp(sep->arg[1], "aggroradius")) {
if (sep->IsNumber(2)) { if (sep->IsNumber(2)) {
-9
View File
@@ -1,9 +0,0 @@
#include "../client.h"
#include "../../common/patches/patches.h"
void command_opcode(Client *c, const Seperator *sep)
{
ReloadAllPatches();
c->Message(Chat::White, "Opcodes for all patches have been reloaded");
}
+9 -2
View File
@@ -11,8 +11,15 @@ void command_questerrors(Client *c, const Seperator *sep)
int error_index = 0; int error_index = 0;
for (auto quest_error : quest_errors) { for (auto quest_error : quest_errors) {
if (error_index >= 30) { if (error_index >= RuleI(World, MaximumQuestErrors)) {
c->Message(Chat::White, "Maximum of 30 errors shown."); c->Message(
Chat::White,
fmt::format(
"Maximum of {} error{} shown.",
RuleI(World, MaximumQuestErrors),
RuleI(World, MaximumQuestErrors) != 1 ? "s" : ""
).c_str()
);
break; break;
} }
+37 -61
View File
@@ -1,16 +1,18 @@
#include "../client.h" #include "../client.h"
#include "../../common/patches/patches.h"
void command_reload(Client *c, const Seperator *sep) void command_reload(Client *c, const Seperator *sep)
{ {
std::string command = sep->arg[0] ? sep->arg[0] : ""; std::string command = sep->arg[0] ? sep->arg[0] : "";
int arguments = sep->argnum; const auto arguments = sep->argnum;
if (!arguments && Strings::Contains(command, "#reload")) { if (!arguments && Strings::Contains(command, "#reload")) {
c->SendReloadCommandMessages(); c->SendReloadCommandMessages();
return; return;
} }
bool is_rq_alias = sep->arg[0] && Strings::Contains(command, "#rq");
bool is_logs_reload_alias = sep->arg[0] && Strings::Contains(command, "#rl"); bool is_logs_reload_alias = sep->arg[0] && Strings::Contains(command, "#rl");
bool is_opcodes_reload_alias = sep->arg[0] && Strings::Contains(command, "#opcode");
bool is_rq_alias = sep->arg[0] && Strings::Contains(command, "#rq");
bool is_aa = !strcasecmp(sep->arg[1], "aa"); bool is_aa = !strcasecmp(sep->arg[1], "aa");
bool is_alternate_currencies = !strcasecmp(sep->arg[1], "alternate_currencies"); bool is_alternate_currencies = !strcasecmp(sep->arg[1], "alternate_currencies");
bool is_blocked_spells = !strcasecmp(sep->arg[1], "blocked_spells"); bool is_blocked_spells = !strcasecmp(sep->arg[1], "blocked_spells");
@@ -24,6 +26,7 @@ void command_reload(Client *c, const Seperator *sep)
bool is_merchants = !strcasecmp(sep->arg[1], "merchants"); bool is_merchants = !strcasecmp(sep->arg[1], "merchants");
bool is_npc_emotes = !strcasecmp(sep->arg[1], "npc_emotes"); bool is_npc_emotes = !strcasecmp(sep->arg[1], "npc_emotes");
bool is_objects = !strcasecmp(sep->arg[1], "objects"); bool is_objects = !strcasecmp(sep->arg[1], "objects");
bool is_opcodes = !strcasecmp(sep->arg[1], "opcodes") || is_opcodes_reload_alias;
bool is_perl_export = !strcasecmp(sep->arg[1], "perl_export"); bool is_perl_export = !strcasecmp(sep->arg[1], "perl_export");
bool is_quest = !strcasecmp(sep->arg[1], "quest") || (is_rq_alias); bool is_quest = !strcasecmp(sep->arg[1], "quest") || (is_rq_alias);
bool is_rules = !strcasecmp(sep->arg[1], "rules"); bool is_rules = !strcasecmp(sep->arg[1], "rules");
@@ -51,6 +54,7 @@ void command_reload(Client *c, const Seperator *sep)
!is_merchants && !is_merchants &&
!is_npc_emotes && !is_npc_emotes &&
!is_objects && !is_objects &&
!is_opcodes &&
!is_perl_export && !is_perl_export &&
!is_quest && !is_quest &&
!is_rules && !is_rules &&
@@ -73,36 +77,28 @@ void command_reload(Client *c, const Seperator *sep)
if (is_aa) { if (is_aa) {
c->Message(Chat::White, "Attempting to reload Alternate Advancement Data globally."); c->Message(Chat::White, "Attempting to reload Alternate Advancement Data globally.");
pack = new ServerPacket(ServerOP_ReloadAAData, 0); pack = new ServerPacket(ServerOP_ReloadAAData, 0);
} } else if (is_alternate_currencies) {
else if (is_alternate_currencies) {
c->Message(Chat::White, "Attempting to reload Alternate Currencies globally."); c->Message(Chat::White, "Attempting to reload Alternate Currencies globally.");
pack = new ServerPacket(ServerOP_ReloadAlternateCurrencies, 0); pack = new ServerPacket(ServerOP_ReloadAlternateCurrencies, 0);
} } else if (is_blocked_spells) {
else if (is_blocked_spells) {
c->Message(Chat::White, "Attempting to reload Blocked Spells globally."); c->Message(Chat::White, "Attempting to reload Blocked Spells globally.");
pack = new ServerPacket(ServerOP_ReloadBlockedSpells, 0); pack = new ServerPacket(ServerOP_ReloadBlockedSpells, 0);
} } else if (is_commands) {
else if (is_commands) {
c->Message(Chat::White, "Attempting to reload Commands globally."); c->Message(Chat::White, "Attempting to reload Commands globally.");
pack = new ServerPacket(ServerOP_ReloadCommands, 0); pack = new ServerPacket(ServerOP_ReloadCommands, 0);
} } else if (is_content_flags) {
else if (is_content_flags) {
c->Message(Chat::White, "Attempting to reload Content Flags globally."); c->Message(Chat::White, "Attempting to reload Content Flags globally.");
pack = new ServerPacket(ServerOP_ReloadContentFlags, 0); pack = new ServerPacket(ServerOP_ReloadContentFlags, 0);
} } else if (is_doors) {
else if (is_doors) {
c->Message(Chat::White, "Attempting to reload Doors globally."); c->Message(Chat::White, "Attempting to reload Doors globally.");
pack = new ServerPacket(ServerOP_ReloadDoors, 0); pack = new ServerPacket(ServerOP_ReloadDoors, 0);
} } else if (is_dztemplates) {
else if (is_dztemplates) {
c->Message(Chat::White, "Attempting to reload Dynamic Zone Templates globally."); c->Message(Chat::White, "Attempting to reload Dynamic Zone Templates globally.");
pack = new ServerPacket(ServerOP_ReloadDzTemplates, 0); pack = new ServerPacket(ServerOP_ReloadDzTemplates, 0);
} } else if (is_ground_spawns) {
else if (is_ground_spawns) {
c->Message(Chat::White, "Attempting to reload Ground Spawns globally."); c->Message(Chat::White, "Attempting to reload Ground Spawns globally.");
pack = new ServerPacket(ServerOP_ReloadGroundSpawns, 0); pack = new ServerPacket(ServerOP_ReloadGroundSpawns, 0);
} } else if (is_level_mods) {
else if (is_level_mods) {
if (!RuleB(Zone, LevelBasedEXPMods)) { if (!RuleB(Zone, LevelBasedEXPMods)) {
c->Message(Chat::White, "Level Based Experience Modifiers are disabled."); c->Message(Chat::White, "Level Based Experience Modifiers are disabled.");
return; return;
@@ -110,75 +106,60 @@ void command_reload(Client *c, const Seperator *sep)
c->Message(Chat::White, "Attempting to reload Level Based Experience Modifiers globally."); c->Message(Chat::White, "Attempting to reload Level Based Experience Modifiers globally.");
pack = new ServerPacket(ServerOP_ReloadLevelEXPMods, 0); pack = new ServerPacket(ServerOP_ReloadLevelEXPMods, 0);
} } else if (is_logs) {
else if (is_logs) {
c->Message(Chat::White, "Attempting to reload Log Settings globally."); c->Message(Chat::White, "Attempting to reload Log Settings globally.");
pack = new ServerPacket(ServerOP_ReloadLogs, 0); pack = new ServerPacket(ServerOP_ReloadLogs, 0);
} } else if (is_merchants) {
else if (is_merchants) {
c->Message(Chat::White, "Attempting to reload Merchants globally."); c->Message(Chat::White, "Attempting to reload Merchants globally.");
pack = new ServerPacket(ServerOP_ReloadMerchants, 0); pack = new ServerPacket(ServerOP_ReloadMerchants, 0);
} } else if (is_npc_emotes) {
else if (is_npc_emotes) {
c->Message(Chat::White, "Attempting to reload NPC Emotes globally."); c->Message(Chat::White, "Attempting to reload NPC Emotes globally.");
pack = new ServerPacket(ServerOP_ReloadNPCEmotes, 0); pack = new ServerPacket(ServerOP_ReloadNPCEmotes, 0);
} } else if (is_objects) {
else if (is_objects) {
c->Message(Chat::White, "Attempting to reload Objects globally."); c->Message(Chat::White, "Attempting to reload Objects globally.");
pack = new ServerPacket(ServerOP_ReloadObjects, 0); pack = new ServerPacket(ServerOP_ReloadObjects, 0);
} } else if (is_opcodes) {
else if (is_perl_export) { c->Message(Chat::White, "Attempting to reload Opcodes globally.");
pack = new ServerPacket(ServerOP_ReloadOpcodes, 0);
} else if (is_perl_export) {
c->Message(Chat::White, "Attempting to reload Perl Event Export Settings globally."); c->Message(Chat::White, "Attempting to reload Perl Event Export Settings globally.");
pack = new ServerPacket(ServerOP_ReloadPerlExportSettings, 0); pack = new ServerPacket(ServerOP_ReloadPerlExportSettings, 0);
} } else if (is_quest) {
else if (is_quest) { const auto stop_timers = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
bool stop_timers = false;
if (sep->IsNumber(2)) {
stop_timers = Strings::ToInt(sep->arg[2]) != 0 ? true : false;
}
std::string stop_timers_message = stop_timers ? " and timers stopped" : "";
c->Message( c->Message(
Chat::Yellow, Chat::Yellow,
fmt::format( fmt::format(
"Quests reloaded{} for {}.", "Quests reloaded{} for {}.",
stop_timers_message, stop_timers ? " and timers stopped" : "",
zone->GetZoneDescription() zone->GetZoneDescription()
).c_str() ).c_str()
); );
entity_list.ClearAreas(); entity_list.ClearAreas();
parse->ReloadQuests(stop_timers); parse->ReloadQuests(stop_timers);
} } else if (is_rules) {
else if (is_rules) {
c->Message(Chat::White, "Attempting to reload Rules globally."); c->Message(Chat::White, "Attempting to reload Rules globally.");
pack = new ServerPacket(ServerOP_ReloadRules, 0); pack = new ServerPacket(ServerOP_ReloadRules, 0);
} } else if (is_static) {
else if (is_static) {
c->Message(Chat::White, "Attempting to reload Static Zone Data globally."); c->Message(Chat::White, "Attempting to reload Static Zone Data globally.");
pack = new ServerPacket(ServerOP_ReloadStaticZoneData, 0); pack = new ServerPacket(ServerOP_ReloadStaticZoneData, 0);
} } else if (is_tasks) {
else if (is_tasks) {
uint32 task_id = 0; uint32 task_id = 0;
if (!sep->IsNumber(2)) { if (!sep->IsNumber(2)) {
c->Message(Chat::White, "Attempting to reload Tasks globally."); c->Message(Chat::White, "Attempting to reload Tasks globally.");
pack = new ServerPacket(ServerOP_ReloadTasks, sizeof(ReloadTasks_Struct)); pack = new ServerPacket(ServerOP_ReloadTasks, sizeof(ReloadTasks_Struct));
} } else {
else {
task_id = Strings::ToUnsignedInt(sep->arg[2]); task_id = Strings::ToUnsignedInt(sep->arg[2]);
} }
auto rts = (ReloadTasks_Struct *) pack->pBuffer; auto rts = (ReloadTasks_Struct *) pack->pBuffer;
rts->reload_type = RELOADTASKS; rts->reload_type = RELOADTASKS;
rts->task_id = task_id; rts->task_id = task_id;
} } else if (is_titles) {
else if (is_titles) {
c->Message(Chat::White, "Attempting to reload Titles globally."); c->Message(Chat::White, "Attempting to reload Titles globally.");
pack = new ServerPacket(ServerOP_ReloadTitles, 0); pack = new ServerPacket(ServerOP_ReloadTitles, 0);
} } else if (is_traps) {
else if (is_traps) {
if (arguments < 2 || !sep->IsNumber(2)) { if (arguments < 2 || !sep->IsNumber(2)) {
entity_list.UpdateAllTraps(true, true); entity_list.UpdateAllTraps(true, true);
c->Message( c->Message(
@@ -191,7 +172,7 @@ void command_reload(Client *c, const Seperator *sep)
return; return;
} }
bool global = Strings::ToInt(sep->arg[2]) ? true : false; const auto global = Strings::ToBool(sep->arg[2]);
if (!global) { if (!global) {
entity_list.UpdateAllTraps(true, true); entity_list.UpdateAllTraps(true, true);
@@ -207,16 +188,13 @@ void command_reload(Client *c, const Seperator *sep)
c->Message(Chat::White, "Attempting to reload Traps globally."); c->Message(Chat::White, "Attempting to reload Traps globally.");
pack = new ServerPacket(ServerOP_ReloadTraps, 0); pack = new ServerPacket(ServerOP_ReloadTraps, 0);
} } else if (is_variables) {
else if (is_variables) {
c->Message(Chat::White, "Attempting to reload Variables globally."); c->Message(Chat::White, "Attempting to reload Variables globally.");
pack = new ServerPacket(ServerOP_ReloadVariables, 0); pack = new ServerPacket(ServerOP_ReloadVariables, 0);
} } else if (is_veteran_rewards) {
else if (is_veteran_rewards) {
c->Message(Chat::White, "Attempting to reload Veteran Rewards globally."); c->Message(Chat::White, "Attempting to reload Veteran Rewards globally.");
pack = new ServerPacket(ServerOP_ReloadVeteranRewards, 0); pack = new ServerPacket(ServerOP_ReloadVeteranRewards, 0);
} } else if (is_world) {
else if (is_world) {
uint8 global_repop = ReloadWorld::NoRepop; uint8 global_repop = ReloadWorld::NoRepop;
if (sep->IsNumber(2)) { if (sep->IsNumber(2)) {
@@ -246,8 +224,7 @@ void command_reload(Client *c, const Seperator *sep)
pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
auto RW = (ReloadWorld_Struct *) pack->pBuffer; auto RW = (ReloadWorld_Struct *) pack->pBuffer;
RW->global_repop = global_repop; RW->global_repop = global_repop;
} } else if (is_zone) {
else if (is_zone) {
zone_store.LoadZones(content_db); zone_store.LoadZones(content_db);
if (arguments < 2) { if (arguments < 2) {
@@ -316,8 +293,7 @@ void command_reload(Client *c, const Seperator *sep)
) )
).c_str() ).c_str()
); );
} } else if (is_zone_points) {
else if (is_zone_points) {
c->Message(Chat::White, "Attempting to reloading Zone Points globally."); c->Message(Chat::White, "Attempting to reloading Zone Points globally.");
pack = new ServerPacket(ServerOP_ReloadZonePoints, 0); pack = new ServerPacket(ServerOP_ReloadZonePoints, 0);
} }
+41 -19
View File
@@ -2,9 +2,24 @@
void command_setanim(Client *c, const Seperator *sep) void command_setanim(Client *c, const Seperator *sep)
{ {
int arguments = sep->argnum; const auto arguments = sep->argnum;
if (!arguments || !sep->IsNumber(1)) { if (!arguments || !sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #setanim [Animation ID (IDs are 0 to 4)]"); c->Message(Chat::White, "Usage: #setanim [Animation ID]");
uint32 animation_number = 1;
for (const auto& a : EQ::constants::GetSpawnAnimationMap()) {
c->Message(
Chat::White,
fmt::format(
"Animation {} | ID: {} Name: {}",
animation_number,
a.first,
a.second
).c_str()
);
animation_number++;
}
return; return;
} }
@@ -13,29 +28,36 @@ void command_setanim(Client *c, const Seperator *sep)
target = c->GetTarget(); target = c->GetTarget();
} }
const auto animation_id = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1]));
int animation_id = Strings::ToInt(sep->arg[1]);
if ( if (
animation_id < 0 || !EQ::ValueWithin(
animation_id > eaLooting animation_id,
static_cast<uint8>(eaStanding),
static_cast<uint8>(eaLooting)
)
) { ) {
c->Message(Chat::White, "Usage: #setanim [Animation ID (IDs are 0 to 4)]"); c->Message(Chat::White, "Usage: #setanim [Animation ID]");
uint32 animation_number = 1;
for (const auto& a : EQ::constants::GetSpawnAnimationMap()) {
c->Message(
Chat::White,
fmt::format(
"Animation {} | ID: {} Name: {}",
animation_number,
a.first,
a.second
).c_str()
);
animation_number++;
}
return; return;
} }
target->SetAppearance(static_cast<EmuAppearance>(animation_id), false); target->SetAppearance(static_cast<EmuAppearance>(animation_id), false);
std::string animation_name;
if (animation_id == eaStanding) { const auto animation_name = EQ::constants::GetSpawnAnimationName(animation_id);
animation_name = "Standing";
} else if (animation_id == eaSitting) {
animation_name = "Sitting";
} else if (animation_id == eaCrouching) {
animation_name = "Crouching";
} else if (animation_id == eaDead) {
animation_name = "Dead";
} else if (animation_id == eaLooting) {
animation_name = "Looting";
}
c->Message( c->Message(
Chat::White, Chat::White,
+27 -36
View File
@@ -2,54 +2,45 @@
void command_setskill(Client *c, const Seperator *sep) void command_setskill(Client *c, const Seperator *sep)
{ {
Client *target = c; const auto arguments = sep->argnum;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient();
}
auto skill_id = sep->IsNumber(1) ? Strings::ToInt(sep->arg[1]) : -1; if (arguments < 2 || !sep->IsNumber(1) || !sep->IsNumber(2)) {
auto skill_value = sep->IsNumber(2) ? Strings::ToInt(sep->arg[2]) : -1;
if (
skill_id < 0 ||
skill_id > EQ::skills::HIGHEST_SKILL ||
skill_value < 0 ||
skill_value > HIGHEST_CAN_SET_SKILL
) {
c->Message(Chat::White, "Usage: #setskill [Skill ID] [Skill Value]"); c->Message(Chat::White, "Usage: #setskill [Skill ID] [Skill Value]");
c->Message(Chat::White, fmt::format("Skill ID = 0 to {}", EQ::skills::HIGHEST_SKILL).c_str()); return;
c->Message(Chat::White, fmt::format("Skill Value = 0 to {}", HIGHEST_CAN_SET_SKILL).c_str());
} }
else {
LogInfo( auto t = c;
"Set skill request from [{}], Target: [{}] Skill ID: [{}] Skill Value: [{}]", if (c->GetTarget() && c->GetTarget()->IsClient()) {
c->GetCleanName(), t = c->GetTarget()->CastToClient();
c->GetTargetDescription(target), }
skill_id,
skill_value const auto skill_id = Strings::ToInt(sep->arg[1]);
const auto skill_value = Strings::ToInt(sep->arg[2]);
if (!EQ::ValueWithin(skill_id, EQ::skills::Skill1HBlunt, EQ::skills::HIGHEST_SKILL)) {
c->Message(Chat::White, "Usage: #setskill [Skill ID] [Skill Value]");
c->Message(Chat::White, fmt::format("Skill ID: 0 to {}", EQ::skills::HIGHEST_SKILL).c_str());
return;
}
const auto skill_type = static_cast<EQ::skills::SkillType>(skill_id);
t->SetSkill(
skill_type,
skill_value > t->MaxSkill(skill_type) ? t->MaxSkill(skill_type) : skill_value
); );
if ( if (c != t) {
skill_id >= EQ::skills::Skill1HBlunt &&
skill_id <= EQ::skills::HIGHEST_SKILL
) {
target->SetSkill(
(EQ::skills::SkillType) skill_id,
skill_value
);
if (c != target) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Set {} ({}) to {} for {}.", "Set {} ({}) to {} for {}.",
EQ::skills::GetSkillName((EQ::skills::SkillType) skill_id), EQ::skills::GetSkillName(skill_type),
skill_id, skill_id,
skill_value, skill_value > t->MaxSkill(skill_type) ? t->MaxSkill(skill_type) : skill_value,
c->GetTargetDescription(target) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
} }
} }
}
}
+27 -30
View File
@@ -2,45 +2,42 @@
void command_setskillall(Client *c, const Seperator *sep) void command_setskillall(Client *c, const Seperator *sep)
{ {
auto target = c; const auto arguments = sep->argnum;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient(); if (!arguments || !sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #setskillall [Skill Level] - Set all of your or your target's skills to the specified skill level");
return;
} }
if (!sep->IsNumber(1)) { auto t = c;
c->Message(Chat::White, "Usage: #setskillall [Skill Level] - Set all of your or your target's skills to the specified skill level"); if (c->GetTarget() && c->GetTarget()->IsClient()) {
c->Message( t = c->GetTarget()->CastToClient();
Chat::White, }
fmt::format(
"Note: Skill Level ranges from 0 to {}", if (c->Admin() < commandSetSkillsOther && t != c) {
HIGHEST_CAN_SET_SKILL c->Message(Chat::White, "Your status is not high enough to set another player's skills.");
).c_str() return;
); }
} else {
if (c->Admin() >= commandSetSkillsOther || c->GetTarget() == c) {
LogInfo(
"Set ALL skill request from [{}], target:[{}]",
c->GetCleanName(),
c->GetTargetDescription(target)
);
auto skill_level = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[1])); auto skill_level = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[1]));
for (const auto& s : EQ::skills::GetSkillTypeMap()) {
if (c != t) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Setting all skills to {} for {}.", "Setting {} ({}) to {} for {}.",
skill_level, s.second,
c->GetTargetDescription(target) s.first,
skill_level > t->MaxSkill(s.first) ? t->MaxSkill(s.first) : skill_level,
c->GetTargetDescription(t)
).c_str() ).c_str()
); );
for (EQ::skills::SkillType skill_num = EQ::skills::Skill1HBlunt; skill_num <= EQ::skills::HIGHEST_SKILL; skill_num = (EQ::skills::SkillType) (skill_num + 1)) {
target->SetSkill(skill_num, skill_level);
}
} else {
c->Message(Chat::White, "Your status is not high enough to set another player's skills.");
}
}
} }
t->SetSkill(
s.first,
skill_level > t->MaxSkill(s.first) ? t->MaxSkill(s.first) : skill_level
);
}
}
+24 -7
View File
@@ -2,19 +2,36 @@
void command_spawn(Client *c, const Seperator *sep) void command_spawn(Client *c, const Seperator *sep)
{ {
if (sep->arg[1][0] != 0) { const auto arguments = sep->argnum;
Client *client = entity_list.GetClientByName(sep->arg[1]); if (!arguments) {
if (client) { c->Message(Chat::White, "Usage: #spawn [Name]");
c->Message(
Chat::White,
"Optional Usage: #spawn [Name] [Race] [Level] [Texture] [Health] [Gender] [Class] [Primary Model] [Secondary Model] [Merchant ID] [Body Type]"
);
c->Message(
Chat::White,
"Name Format: NPCFirstname_NPCLastname - All numbers in a name are stripped and \"_\" characters become a space."
);
c->Message(
Chat::White,
"Note: Using \"-\" for gender will autoselect the gender for the race. Using \"-\" for HP will use the calculated maximum HP."
);
return;
}
const auto* m = entity_list.GetClientByName(sep->arg[1]);
if (m) {
c->Message(Chat::White, "You cannot spawn a mob with the same name as a character!"); c->Message(Chat::White, "You cannot spawn a mob with the same name as a character!");
return; return;
} }
}
NPC *npc = NPC::SpawnNPC(sep->argplus[1], c->GetPosition(), c); const auto* n = NPC::SpawnNPC(sep->argplus[1], c->GetPosition(), c);
if (!npc) { if (!n) {
c->Message(Chat::White, "Usage: #spawn [Name]");
c->Message( c->Message(
Chat::White, Chat::White,
"Format: #spawn name race level material hp gender class priweapon secweapon merchantid bodytype - spawns a npc those parameters." "Optional Usage: #spawn [Name] [Race] [Level] [Texture] [Health] [Gender] [Class] [Primary Model] [Secondary Model] [Merchant ID] [Body Type]"
); );
c->Message( c->Message(
Chat::White, Chat::White,
+10 -10
View File
@@ -3,18 +3,18 @@
void command_unscribespell(Client *c, const Seperator *sep) void command_unscribespell(Client *c, const Seperator *sep)
{ {
int arguments = sep->argnum; const auto arguments = sep->argnum;
if (!arguments || !sep->IsNumber(1)) { if (!arguments || !sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #unscribespell [Spell ID] - Unscribe a spell from your or your target's spell book by Spell ID"); c->Message(Chat::White, "Usage: #unscribespell [Spell ID] - Unscribe a spell from your or your target's spell book by Spell ID");
return; return;
} }
auto target = c; auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) { if (c->GetTarget() && c->GetTarget()->IsClient() && c->GetGM()) {
target = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
uint16 spell_id = EQ::Clamp(Strings::ToInt(sep->arg[1]), 0, 65535); const uint16 spell_id = EQ::Clamp(Strings::ToInt(sep->arg[1]), 0, 65535);
if (!IsValidSpell(spell_id)) { if (!IsValidSpell(spell_id)) {
c->Message( c->Message(
@@ -29,16 +29,16 @@ void command_unscribespell(Client *c, const Seperator *sep)
auto spell_name = GetSpellName(spell_id); auto spell_name = GetSpellName(spell_id);
if (target->HasSpellScribed(spell_id)) { if (t->HasSpellScribed(spell_id)) {
target->UnscribeSpellBySpellID(spell_id); t->UnscribeSpellBySpellID(spell_id);
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Unscribing {} ({}) for {}.", "Unscribing {} ({}) from {}.",
spell_name, spell_name,
spell_id, spell_id,
c->GetTargetDescription(target) c->GetTargetDescription(t, TargetDescriptionType::LCSelf)
).c_str() ).c_str()
); );
} else { } else {
@@ -46,8 +46,8 @@ void command_unscribespell(Client *c, const Seperator *sep)
Chat::White, Chat::White,
fmt::format( fmt::format(
"{} {} not have {} ({}) scribed.", "{} {} not have {} ({}) scribed.",
c->GetTargetDescription(target), c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == target ? "do" : "does", c == t ? "do" : "does",
spell_name, spell_name,
spell_id spell_id
).c_str() ).c_str()
+1 -1
View File
@@ -34,7 +34,7 @@ void command_xtargets(Client *c, const Seperator *sep)
fmt::format( fmt::format(
"Max number of XTargets set to {} for {}.", "Max number of XTargets set to {} for {}.",
new_max, new_max,
c->GetTargetDescription(t, TargetDescriptionType::LCSelf) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
} }
+8 -8
View File
@@ -2,16 +2,16 @@
void command_zheader(Client *c, const Seperator *sep) void command_zheader(Client *c, const Seperator *sep)
{ {
int arguments = sep->argnum; const auto arguments = sep->argnum;
if (!arguments) { if (!arguments) {
c->Message(Chat::White, "Usage: #zheader [Zone ID|Zone Short Name] [Version]"); c->Message(Chat::White, "Usage: #zheader [Zone ID|Zone Short Name] [Version]");
return; return;
} }
auto zone_id = ( const auto zone_id = (
sep->IsNumber(2) ? sep->IsNumber(1) ?
Strings::ToUnsignedInt(sep->arg[2]) : Strings::ToUnsignedInt(sep->arg[1]) :
ZoneID(sep->arg[2]) ZoneID(sep->arg[1])
); );
if (!zone_id) { if (!zone_id) {
c->Message( c->Message(
@@ -26,9 +26,9 @@ void command_zheader(Client *c, const Seperator *sep)
auto zone_short_name = ZoneName(zone_id); auto zone_short_name = ZoneName(zone_id);
auto zone_long_name = ZoneLongName(zone_id); auto zone_long_name = ZoneLongName(zone_id);
auto version = ( const auto version = (
sep->IsNumber(3) ? sep->IsNumber(2) ?
Strings::ToUnsignedInt(sep->arg[3]) : Strings::ToUnsignedInt(sep->arg[2]) :
0 0
); );
+7
View File
@@ -1156,6 +1156,13 @@ bool Group::LearnMembers() {
); );
} }
for(int i = 0; i < MAX_GROUP_MEMBERS; ++i)
{
members[i] = nullptr;
memset(membername[i],0,64);
MemberRoles[i] = 0;
}
int memberIndex = 0; int memberIndex = 0;
for (const auto& member : rows) { for (const auto& member : rows) {
if (memberIndex >= MAX_GROUP_MEMBERS) { if (memberIndex >= MAX_GROUP_MEMBERS) {
+38 -48
View File
@@ -42,19 +42,6 @@ HateList::~HateList()
{ {
} }
// added for frenzy support
// checks if target still is in frenzy mode
void HateList::IsEntityInFrenzyMode()
{
auto iterator = list.begin();
while (iterator != list.end())
{
if ((*iterator)->entity_on_hatelist->GetHPRatio() >= 20)
(*iterator)->is_entity_frenzy = false;
++iterator;
}
}
void HateList::WipeHateList() void HateList::WipeHateList()
{ {
auto iterator = list.begin(); auto iterator = list.begin();
@@ -155,28 +142,54 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater)
return current; return current;
} }
Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed) { Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilterType entity_type) {
Mob* close_entity = nullptr; Mob* close_entity = nullptr;
float close_distance = 99999.9f; float close_distance = 99999.9f;
float this_distance; float this_distance;
auto iterator = list.begin(); for (const auto& e : list) {
while (iterator != list.end()) { if (!e->entity_on_hatelist) {
if (skip_mezzed && (*iterator)->entity_on_hatelist->IsMezzed()) {
++iterator;
continue; continue;
} }
this_distance = DistanceSquaredNoZ((*iterator)->entity_on_hatelist->GetPosition(), hater->GetPosition()); if (skip_mezzed && e->entity_on_hatelist->IsMezzed()) {
if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) { continue;
close_distance = this_distance;
close_entity = (*iterator)->entity_on_hatelist;
}
++iterator;
} }
if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura())) switch (entity_type) {
case EntityFilterType::Bots:
if (!e->entity_on_hatelist->IsBot()) {
continue;
}
break;
case EntityFilterType::Clients:
if (!e->entity_on_hatelist->IsClient()) {
continue;
}
break;
case EntityFilterType::NPCs:
if (!e->entity_on_hatelist->IsNPC()) {
continue;
}
break;
case EntityFilterType::All:
default:
break;
}
this_distance = DistanceSquaredNoZ(e->entity_on_hatelist->GetPosition(), hater->GetPosition());
if (this_distance <= close_distance) {
close_distance = this_distance;
close_entity = e->entity_on_hatelist;
}
}
if (
(!close_entity && hater->IsNPC()) ||
(close_entity && close_entity->DivineAura())
) {
close_entity = hater->CastToNPC()->GetHateTop(); close_entity = hater->CastToNPC()->GetHateTop();
}
return close_entity; return close_entity;
} }
@@ -591,29 +604,6 @@ Mob *HateList::GetRandomEntOnHateList(bool skip_mezzed)
return nullptr; return nullptr;
} }
Mob *HateList::GetEscapingEntOnHateList() {
// function is still in design stage
for (auto iter : list) {
if (!iter->entity_on_hatelist)
continue;
if (!iter->entity_on_hatelist->IsFeared())
continue;
if (iter->entity_on_hatelist->IsRooted())
continue;
if (iter->entity_on_hatelist->IsMezzed())
continue;
if (iter->entity_on_hatelist->IsStunned())
continue;
return iter->entity_on_hatelist;
}
return nullptr;
}
Mob *HateList::GetEscapingEntOnHateList(Mob *center, float range, bool first) { Mob *HateList::GetEscapingEntOnHateList(Mob *center, float range, bool first) {
// function is still in design stage // function is still in design stage
+1 -3
View File
@@ -41,12 +41,11 @@ public:
HateList(); HateList();
~HateList(); ~HateList();
Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false); Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType entity_type = EntityFilterType::All);
Mob *GetDamageTopOnHateList(Mob *hater); // didn't add 'skip_mezzed' due to calls being in ::Death() Mob *GetDamageTopOnHateList(Mob *hater); // didn't add 'skip_mezzed' due to calls being in ::Death()
Mob *GetEntWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false); Mob *GetEntWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false);
Mob *GetRandomEntOnHateList(bool skip_mezzed = false); Mob *GetRandomEntOnHateList(bool skip_mezzed = false);
Mob *GetEntWithMostHateOnList(bool skip_mezzed = false); Mob *GetEntWithMostHateOnList(bool skip_mezzed = false);
Mob *GetEscapingEntOnHateList(); // returns first eligble entity
Mob *GetEscapingEntOnHateList(Mob *center, float range = 0.0f, bool first = false); Mob *GetEscapingEntOnHateList(Mob *center, float range = 0.0f, bool first = false);
Bot* GetRandomBotOnHateList(bool skip_mezzed = false); Bot* GetRandomBotOnHateList(bool skip_mezzed = false);
@@ -85,7 +84,6 @@ public:
bool add_to_hate_list_if_not_exist = true bool add_to_hate_list_if_not_exist = true
); );
void DoFactionHits(int64 npc_faction_level_id, int32 faction_id, int32 faction_value); void DoFactionHits(int64 npc_faction_level_id, int32 faction_id, int32 faction_value);
void IsEntityInFrenzyMode();
void PrintHateListToClient(Client *c); void PrintHateListToClient(Client *c);
void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage); void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage);
void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; } void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; }
+152 -164
View File
@@ -416,170 +416,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check for augment to item restriction // check for augment to item restriction
if (enforce_restrictions) { if (enforce_restrictions) {
bool is_restricted = false; bool is_restricted = IsAugmentRestricted(item->ItemType, augtest->AugRestrict);
uint8 item_type = item->ItemType;
switch (augtest->AugRestrict) {
case EQ::item::AugRestrictionAny:
break;
case EQ::item::AugRestrictionArmor:
switch (item_type) {
case EQ::item::ItemTypeArmor:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestrictionWeapons:
switch (item_type) {
case EQ::item::ItemType1HSlash:
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemType1HPiercing:
case EQ::item::ItemTypeMartial:
case EQ::item::ItemType2HSlash:
case EQ::item::ItemType2HBlunt:
case EQ::item::ItemType2HPiercing:
case EQ::item::ItemTypeBow:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction1HWeapons:
switch (item_type) {
case EQ::item::ItemType1HSlash:
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemType1HPiercing:
case EQ::item::ItemTypeMartial:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction2HWeapons:
switch (item_type) {
case EQ::item::ItemType2HSlash:
case EQ::item::ItemType2HBlunt:
case EQ::item::ItemType2HPiercing:
case EQ::item::ItemTypeBow:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction1HSlash:
switch (item_type) {
case EQ::item::ItemType1HSlash:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction1HBlunt:
switch (item_type) {
case EQ::item::ItemType1HBlunt:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestrictionPiercing:
switch (item_type) {
case EQ::item::ItemType1HPiercing:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestrictionHandToHand:
switch (item_type) {
case EQ::item::ItemTypeMartial:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction2HSlash:
switch (item_type) {
case EQ::item::ItemType2HSlash:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction2HBlunt:
switch (item_type) {
case EQ::item::ItemType2HBlunt:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction2HPierce:
switch (item_type) {
case EQ::item::ItemType2HPiercing:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestrictionBows:
switch (item_type) {
case EQ::item::ItemTypeBow:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestrictionShields:
switch (item_type) {
case EQ::item::ItemTypeShield:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction1HSlash1HBluntOrHandToHand:
switch (item_type) {
case EQ::item::ItemType1HSlash:
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemTypeMartial:
break;
default:
is_restricted = true;
break;
}
break;
case EQ::item::AugRestriction1HBluntOrHandToHand:
switch (item_type) {
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemTypeMartial:
break;
default:
is_restricted = true;
break;
}
break;
// These 3 are in-work
case EQ::item::AugRestrictionUnknown1:
case EQ::item::AugRestrictionUnknown2:
case EQ::item::AugRestrictionUnknown3:
default:
is_restricted = true;
break;
}
if (is_restricted) { if (is_restricted) {
Message( Message(
@@ -4766,3 +4603,154 @@ int32 Bot::GetAugmentIDAt(int16 slot_id, uint8 augslot) {
// None found // None found
return INVALID_ID; return INVALID_ID;
} }
bool Client::IsAugmentRestricted(uint8 item_type, uint32 augment_restriction)
{
switch (augment_restriction) {
case EQ::item::AugRestrictionAny:
break;
case EQ::item::AugRestrictionArmor:
switch (item_type) {
case EQ::item::ItemTypeArmor:
break;
default:
return true;
}
break;
case EQ::item::AugRestrictionWeapons:
switch (item_type) {
case EQ::item::ItemType1HSlash:
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemType1HPiercing:
case EQ::item::ItemTypeMartial:
case EQ::item::ItemType2HSlash:
case EQ::item::ItemType2HBlunt:
case EQ::item::ItemType2HPiercing:
case EQ::item::ItemTypeBow:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction1HWeapons:
switch (item_type) {
case EQ::item::ItemType1HSlash:
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemType1HPiercing:
case EQ::item::ItemTypeMartial:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction2HWeapons:
switch (item_type) {
case EQ::item::ItemType2HSlash:
case EQ::item::ItemType2HBlunt:
case EQ::item::ItemType2HPiercing:
case EQ::item::ItemTypeBow:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction1HSlash:
switch (item_type) {
case EQ::item::ItemType1HSlash:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction1HBlunt:
switch (item_type) {
case EQ::item::ItemType1HBlunt:
break;
default:
return true;
}
break;
case EQ::item::AugRestrictionPiercing:
switch (item_type) {
case EQ::item::ItemType1HPiercing:
break;
default:
return true;
}
break;
case EQ::item::AugRestrictionHandToHand:
switch (item_type) {
case EQ::item::ItemTypeMartial:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction2HSlash:
switch (item_type) {
case EQ::item::ItemType2HSlash:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction2HBlunt:
switch (item_type) {
case EQ::item::ItemType2HBlunt:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction2HPierce:
switch (item_type) {
case EQ::item::ItemType2HPiercing:
break;
default:
return true;
}
break;
case EQ::item::AugRestrictionBows:
switch (item_type) {
case EQ::item::ItemTypeBow:
break;
default:
return true;
}
break;
case EQ::item::AugRestrictionShields:
switch (item_type) {
case EQ::item::ItemTypeShield:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction1HSlash1HBluntOrHandToHand:
switch (item_type) {
case EQ::item::ItemType1HSlash:
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemTypeMartial:
break;
default:
return true;
}
break;
case EQ::item::AugRestriction1HBluntOrHandToHand:
switch (item_type) {
case EQ::item::ItemType1HBlunt:
case EQ::item::ItemTypeMartial:
break;
default:
return true;
}
break;
case EQ::item::AugRestrictionUnknown1:
case EQ::item::AugRestrictionUnknown2:
case EQ::item::AugRestrictionUnknown3:
default:
return true;
}
return false;
}
+6
View File
@@ -395,7 +395,13 @@ void NPC::AddLootDrop(
foundslot = i; foundslot = i;
} }
else { else {
// Unequip old item
auto* olditem = GetItem(i);
olditem->equip_slot = EQ::invslot::SLOT_INVALID;
equipment[i] = item2->ID; equipment[i] = item2->ID;
foundslot = i; foundslot = i;
found = true; found = true;
} }
+12
View File
@@ -2504,6 +2504,10 @@ int Lua_Client::GetSpellDamage() {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->GetSpellDmg(); return self->GetSpellDmg();
} }
int Lua_Client::GetIntoxication() {
Lua_Safe_Call_Int();
return self->GetIntoxication();
}
void Lua_Client::TaskSelector(luabind::adl::object table) { void Lua_Client::TaskSelector(luabind::adl::object table) {
TaskSelector(table, false); TaskSelector(table, false);
@@ -3050,6 +3054,12 @@ bool Lua_Client::ReloadDataBuckets() {
return DataBucket::GetDataBuckets(self); return DataBucket::GetDataBuckets(self);
} }
uint32 Lua_Client::GetEXPForLevel(uint16 check_level)
{
Lua_Safe_Call_Int();
return self->GetEXPForLevel(check_level);
}
luabind::scope lua_register_client() { luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client") return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@@ -3213,6 +3223,7 @@ luabind::scope lua_register_client() {
.def("GetDisciplineTimer", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetDisciplineTimer) .def("GetDisciplineTimer", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetDisciplineTimer)
.def("GetDuelTarget", (int(Lua_Client::*)(void))&Lua_Client::GetDuelTarget) .def("GetDuelTarget", (int(Lua_Client::*)(void))&Lua_Client::GetDuelTarget)
.def("GetEXP", (uint32(Lua_Client::*)(void))&Lua_Client::GetEXP) .def("GetEXP", (uint32(Lua_Client::*)(void))&Lua_Client::GetEXP)
.def("GetEXPForLevel", (uint32(Lua_Client::*)(uint16))&Lua_Client::GetEXPForLevel)
.def("GetEXPModifier", (double(Lua_Client::*)(uint32))&Lua_Client::GetEXPModifier) .def("GetEXPModifier", (double(Lua_Client::*)(uint32))&Lua_Client::GetEXPModifier)
.def("GetEXPModifier", (double(Lua_Client::*)(uint32,int16))&Lua_Client::GetEXPModifier) .def("GetEXPModifier", (double(Lua_Client::*)(uint32,int16))&Lua_Client::GetEXPModifier)
.def("GetEbonCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetEbonCrystals) .def("GetEbonCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetEbonCrystals)
@@ -3237,6 +3248,7 @@ luabind::scope lua_register_client() {
.def("GetIPExemption", (int(Lua_Client::*)(void))&Lua_Client::GetIPExemption) .def("GetIPExemption", (int(Lua_Client::*)(void))&Lua_Client::GetIPExemption)
.def("GetIPString", (std::string(Lua_Client::*)(void))&Lua_Client::GetIPString) .def("GetIPString", (std::string(Lua_Client::*)(void))&Lua_Client::GetIPString)
.def("GetInstrumentMod", (int(Lua_Client::*)(int))&Lua_Client::GetInstrumentMod) .def("GetInstrumentMod", (int(Lua_Client::*)(int))&Lua_Client::GetInstrumentMod)
.def("GetIntoxication", (int(Lua_Client::*)(void))&Lua_Client::GetIntoxication)
.def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory) .def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory)
.def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage) .def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage)
.def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt) .def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt)
+2
View File
@@ -395,6 +395,7 @@ public:
void QueuePacket(Lua_Packet app, bool ack_req, int client_connection_status, int filter); void QueuePacket(Lua_Packet app, bool ack_req, int client_connection_status, int filter);
int GetHunger(); int GetHunger();
int GetThirst(); int GetThirst();
int GetIntoxication();
void SetHunger(int in_hunger); void SetHunger(int in_hunger);
void SetThirst(int in_thirst); void SetThirst(int in_thirst);
void SetConsumption(int in_hunger, int in_thirst); void SetConsumption(int in_hunger, int in_thirst);
@@ -467,6 +468,7 @@ public:
void UseAugmentContainer(int container_slot); void UseAugmentContainer(int container_slot);
bool IsAutoAttackEnabled(); bool IsAutoAttackEnabled();
bool IsAutoFireEnabled(); bool IsAutoFireEnabled();
uint32 GetEXPForLevel(uint16 check_level);
void ApplySpell(int spell_id); void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration); void ApplySpell(int spell_id, int duration);
+1458 -1
View File
File diff suppressed because it is too large Load Diff
+43 -1
View File
@@ -2376,6 +2376,41 @@ Lua_Mob Lua_Mob::GetHateClosest() {
return Lua_Mob(self->GetHateClosest()); return Lua_Mob(self->GetHateClosest());
} }
Lua_Mob Lua_Mob::GetHateClosest(bool skip_mezzed) {
Lua_Safe_Call_Class(Lua_Mob);
return Lua_Mob(self->GetHateClosest(skip_mezzed));
}
Lua_Bot Lua_Mob::GetHateClosestBot() {
Lua_Safe_Call_Class(Lua_Bot);
return Lua_Bot(self->GetHateClosestBot());
}
Lua_Bot Lua_Mob::GetHateClosestBot(bool skip_mezzed) {
Lua_Safe_Call_Class(Lua_Bot);
return Lua_Bot(self->GetHateClosestBot());
}
Lua_Client Lua_Mob::GetHateClosestClient() {
Lua_Safe_Call_Class(Lua_Client);
return Lua_Client(self->GetHateClosestClient());
}
Lua_Client Lua_Mob::GetHateClosestClient(bool skip_mezzed) {
Lua_Safe_Call_Class(Lua_Client);
return Lua_Client(self->GetHateClosestClient(skip_mezzed));
}
Lua_NPC Lua_Mob::GetHateClosestNPC() {
Lua_Safe_Call_Class(Lua_NPC);
return Lua_NPC(self->GetHateClosestNPC());
}
Lua_NPC Lua_Mob::GetHateClosestNPC(bool skip_mezzed) {
Lua_Safe_Call_Class(Lua_NPC);
return Lua_NPC(self->GetHateClosestNPC(skip_mezzed));
}
Lua_HateList Lua_Mob::GetHateListByDistance() { Lua_HateList Lua_Mob::GetHateListByDistance() {
Lua_Safe_Call_Class(Lua_HateList); Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret; Lua_HateList ret;
@@ -3253,7 +3288,14 @@ luabind::scope lua_register_mob() {
.def("GetHaste", (int(Lua_Mob::*)(void))&Lua_Mob::GetHaste) .def("GetHaste", (int(Lua_Mob::*)(void))&Lua_Mob::GetHaste)
.def("GetHateAmount", (int64(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetHateAmount) .def("GetHateAmount", (int64(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetHateAmount)
.def("GetHateAmount", (int64(Lua_Mob::*)(Lua_Mob,bool))&Lua_Mob::GetHateAmount) .def("GetHateAmount", (int64(Lua_Mob::*)(Lua_Mob,bool))&Lua_Mob::GetHateAmount)
.def("GetHateClosest", &Lua_Mob::GetHateClosest) .def("GetHateClosest", (Lua_Mob(Lua_Mob::*)(void))&Lua_Mob::GetHateClosest)
.def("GetHateClosest", (Lua_Mob(Lua_Mob::*)(bool))&Lua_Mob::GetHateClosest)
.def("GetHateClosestBot", (Lua_Bot(Lua_Mob::*)(void))&Lua_Mob::GetHateClosestBot)
.def("GetHateClosestBot", (Lua_Bot(Lua_Mob::*)(bool))&Lua_Mob::GetHateClosestBot)
.def("GetHateClosestClient", (Lua_Client(Lua_Mob::*)(void))&Lua_Mob::GetHateClosestClient)
.def("GetHateClosestClient", (Lua_Client(Lua_Mob::*)(bool))&Lua_Mob::GetHateClosestClient)
.def("GetHateClosestNPC", (Lua_NPC(Lua_Mob::*)(void))&Lua_Mob::GetHateClosestNPC)
.def("GetHateClosestNPC", (Lua_NPC(Lua_Mob::*)(bool))&Lua_Mob::GetHateClosestNPC)
.def("GetHateDamageTop", (Lua_Mob(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetHateDamageTop) .def("GetHateDamageTop", (Lua_Mob(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetHateDamageTop)
.def("GetHateList", &Lua_Mob::GetHateList) .def("GetHateList", &Lua_Mob::GetHateList)
.def("GetHateListBots", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListBots) .def("GetHateListBots", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListBots)
+7
View File
@@ -227,6 +227,13 @@ public:
Lua_Client GetHateRandomClient(); Lua_Client GetHateRandomClient();
Lua_NPC GetHateRandomNPC(); Lua_NPC GetHateRandomNPC();
Lua_Mob GetHateClosest(); Lua_Mob GetHateClosest();
Lua_Mob GetHateClosest(bool skip_mezzed);
Lua_Bot GetHateClosestBot();
Lua_Bot GetHateClosestBot(bool skip_mezzed);
Lua_Client GetHateClosestClient();
Lua_Client GetHateClosestClient(bool skip_mezzed);
Lua_NPC GetHateClosestNPC();
Lua_NPC GetHateClosestNPC(bool skip_mezzed);
void AddToHateList(Lua_Mob other); void AddToHateList(Lua_Mob other);
void AddToHateList(Lua_Mob other, int64 hate); void AddToHateList(Lua_Mob other, int64 hate);
void AddToHateList(Lua_Mob other, int64 hate, int64 damage); void AddToHateList(Lua_Mob other, int64 hate, int64 damage);
+9 -1
View File
@@ -164,7 +164,11 @@ const char *LuaEvents[_LargestEventID] = {
"event_item_click_client", "event_item_click_client",
"event_item_click_cast_client", "event_item_click_cast_client",
"event_destroy_item_client", "event_destroy_item_client",
"event_drop_item_client" "event_drop_item_client",
"event_memorize_spell",
"event_unmemorize_spell",
"event_scribe_spell",
"event_unscribe_spell"
}; };
extern Zone *zone; extern Zone *zone;
@@ -292,6 +296,10 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_DESTROY_ITEM_CLIENT] = handle_player_destroy_item; PlayerArgumentDispatch[EVENT_DESTROY_ITEM_CLIENT] = handle_player_destroy_item;
PlayerArgumentDispatch[EVENT_TARGET_CHANGE] = handle_player_target_change; PlayerArgumentDispatch[EVENT_TARGET_CHANGE] = handle_player_target_change;
PlayerArgumentDispatch[EVENT_DROP_ITEM_CLIENT] = handle_player_drop_item; PlayerArgumentDispatch[EVENT_DROP_ITEM_CLIENT] = handle_player_drop_item;
PlayerArgumentDispatch[EVENT_MEMORIZE_SPELL] = handle_player_memorize_scribe_spell;
PlayerArgumentDispatch[EVENT_UNMEMORIZE_SPELL] = handle_player_memorize_scribe_spell;
PlayerArgumentDispatch[EVENT_SCRIBE_SPELL] = handle_player_memorize_scribe_spell;
PlayerArgumentDispatch[EVENT_UNSCRIBE_SPELL] = handle_player_memorize_scribe_spell;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
+29
View File
@@ -1411,6 +1411,35 @@ void handle_player_target_change(
} }
} }
void handle_player_memorize_scribe_spell(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "slot_id");
lua_pushnumber(L, Strings::ToUnsignedInt(sep.arg[1]));
lua_setfield(L, -2, "spell_id");
if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[1]))) {
Lua_Spell l_spell(&spells[Strings::ToUnsignedInt(sep.arg[1])]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
l_spell_o.push(L);
lua_setfield(L, -2, "spell");
} else {
Lua_Spell l_spell(nullptr);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
l_spell_o.push(L);
lua_setfield(L, -2, "spell");
}
}
// Item // Item
void handle_item_click( void handle_item_click(
QuestInterface *parse, QuestInterface *parse,
+9
View File
@@ -734,6 +734,15 @@ void handle_player_drop_item(
std::vector<std::any> *extra_pointers std::vector<std::any> *extra_pointers
); );
void handle_player_memorize_scribe_spell(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Item // Item
void handle_item_click( void handle_item_click(
QuestInterface *parse, QuestInterface *parse,
+1 -1
View File
@@ -770,7 +770,7 @@ void Merc::CalcRestState() {
for (unsigned int j = 0; j < buff_count; j++) { for (unsigned int j = 0; j < buff_count; j++) {
if(IsValidSpell(buffs[j].spellid)) { if(IsValidSpell(buffs[j].spellid)) {
if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0)) if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
if(!DetrimentalSpellAllowsRest(buffs[j].spellid)) if(!IsRestAllowedSpell(buffs[j].spellid))
return; return;
} }
} }
-7
View File
@@ -1,7 +0,0 @@
struct Msg {
int id;
char* Sender;
char* Subject;
char* Body;
char* Date;
};
+5 -1
View File
@@ -2483,8 +2483,12 @@ void Mob::SendIllusionPacket(
// update internal values for mob // update internal values for mob
size = (in_size <= 0.0f) ? GetRaceGenderDefaultHeight(race, gender) : in_size; size = (in_size <= 0.0f) ? GetRaceGenderDefaultHeight(race, gender) : in_size;
if (new_texture != 0xFF) {
texture = new_texture; texture = new_texture;
}
if (new_helmtexture != 0xFF) {
helmtexture = new_helmtexture; helmtexture = new_helmtexture;
}
haircolor = new_haircolor; haircolor = new_haircolor;
beardcolor = new_beardcolor; beardcolor = new_beardcolor;
eyecolor1 = new_eyecolor1; eyecolor1 = new_eyecolor1;
@@ -4391,7 +4395,7 @@ int Mob::CountDispellableBuffs()
if(buffs[x].counters) if(buffs[x].counters)
continue; continue;
if(spells[buffs[x].spellid].good_effect == 0) if(spells[buffs[x].spellid].good_effect == DETRIMENTAL_EFFECT)
continue; continue;
if(IsValidSpell(buffs[x].spellid) && spells[buffs[x].spellid].buff_duration_formula != DF_Permanent) { if(IsValidSpell(buffs[x].spellid) && spells[buffs[x].spellid].buff_duration_formula != DF_Permanent) {
+4 -1
View File
@@ -732,7 +732,10 @@ public:
NPC* GetHateRandomNPC() { return hate_list.GetRandomNPCOnHateList(); } NPC* GetHateRandomNPC() { return hate_list.GetRandomNPCOnHateList(); }
Bot* GetHateRandomBot() { return hate_list.GetRandomBotOnHateList(); } Bot* GetHateRandomBot() { return hate_list.GetRandomBotOnHateList(); }
Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();}
Mob* GetHateClosest() { return hate_list.GetClosestEntOnHateList(this); } Mob* GetHateClosest(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed); }
Bot* GetHateClosestBot(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Bots)->CastToBot(); }
Client* GetHateClosestClient(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Clients)->CastToClient(); }
NPC* GetHateClosestNPC(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::NPCs)->CastToNPC(); }
bool IsEngaged() { return(!hate_list.IsHateListEmpty()); } bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
bool HasPrimaryAggro() { return PrimaryAggro; } bool HasPrimaryAggro() { return PrimaryAggro; }
bool HasAssistAggro() { return AssistAggro; } bool HasAssistAggro() { return AssistAggro; }
+1 -1
View File
@@ -653,7 +653,7 @@ void Client::AI_SpellCast()
slot_to_use = static_cast<EQ::spells::CastingSlot>(slots[idx]); slot_to_use = static_cast<EQ::spells::CastingSlot>(slots[idx]);
} }
if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast)) if(IsMesmerizeSpell(spell_to_cast) || IsFearSpell(spell_to_cast))
{ {
Mob *tar = entity_list.GetTargetForMez(this); Mob *tar = entity_list.GetTargetForMez(this);
if(!tar) if(!tar)
+63 -25
View File
@@ -832,14 +832,6 @@ void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_
platinum = 0; platinum = 0;
} }
void NPC::AddCash()
{
copper = zone->random.Int(1, 100);
silver = zone->random.Int(1, 50);
gold = zone->random.Int(1, 10);
platinum = zone->random.Int(1, 5);
}
void NPC::RemoveCash() { void NPC::RemoveCash() {
copper = 0; copper = 0;
silver = 0; silver = 0;
@@ -1194,7 +1186,7 @@ bool NPC::DatabaseCastAccepted(int spell_id) {
break; break;
} }
default: default:
if(spells[spell_id].good_effect == 1 && !(spells[spell_id].buff_duration == 0 && GetHPRatio() == 100) && !IsEngaged()) if(spells[spell_id].good_effect == BENEFICIAL_EFFECT && !(spells[spell_id].buff_duration == 0 && GetHPRatio() == 100) && !IsEngaged())
return true; return true;
return false; return false;
} }
@@ -1387,42 +1379,54 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
if (!sep.IsNumber(1)) { if (!sep.IsNumber(1)) {
sprintf(sep.arg[1], "1"); sprintf(sep.arg[1], "1");
} }
if (!sep.IsNumber(2)) { if (!sep.IsNumber(2)) {
sprintf(sep.arg[2], "1"); sprintf(sep.arg[2], "1");
} }
if (!sep.IsNumber(3)) { if (!sep.IsNumber(3)) {
sprintf(sep.arg[3], "0"); sprintf(sep.arg[3], "0");
} }
if (Strings::ToInt(sep.arg[4]) > 2100000000 || Strings::ToInt(sep.arg[4]) <= 0) { if (Strings::ToInt(sep.arg[4]) > 2100000000 || Strings::ToInt(sep.arg[4]) <= 0) {
sprintf(sep.arg[4], " "); sprintf(sep.arg[4], " ");
} }
if (!strcmp(sep.arg[5], "-")) { if (!strcmp(sep.arg[5], "-")) {
sprintf(sep.arg[5], " "); sprintf(sep.arg[5], " ");
} }
if (!sep.IsNumber(5)) { if (!sep.IsNumber(5)) {
sprintf(sep.arg[5], " "); sprintf(sep.arg[5], " ");
} }
if (!sep.IsNumber(6)) { if (!sep.IsNumber(6)) {
sprintf(sep.arg[6], "1"); sprintf(sep.arg[6], "1");
} }
if (!sep.IsNumber(8)) { if (!sep.IsNumber(8)) {
sprintf(sep.arg[8], "0"); sprintf(sep.arg[8], "0");
} }
if (!sep.IsNumber(9)) { if (!sep.IsNumber(9)) {
sprintf(sep.arg[9], "0"); sprintf(sep.arg[9], "0");
} }
if (!sep.IsNumber(7)) { if (!sep.IsNumber(7)) {
sprintf(sep.arg[7], "0"); sprintf(sep.arg[7], "0");
} }
if (!strcmp(sep.arg[4], "-")) { if (!strcmp(sep.arg[4], "-")) {
sprintf(sep.arg[4], " "); sprintf(sep.arg[4], " ");
} }
if (!sep.IsNumber(10)) { // bodytype if (!sep.IsNumber(10)) { // bodytype
sprintf(sep.arg[10], "0"); sprintf(sep.arg[10], "0");
} }
//Calc MaxHP if client neglected to enter it... //Calc MaxHP if client neglected to enter it...
if (sep.arg[4] && !sep.IsNumber(4)) { if (sep.arg[4] && !sep.IsNumber(4)) {
sprintf(sep.arg[4], "0"); sprintf(sep.arg[4], "1");
} }
// Autoselect NPC Gender // Autoselect NPC Gender
@@ -1435,6 +1439,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
memset(npc_type, 0, sizeof(NPCType)); memset(npc_type, 0, sizeof(NPCType));
strncpy(npc_type->name, sep.arg[0], 60); strncpy(npc_type->name, sep.arg[0], 60);
npc_type->current_hp = Strings::ToInt(sep.arg[4]); npc_type->current_hp = Strings::ToInt(sep.arg[4]);
npc_type->max_hp = Strings::ToInt(sep.arg[4]); npc_type->max_hp = Strings::ToInt(sep.arg[4]);
npc_type->race = Strings::ToInt(sep.arg[1]); npc_type->race = Strings::ToInt(sep.arg[1]);
@@ -1445,8 +1450,8 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
npc_type->npc_id = 0; npc_type->npc_id = 0;
npc_type->loottable_id = 0; npc_type->loottable_id = 0;
npc_type->texture = Strings::ToInt(sep.arg[3]); npc_type->texture = Strings::ToInt(sep.arg[3]);
npc_type->light = 0; // spawncommand needs update npc_type->light = 0;
npc_type->runspeed = 1.25; npc_type->runspeed = 1.25f;
npc_type->d_melee_texture1 = Strings::ToInt(sep.arg[7]); npc_type->d_melee_texture1 = Strings::ToInt(sep.arg[7]);
npc_type->d_melee_texture2 = Strings::ToInt(sep.arg[8]); npc_type->d_melee_texture2 = Strings::ToInt(sep.arg[8]);
npc_type->merchanttype = Strings::ToInt(sep.arg[9]); npc_type->merchanttype = Strings::ToInt(sep.arg[9]);
@@ -1462,8 +1467,8 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
npc_type->attack_delay = 3000; npc_type->attack_delay = 3000;
npc_type->prim_melee_type = 28; npc_type->prim_melee_type = static_cast<uint8>(EQ::skills::SkillHandtoHand);
npc_type->sec_melee_type = 28; npc_type->sec_melee_type = static_cast<uint8>(EQ::skills::SkillHandtoHand);
auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Water); auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Water);
npc->GiveNPCTypeData(npc_type); npc->GiveNPCTypeData(npc_type);
@@ -1472,17 +1477,34 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
if (client) { if (client) {
// Notify client of spawn data // Notify client of spawn data
client->Message(Chat::White, "New spawn:"); client->Message(Chat::White, fmt::format("Name | {}", npc->name).c_str());
client->Message(Chat::White, "Name: %s", npc->name); client->Message(Chat::White, fmt::format("Level | {}", npc->level).c_str());
client->Message(Chat::White, "Race: %u", npc->race); client->Message(Chat::White, fmt::format("Health | {}", npc->max_hp).c_str());
client->Message(Chat::White, "Level: %u", npc->level); client->Message(Chat::White, fmt::format("Race | {} ({})", GetRaceIDName(npc->race), npc->race).c_str());
client->Message(Chat::White, "Material: %u", npc->texture); client->Message(Chat::White, fmt::format("Class | {} ({})", GetClassIDName(npc->class_), npc->class_).c_str());
client->Message(Chat::White, "Current/Max HP: %i", npc->max_hp); client->Message(Chat::White, fmt::format("Gender | {} ({})", GetGenderName(npc->gender), npc->gender).c_str());
client->Message(Chat::White, "Gender: %u", npc->gender); client->Message(Chat::White, fmt::format("Texture | {}", npc->texture).c_str());
client->Message(Chat::White, "Class: %u", npc->class_);
client->Message(Chat::White, "Weapon Item Number: %u/%u", npc->d_melee_texture1, npc->d_melee_texture2); if (npc->d_melee_texture1 || npc->d_melee_texture2) {
client->Message(Chat::White, "MerchantID: %u", npc->MerchantType); client->Message(
client->Message(Chat::White, "Bodytype: %u", npc->bodytype); Chat::White,
fmt::format(
"Weapon Item Number | Primary: {} Secondary: {}",
npc->d_melee_texture1,
npc->d_melee_texture2
).c_str()
);
}
if (npc->MerchantType) {
client->Message(Chat::White, fmt::format("Merchant ID | {}", npc->MerchantType).c_str());
}
if (npc->bodytype) {
client->Message(Chat::White, fmt::format("Body Type | {} ({})", EQ::constants::GetBodyTypeName(npc->bodytype), npc->bodytype).c_str());
}
client->Message(Chat::White, "New NPC spawned!");
} }
return npc; return npc;
@@ -2612,14 +2634,30 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value)
} }
else if (stat_lower == "min_hit") { else if (stat_lower == "min_hit") {
min_dmg = Strings::ToInt(value); min_dmg = Strings::ToInt(value);
// TODO: fix DB // TODO: fix DB
if (min_dmg > max_dmg) {
const auto temporary_damage = max_dmg;
max_dmg = min_dmg;
min_dmg = temporary_damage;
}
base_damage = round((max_dmg - min_dmg) / 1.9); base_damage = round((max_dmg - min_dmg) / 1.9);
min_damage = min_dmg - round(base_damage / 10.0); min_damage = min_dmg - round(base_damage / 10.0);
return; return;
} }
else if (stat_lower == "max_hit") { else if (stat_lower == "max_hit") {
max_dmg = Strings::ToInt(value); max_dmg = Strings::ToInt(value);
// TODO: fix DB // TODO: fix DB
if (max_dmg < min_dmg) {
const auto temporary_damage = min_dmg;
min_dmg = max_dmg;
max_dmg = temporary_damage;
}
base_damage = round((max_dmg - min_dmg) / 1.9); base_damage = round((max_dmg - min_dmg) / 1.9);
min_damage = min_dmg - round(base_damage / 10.0); min_damage = min_dmg - round(base_damage / 10.0);
return; return;
-3
View File
@@ -191,8 +191,6 @@ public:
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name); void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
void SetPetState(SpellBuff_Struct *buffs, uint32 *items); void SetPetState(SpellBuff_Struct *buffs, uint32 *items);
void InteractiveChat(uint8 chan_num, uint8 language, const char * message, const char* targetname,Mob* sender);
void TakenAction(uint8 action,Mob* actiontaker);
virtual void SpellProcess(); virtual void SpellProcess();
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
@@ -208,7 +206,6 @@ public:
inline const ItemList &GetItemList() { return itemlist; } inline const ItemList &GetItemList() { return itemlist; }
ServerLootItem_Struct* GetItem(int slot_id); ServerLootItem_Struct* GetItem(int slot_id);
void AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum); void AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum);
void AddCash();
void RemoveCash(); void RemoveCash();
void QueryLoot(Client* to, bool is_pet_query = false); void QueryLoot(Client* to, bool is_pet_query = false);
bool HasItem(uint32 item_id); bool HasItem(uint32 item_id);
+4 -1
View File
@@ -135,6 +135,8 @@ void NpcScaleManager::ScaleNPC(
npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist)); npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist));
} }
auto min_damage_set = false;
if (always_scale || npc->GetMinDMG() == 0) { if (always_scale || npc->GetMinDMG() == 0) {
int64 min_dmg = scale_data.min_dmg; int64 min_dmg = scale_data.min_dmg;
if (RuleB(Combat, UseNPCDamageClassLevelMods)) { if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
@@ -145,9 +147,10 @@ void NpcScaleManager::ScaleNPC(
} }
npc->ModifyNPCStat("min_hit", std::to_string(min_dmg)); npc->ModifyNPCStat("min_hit", std::to_string(min_dmg));
min_damage_set = true;
} }
if (always_scale || npc->GetMaxDMG() == 0) { if (always_scale || npc->GetMaxDMG() == 0 || min_damage_set) {
int64 max_dmg = scale_data.max_dmg; int64 max_dmg = scale_data.max_dmg;
if (RuleB(Combat, UseNPCDamageClassLevelMods)) { if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
uint32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass()); uint32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass());
-2
View File
@@ -112,8 +112,6 @@ public:
static void HandleAugmentation(Client* user, const AugmentItem_Struct* in_augment, Object *worldo); static void HandleAugmentation(Client* user, const AugmentItem_Struct* in_augment, Object *worldo);
static void HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac); static void HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac);
static EQ::skills::SkillType TypeToSkill(uint32 type);
// Packet functions // Packet functions
void CreateSpawnPacket(EQApplicationPacket* app); void CreateSpawnPacket(EQApplicationPacket* app);
void CreateDeSpawnPacket(EQApplicationPacket* app); void CreateDeSpawnPacket(EQApplicationPacket* app);
+13 -1
View File
@@ -1522,6 +1522,11 @@ int Perl_Client_GetThirst(Client* self) // @categories Account and Character, St
return self->GetThirst(); return self->GetThirst();
} }
int Perl_Client_GetIntoxication(Client* self) // @categories Account and Character, Stats and Attributes
{
return self->GetIntoxication();
}
void Perl_Client_SetHunger(Client* self, int in_hunger) // @categories Script Utility, Stats and Attributes void Perl_Client_SetHunger(Client* self, int in_hunger) // @categories Script Utility, Stats and Attributes
{ {
self->SetHunger(in_hunger); self->SetHunger(in_hunger);
@@ -1550,7 +1555,7 @@ void Perl_Client_SilentMessage(Client* self, const char* message) // @categories
if (self->GetTarget()->CastToNPC()->IsMoving() && if (self->GetTarget()->CastToNPC()->IsMoving() &&
!self->GetTarget()->CastToNPC()->IsOnHatelist(self->GetTarget())) !self->GetTarget()->CastToNPC()->IsOnHatelist(self->GetTarget()))
self->GetTarget()->CastToNPC()->PauseWandering(RuleI(NPC, SayPauseTimeInSec)); self->GetTarget()->CastToNPC()->PauseWandering(RuleI(NPC, SayPauseTimeInSec));
self->ChannelMessageReceived(8, 0, 100, message, nullptr, true); self->ChannelMessageReceived(ChatChannel_Say, 0, 100, message, nullptr, true);
} }
} }
} }
@@ -2907,6 +2912,11 @@ bool Perl_Client_ReloadDataBuckets(Client* self)
return DataBucket::GetDataBuckets(self); return DataBucket::GetDataBuckets(self);
} }
uint32 Perl_Client_GetEXPForLevel(Client* self, uint16 check_level)
{
return self->GetEXPForLevel(check_level);
}
void perl_register_client() void perl_register_client()
{ {
perl::interpreter perl(PERL_GET_THX); perl::interpreter perl(PERL_GET_THX);
@@ -3070,6 +3080,7 @@ void perl_register_client()
package.add("GetDuelTarget", &Perl_Client_GetDuelTarget); package.add("GetDuelTarget", &Perl_Client_GetDuelTarget);
package.add("GetEnvironmentDamageModifier", &Perl_Client_GetEnvironmentDamageModifier); package.add("GetEnvironmentDamageModifier", &Perl_Client_GetEnvironmentDamageModifier);
package.add("GetEXP", &Perl_Client_GetEXP); package.add("GetEXP", &Perl_Client_GetEXP);
package.add("GetEXPForLevel", &Perl_Client_GetEXPForLevel);
package.add("GetEXPModifier", (double(*)(Client*, uint32))&Perl_Client_GetEXPModifier); package.add("GetEXPModifier", (double(*)(Client*, uint32))&Perl_Client_GetEXPModifier);
package.add("GetEXPModifier", (double(*)(Client*, uint32, int16))&Perl_Client_GetEXPModifier); package.add("GetEXPModifier", (double(*)(Client*, uint32, int16))&Perl_Client_GetEXPModifier);
package.add("GetEbonCrystals", &Perl_Client_GetEbonCrystals); package.add("GetEbonCrystals", &Perl_Client_GetEbonCrystals);
@@ -3093,6 +3104,7 @@ void perl_register_client()
package.add("GetHorseId", &Perl_Client_GetHorseId); package.add("GetHorseId", &Perl_Client_GetHorseId);
package.add("GetHealAmount", &Perl_Client_GetHealAmount); package.add("GetHealAmount", &Perl_Client_GetHealAmount);
package.add("GetHunger", &Perl_Client_GetHunger); package.add("GetHunger", &Perl_Client_GetHunger);
package.add("GetIntoxication", &Perl_Client_GetIntoxication);
package.add("GetIP", &Perl_Client_GetIP); package.add("GetIP", &Perl_Client_GetIP);
package.add("GetIPExemption", &Perl_Client_GetIPExemption); package.add("GetIPExemption", &Perl_Client_GetIPExemption);
package.add("GetIPString", &Perl_Client_GetIPString); package.add("GetIPString", &Perl_Client_GetIPString);
+49 -1
View File
@@ -1054,6 +1054,11 @@ void Perl_Mob_SetPetID(Mob* self, uint16 new_pet_id) // @categories Pet
self->SetPetID(new_pet_id); self->SetPetID(new_pet_id);
} }
Mob* Perl_Mob_GetPet(Mob* self) // @categories Script Utility, Pet
{
return self->GetPet();
}
int Perl_Mob_GetPetID(Mob* self) // @categories Script Utility, Pet int Perl_Mob_GetPetID(Mob* self) // @categories Script Utility, Pet
{ {
return self->GetPetID(); return self->GetPetID();
@@ -2432,6 +2437,41 @@ Mob* Perl_Mob_GetHateClosest(Mob* self) // @categories Hate and Aggro
return self->GetHateClosest(); return self->GetHateClosest();
} }
Mob* Perl_Mob_GetHateClosest(Mob* self, bool skip_mezzed) // @categories Hate and Aggro
{
return self->GetHateClosest(skip_mezzed);
}
Bot* Perl_Mob_GetHateClosestBot(Mob* self) // @categories Hate and Aggro
{
return self->GetHateClosestBot();
}
Bot* Perl_Mob_GetHateClosestBot(Mob* self, bool skip_mezzed) // @categories Hate and Aggro
{
return self->GetHateClosestBot(skip_mezzed);
}
Client* Perl_Mob_GetHateClosestClient(Mob* self) // @categories Hate and Aggro
{
return self->GetHateClosestClient();
}
Client* Perl_Mob_GetHateClosestClient(Mob* self, bool skip_mezzed) // @categories Hate and Aggro
{
return self->GetHateClosestClient(skip_mezzed);
}
NPC* Perl_Mob_GetHateClosestNPC(Mob* self) // @categories Hate and Aggro
{
return self->GetHateClosestNPC();
}
NPC* Perl_Mob_GetHateClosestNPC(Mob* self, bool skip_mezzed) // @categories Hate and Aggro
{
return self->GetHateClosestNPC(skip_mezzed);
}
std::string Perl_Mob_GetLastName(Mob* self) // @categories Script Utility std::string Perl_Mob_GetLastName(Mob* self) // @categories Script Utility
{ {
return self->GetLastName(); return self->GetLastName();
@@ -3188,7 +3228,14 @@ void perl_register_mob()
package.add("GetHaste", &Perl_Mob_GetHaste); package.add("GetHaste", &Perl_Mob_GetHaste);
package.add("GetHateAmount", (int64_t(*)(Mob*, Mob*))&Perl_Mob_GetHateAmount); package.add("GetHateAmount", (int64_t(*)(Mob*, Mob*))&Perl_Mob_GetHateAmount);
package.add("GetHateAmount", (int64_t(*)(Mob*, Mob*, bool))&Perl_Mob_GetHateAmount); package.add("GetHateAmount", (int64_t(*)(Mob*, Mob*, bool))&Perl_Mob_GetHateAmount);
package.add("GetHateClosest", &Perl_Mob_GetHateClosest); package.add("GetHateClosest", (Mob*(*)(Mob*))&Perl_Mob_GetHateClosest);
package.add("GetHateClosest", (Mob*(*)(Mob*, bool))&Perl_Mob_GetHateClosest);
package.add("GetHateClosestBot", (Bot*(*)(Mob*))&Perl_Mob_GetHateClosestBot);
package.add("GetHateClosestBot", (Bot*(*)(Mob*, bool))&Perl_Mob_GetHateClosestBot);
package.add("GetHateClosestClient", (Client*(*)(Mob*))&Perl_Mob_GetHateClosestClient);
package.add("GetHateClosestClient", (Client*(*)(Mob*, bool))&Perl_Mob_GetHateClosestClient);
package.add("GetHateClosestNPC", (NPC*(*)(Mob*))&Perl_Mob_GetHateClosestNPC);
package.add("GetHateClosestNPC", (NPC*(*)(Mob*, bool))&Perl_Mob_GetHateClosestNPC);
package.add("GetHateDamageTop", &Perl_Mob_GetHateDamageTop); package.add("GetHateDamageTop", &Perl_Mob_GetHateDamageTop);
package.add("GetHateList", &Perl_Mob_GetHateList); package.add("GetHateList", &Perl_Mob_GetHateList);
package.add("GetHateListBots", (perl::array(*)(Mob*))&Perl_Mob_GetHateListBots); package.add("GetHateListBots", (perl::array(*)(Mob*))&Perl_Mob_GetHateListBots);
@@ -3242,6 +3289,7 @@ void perl_register_mob()
package.add("GetOwner", &Perl_Mob_GetOwner); package.add("GetOwner", &Perl_Mob_GetOwner);
package.add("GetOwnerID", &Perl_Mob_GetOwnerID); package.add("GetOwnerID", &Perl_Mob_GetOwnerID);
package.add("GetPR", &Perl_Mob_GetPR); package.add("GetPR", &Perl_Mob_GetPR);
package.add("GetPet", &Perl_Mob_GetPet);
package.add("GetPetID", &Perl_Mob_GetPetID); package.add("GetPetID", &Perl_Mob_GetPetID);
package.add("GetPetOrder", &Perl_Mob_GetPetOrder); package.add("GetPetOrder", &Perl_Mob_GetPetOrder);
package.add("GetPetType", &Perl_Mob_GetPetType); package.add("GetPetType", &Perl_Mob_GetPetType);
+14 -13
View File
@@ -406,21 +406,22 @@ bool ZoneDatabase::GetPoweredPetEntry(const char *pet_type, int16 petpower, PetR
} }
Mob* Mob::GetPet() { Mob* Mob::GetPet() {
if(GetPetID() == 0) if (!GetPetID()) {
return(nullptr); return nullptr;
Mob* tmp = entity_list.GetMob(GetPetID());
if(tmp == nullptr) {
SetPetID(0);
return(nullptr);
} }
if(tmp->GetOwnerID() != GetID()) { const auto m = entity_list.GetMob(GetPetID());
if (!m) {
SetPetID(0); SetPetID(0);
return(nullptr); return nullptr;
} }
return(tmp); if (m->GetOwnerID() != GetID()) {
SetPetID(0);
return nullptr;
}
return m;
} }
bool Mob::HasPet() const { bool Mob::HasPet() const {
@@ -537,13 +538,13 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) {
case SE_WeaponProc: case SE_WeaponProc:
// We need to reapply buff based procs // We need to reapply buff based procs
// We need to do this here so suspended pets also regain their procs. // We need to do this here so suspended pets also regain their procs.
AddProcToWeapon(GetProcID(buffs[j1].spellid,x1), false, 100+spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC)); AddProcToWeapon(GetProcID(buffs[j1].spellid,x1), false, 100+spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
break; break;
case SE_DefensiveProc: case SE_DefensiveProc:
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC)); AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
break; break;
case SE_RangedProc: case SE_RangedProc:
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC)); AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
break; break;
case SE_Charm: case SE_Charm:
case SE_Rune: case SE_Rune:
+1 -2
View File
@@ -116,7 +116,6 @@ public:
virtual uint32 GetIdentifier() = 0; virtual uint32 GetIdentifier() = 0;
virtual void RemoveEncounter(const std::string &name) { } virtual void RemoveEncounter(const std::string &name) { }
//TODO: Set maximum quest errors instead of hard coding it
virtual void GetErrors(std::list<std::string> &quest_errors) { virtual void GetErrors(std::list<std::string> &quest_errors) {
quest_errors.insert(quest_errors.end(), errors_.begin(), errors_.end()); quest_errors.insert(quest_errors.end(), errors_.begin(), errors_.end());
} }
@@ -126,7 +125,7 @@ public:
LogQuestErrors("{}", Strings::Trim(error)); LogQuestErrors("{}", Strings::Trim(error));
errors_.push_back(error); errors_.push_back(error);
if(errors_.size() > 30) { if (errors_.size() > RuleI(World, MaximumQuestErrors)) {
errors_.pop_front(); errors_.pop_front();
} }
} }
+15
View File
@@ -2887,6 +2887,21 @@ void QuestManager::we(int type, const char *str) {
); );
} }
void QuestManager::SendChannelMessage(uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message)
{
worldserver.SendChannelMessage(0, 0, channel_number, guild_id, language_id, language_skill, message);
}
void QuestManager::SendChannelMessage(Client* from, uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message)
{
worldserver.SendChannelMessage(from, 0, channel_number, guild_id, language_id, language_skill, message);
}
void QuestManager::SendChannelMessage(Client* from, const char* to, uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message)
{
worldserver.SendChannelMessage(from, to, channel_number, guild_id, language_id, language_skill, message);
}
void QuestManager::message(uint32 type, const char *message) { void QuestManager::message(uint32 type, const char *message) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
if (!initiator) { if (!initiator) {
+3
View File
@@ -348,6 +348,9 @@ public:
bool DoAugmentSlotsMatch(uint32 item_one, uint32 item_two); bool DoAugmentSlotsMatch(uint32 item_one, uint32 item_two);
int8 DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot = 255); int8 DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot = 255);
void SendPlayerHandinEvent(); void SendPlayerHandinEvent();
void SendChannelMessage(uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message);
void SendChannelMessage(Client* from, uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message);
void SendChannelMessage(Client* from, const char* to, uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message);
Bot *GetBot() const; Bot *GetBot() const;
Client *GetInitiator() const; Client *GetInitiator() const;
-2
View File
@@ -112,7 +112,6 @@ public:
void SetRaidLeader(const char *wasLead, const char *name); void SetRaidLeader(const char *wasLead, const char *name);
bool Process(); bool Process();
bool IsRaid() { return true; }
void AddMember(Client *c, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false); void AddMember(Client *c, uint32 group = 0xFFFFFFFF, bool rleader=false, bool groupleader=false, bool looter=false);
void AddBot(Bot* b, uint32 group = 0xFFFFFFFF, bool raid_leader=false, bool group_leader=false, bool looter=false); void AddBot(Bot* b, uint32 group = 0xFFFFFFFF, bool raid_leader=false, bool group_leader=false, bool looter=false);
@@ -263,7 +262,6 @@ public:
protected: protected:
Client *leader; Client *leader;
bool locked; bool locked;
uint16 numMembers;
uint32 LootType; uint32 LootType;
bool disbandCheck; bool disbandCheck;
bool forceDisband; bool forceDisband;
-139
View File
@@ -429,114 +429,6 @@ void Spawn2::DeathReset(bool realdeath)
} }
} }
bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, const glm::vec4& client_position, uint32 repop_distance)
{
std::unordered_map<uint32, uint32> spawn_times;
float mob_distance = 0;
timeval tv;
gettimeofday(&tv, nullptr);
/* Bulk Load NPC Types Data into the cache */
content_db.LoadNPCTypesData(0, true);
std::string spawn_query = StringFormat(
"SELECT "
"respawn_times.id, "
"respawn_times.`start`, "
"respawn_times.duration "
"FROM "
"respawn_times "
"WHERE instance_id = %u",
zone->GetInstanceID()
);
auto results = QueryDatabase(spawn_query);
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 start_duration = Strings::ToInt(row[1]) > 0 ? Strings::ToInt(row[1]) : 0;
uint32 end_duration = Strings::ToInt(row[2]) > 0 ? Strings::ToInt(row[2]) : 0;
/* Our current time was expired */
if ((start_duration + end_duration) <= tv.tv_sec) {
spawn_times[Strings::ToInt(row[0])] = 0;
}
/* We still have time left on this timer */
else {
spawn_times[Strings::ToInt(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000;
}
}
const char *zone_name = ZoneName(zoneid);
std::string query = StringFormat(
"SELECT "
"id, "
"spawngroupID, "
"x, "
"y, "
"z, "
"heading, "
"respawntime, "
"variance, "
"pathgrid, "
"path_when_zone_idle, "
"_condition, "
"cond_value, "
"enabled, "
"animation "
"FROM "
"spawn2 "
"WHERE zone = '%s' AND (version = %u OR version = -1) ",
zone_name,
version
);
results = database.QueryDatabase(query);
if (!results.Success()) {
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 spawn_time_left = 0;
Spawn2* new_spawn = 0;
bool perl_enabled = Strings::ToInt(row[12]) == 1 ? true : false;
if (spawn_times.count(Strings::ToInt(row[0])) != 0)
spawn_time_left = spawn_times[Strings::ToInt(row[0])];
glm::vec4 point;
point.x = Strings::ToFloat(row[2]);
point.y = Strings::ToFloat(row[3]);
mob_distance = DistanceNoZ(client_position, point);
if (mob_distance > repop_distance)
continue;
new_spawn = new Spawn2(
Strings::ToInt(row[0]), // uint32 in_spawn2_id
Strings::ToInt(row[1]), // uint32 spawngroup_id
Strings::ToFloat(row[2]), // float in_x
Strings::ToFloat(row[3]), // float in_y
Strings::ToFloat(row[4]), // float in_z
Strings::ToFloat(row[5]), // float in_heading
Strings::ToInt(row[6]), // uint32 respawn
Strings::ToInt(row[7]), // uint32 variance
spawn_time_left, // uint32 timeleft
Strings::ToInt(row[8]), // uint32 grid
(bool)Strings::ToInt(row[9]), // bool path_when_zone_idle
Strings::ToInt(row[10]), // uint16 in_cond_id
Strings::ToInt(row[11]), // int16 in_min_value
perl_enabled, // bool in_enabled
(EmuAppearance)Strings::ToInt(row[13]) // EmuAppearance anim
);
spawn2_list.Insert(new_spawn);
}
return true;
}
bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version) { bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version) {
std::unordered_map<uint32, uint32> spawn_times; std::unordered_map<uint32, uint32> spawn_times;
@@ -640,37 +532,6 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
return true; return true;
} }
Spawn2* ZoneDatabase::LoadSpawn2(LinkedList<Spawn2*> &spawn2_list, uint32 spawn2id, uint32 timeleft) {
std::string query = StringFormat("SELECT id, spawngroupID, x, y, z, heading, "
"respawntime, variance, pathgrid, "
"path_when_zone_idle, _condition, "
"cond_value, enabled, animation FROM spawn2 "
"WHERE id = %i", spawn2id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return nullptr;
}
if (results.RowCount() != 1) {
return nullptr;
}
auto row = results.begin();
bool perl_enabled = Strings::ToInt(row[12]) == 1 ? true : false;
auto newSpawn = new Spawn2(Strings::ToInt(row[0]), Strings::ToInt(row[1]), Strings::ToFloat(row[2]),
Strings::ToFloat(row[3]), Strings::ToFloat(row[4]), Strings::ToFloat(row[5]), Strings::ToInt(row[6]), Strings::ToInt(row[7]),
timeleft, Strings::ToInt(row[8]), (bool) Strings::ToInt(row[9]), Strings::ToInt(row[10]),
Strings::ToInt(row[11]), perl_enabled, (EmuAppearance)Strings::ToInt(row[13]));
spawn2_list.Insert(newSpawn);
return newSpawn;
}
bool ZoneDatabase::CreateSpawn2(Client *client, uint32 spawngroup, const char* zone, const glm::vec4& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value) bool ZoneDatabase::CreateSpawn2(Client *client, uint32 spawngroup, const char* zone, const glm::vec4& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value)
{ {
+2 -2
View File
@@ -241,7 +241,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas
hate += item->GetItem()->AC; hate += item->GetItem()->AC;
} }
const EQ::ItemData *itm = item->GetItem(); const EQ::ItemData *itm = item->GetItem();
auto fbash = GetFuriousBash(itm->Focus.Effect); auto fbash = GetSpellFuriousBash(itm->Focus.Effect);
hate = hate * (100 + fbash) / 100; hate = hate * (100 + fbash) / 100;
if (fbash) if (fbash)
MessageString(Chat::FocusEffect, GLOWS_RED, itm->Name); MessageString(Chat::FocusEffect, GLOWS_RED, itm->Name);
@@ -2347,7 +2347,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, int32 weapon_damage, EQ::skills::Ski
hate += item->GetItem()->AC; hate += item->GetItem()->AC;
} }
const EQ::ItemData *itm = item->GetItem(); const EQ::ItemData *itm = item->GetItem();
hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100; hate = hate * (100 + GetSpellFuriousBash(itm->Focus.Effect)) / 100;
} }
} }
+16 -16
View File
@@ -212,11 +212,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
viral_timer.Start(1000); viral_timer.Start(1000);
} }
buffs[buffslot].virus_spread_time = zone->random.Int(GetViralMinSpreadTime(spell_id), GetViralMaxSpreadTime(spell_id)); buffs[buffslot].virus_spread_time = zone->random.Int(GetSpellViralMinimumSpreadTime(spell_id), GetSpellViralMaximumSpreadTime(spell_id));
} }
if (!IsPowerDistModSpell(spell_id)) if (!IsDistanceModifierSpell(spell_id))
SetSpellPowerDistanceMod(0); SetSpellPowerDistanceMod(0);
bool spell_trigger_cast_complete = false; //Used with SE_Spell_Trigger and SE_Chance_Best_in_Spell_Grp, true when spell has been triggered. bool spell_trigger_cast_complete = false; //Used with SE_Spell_Trigger and SE_Chance_Best_in_Spell_Grp, true when spell has been triggered.
@@ -1331,7 +1331,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
snprintf(effect_desc, _EDLEN, "Blind: %+i", effect_value); snprintf(effect_desc, _EDLEN, "Blind: %+i", effect_value);
#endif #endif
// 'cure blind' // 'cure blind'
if (BeneficialSpell(spell_id) && spells[spell_id].buff_duration == 0) { if (IsBeneficialSpell(spell_id) && spells[spell_id].buff_duration == 0) {
int buff_count = GetMaxBuffSlots(); int buff_count = GetMaxBuffSlots();
for (int slot = 0; slot < buff_count; slot++) { for (int slot = 0; slot < buff_count; slot++) {
if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SE_Blind)) { if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SE_Blind)) {
@@ -1873,7 +1873,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
#ifdef SPELL_EFFECT_SPAM #ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Weapon Proc: %s (id %d)", spells[effect_value].name, procid); snprintf(effect_desc, _EDLEN, "Weapon Proc: %s (id %d)", spells[effect_value].name, procid);
#endif #endif
AddProcToWeapon(procid, false, 100 + spells[spell_id].limit_value[i], spell_id, caster_level, GetProcLimitTimer(spell_id, ProcType::MELEE_PROC)); AddProcToWeapon(procid, false, 100 + spells[spell_id].limit_value[i], spell_id, caster_level, GetSpellProcLimitTimer(spell_id, ProcType::MELEE_PROC));
break; break;
} }
@@ -1883,7 +1883,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
#ifdef SPELL_EFFECT_SPAM #ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Ranged Proc: %+i", effect_value); snprintf(effect_desc, _EDLEN, "Ranged Proc: %+i", effect_value);
#endif #endif
AddRangedProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetProcLimitTimer(spell_id, ProcType::RANGED_PROC)); AddRangedProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetSpellProcLimitTimer(spell_id, ProcType::RANGED_PROC));
break; break;
} }
@@ -1893,7 +1893,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
#ifdef SPELL_EFFECT_SPAM #ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Defensive Proc: %s (id %d)", spells[effect_value].name, procid); snprintf(effect_desc, _EDLEN, "Defensive Proc: %s (id %d)", spells[effect_value].name, procid);
#endif #endif
AddDefensiveProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetProcLimitTimer(spell_id, ProcType::DEFENSIVE_PROC)); AddDefensiveProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetSpellProcLimitTimer(spell_id, ProcType::DEFENSIVE_PROC));
break; break;
} }
@@ -3400,7 +3400,7 @@ int64 Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level
// this doesn't actually need to be a song to get mods, just the right skill // this doesn't actually need to be a song to get mods, just the right skill
if (EQ::skills::IsBardInstrumentSkill(spells[spell_id].skill) if (EQ::skills::IsBardInstrumentSkill(spells[spell_id].skill)
&& IsInstrumentModAppliedToSpellEffect(spell_id, spells[spell_id].effect_id[effect_id])) { && IsInstrumentModifierAppliedToSpellEffect(spell_id, spells[spell_id].effect_id[effect_id])) {
oval = effect_value; oval = effect_value;
effect_value = effect_value * static_cast<int>(instrument_mod) / 10; effect_value = effect_value * static_cast<int>(instrument_mod) / 10;
LogSpells("Effect value [{}] altered with bard modifier of [{}] to yeild [{}]", LogSpells("Effect value [{}] altered with bard modifier of [{}] to yeild [{}]",
@@ -3959,7 +3959,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
} }
case SE_WipeHateList: { case SE_WipeHateList: {
if (IsMezSpell(buff.spellid)) { if (IsMesmerizeSpell(buff.spellid)) {
break; break;
} }
@@ -4054,7 +4054,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
case SE_InterruptCasting: { case SE_InterruptCasting: {
if (IsCasting()) { if (IsCasting()) {
const auto &spell = spells[casting_spell_id]; const auto &spell = spells[casting_spell_id];
if (!IgnoreCastingRestriction(spell.id) && zone->random.Roll(spells[buff.spellid].base_value[i])) { if (!IsCastNotStandingSpell(spell.id) && zone->random.Roll(spells[buff.spellid].base_value[i])) {
InterruptSpell(); InterruptSpell();
} }
} }
@@ -4363,7 +4363,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
for (unsigned int j = 0; j < buff_count; j++) { for (unsigned int j = 0; j < buff_count; j++) {
if (IsValidSpell(tar->GetBuffs()[j].spellid)) { if (IsValidSpell(tar->GetBuffs()[j].spellid)) {
auto spell = spells[tar->GetBuffs()[j].spellid]; auto spell = spells[tar->GetBuffs()[j].spellid];
if (spell.good_effect == 0 && IsEffectInSpell(spell.id, SE_CurrentHP) && tar->GetBuffs()[j].casterid == GetID()) { if (spell.good_effect == DETRIMENTAL_EFFECT && IsEffectInSpell(spell.id, SE_CurrentHP) && tar->GetBuffs()[j].casterid == GetID()) {
tar->BuffFadeBySpellID(spell.id); tar->BuffFadeBySpellID(spell.id);
} }
} }
@@ -4377,7 +4377,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
for (unsigned int j = 0; j < buff_count; j++) { for (unsigned int j = 0; j < buff_count; j++) {
if (IsValidSpell(GetBuffs()[j].spellid )) { if (IsValidSpell(GetBuffs()[j].spellid )) {
auto spell = spells[GetBuffs()[j].spellid]; auto spell = spells[GetBuffs()[j].spellid];
if (spell.good_effect == 0 && IsEffectInSpell(spell.id, SE_CurrentHP)) { if (spell.good_effect == DETRIMENTAL_EFFECT && IsEffectInSpell(spell.id, SE_CurrentHP)) {
BuffFadeBySpellID(spell.id); BuffFadeBySpellID(spell.id);
} }
} }
@@ -4785,7 +4785,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
LimitInclude[IncludeExistsSELimitEffect] = true; LimitInclude[IncludeExistsSELimitEffect] = true;
// they use 33 here for all classes ... unsure if the type check is really needed // they use 33 here for all classes ... unsure if the type check is really needed
if (base_value == SE_SummonPet && type == focusReagentCost) { if (base_value == SE_SummonPet && type == focusReagentCost) {
if (IsSummonPetSpell(spell_id) || IsSummonSkeletonSpell(spell_id)) { if (IsPetSpell(spell_id)) {
LimitInclude[IncludeFoundSELimitEffect] = true; LimitInclude[IncludeFoundSELimitEffect] = true;
} }
} }
@@ -6262,7 +6262,7 @@ bool Mob::TryTriggerOnCastProc(uint16 focusspellid, uint16 spell_id, uint16 proc
return true; return true;
} }
// Edge cases where proc spell does not require a target such as PBAE, allows proc to still occur even if target potentially dead. Live spells exist with PBAE procs. // Edge cases where proc spell does not require a target such as PBAE, allows proc to still occur even if target potentially dead. Live spells exist with PBAE procs.
else if (!SpellRequiresTarget(proc_spellid)) { else if (!IsTargetRequiredForSpell(proc_spellid)) {
SpellFinished(proc_spellid, this, EQ::spells::CastingSlot::Item, 0, -1, spells[proc_spellid].resist_difficulty); SpellFinished(proc_spellid, this, EQ::spells::CastingSlot::Item, 0, -1, spells[proc_spellid].resist_difficulty);
return true; return true;
} }
@@ -9608,7 +9608,7 @@ void Mob::CastSpellOnLand(Mob* caster, int32 spell_id)
void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster)
{ {
if (IsPowerDistModSpell(spell_id)){ if (IsDistanceModifierSpell(spell_id)){
float distance = 0; float distance = 0;
@@ -9959,7 +9959,7 @@ void Mob::VirusEffectProcess()
} }
if (buffs[buffs_i].virus_spread_time <= 0) { if (buffs[buffs_i].virus_spread_time <= 0) {
buffs[buffs_i].virus_spread_time = zone->random.Int(GetViralMinSpreadTime(buffs[buffs_i].spellid), GetViralMaxSpreadTime(buffs[buffs_i].spellid)); buffs[buffs_i].virus_spread_time = zone->random.Int(GetSpellViralMinimumSpreadTime(buffs[buffs_i].spellid), GetSpellViralMaximumSpreadTime(buffs[buffs_i].spellid));
SpreadVirusEffect(buffs[buffs_i].spellid, buffs[buffs_i].casterid, buffs[buffs_i].ticsremaining); SpreadVirusEffect(buffs[buffs_i].spellid, buffs[buffs_i].casterid, buffs[buffs_i].ticsremaining);
stop_timer = false; stop_timer = false;
} }
@@ -9982,7 +9982,7 @@ void Mob::SpreadVirusEffect(int32 spell_id, uint32 caster_id, int32 buff_tics_re
std::vector<Mob *> targets_in_range = entity_list.GetTargetsForVirusEffect( std::vector<Mob *> targets_in_range = entity_list.GetTargetsForVirusEffect(
this, this,
caster, caster,
GetViralSpreadRange(spell_id), GetSpellViralSpreadRange(spell_id),
spells[spell_id].pcnpc_only_flag, spells[spell_id].pcnpc_only_flag,
spell_id spell_id
); );
+63 -28
View File
@@ -545,7 +545,7 @@ bool Mob::DoCastingChecksOnCaster(int32 spell_id, CastingSlot slot) {
/* /*
Cannot cast if stunned or mezzed, unless spell has 'cast_not_standing' flag. Cannot cast if stunned or mezzed, unless spell has 'cast_not_standing' flag.
*/ */
if ((IsStunned() || IsMezzed()) && !IgnoreCastingRestriction(spell_id)) { if ((IsStunned() || IsMezzed()) && !IsCastNotStandingSpell(spell_id)) {
LogSpells("Spell casting canceled [{}] : can not cast spell when stunned.", spell_id); LogSpells("Spell casting canceled [{}] : can not cast spell when stunned.", spell_id);
return false; return false;
} }
@@ -575,7 +575,7 @@ bool Mob::DoCastingChecksOnCaster(int32 spell_id, CastingSlot slot) {
/* /*
Cannot cast under divine aura, unless spell has 'cast_not_standing' flag. Cannot cast under divine aura, unless spell has 'cast_not_standing' flag.
*/ */
if (DivineAura() && !IgnoreCastingRestriction(spell_id)) { if (DivineAura() && !IsCastNotStandingSpell(spell_id)) {
LogSpells("Spell casting canceled [{}] : cannot cast while Divine Aura is in effect.", spell_id); LogSpells("Spell casting canceled [{}] : cannot cast while Divine Aura is in effect.", spell_id);
InterruptSpell(173, 0x121, false); //not sure we need this. InterruptSpell(173, 0x121, false); //not sure we need this.
return false; return false;
@@ -873,7 +873,7 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
/* /*
Requires target to be in same group or same raid in order to apply invisible. Requires target to be in same group or same raid in order to apply invisible.
*/ */
if (check_on_casting && RuleB(Spells, InvisRequiresGroup) && IsInvisSpell(spell_id)) { if (check_on_casting && RuleB(Spells, InvisRequiresGroup) && IsInvisibleSpell(spell_id)) {
if (IsClient() && spell_target && spell_target->IsClient()) { if (IsClient() && spell_target && spell_target->IsClient()) {
if (spell_target && spell_target->GetID() != GetID()) { if (spell_target && spell_target->GetID() != GetID()) {
bool cast_failed = true; bool cast_failed = true;
@@ -1781,7 +1781,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
SpellTargetType targetType = spells[spell_id].target_type; SpellTargetType targetType = spells[spell_id].target_type;
bodyType mob_body = spell_target ? spell_target->GetBodyType() : BT_Humanoid; bodyType mob_body = spell_target ? spell_target->GetBodyType() : BT_Humanoid;
if(IsPlayerIllusionSpell(spell_id) if(IsIllusionSpell(spell_id)
&& spell_target != nullptr // null ptr crash safeguard && spell_target != nullptr // null ptr crash safeguard
&& !spell_target->IsNPC() // still self only if NPC targetted && !spell_target->IsNPC() // still self only if NPC targetted
&& IsClient() && IsClient()
@@ -2377,7 +2377,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
range = spells[spell_id].aoe_range; range = spells[spell_id].aoe_range;
range = GetActSpellRange(spell_id, range); range = GetActSpellRange(spell_id, range);
if(IsClient() && IsPlayerIllusionSpell(spell_id) && (HasProjectIllusion())){ if(IsClient() && IsIllusionSpell(spell_id) && (HasProjectIllusion())){
range = 100; range = 100;
} }
@@ -2461,7 +2461,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
} }
} }
if(IsPlayerIllusionSpell(spell_id) if(IsIllusionSpell(spell_id)
&& IsClient() && IsClient()
&& (HasProjectIllusion())){ && (HasProjectIllusion())){
LogAA("Effect Project Illusion for [{}] on spell id: [{}] was ON", GetName(), spell_id); LogAA("Effect Project Illusion for [{}] on spell id: [{}] was ON", GetName(), spell_id);
@@ -2604,7 +2604,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
} }
// Set and send the nimbus effect if this spell has one // Set and send the nimbus effect if this spell has one
int NimbusEffect = GetNimbusEffect(spell_id); int NimbusEffect = GetSpellNimbusEffect(spell_id);
if(NimbusEffect) { if(NimbusEffect) {
if(!IsNimbusEffectActive(NimbusEffect)) { if(!IsNimbusEffectActive(NimbusEffect)) {
SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true); SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true);
@@ -2754,7 +2754,7 @@ bool Mob::ApplyBardPulse(int32 spell_id, Mob *spell_target, CastingSlot slot) {
/* /*
If divine aura applied while pulsing, it is not interrupted but does not reapply until DA fades. If divine aura applied while pulsing, it is not interrupted but does not reapply until DA fades.
*/ */
if (DivineAura() && !IgnoreCastingRestriction(spell_id)) { if (DivineAura() && !IsCastNotStandingSpell(spell_id)) {
return true; return true;
} }
/* /*
@@ -2931,7 +2931,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
return -1; return -1;
} }
if (!IsStackableDot(spellid1) && !IsEffectInSpell(spellid1, SE_ManaBurn)) { // mana burn spells we need to use the stacking command blocks live actually checks those first, we should probably rework to that too if (!IsStackableDOT(spellid1) && !IsEffectInSpell(spellid1, SE_ManaBurn)) { // mana burn spells we need to use the stacking command blocks live actually checks those first, we should probably rework to that too
if (caster_level1 > caster_level2) { // cur buff higher level than new if (caster_level1 > caster_level2) { // cur buff higher level than new
if (IsEffectInSpell(spellid1, SE_ImprovedTaunt)) { if (IsEffectInSpell(spellid1, SE_ImprovedTaunt)) {
LogSpells("SE_ImprovedTaunt level exception, overwriting"); LogSpells("SE_ImprovedTaunt level exception, overwriting");
@@ -3005,21 +3005,21 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
if (spellbonuses.BStacker[SBIndex::BUFFSTACKER_EXISTS]) { if (spellbonuses.BStacker[SBIndex::BUFFSTACKER_EXISTS]) {
if ((effect2 == SE_BStacker) && (sp2.effect_id[i] <= spellbonuses.BStacker[SBIndex::BUFFSTACKER_VALUE])) if ((effect2 == SE_BStacker) && (sp2.effect_id[i] <= spellbonuses.BStacker[SBIndex::BUFFSTACKER_VALUE]))
return -1; return -1;
if ((effect2 == SE_AStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker))) if ((effect2 == SE_AStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker)))
return -1; return -1;
} }
if (spellbonuses.CStacker[SBIndex::BUFFSTACKER_EXISTS]) { if (spellbonuses.CStacker[SBIndex::BUFFSTACKER_EXISTS]) {
if ((effect2 == SE_CStacker) && (sp2.effect_id[i] <= spellbonuses.CStacker[SBIndex::BUFFSTACKER_VALUE])) if ((effect2 == SE_CStacker) && (sp2.effect_id[i] <= spellbonuses.CStacker[SBIndex::BUFFSTACKER_VALUE]))
return -1; return -1;
if ((effect2 == SE_BStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker))) if ((effect2 == SE_BStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker)))
return -1; return -1;
} }
if (spellbonuses.DStacker[SBIndex::BUFFSTACKER_EXISTS]) { if (spellbonuses.DStacker[SBIndex::BUFFSTACKER_EXISTS]) {
if ((effect2 == SE_DStacker) && (sp2.effect_id[i] <= spellbonuses.DStacker[SBIndex::BUFFSTACKER_VALUE])) if ((effect2 == SE_DStacker) && (sp2.effect_id[i] <= spellbonuses.DStacker[SBIndex::BUFFSTACKER_VALUE]))
return -1; return -1;
if ((effect2 == SE_CStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker))) if ((effect2 == SE_CStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker)))
return -1; return -1;
} }
@@ -3037,6 +3037,12 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
if(sp1_value < overwrite_below_value) if(sp1_value < overwrite_below_value)
{ {
if (IsResurrectionEffects(spellid1)) {
int8 res_effect_check = GetSpellResurrectionSicknessCheck(spellid1, spellid2);
if (res_effect_check != 0) {
return res_effect_check;
}
}
LogSpells("Overwrite spell because sp1_value < overwrite_below_value"); LogSpells("Overwrite spell because sp1_value < overwrite_below_value");
return 1; // overwrite spell if its value is less return 1; // overwrite spell if its value is less
} }
@@ -3162,6 +3168,13 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
if(sp2_value < 0) if(sp2_value < 0)
sp2_value = 0 - sp2_value; sp2_value = 0 - sp2_value;
if (IsResurrectionEffects(spellid1)) {
int8 res_effect_check = GetSpellResurrectionSicknessCheck(spellid1, spellid2);
if (res_effect_check != 0) {
return res_effect_check;
}
}
if(sp2_value < sp1_value) { if(sp2_value < sp1_value) {
LogSpells("Spell [{}] (value [{}]) is not as good as [{}] (value [{}]). Rejecting [{}]", LogSpells("Spell [{}] (value [{}]) is not as good as [{}] (value [{}]). Rejecting [{}]",
sp2.name, sp2_value, sp1.name, sp1_value, sp2.name); sp2.name, sp2_value, sp1.name, sp1_value, sp2.name);
@@ -3170,10 +3183,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
if (sp2_value != sp1_value) if (sp2_value != sp1_value)
values_equal = false; values_equal = false;
if (RuleB(Spells, ResurrectionEffectsBlock) && IsResurrectionEffects(spellid1)) {
LogSpells("ResurrectionEffectsBlock triggered -- [{}] is blocked by [{}]", sp2.name, sp1.name);
return -1; // can't stack
}
//we dont return here... a better value on this one effect dosent mean they are //we dont return here... a better value on this one effect dosent mean they are
//all better... //all better...
@@ -3238,7 +3247,7 @@ bool Mob::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id)
} }
if (check_for_restrictions) { if (check_for_restrictions) {
int spell_level = GetMinLevel(spell_id); int spell_level = GetSpellMinimumLevel(spell_id);
// Only check for beneficial buffs // Only check for beneficial buffs
if (IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) { if (IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) {
@@ -3364,6 +3373,10 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
will_overwrite = true; will_overwrite = true;
overwrite_slots.push_back(buffslot); overwrite_slots.push_back(buffslot);
} }
if (ret == 2) { //ResurrectionEffectBlock handling to move potential overwrites to a new buff slock while keeping Res Sickness
LogSpells("Adding buff [{}] will overwrite spell [{}] in slot [{}] with caster level [{}], but ResurrectionEffectBlock is set to 2. Attempting to move [{}] to an empty buff slot.",
spell_id, curbuf.spellid, buffslot, curbuf.casterlevel, spell_id);
}
} else { } else {
if (emptyslot == -1) { if (emptyslot == -1) {
if (buffslot >= start_slot && buffslot < end_slot) { if (buffslot >= start_slot && buffslot < end_slot) {
@@ -3521,6 +3534,19 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite)
LogAIDetail("Buff [{}] would conflict with [{}] in slot [{}], reporting stack failure", spellid, curbuf.spellid, i); LogAIDetail("Buff [{}] would conflict with [{}] in slot [{}], reporting stack failure", spellid, curbuf.spellid, i);
return -1; // stop the spell, can't stack it return -1; // stop the spell, can't stack it
} }
if (ret == 2) { //ResurrectionEffectBlock handling to move potential overwrites to a new buff slock while keeping Res Sickness
LogAIDetail("Adding buff [{}] will overwrite spell [{}] in slot [{}] with caster level [{}], but ResurrectionEffectBlock is set to 2. Attempting to move [{}] to an empty buff slot.",
spellid, curbuf.spellid, i, curbuf.casterlevel, spellid);
for (int x = 0; x < buff_count; x++) {
const Buffs_Struct& curbuf = buffs[x];
if (IsValidSpell(curbuf.spellid)) {
continue;
}
else {
firstfree = x;
}
}
}
} }
LogAIDetail("Reporting that buff [{}] could successfully be placed into slot [{}]", spellid, firstfree); LogAIDetail("Reporting that buff [{}] could successfully be placed into slot [{}]", spellid, firstfree);
@@ -3746,7 +3772,7 @@ bool Mob::SpellOnTarget(
if ( if (
(spelltar->GetInvul() && !spelltar->DivineAura()) || (spelltar->GetInvul() && !spelltar->DivineAura()) ||
(spelltar != this && spelltar->DivineAura()) || (spelltar != this && spelltar->DivineAura()) ||
(spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id)) (spelltar == this && spelltar->DivineAura() && !IsCastNotStandingSpell(spell_id))
) { ) {
LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName()); LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName());
safe_delete(action_packet); safe_delete(action_packet);
@@ -3857,7 +3883,7 @@ bool Mob::SpellOnTarget(
} }
if ( if (
(!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) || (!IsAllianceSpell(spell_id) && !IsBeneficialAllowed(spelltar)) ||
(IsGroupOnlySpell(spell_id) && (IsGroupOnlySpell(spell_id) &&
!( !(
( (
@@ -4089,7 +4115,7 @@ bool Mob::SpellOnTarget(
if ( if (
IsCharmSpell(spell_id) || IsCharmSpell(spell_id) ||
IsMezSpell(spell_id) || IsMesmerizeSpell(spell_id) ||
IsFearSpell(spell_id) IsFearSpell(spell_id)
) { ) {
spell_effectiveness = spelltar->ResistSpell( spell_effectiveness = spelltar->ResistSpell(
@@ -4118,7 +4144,7 @@ bool Mob::SpellOnTarget(
} }
if (spell_effectiveness < 100) { if (spell_effectiveness < 100) {
if (spell_effectiveness == 0 || !IsPartialCapableSpell(spell_id)) { if (spell_effectiveness == 0 || !IsPartialResistableSpell(spell_id)) {
LogSpells("Spell [{}] was completely resisted by [{}]", spell_id, spelltar->GetName()); LogSpells("Spell [{}] was completely resisted by [{}]", spell_id, spelltar->GetName());
if (spells[spell_id].resist_type == RESIST_PHYSICAL){ if (spells[spell_id].resist_type == RESIST_PHYSICAL){
@@ -4661,7 +4687,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
if(IsBeneficialSpell(spell_id) && (caster->GetNPCTypeID())) //then skip the rest, stop NPCs aggroing each other with buff spells. 2013-03-05 if(IsBeneficialSpell(spell_id) && (caster->GetNPCTypeID())) //then skip the rest, stop NPCs aggroing each other with buff spells. 2013-03-05
return false; return false;
if(IsMezSpell(spell_id)) if(IsMesmerizeSpell(spell_id))
{ {
if(GetSpecialAbility(UNMEZABLE)) { if(GetSpecialAbility(UNMEZABLE)) {
LogSpells("We are immune to Mez spells"); LogSpells("We are immune to Mez spells");
@@ -5124,7 +5150,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
{ {
//This is confusing but it's basically right //This is confusing but it's basically right
//It skews partial resists up over 100 more often than not //It skews partial resists up over 100 more often than not
if(!IsPartialCapableSpell(spell_id)) if(!IsPartialResistableSpell(spell_id))
{ {
return 0; return 0;
} }
@@ -5495,13 +5521,14 @@ void Client::UnmemSpell(int slot, bool update_client)
} }
LogSpells("Spell [{}] forgotten from slot [{}]", m_pp.mem_spells[slot], slot); LogSpells("Spell [{}] forgotten from slot [{}]", m_pp.mem_spells[slot], slot);
m_pp.mem_spells[slot] = 0xFFFFFFFF;
database.DeleteCharacterMemorizedSpell(CharacterID(), m_pp.mem_spells[slot], slot); database.DeleteCharacterMemorizedSpell(CharacterID(), m_pp.mem_spells[slot], slot);
if (update_client) { if (update_client) {
MemorizeSpell(slot, m_pp.mem_spells[slot], memSpellForget); MemorizeSpell(slot, m_pp.mem_spells[slot], memSpellForget);
} }
m_pp.mem_spells[slot] = UINT32_MAX;
} }
void Client::UnmemSpellBySpellID(int32 spell_id) void Client::UnmemSpellBySpellID(int32 spell_id)
@@ -5573,7 +5600,7 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client, bool def
} }
if (update_client) { if (update_client) {
if (m_pp.spell_book[slot] != 0xFFFFFFFF) { if (m_pp.spell_book[slot] != UINT32_MAX) {
UnscribeSpell(slot, update_client, defer_save); UnscribeSpell(slot, update_client, defer_save);
} }
} }
@@ -5593,12 +5620,11 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client, bool def
void Client::UnscribeSpell(int slot, bool update_client, bool defer_save) void Client::UnscribeSpell(int slot, bool update_client, bool defer_save)
{ {
if (slot >= EQ::spells::SPELLBOOK_SIZE || slot < 0) { if (!EQ::ValueWithin(slot, 0, (EQ::spells::SPELLBOOK_SIZE - 1))) {
return; return;
} }
LogSpells("Spell [{}] erased from spell book slot [{}]", m_pp.spell_book[slot], slot); LogSpells("Spell [{}] erased from spell book slot [{}]", m_pp.spell_book[slot], slot);
m_pp.spell_book[slot] = 0xFFFFFFFF;
if (!defer_save) { if (!defer_save) {
database.DeleteCharacterSpell(CharacterID(), m_pp.spell_book[slot], slot); database.DeleteCharacterSpell(CharacterID(), m_pp.spell_book[slot], slot);
@@ -5606,12 +5632,21 @@ void Client::UnscribeSpell(int slot, bool update_client, bool defer_save)
if (update_client && slot < EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize) { if (update_client && slot < EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize) {
auto outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct)); auto outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct));
DeleteSpell_Struct *del = (DeleteSpell_Struct *) outapp->pBuffer; auto* del = (DeleteSpell_Struct *) outapp->pBuffer;
del->spell_slot = slot; del->spell_slot = slot;
del->success = 1; del->success = 1;
QueuePacket(outapp); QueuePacket(outapp);
safe_delete(outapp); safe_delete(outapp);
} }
if (parse->PlayerHasQuestSub(EVENT_UNSCRIBE_SPELL)) {
const auto export_string = fmt::format("{} {}", slot, m_pp.spell_book[slot]);
parse->EventPlayer(EVENT_UNSCRIBE_SPELL, this, export_string, 0);
}
m_pp.spell_book[slot] = UINT32_MAX;
} }
void Client::UnscribeSpellAll(bool update_client) void Client::UnscribeSpellAll(bool update_client)
+2
View File
@@ -100,6 +100,7 @@
#define DUP_LORE 290 //Duplicate lore items are not allowed. #define DUP_LORE 290 //Duplicate lore items are not allowed.
#define TGB_ON 293 //Target other group buff is *ON*. #define TGB_ON 293 //Target other group buff is *ON*.
#define TGB_OFF 294 //Target other group buff is *OFF*. #define TGB_OFF 294 //Target other group buff is *OFF*.
#define DONT_SEE_TARGET 303 //I don't see anyone by that name around here...
#define DISARMED_TRAP 305 //You have disarmed the trap. #define DISARMED_TRAP 305 //You have disarmed the trap.
#define LDON_SENSE_TRAP1 306 //You do not Sense any traps. #define LDON_SENSE_TRAP1 306 //You do not Sense any traps.
#define TRADESKILL_NOCOMBINE 334 //You cannot combine these items in this container type! #define TRADESKILL_NOCOMBINE 334 //You cannot combine these items in this container type!
@@ -368,6 +369,7 @@
#define DUNGEON_SEALED 5141 //The gateway to the dungeon is sealed off to you. Perhaps you would be able to enter if you needed to adventure there. #define DUNGEON_SEALED 5141 //The gateway to the dungeon is sealed off to you. Perhaps you would be able to enter if you needed to adventure there.
#define ADVENTURE_COMPLETE 5147 //You received %1 points for successfully completing the adventure. #define ADVENTURE_COMPLETE 5147 //You received %1 points for successfully completing the adventure.
#define SUCCOR_FAIL 5169 //The portal collapes before you can escape! #define SUCCOR_FAIL 5169 //The portal collapes before you can escape!
#define AUGMENT_RESTRICTED 5480 //The item does not satisfy the augment's restrictions.
#define PET_ATTACKING 5501 //%1 tells you, 'Attacking %2 Master.' #define PET_ATTACKING 5501 //%1 tells you, 'Attacking %2 Master.'
#define AVOID_STUNNING_BLOW 5753 //You avoid the stunning blow. #define AVOID_STUNNING_BLOW 5753 //You avoid the stunning blow.
#define FATAL_BOW_SHOT 5745 //%1 performs a FATAL BOW SHOT!! #define FATAL_BOW_SHOT 5745 //%1 performs a FATAL BOW SHOT!!

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