Compare commits

...

105 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
Chris Miles c64a2aec94 [Release] 22.11.0 (#3328)
* [Release] 22.11.0

* Update version.h
2023-04-29 20:37:04 -05:00
Alex King 0e582eda82 [Quest API] Add HasSpellEffect() to Perl/Lua (#3319)
* [Quest API] Add HasSpellEffect() to Perl/Lua

# Perl
- Add `$mob->HasSpellEffect(effect_id)`.

# Lua
- Add `mob:HasSpellEffect(effect_id)`.

# Notes
- Allows operators to see if a Mob has an effect ID from any of their buffs.

* Update mob.cpp
2023-04-29 20:09:00 -05:00
Alex King 7eff6ada87 [Cleanup] Remove unused code in zone/pets.cpp (#3310)
# Notes
- This code is unused.
2023-04-29 20:00:37 -05:00
Alex King 291997d35b [Cleanup] Remove pDontCastBefore_casting_spell from zone/npc.h (#3311)
# Notes
- This is unused.
2023-04-29 20:00:20 -05:00
Alex King ac4572bf79 [Cleanup] Remove unused methods in zone/client.cpp and zone/client.h (#3312)
* [Cleanup] Remove unused methods in zone/client.cpp and zone/client.h

# Notes
- Remove `CheckAccess()` in `zone/client.cpp`.
- Remove `CheckAccess()` in `zone/client.h`.
- Remove `CheckQuests()` in `zone/client.h`.
- Remove `MakeCorpse()` in `zone/client.h`.
- Remove `HPTick()` in `zone/client.h`.
- These methods are unused.

* Update client.h
2023-04-29 20:00:08 -05:00
Alex King f0a9578b6a [Cleanup] Remove GetClassHPFactor() from zone/merc.h (#3314)
# Notes
- This is unused.
2023-04-29 19:59:50 -05:00
Alex King baa824d8fb [Cleanup] Remove GetClassHPFactor() from zone/client_mods.cpp and zone/client.h (#3313)
# Notes
- This is unused.
2023-04-29 19:59:19 -05:00
Alex King b19d3ac8a2 [Cleanup] Remove unused methods in zone/bot.cpp and zone/bot.h (#3315)
# Notes
- Remove `DoFinishedSpellAETarget()`.
- Remove `SendBotArcheryWearChange()`.
- These are unused.
2023-04-29 19:59:05 -05:00
Alex King 6a393bf0c3 [Quest API] Add GetDefaultRaceSize() overloads to Perl/Lua (#3320)
# Perl
- Add `$mob->GetDefaultRaceSize(race_id)`.
- Add `$mob->GetDefaultRaceSize(race_id, gender_id)`.

# Lua
- Add `mob:GetDefaultRaceSize(race_id)`.
- Add `mob:GetDefaultRaceSize(race_id, gender_id)`.

# Notes
- This allows you to get a default size for a race and gender that isn't the current mob's race and gender.
2023-04-29 19:53:49 -05:00
Alex King 09a5551de1 [Cleanup] quest::setallskill() had always true condition. (#3301)
# Notes
- Remove unnecessary double check of `initiator`.
- Cleanup logic to use `EQ::skills::GetSkillTypeMap()`.
2023-04-29 19:52:30 -05:00
Alex King 6e2e035d66 [Cleanup] Remove unused variable in common/crash.cpp (#3308)
# Notes
- This variable is unused.
2023-04-29 19:51:41 -05:00
Alex King ac5922bb32 [Cleanup] Use default ctor/dtor in oriented_bounding_box.h (#3307)
# Notes
- Use default ctor/dtor instead of empty ones.
2023-04-29 19:51:21 -05:00
Chris Miles ecf2a369cc [Discord] Add Discord webhook callback processing to world (#3322) 2023-04-29 20:49:06 -04:00
Chris Miles 95b306599f [Maps] Update download with faster releases link (#3321) 2023-04-29 19:39:24 -05:00
Chris Miles 497d20512a [Crash] Fix UCS crash that occurs during log reloading (#3324) 2023-04-29 19:39:13 -05:00
Aeadoin db916e946e [Bug Fix] Fix issue with spawning Mercs (#3327) 2023-04-29 18:45:35 -04:00
Alex King 958549b407 [Bug Fix] Possible issues with SummonItem in Client::QuestReward() methods (#3325)
# Notes
- These methods were ignoring the sixth augment slot and could cause item to be summoned attuned being `EQ::invslot::slotCursor` is a non-zero value.
2023-04-26 21:28:24 -04:00
Paul Coene 71ebf1b2d4 [Messages] Remove duplicate you have lost a level message (#3323) 2023-04-25 17:42:31 -04:00
Paul Coene e19b8d3056 [Bug Fix] Fix issue with NPCs no longer using some armor. (#3318)
* [BugFix/NPCs] Fix issue with NPCs no longer using some armor.

* Removed redundant memory clear
2023-04-24 17:05:29 -04:00
Alex King 8b1d64a043 [Cleanup] quest::createBot() unnecessary check against nullptr (#3302)
# Notes
- We initialize this variable, so it can never be a nullptr.
2023-04-23 15:08:50 -04:00
Alex King 576f99f292 [Cleanup] Add initiator/owner checks to various methods in questmgr.cpp (#3306)
* [Cleanup] Add initiator/owner checks to various methods in questmgr.cpp

# Notes
- Add `initiator` check to `quest::permaclass()`.
- Add `initiator` check to `quest::permarace()`.
- Add `initiator` check to `quest::permagender()`.
- Add `initiator` check to `quest::scribespells()`.
- Add `initiator` check to `quest::traindiscs()`.
- Add `initiator` check to `quest::unscribespells()`.
- Add `initiator` check to `quest::untraindiscs()`.
- Cleanup `initiator` check in `quest::pvp()`.
- Cleanup `initiator` check in `quest::movepc()`.
- Cleanup `initiator` check in `quest::gmmove()`.
- Cleanup `initiator` check in `quest::movegrp()`.
- Add `owner` check to `quest::doanim()`.
- Cleanup `initiator` check in `quest::addskill()`.
- Cleanup `initiator` check in `quest::setlanguage()`.
- Cleanup `initiator` check in `quest::setskill()`.

* Update questmgr.cpp

* Update questmgr.cpp

* Update questmgr.cpp

* Update questmgr.cpp
2023-04-23 15:08:32 -04:00
Alex King e3761cf2a3 [Cleanup] Add check for owner in quest::resumetimer() (#3305)
# Notes
- We didn't check for owner before doing `owner->GetName()`.
2023-04-23 15:07:49 -04:00
Alex King ad1764b464 [Cleanup] Add cehck for owner in quest::pausetimer() (#3304)
# Notes
- We didn't check for `owner` before doing `owner->GetName()`.
2023-04-23 15:07:09 -04:00
Alex King 1c9ea57a4e [Cleanup] Fix possible nullptr in quest::addloot() (#3303)
# Notes
- We didn't check for `owner` before calling `owner->IsNPC()`.
2023-04-23 15:06:53 -04:00
Alex King 03c158b674 [Crash] Fix possible nullptr in Client::GetCharMaxLevelFromQGlobal() (#3317)
# Notes
- We could possibly not have a `zone` here, causing a crash.
- http://spire.akkadius.com/dev/release/22.9.1?id=3051
- http://spire.akkadius.com/dev/release/22.9.1?id=3052
- http://spire.akkadius.com/dev/release/22.9.1?id=3073
- http://spire.akkadius.com/dev/release/22.9.1?id=3102
- http://spire.akkadius.com/dev/release/22.9.1?id=3103
- http://spire.akkadius.com/dev/release/22.9.1?id=3104
- http://spire.akkadius.com/dev/release/22.9.1?id=3107
- http://spire.akkadius.com/dev/release/22.9.1?id=3108
- http://spire.akkadius.com/dev/release/22.9.1?id=3109
- http://spire.akkadius.com/dev/release/22.9.1?id=3110
- http://spire.akkadius.com/dev/release/22.9.1?id=3111
- http://spire.akkadius.com/dev/release/22.9.1?id=3112
- http://spire.akkadius.com/dev/release/22.9.1?id=3113
- http://spire.akkadius.com/dev/release/22.9.1?id=3114
2023-04-23 15:05:47 -04:00
Aeadoin 39b5374e92 [Crash] Fix possible dereference of nullptr in Client::CalcHPRegen (#3316) 2023-04-23 14:27:43 -04:00
118 changed files with 8366 additions and 2739 deletions
+181
View File
@@ -1,3 +1,184 @@
## [22.13.1] - 06/13/2023
### Targeting
* Revert #3383 ([#3405](https://github.com/EQEmu/Server/pull/3405)) @noudess 2023-06-13
## [22.13.0] - 06/12/2023
### Code
* Add GMFind_Struct to packet structures ([#3402](https://github.com/EQEmu/Server/pull/3402)) @Kinglykrab 2023-06-12
* Remove CHECK_LOS_STEP from zone/common.h ([#3398](https://github.com/EQEmu/Server/pull/3398)) @Kinglykrab 2023-06-12
* Remove CheckCoordLosNoZLeaps() from zone/entity.cpp and zone/entity.h ([#3384](https://github.com/EQEmu/Server/pull/3384)) @Kinglykrab 2023-06-12
* Remove CountTempPets() from zone/entity.cpp and zone/entity.h ([#3390](https://github.com/EQEmu/Server/pull/3390)) @Kinglykrab 2023-06-12
* Remove Evade() from zone/entity.cpp and zone/entity.h ([#3394](https://github.com/EQEmu/Server/pull/3394)) @Kinglykrab 2023-06-12
* Remove GateAllClients() from zone/entity.cpp and zone/entity.h ([#3391](https://github.com/EQEmu/Server/pull/3391)) @Kinglykrab 2023-06-12
* Remove GetClient(ip, port) from zone/entity.h ([#3386](https://github.com/EQEmu/Server/pull/3386)) @Kinglykrab 2023-06-12
* Remove GetClientCount() from zone/entity.cpp and zone/entity.h ([#3392](https://github.com/EQEmu/Server/pull/3392)) @Kinglykrab 2023-06-12
* Remove GetGroupByBot(), GetRaidByMob(), and GetRaidByLeaderName() from zone/entity.cpp and zone/entity.h ([#3387](https://github.com/EQEmu/Server/pull/3387)) @Kinglykrab 2023-06-12
* Remove InteractiveChat() and TakenAction() from zone/npc.h ([#3382](https://github.com/EQEmu/Server/pull/3382)) @Kinglykrab 2023-06-12
* Remove LimitCheckBoth() from zone/entity.cpp and zone/entity.h ([#3393](https://github.com/EQEmu/Server/pull/3393)) @Kinglykrab 2023-06-12
* Remove NPC::AddCash() from npc.cpp/npc.h ([#3380](https://github.com/EQEmu/Server/pull/3380)) @Kinglykrab 2023-06-09
* Remove RemoveMob() and RemoveRaid() from zone/entity.cpp and zone/entity.h ([#3389](https://github.com/EQEmu/Server/pull/3389)) @Kinglykrab 2023-06-12
* Remove SPECIALIZE_MANA_REDUCE from zone/common.h ([#3400](https://github.com/EQEmu/Server/pull/3400)) @Kinglykrab 2023-06-12
* Remove SendAATimer() from zone/entity.h ([#3388](https://github.com/EQEmu/Server/pull/3388)) @Kinglykrab 2023-06-12
* Remove WriteEntityIDs() from zone/entity.cpp and zone/entity.h ([#3395](https://github.com/EQEmu/Server/pull/3395)) @Kinglykrab 2023-06-12
* Remove _BECOMENPCPET() and _NPCPET() from zone/common.h ([#3399](https://github.com/EQEmu/Server/pull/3399)) @Kinglykrab 2023-06-12
* Remove pDBAsyncWorkID from zone/entity.h ([#3385](https://github.com/EQEmu/Server/pull/3385)) @Kinglykrab 2023-06-12
* Remove struct DynamicZoneSafeReturn from zone/entity.h ([#3396](https://github.com/EQEmu/Server/pull/3396)) @Kinglykrab 2023-06-12
* Remove struct TradeEntity from zone/common.h ([#3397](https://github.com/EQEmu/Server/pull/3397)) @Kinglykrab 2023-06-12
### Commands
* Assign #opcode to a #reload alias ([#3401](https://github.com/EQEmu/Server/pull/3401)) @Kinglykrab 2023-06-12
### Illusions
* RandomizeFeatures and SetGender were killing db texture ([#3376](https://github.com/EQEmu/Server/pull/3376)) @noudess 2023-06-06
### Logging
* Fixed statements that logged incorrect data ([#3381](https://github.com/EQEmu/Server/pull/3381)) @noudess 2023-06-07
### Quest API
* Add GetEXPForLevel() to Perl/Lua ([#3403](https://github.com/EQEmu/Server/pull/3403)) @Kinglykrab 2023-06-12
* Add SendChannelMessage() to Perl/Lua ([#3378](https://github.com/EQEmu/Server/pull/3378)) @Kinglykrab 2023-06-04
* Add several spell methods to Perl/Lua ([#3379](https://github.com/EQEmu/Server/pull/3379)) @Kinglykrab 2023-06-12
### Targeting
* /tar <bad target> should not untarget existing target ([#3383](https://github.com/EQEmu/Server/pull/3383)) @noudess 2023-06-12
## [22.12.0] - 05/29/2023
### Code
* Cleanup #setskill and #setskillall Commands ([#3367](https://github.com/EQEmu/Server/pull/3367)) @Kinglykrab 2023-05-25
* Delete message.h ([#3348](https://github.com/EQEmu/Server/pull/3348)) @Kinglykrab 2023-05-17
* Fix #spawn command NPCs having 0 health ([#3371](https://github.com/EQEmu/Server/pull/3371)) @Kinglykrab 2023-05-21
* Remove CalcPetHp from spdat.h ([#3364](https://github.com/EQEmu/Server/pull/3364)) @Kinglykrab 2023-05-25
* Remove CountNPC() and QueueManaged() from entity.cpp/entity.h ([#3346](https://github.com/EQEmu/Server/pull/3346)) @Kinglykrab 2023-05-17
* Remove DumpMerchantList() from zone.cpp/zone.h ([#3343](https://github.com/EQEmu/Server/pull/3343)) @Kinglykrab 2023-05-17
* Remove GetDamageReceived() and GetHealReceived() from combat_record.cpp/combat_record.h ([#3358](https://github.com/EQEmu/Server/pull/3358)) @Kinglykrab 2023-05-17
* Remove GetEscapingEntOnHateList() from hate_list.cpp/hate_list.h ([#3353](https://github.com/EQEmu/Server/pull/3353)) @Kinglykrab 2023-05-17
* Remove GetMaxRank() from aa_ability.cpp/aa_ability.h ([#3347](https://github.com/EQEmu/Server/pull/3347)) @Kinglykrab 2023-05-25
* Remove IsEntityInFrenzyMode() from hate_list.cpp/hate_list.h ([#3352](https://github.com/EQEmu/Server/pull/3352)) @Kinglykrab 2023-05-17
* Remove IsRaid() from raids.h ([#3361](https://github.com/EQEmu/Server/pull/3361)) @Kinglykrab 2023-05-25
* Remove LoadSpawn2() and PopulateZoneSpawnListClose() from spawn2.cpp/zonedb.h ([#3344](https://github.com/EQEmu/Server/pull/3344)) @Kinglykrab 2023-05-25
* Remove SetGraveyard() from zone.cpp/zone.h ([#3354](https://github.com/EQEmu/Server/pull/3354)) @Kinglykrab 2023-05-17
* Remove SetTradeCash() from trading.cpp/common.h ([#3356](https://github.com/EQEmu/Server/pull/3356)) @Kinglykrab 2023-05-17
* Remove TraderUpdate() from trading.cpp/client.h ([#3357](https://github.com/EQEmu/Server/pull/3357)) @Kinglykrab 2023-05-17
* Remove TypeToSkill() from tradeskills.cpp/object.h ([#3355](https://github.com/EQEmu/Server/pull/3355)) @Kinglykrab 2023-05-17
* Remove Z_AGGRO from spdat.h ([#3365](https://github.com/EQEmu/Server/pull/3365)) @Kinglykrab 2023-05-25
* Remove numMembers from raids.h ([#3362](https://github.com/EQEmu/Server/pull/3362)) @Kinglykrab 2023-05-25
* Set GetAugmentType() to int again ([#3335](https://github.com/EQEmu/Server/pull/3335)) @Kinglykrab 2023-05-08
### Commands
* Add #findcurrency Command ([#3368](https://github.com/EQEmu/Server/pull/3368)) @Kinglykrab 2023-05-25
* Add entity variable command ([#3345](https://github.com/EQEmu/Server/pull/3345)) @Kinglykrab 2023-05-25
* Cleanup #setanim ([#3350](https://github.com/EQEmu/Server/pull/3350)) @Kinglykrab 2023-05-25
### Feature
* Intoxication setter/getter for source, getter for Perl/Lua ([#3330](https://github.com/EQEmu/Server/pull/3330)) @JasXSL 2023-05-03
### Fixes
* #augmentitem bypasses augment restrictions ([#3332](https://github.com/EQEmu/Server/pull/3332)) @Kinglykrab 2023-05-07
* Fix Heroic INT/WIS Bonuses ([#3341](https://github.com/EQEmu/Server/pull/3341)) @RekkasGit 2023-05-15
* Fix duplicate messages in #npcedit ([#3372](https://github.com/EQEmu/Server/pull/3372)) @Kinglykrab 2023-05-21
* Fix issue with Group Pointers/Member roles ([#3374](https://github.com/EQEmu/Server/pull/3374)) @Aeadoin 2023-05-25
* Fix mob item bonus calc ([#3334](https://github.com/EQEmu/Server/pull/3334)) @Akkadius 2023-05-07
* Fix typos in #zheader ([#3370](https://github.com/EQEmu/Server/pull/3370)) @Kinglykrab 2023-05-21
* Mob scaling issue with min dmg set to zero while max dmg is not ([#3351](https://github.com/EQEmu/Server/pull/3351)) @RekkasGit 2023-05-20
* NPC Armor Upgrade to a slot not handled correctly ([#3366](https://github.com/EQEmu/Server/pull/3366)) @noudess 2023-05-20
* ReloadQuests() on Zone::Init() to avoid cached global quests/plugins ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Kinglykrab 2023-05-07
* Revert " ReloadQuests() on Zone::Init() to avoid cached global quests/plugins " ([#3333](https://github.com/EQEmu/Server/pull/3333)) @Akkadius 2023-05-08
### Memory Leak
* Fix large memory leak introduced in CalcItemBonuses ([#3331](https://github.com/EQEmu/Server/pull/3331)) @Akkadius 2023-05-07
### Messages
* Remove duplicate heal message for healing yourself ([#3329](https://github.com/EQEmu/Server/pull/3329)) @noudess 2023-05-03
### Performance
* Character bind is now bulk saved ([#3338](https://github.com/EQEmu/Server/pull/3338)) @Akkadius 2023-05-09
* Character buffs now save in bulk ([#3336](https://github.com/EQEmu/Server/pull/3336)) @Akkadius 2023-05-09
* Character pet bulk saving ([#3337](https://github.com/EQEmu/Server/pull/3337)) @Akkadius 2023-05-09
* Character tribute is now bulk saved ([#3340](https://github.com/EQEmu/Server/pull/3340)) @Kinglykrab 2023-05-25
* Mail key is now cached during player load ([#3339](https://github.com/EQEmu/Server/pull/3339)) @Akkadius 2023-05-09
### Pets
* Fix saving inconsistencies with pets ([#3375](https://github.com/EQEmu/Server/pull/3375)) @Akkadius 2023-05-25
### Quest API
* Add GetHateListClosest(), GetHateListClosestBot(), GetHateListClosestClient(), and GetHateListClosestNPC() methods/overloads to Perl/Lua ([#3359](https://github.com/EQEmu/Server/pull/3359)) @RekkasGit 2023-05-16
* Add GetPet() to Perl ([#3309](https://github.com/EQEmu/Server/pull/3309)) @Kinglykrab 2023-05-08
* Add Memorize and Scribe Spell Events to Perl/Lua ([#3363](https://github.com/EQEmu/Server/pull/3363)) @Kinglykrab 2023-05-25
* Add zone data methods to Perl/Lua ([#3342](https://github.com/EQEmu/Server/pull/3342)) @Kinglykrab 2023-05-24
* Cleanup The Darkened Sea Quest Methods Names ([#3369](https://github.com/EQEmu/Server/pull/3369)) @Kinglykrab 2023-05-21
### Rules
* Add World:MaximumQuestErrors Rule ([#3349](https://github.com/EQEmu/Server/pull/3349)) @Kinglykrab 2023-05-21
* ResurrectionEffectBlock to prevent/allow/move buffs. ([#3288](https://github.com/EQEmu/Server/pull/3288)) @nytmyr 2023-05-08
## [22.11.0] - 04/29/2023
### Code
* Add check for owner in quest::pausetimer() ([#3304](https://github.com/EQEmu/Server/pull/3304)) @Kinglykrab 2023-04-23
* Add check for owner in quest::resumetimer() ([#3305](https://github.com/EQEmu/Server/pull/3305)) @Kinglykrab 2023-04-23
* Add initiator/owner checks to various methods in questmgr.cpp ([#3306](https://github.com/EQEmu/Server/pull/3306)) @Kinglykrab 2023-04-23
* Fix possible nullptr in quest::addloot() ([#3303](https://github.com/EQEmu/Server/pull/3303)) @Kinglykrab 2023-04-23
* Remove GetClassHPFactor() from zone/client_mods.cpp and zone/client.h ([#3313](https://github.com/EQEmu/Server/pull/3313)) @Kinglykrab 2023-04-30
* Remove GetClassHPFactor() from zone/merc.h ([#3314](https://github.com/EQEmu/Server/pull/3314)) @Kinglykrab 2023-04-30
* Remove pDontCastBefore_casting_spell from zone/npc.h ([#3311](https://github.com/EQEmu/Server/pull/3311)) @Kinglykrab 2023-04-30
* Remove unused code in zone/pets.cpp ([#3310](https://github.com/EQEmu/Server/pull/3310)) @Kinglykrab 2023-04-30
* Remove unused methods in zone/bot.cpp and zone/bot.h ([#3315](https://github.com/EQEmu/Server/pull/3315)) @Kinglykrab 2023-04-30
* Remove unused methods in zone/client.cpp and zone/client.h ([#3312](https://github.com/EQEmu/Server/pull/3312)) @Kinglykrab 2023-04-30
* Remove unused variable in common/crash.cpp ([#3308](https://github.com/EQEmu/Server/pull/3308)) @Kinglykrab 2023-04-30
* Use default ctor/dtor in oriented_bounding_box.h ([#3307](https://github.com/EQEmu/Server/pull/3307)) @Kinglykrab 2023-04-30
* quest::createBot() unnecessary check against nullptr ([#3302](https://github.com/EQEmu/Server/pull/3302)) @Kinglykrab 2023-04-23
* quest::setallskill() had always true condition. ([#3301](https://github.com/EQEmu/Server/pull/3301)) @Kinglykrab 2023-04-30
### Crash
* Fix UCS crash that occurs during log reloading ([#3324](https://github.com/EQEmu/Server/pull/3324)) @Akkadius 2023-04-30
* Fix possible dereference of nullptr in Client::CalcHPRegen ([#3316](https://github.com/EQEmu/Server/pull/3316)) @Aeadoin 2023-04-23
* Fix possible nullptr in Client::GetCharMaxLevelFromQGlobal() ([#3317](https://github.com/EQEmu/Server/pull/3317)) @Kinglykrab 2023-04-23
### Discord
* Add Discord webhook callback processing to world ([#3322](https://github.com/EQEmu/Server/pull/3322)) @Akkadius 2023-04-30
### Fixes
* Fix issue with NPCs no longer using some armor. ([#3318](https://github.com/EQEmu/Server/pull/3318)) @noudess 2023-04-24
* Fix issue with spawning Mercs ([#3327](https://github.com/EQEmu/Server/pull/3327)) @Aeadoin 2023-04-29
* Possible issues with SummonItem in Client::QuestReward() methods ([#3325](https://github.com/EQEmu/Server/pull/3325)) @Kinglykrab 2023-04-27
### Maps
* Update download with faster releases link ([#3321](https://github.com/EQEmu/Server/pull/3321)) @Akkadius 2023-04-30
### Messages
* Remove duplicate you have lost a level message ([#3323](https://github.com/EQEmu/Server/pull/3323)) @noudess 2023-04-25
### Quest API
* Add GetDefaultRaceSize() overloads to Perl/Lua ([#3320](https://github.com/EQEmu/Server/pull/3320)) @Kinglykrab 2023-04-30
* Add HasSpellEffect() to Perl/Lua ([#3319](https://github.com/EQEmu/Server/pull/3319)) @Kinglykrab 2023-04-30
## [22.10.0] - 04/22/2023
### Backups
+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)
{
switch (class_id) {
@@ -642,6 +656,21 @@ bool IsWISCasterClass(uint8 class_id)
}
}
bool IsHeroicWISCasterClass(uint8 class_id)
{
switch (class_id) {
case CLERIC:
case DRUID:
case SHAMAN:
case PALADIN:
case BEASTLORD:
case RANGER:
return true;
default:
return false;
}
}
bool IsPlateClass(uint8 class_id)
{
switch (class_id) {
+2 -1
View File
@@ -140,7 +140,8 @@ bool IsHybridClass(uint8 class_id);
bool IsCasterClass(uint8 class_id);
bool IsINTCasterClass(uint8 class_id);
bool IsWISCasterClass(uint8 class_id);
bool IsHeroicINTCasterClass(uint8 class_id);
bool IsHeroicWISCasterClass(uint8 class_id);
bool IsPlateClass(uint8 class_id);
bool IsChainClass(uint8 class_id);
bool IsLeatherClass(uint8 class_id);
-3
View File
@@ -41,9 +41,6 @@ void SendCrashReport(const std::string &crash_report)
r.set_connection_timeout(1, 0);
r.set_read_timeout(1, 0);
r.set_write_timeout(1, 0);
httplib::Headers headers = {
{"Content-Type", "application/json"}
};
// os info
auto os = EQ::GetOS();
+1 -1
View File
@@ -68,7 +68,7 @@ namespace DatabaseSchema {
{"character_spells", "id"},
{"character_task_timers", "character_id"},
{"character_tasks", "charid"},
{"character_tribute", "id"},
{"character_tribute", "character_id"},
{"completed_tasks", "charid"},
{"data_buckets", "id"},
{"faction_values", "char_id"},
+7
View File
@@ -1045,4 +1045,11 @@ enum ResurrectionActions
Accept
};
enum ScribeSpellActions
{
Scribe,
Memorize,
Unmemorize
};
#endif /*COMMON_EQ_CONSTANTS_H*/
+11
View File
@@ -1793,6 +1793,17 @@ struct GMSummon_Struct {
/*104*/ uint32 unknown2; // E0 E0 56 00
};
struct GMFind_Struct {
char charname[64];
char gmname[64];
uint32 success;
uint32 zoneID;
float x;
float y;
float z;
uint32 unknown2;
};
struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet
/* 0*/ char charname[64];
+2 -1
View File
@@ -108,7 +108,8 @@ namespace EQ
bool AvailableWearSlot(uint32 aug_wear_slots) const;
int8 AvailableAugmentSlot(int32 augment_type) const;
bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const;
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); }
inline int GetAugmentType() const { return m_item ? m_item->AugType : 0; }
inline uint32 GetAugmentRestriction() const { return m_item ? m_item->AugRestrict : 0; }
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); }
@@ -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, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30")
RULE_CATEGORY_END()
RULE_CATEGORY(Zone)
@@ -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, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type")
RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true")
RULE_BOOL(Spells, ResurrectionEffectsBlock, true, "If enabled, resurrection effects cannot be overwritten.")
RULE_INT(Spells, ResurrectionEffectBlock, 2, "0 = allow overwrites/rule disabled. If set to 1 = Block all buffs that would overwrite Resurrection Effects. If set to 2 = Will not overwrite Resurrection Effects, instead moves new buff to an empty slot if available. Default is 2.")
RULE_CATEGORY_END()
RULE_CATEGORY(Combat)
+13 -12
View File
@@ -235,18 +235,19 @@
#define ServerOP_ReloadMerchants 0x4109
#define ServerOP_ReloadNPCEmotes 0x4110
#define ServerOP_ReloadObjects 0x4111
#define ServerOP_ReloadPerlExportSettings 0x4112
#define ServerOP_ReloadRules 0x4113
#define ServerOP_ReloadStaticZoneData 0x4114
#define ServerOP_ReloadTasks 0x4115
#define ServerOP_ReloadTitles 0x4116
#define ServerOP_ReloadTraps 0x4117
#define ServerOP_ReloadVariables 0x4118
#define ServerOP_ReloadVeteranRewards 0x4119
#define ServerOP_ReloadWorld 0x4120
#define ServerOP_ReloadZonePoints 0x4121
#define ServerOP_ReloadDzTemplates 0x4122
#define ServerOP_ReloadZoneData 0x4123
#define ServerOP_ReloadOpcodes 0x4112
#define ServerOP_ReloadPerlExportSettings 0x4113
#define ServerOP_ReloadRules 0x4114
#define ServerOP_ReloadStaticZoneData 0x4115
#define ServerOP_ReloadTasks 0x4116
#define ServerOP_ReloadTitles 0x4117
#define ServerOP_ReloadTraps 0x4118
#define ServerOP_ReloadVariables 0x4119
#define ServerOP_ReloadVeteranRewards 0x4120
#define ServerOP_ReloadWorld 0x4121
#define ServerOP_ReloadZonePoints 0x4122
#define ServerOP_ReloadDzTemplates 0x4123
#define ServerOP_ReloadZoneData 0x4124
#define ServerOP_CZDialogueWindow 0x4500
#define ServerOP_CZLDoNUpdate 0x4501
+31 -32
View File
@@ -133,55 +133,54 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
{
char MailKeyString[17];
char mail_key[17];
if (RuleB(Chat, EnableMailKeyIPVerification) == true)
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
else
sprintf(MailKeyString, "%08X", MailKey);
if (RuleB(Chat, EnableMailKeyIPVerification) == true) {
sprintf(mail_key, "%08X%08X", IPAddress, MailKey);
}
else {
sprintf(mail_key, "%08X", MailKey);
}
const std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
MailKeyString, CharID);
const auto results = QueryDatabase(query);
if (!results.Success())
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, MailKeyString, results.ErrorMessage().c_str());
const std::string query = StringFormat(
"UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
mail_key, CharID
);
const auto results = QueryDatabase(query);
if (!results.Success()) {
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, mail_key, results.ErrorMessage().c_str());
}
}
std::string SharedDatabase::GetMailKey(int CharID, bool key_only)
SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id)
{
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID);
auto results = QueryDatabase(query);
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", character_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
Log(Logs::Detail, Logs::MySQLError, "Error retrieving mailkey from database: %s", results.ErrorMessage().c_str());
return std::string();
return MailKeys{};
}
if (!results.RowCount()) {
Log(Logs::General, Logs::ClientLogin, "Error: Mailkey for character id [%i] does not exist or could not be found", CharID);
return std::string();
Log(Logs::General,
Logs::ClientLogin,
"Error: Mailkey for character id [%i] does not exist or could not be found",
character_id
);
return MailKeys{};
}
auto& row = results.begin();
auto &row = results.begin();
if (row != results.end()) {
std::string mail_key = row[0];
if (mail_key.length() > 8 && key_only) {
return mail_key.substr(8);
}
else {
return mail_key;
}
return MailKeys{
.mail_key = mail_key.substr(8),
.mail_key_full = mail_key
};
}
else {
Log(Logs::General, Logs::MySQLError, "Internal MySQL error in SharedDatabase::GetMailKey(int, bool)");
return std::string();
}
return MailKeys{};
}
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQ::ItemInstance*>::const_iterator &start, std::list<EQ::ItemInstance*>::const_iterator &end)
+5 -1
View File
@@ -81,7 +81,11 @@ public:
bool SetGMInvul(uint32 account_id, bool gminvul);
bool SetGMFlymode(uint32 account_id, uint8 flymode);
void SetMailKey(int CharID, int IPAddress, int MailKey);
std::string GetMailKey(int CharID, bool key_only = false);
struct MailKeys {
std::string mail_key;
std::string mail_key_full;
};
MailKeys GetMailKey(int character_id);
bool SaveCursor(
uint32 char_id,
std::list<EQ::ItemInstance *>::const_iterator &start,
+1177 -700
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_UNSUMMON_SELF 892
#define SPELL_ANCIENT_LIFEBANE 2115
#define SPELL_GMHP25K 6817
#define SPELL_GMHP50K 6818
#define SPELL_GMHP100K 6819
#define SPELL_GMHP225K 6820
#define SPELL_GMHP475K 6821
#define SPELL_GMHP925K 6822
#define SPELL_GMHP2M 6823
#define SPELL_GMHP3M 6824
#define SPELL_GMHP5M 39851
#define SPELL_GUIDE_ACTING_ONE 778
#define SPELL_GUIDE_ALLIANCE_ONE 810
#define SPELL_GUIDE_CANCEL_MAGIC_ONE 811
#define SPELL_GUIDE_JOURNEY_ONE 813
#define SPELL_GUIDE_VISION_ONE 814
#define SPELL_GUIDE_HEALTH_ONE 815
#define SPELL_GUIDE_INVULNERABILITY_ONE 816
#define SPELL_GUIDE_BOLT_ONE 817
#define SPELL_GUIDE_MEMORY_BLUR_ONE 818
#define SPELL_GUIDE_ACTING_TWO 1209
#define SPELL_GUIDE_CANCEL_MAGIC_TWO 1211
#define SPELL_GUIDE_JOURNEY_TWO 1212
#define SPELL_GUIDE_VISION_TWO 1213
#define SPELL_GUIDE_HEALTH_TWO 1214
#define SPELL_GUIDE_INVULNERABILITY_TWO 1215
#define SPELL_GUIDE_BOLT_TWO 1216
#define SPELL_GUIDE_MEMORY_BLUR_TWO 1217
#define SPELL_GUIDE_ALLIANCE_TWO 1219
#define SPELL_GUIDE_EVACUATION 3921
#define SPELL_GUIDE_LEVITATION 39852
#define SPELL_GUIDE_SPELL_HASTE 39853
#define SPELL_GUIDE_HASTE 39854
//spellgroup ids
#define SPELLGROUP_FRENZIED_BURNOUT 2754
@@ -201,8 +232,22 @@
#define INSTRUMENT_LUTE 13011
#define INSTRUMENT_HORN 13012
//option types for the rule Spells:ResurrectionEffectBlock
#define RES_EFFECTS_CANNOT_STACK -1
#define NO_RES_EFFECTS_BLOCK 0
#define RES_EFFECTS_BLOCK 1
#define RES_EFFECTS_BLOCK_WITH_BUFFS 2
#define MOVE_NEW_SLOT 2
const int Z_AGGRO=10;
#define PARTIAL_DEATH_SAVE 1
#define FULL_DEATH_SAVE 2
#define MAX_FAST_HEAL_CASTING_TIME 2000
#define MAX_VERY_FAST_HEAL_CASTING_TIME 1000
#define DETRIMENTAL_EFFECT 0
#define BENEFICIAL_EFFECT 1
#define BENEFICIAL_EFFECT_GROUP_ONLY 2
const uint32 MobAISpellRange=100; // max range of buffs
@@ -1160,7 +1205,7 @@ typedef enum {
#define SE_LimitUseMin 422 // implemented, @Ff Minium amount of numhits for a spell to be focused, base: numhit amt
#define SE_LimitUseType 423 // implemented, @Ff Focus will only affect if has this numhits type, base: numhit type
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_SkillProcAttempt 427 // implemented - chance to proc when using a skill(ie taunt)
#define SE_LimitToSkill 428 // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none
@@ -1443,7 +1488,7 @@ extern int32 SPDAT_RECORDS;
bool IsTargetableAESpell(uint16 spell_id);
bool IsSacrificeSpell(uint16 spell_id);
bool IsLifetapSpell(uint16 spell_id);
bool IsMezSpell(uint16 spell_id);
bool IsMesmerizeSpell(uint16 spell_id);
bool IsStunSpell(uint16 spell_id);
bool IsSlowSpell(uint16 spell_id);
bool IsHasteSpell(uint16 spell_id);
@@ -1452,22 +1497,23 @@ bool IsPercentalHealSpell(uint16 spell_id);
bool IsGroupOnlySpell(uint16 spell_id);
bool IsBeneficialSpell(uint16 spell_id);
bool IsDetrimentalSpell(uint16 spell_id);
bool IsInvisSpell(uint16 spell_id);
bool IsInvisibleSpell(uint16 spell_id);
bool IsInvulnerabilitySpell(uint16 spell_id);
bool IsCHDurationSpell(uint16 spell_id);
bool IsCompleteHealDurationSpell(uint16 spell_id);
bool IsPoisonCounterSpell(uint16 spell_id);
bool IsDiseaseCounterSpell(uint16 spell_id);
bool IsSummonItemSpell(uint16 spell_id);
bool IsSummonSkeletonSpell(uint16 spell_id);
bool IsSummonPetSpell(uint16 spell_id);
bool IsSummonPCSpell(uint16 spell_id);
bool IsPetSpell(uint16 spell_id);
bool IsCharmSpell(uint16 spell_id);
bool IsBlindSpell(uint16 spell_id);
bool IsEffectHitpointsSpell(uint16 spell_id);
bool IsReduceCastTimeSpell(uint16 spell_id);
bool IsHealthSpell(uint16 spell_id);
bool IsCastTimeReductionSpell(uint16 spell_id);
bool IsIncreaseDurationSpell(uint16 spell_id);
bool IsReduceManaSpell(uint16 spell_id);
bool IsExtRangeSpell(uint16 spell_id);
bool IsManaCostReductionSpell(uint16 spell_id);
bool IsIncreaseRangeSpell(uint16 spell_id);
bool IsImprovedHealingSpell(uint16 spell_id);
bool IsImprovedDamageSpell(uint16 spell_id);
bool IsAEDurationSpell(uint16 spell_id);
@@ -1475,26 +1521,22 @@ bool IsPureNukeSpell(uint16 spell_id);
bool IsAENukeSpell(uint16 spell_id);
bool IsPBAENukeSpell(uint16 spell_id);
bool IsAERainNukeSpell(uint16 spell_id);
bool IsPartialCapableSpell(uint16 spell_id);
bool IsPartialResistableSpell(uint16 spell_id);
bool IsResistableSpell(uint16 spell_id);
bool IsGroupSpell(uint16 spell_id);
bool IsTGBCompatibleSpell(uint16 spell_id);
bool IsBardSong(uint16 spell_id);
bool IsEffectInSpell(uint16 spellid, int effect);
uint16 GetTriggerSpellID(uint16 spell_id, uint32 effect);
bool IsBlankSpellEffect(uint16 spellid, int effect_index);
bool IsValidSpell(uint32 spellid);
bool IsSummonSpell(uint16 spellid);
bool IsEvacSpell(uint16 spellid);
bool IsDamageSpell(uint16 spellid);
bool IsFearSpell(uint16 spellid);
bool IsCureSpell(uint16 spellid);
bool BeneficialSpell(uint16 spell_id);
bool GroupOnlySpell(uint16 spell_id);
int GetSpellEffectIndex(uint16 spell_id, int effect);
int CanUseSpell(uint16 spellid, int classa, int level);
int GetMinLevel(uint16 spell_id);
int GetSpellLevel(uint16 spell_id, int classa);
bool IsEffectInSpell(uint16 spell_id, int effect_id);
uint16 GetSpellTriggerSpellID(uint16 spell_id, int effect_id);
bool IsBlankSpellEffect(uint16 spell_id, int effect_index);
bool IsValidSpell(uint32 spell_id);
bool IsSummonSpell(uint16 spell_id);
bool IsDamageSpell(uint16 spell_id);
bool IsFearSpell(uint16 spell_id);
bool IsCureSpell(uint16 spell_id);
int GetSpellEffectIndex(uint16 spell_id, int effect_id);
uint8 GetSpellMinimumLevel(uint16 spell_id);
uint8 GetSpellLevel(uint16 spell_id, uint8 class_id);
int CalcBuffDuration_formula(int level, int formula, int duration);
int32 CalculatePoisonCounters(uint16 spell_id);
int32 CalculateDiseaseCounters(uint16 spell_id);
@@ -1505,10 +1547,11 @@ bool IsDisciplineBuff(uint16 spell_id);
bool IsDiscipline(uint16 spell_id);
bool IsCombatSkill(uint16 spell_id);
bool IsResurrectionEffects(uint16 spell_id);
int8 GetSpellResurrectionSicknessCheck(uint16 spell_id_one, uint16 spell_id_two);
bool IsRuneSpell(uint16 spell_id);
bool IsMagicRuneSpell(uint16 spell_id);
bool IsManaTapSpell(uint16 spell_id);
bool IsAllianceSpellLine(uint16 spell_id);
bool IsAllianceSpell(uint16 spell_id);
bool IsDeathSaveSpell(uint16 spell_id);
bool IsFullDeathSaveSpell(uint16 spell_id);
bool IsPartialDeathSaveSpell(uint16 spell_id);
@@ -1517,10 +1560,10 @@ bool IsSuccorSpell(uint16 spell_id);
bool IsTeleportSpell(uint16 spell_id);
bool IsTranslocateSpell(uint16 spell_id);
bool IsGateSpell(uint16 spell_id);
bool IsPlayerIllusionSpell(uint16 spell_id); // seveian 2008-09-23
bool IsIllusionSpell(uint16 spell_id);
bool IsLDoNObjectSpell(uint16 spell_id);
int32 GetSpellResistType(uint16 spell_id);
int32 GetSpellTargetType(uint16 spell_id);
int GetSpellResistType(uint16 spell_id);
int GetSpellTargetType(uint16 spell_id);
bool IsHealOverTimeSpell(uint16 spell_id);
bool IsCompleteHealSpell(uint16 spell_id);
bool IsFastHealSpell(uint16 spell_id);
@@ -1535,38 +1578,36 @@ bool IsSelfConversionSpell(uint16 spell_id);
bool IsBuffSpell(uint16 spell_id);
bool IsPersistDeathSpell(uint16 spell_id);
bool IsSuspendableSpell(uint16 spell_id);
uint32 GetMorphTrigger(uint32 spell_id);
bool IsCastonFadeDurationSpell(uint16 spell_id);
bool IsPowerDistModSpell(uint16 spell_id);
uint32 GetPartialMeleeRuneReduction(uint32 spell_id);
uint32 GetPartialMagicRuneReduction(uint32 spell_id);
uint32 GetPartialMeleeRuneAmount(uint32 spell_id);
uint32 GetPartialMagicRuneAmount(uint32 spell_id);
bool NoDetrimentalSpellAggro(uint16 spell_id);
bool IsStackableDot(uint16 spell_id);
bool IsBardOnlyStackEffect(int effect);
bool IsCastWhileInvis(uint16 spell_id);
bool IsEffectIgnoredInStacking(int spa);
bool IsFocusLimit(int spa);
bool SpellRequiresTarget(int target_type);
bool IsVirusSpell(int32 spell_id);
int GetViralMinSpreadTime(int32 spell_id);
int GetViralMaxSpreadTime(int32 spell_id);
int GetViralSpreadRange(int32 spell_id);
bool IsInstrumentModAppliedToSpellEffect(int32 spell_id, int effect);
bool IsPulsingBardSong(int32 spell_id);
uint32 GetProcLimitTimer(int32 spell_id, int proc_type);
bool IgnoreCastingRestriction(int32 spell_id);
int CalcPetHp(int levelb, int classb, int STA = 75);
int GetSpellEffectDescNum(uint16 spell_id);
DmgShieldType GetDamageShieldType(uint16 spell_id, int32 DSType = 0);
bool DetrimentalSpellAllowsRest(uint16 spell_id);
uint32 GetNimbusEffect(uint16 spell_id);
int32 GetFuriousBash(uint16 spell_id);
bool IsCastOnFadeDurationSpell(uint16 spell_id);
bool IsDistanceModifierSpell(uint16 spell_id);
int GetSpellPartialMeleeRuneReduction(uint16 spell_id);
int GetSpellPartialMagicRuneReduction(uint16 spell_id);
int GetSpellPartialMeleeRuneAmount(uint16 spell_id);
int GetSpellPartialMagicRuneAmount(uint16 spell_id);
bool IsNoDetrimentalSpellAggroSpell(uint16 spell_id);
bool IsStackableDOT(uint16 spell_id);
bool IsBardOnlyStackEffect(int effect_id);
bool IsCastWhileInvisibleSpell(uint16 spell_id);
bool IsEffectIgnoredInStacking(int effect_id);
bool IsFocusLimit(int effect_id);
bool IsTargetRequiredForSpell(uint16 spell_id);
bool IsVirusSpell(uint16 spell_id);
int GetSpellViralMinimumSpreadTime(uint16 spell_id);
int GetSpellViralMaximumSpreadTime(uint16 spell_id);
int GetSpellViralSpreadRange(uint16 spell_id);
bool IsInstrumentModifierAppliedToSpellEffect(uint16 spell_id, int effect_id);
bool IsPulsingBardSong(uint16 spell_id);
int GetSpellProcLimitTimer(uint16 spell_id, int proc_type);
bool IsCastNotStandingSpell(uint16 spell_id);
int GetSpellEffectDescriptionNumber(uint16 spell_id);
DmgShieldType GetDamageShieldType(uint16 spell_id, int damage_shield_type = 0);
bool IsRestAllowedSpell(uint16 spell_id);
int GetSpellNimbusEffect(uint16 spell_id);
int GetSpellFuriousBash(uint16 spell_id);
bool IsShortDurationBuff(uint16 spell_id);
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type);
bool IsSpellUsableInThisZoneType(uint16 spell_id, uint8 zone_type);
const char *GetSpellName(uint16 spell_id);
int GetSpellStatValue(uint32 spell_id, const char* stat_identifier, uint8 slot = 0);
bool CastRestrictedSpell(int spellid);
int GetSpellStatValue(uint16 spell_id, const char* stat_identifier, uint8 slot = 0);
bool IsCastRestrictedSpell(uint16 spell_id);
#endif
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.10.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 COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9227
#define CURRENT_BINARY_DATABASE_VERSION 9228
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9039
File diff suppressed because it is too large Load Diff
+58
View File
@@ -24,6 +24,8 @@
#include "../common/repositories/zone_repository.h"
#include "../common/repositories/base/base_content_flags_repository.h"
#include <glm/vec4.hpp>
class ZoneStore {
public:
ZoneStore();
@@ -43,6 +45,62 @@ public:
const char *GetZoneName(uint32 zone_id, bool error_unknown = false);
const char *GetZoneLongName(uint32 zone_id, bool error_unknown = false);
ZoneRepository::Zone *GetZoneWithFallback(uint32 zone_id, int version = 0);
glm::vec4 GetZoneSafeCoordinates(uint32 zone_id, int version = 0);
float GetZoneGraveyardID(uint32 zone_id, int version = 0);
uint8 GetZoneMinimumLevel(uint32 zone_id, int version = 0);
uint8 GetZoneMaximumLevel(uint32 zone_id, int version = 0);
uint8 GetZoneMinimumStatus(uint32 zone_id, int version = 0);
int GetZoneTimeZone(uint32 zone_id, int version = 0);
int GetZoneMaximumPlayers(uint32 zone_id, int version = 0);
uint32 GetZoneRuleSet(uint32 zone_id, int version = 0);
const std::string& GetZoneNote(uint32 zone_id, int version = 0);
float GetZoneUnderworld(uint32 zone_id, int version = 0);
float GetZoneMinimumClip(uint32 zone_id, int version = 0);
float GetZoneMaximumClip(uint32 zone_id, int version = 0);
float GetZoneFogMinimumClip(uint32 zone_id, uint8 slot = 0, int version = 0);
float GetZoneFogMaximumClip(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneFogRed(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneFogGreen(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneFogBlue(uint32 zone_id, uint8 slot = 0, int version = 0);
uint8 GetZoneSky(uint32 zone_id, int version = 0);
uint8 GetZoneZType(uint32 zone_id, int version = 0);
float GetZoneExperienceMultiplier(uint32 zone_id, int version = 0);
float GetZoneWalkSpeed(uint32 zone_id, int version = 0);
uint8 GetZoneTimeType(uint32 zone_id, int version = 0);
float GetZoneFogDensity(uint32 zone_id, int version = 0);
const std::string& GetZoneFlagNeeded(uint32 zone_id, int version = 0);
int8 GetZoneCanBind(uint32 zone_id, int version = 0);
int8 GetZoneCanCombat(uint32 zone_id, int version = 0);
int8 GetZoneCanLevitate(uint32 zone_id, int version = 0);
int8 GetZoneCastOutdoor(uint32 zone_id, int version = 0);
uint8 GetZoneHotzone(uint32 zone_id, int version = 0);
uint8 GetZoneInstanceType(uint32 zone_id, int version = 0);
uint64 GetZoneShutdownDelay(uint32 zone_id, int version = 0);
int8 GetZonePEQZone(uint32 zone_id, int version = 0);
int8 GetZoneExpansion(uint32 zone_id, int version = 0);
int8 GetZoneBypassExpansionCheck(uint32 zone_id, int version = 0);
uint8 GetZoneSuspendBuffs(uint32 zone_id, int version = 0);
int GetZoneRainChance(uint32 zone_id, uint8 slot = 0, int version = 0);
int GetZoneRainDuration(uint32 zone_id, uint8 slot = 0, int version = 0);
int GetZoneSnowChance(uint32 zone_id, uint8 slot = 0, int version = 0);
int GetZoneSnowDuration(uint32 zone_id, uint8 slot = 0, int version = 0);
float GetZoneGravity(uint32 zone_id, int version = 0);
int GetZoneType(uint32 zone_id, int version = 0);
int8 GetZoneSkyLock(uint32 zone_id, int version = 0);
int GetZoneFastRegenHP(uint32 zone_id, int version = 0);
int GetZoneFastRegenMana(uint32 zone_id, int version = 0);
int GetZoneFastRegenEndurance(uint32 zone_id, int version = 0);
int GetZoneNPCMaximumAggroDistance(uint32 zone_id, int version = 0);
uint32 GetZoneMaximumMovementUpdateRange(uint32 zone_id, int version = 0);
int8 GetZoneMinimumExpansion(uint32 zone_id, int version = 0);
int8 GetZoneMaximumExpansion(uint32 zone_id, int version = 0);
const std::string& GetZoneContentFlags(uint32 zone_id, int version = 0);
const std::string& GetZoneContentFlagsDisabled(uint32 zone_id, int version = 0);
int GetZoneUnderworldTeleportIndex(uint32 zone_id, int version = 0);
int GetZoneLavaDamage(uint32 zone_id, int version = 0);
int GetZoneMinimumLavaDamage(uint32 zone_id, int version = 0);
private:
std::vector<ZoneRepository::Zone> m_zones;
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.10.0",
"version": "22.13.1",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+2
View File
@@ -144,6 +144,8 @@ int main() {
->LoadLogDatabaseSettings()
->StartFileLogs();
player_event_logs.SetDatabase(&database)->Init();
char tmp[64];
// ucs has no 'reload rules' handler
+1 -15
View File
@@ -1801,23 +1801,9 @@ sub fetch_peq_db_full
sub map_files_fetch_bulk
{
print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n";
get_remote_file("http://analytics.akkadius.com/maps.zip", "maps/maps.zip", 1);
get_remote_file("https://github.com/Akkadius/eqemu-maps/releases/latest/download/maps.zip", "maps/maps.zip", 1);
unzip('maps/maps.zip', 'maps/');
my @files;
my $start_dir = "maps/EQEmuMaps-master/";
find(
sub { push @files, $File::Find::name unless -d; },
$start_dir
);
for my $file (@files) {
$destination_file = $file;
$destination_file =~ s/maps\/EQEmuMaps-master\///g;
print "[Install] Installing [" . $destination_file . "]\n";
copy_file($file, "maps/" . $destination_file);
}
print "[Install] Fetched Latest Maps\n";
rmtree('maps/EQEmuMaps-master');
unlink('maps/maps.zip');
}
+1
View File
@@ -481,6 +481,7 @@
9225|2023_01_21_bots_raid_members.sql|SHOW COLUMNS FROM `raid_members` LIKE 'bot_id'|empty|
9226|2023_03_17_corpse_fields.sql|SHOW COLUMNS FROM `character_corpse_items` LIKE 'custom_data'|empty|
9227|2023_03_24_npc_scale_global_base_verify.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'heroic_strikethrough'|not_empty|
9228|2023_05_08_character_tribute_primary_key.sql|SHOW COLUMNS FROM `character_tribute` LIKE 'character_id'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not
@@ -0,0 +1,4 @@
ALTER TABLE `character_tribute`
CHANGE COLUMN `id` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
+5 -5
View File
@@ -361,7 +361,7 @@ void ConsoleTell(
auto join_args = args;
join_args.erase(join_args.begin(), join_args.begin() + 1);
zoneserver_list.SendChannelMessage(tmpname, to.c_str(), 7, 0, Strings::Join(join_args, " ").c_str());
zoneserver_list.SendChannelMessage(tmpname, to.c_str(), ChatChannel_Tell, 0, Strings::Join(join_args, " ").c_str());
}
/**
@@ -382,7 +382,7 @@ void ConsoleBroadcast(
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, Strings::Join(args, " ").c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_Broadcast, 0, Strings::Join(args, " ").c_str());
}
/**
@@ -403,7 +403,7 @@ void ConsoleGMSay(
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, Strings::Join(args, " ").c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_GMSAY, 0, Strings::Join(args, " ").c_str());
}
/**
@@ -457,7 +457,7 @@ void ConsoleOOC(
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, Strings::Join(args, " ").c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_OOC, 0, Strings::Join(args, " ").c_str());
}
/**
@@ -478,7 +478,7 @@ void ConsoleAuction(
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, Strings::Join(args, " ").c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, ChatChannel_Auction, 0, Strings::Join(args, " ").c_str());
}
/**
+1
View File
@@ -146,6 +146,7 @@ std::vector<Reload> reload_types = {
Reload{.command = "merchants", .opcode = ServerOP_ReloadMerchants, .desc = "Merchants"},
Reload{.command = "npc_emotes", .opcode = ServerOP_ReloadNPCEmotes, .desc = "NPC Emotes"},
Reload{.command = "objects", .opcode = ServerOP_ReloadObjects, .desc = "Objects"},
Reload{.command = "opcodes", .opcode = ServerOP_ReloadOpcodes, .desc = "Opcodes"},
Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"},
Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"},
Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"},
+1
View File
@@ -17,6 +17,7 @@ public:
void Disconnect() { if(connection && connection->Handle()) connection->Handle()->Disconnect(); }
void SendMessage(const char *From, const char *Message);
const std::shared_ptr<EQ::Net::ServertalkServerConnection> &GetConnection() const;
inline bool IsConnected() const { return connection->Handle() ? connection->Handle()->IsConnected() : false; }
private:
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
+17
View File
@@ -300,6 +300,8 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings();
LogSys.SetDiscordHandler(&WorldBoot::DiscordWebhookMessageHandler);
if (!ignore_db) {
LogInfo("Checking Database Conversions");
database.CheckDatabaseConversions();
@@ -662,3 +664,18 @@ void WorldBoot::Shutdown()
safe_delete(mutex);
}
void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message)
{
if (UCSLink.IsConnected()) {
auto pack = new ServerPacket(ServerOP_DiscordWebhookMessage, sizeof(DiscordWebhookMessage_Struct) + 1);
auto *q = (DiscordWebhookMessage_Struct *) pack->pBuffer;
strn0cpy(q->message, message.c_str(), 2000);
q->webhook_id = webhook_id;
UCSLink.SendPacket(pack);
safe_delete(pack);
}
}
+13
View File
@@ -3,6 +3,9 @@
#include <string>
#include "../common/types.h"
#include "../common/discord/discord.h"
extern UCSConnection UCSLink;
class WorldBoot {
public:
@@ -16,6 +19,16 @@ public:
static bool DatabaseLoadRoutines(int argc, char **argv);
static void CheckForPossibleConfigurationIssues();
static void Shutdown();
static void SendDiscordMessage(int webhook_id, const std::string& message);
static void DiscordWebhookMessageHandler(uint16 log_category, int webhook_id, const std::string &message)
{
std::string message_prefix = fmt::format(
"[**{}**] **World** ",
Logs::LogCategoryName[log_category]
);
SendDiscordMessage(webhook_id, message_prefix + Discord::FormatDiscordMessage(log_category, message));
};
};
+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/repositories/player_event_logs_repository.h"
#include "../common/events/player_event_logs.h"
#include "../common/patches/patches.h"
extern ClientList client_list;
extern GroupLFPList LFPGroupList;
@@ -1296,6 +1297,10 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
QSLink.SendPacket(pack);
break;
}
case ServerOP_ReloadOpcodes: {
ReloadAllPatches();
break;
}
case ServerOP_CZDialogueWindow:
case ServerOP_CZLDoNUpdate:
case ServerOP_CZMarquee:
-1
View File
@@ -228,7 +228,6 @@ SET(zone_headers
lua_stat_bonuses.h
map.h
masterentity.h
message.h
merc.h
mob.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;
}
if (!IsCastWhileInvis(rank->spell))
if (!IsCastWhileInvisibleSpell(rank->spell))
CommonBreakInvisible();
if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) {
@@ -1333,7 +1333,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
target_id = GetPetID();
// extra handling for cast_not_standing spells
if (!IgnoreCastingRestriction(rank->spell)) {
if (!IsCastNotStandingSpell(rank->spell)) {
if (GetAppearance() == eaSitting) // we need to stand!
SetAppearance(eaStanding, false);
+3 -15
View File
@@ -21,22 +21,10 @@
#include "masterentity.h"
#include "aa_ability.h"
AA::Rank *AA::Ability::GetMaxRank() {
if(!first)
return nullptr;
Rank *current = first;
while(current->next) {
current = current->next;
}
return current;
}
AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) {
if(current_level == 0)
return nullptr;
if(!first)
return nullptr;
@@ -65,6 +53,6 @@ int AA::Ability::GetMaxLevel(Mob *who) {
max_level++;
current = current->next;
}
return max_level;
}
}
-1
View File
@@ -37,7 +37,6 @@ public:
Ability() { }
~Ability() { }
Rank *GetMaxRank();
Rank *GetRankByPointsSpent(int current_level);
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
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
{
if (NoDetrimentalSpellAggro(spell_id))
if (IsNoDetrimentalSpellAggroSpell(spell_id))
return 0;
int32 AggroAmount = 0;
+15 -7
View File
@@ -160,7 +160,7 @@ int Mob::compute_tohit(EQ::skills::SkillType skillinuse)
if (IsNPC())
tohit += CastToNPC()->GetAccuracyRating();
if (IsClient()) {
double reduction = CastToClient()->m_pp.intoxication / 2.0;
double reduction = CastToClient()->GetIntoxication() / 2.0;
if (reduction > 20.0) {
reduction = std::min((110 - reduction) / 100.0, 1.0);
tohit = reduction * static_cast<double>(tohit);
@@ -256,7 +256,7 @@ int Mob::compute_defense()
defense += CastToNPC()->GetAvoidanceRating();
if (IsClient()) {
double reduction = CastToClient()->m_pp.intoxication / 2.0;
double reduction = CastToClient()->GetIntoxication() / 2.0;
if (reduction > 20.0) {
reduction = std::min((110 - reduction) / 100.0, 1.0);
defense = reduction * static_cast<double>(defense);
@@ -2958,7 +2958,7 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient())
return;
if (IsValidSpell(spell_id) && NoDetrimentalSpellAggro(spell_id))
if (IsValidSpell(spell_id) && IsNoDetrimentalSpellAggroSpell(spell_id))
return;
if (other == myowner)
@@ -4447,11 +4447,19 @@ void Mob::HealDamage(uint64 amount, Mob* caster, uint16 spell_id)
}
}
else { // normal heals
FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage,
YOU_HEALED, caster->GetCleanName(), itoa(acthealed));
// Message to caster
if (caster->IsClient()) {
caster->FilteredMessageString(caster, Chat::NonMelee,
FilterSpellDamage, YOU_HEAL, GetCleanName(),
itoa(acthealed));
}
caster->FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage,
YOU_HEAL, GetCleanName(), itoa(acthealed));
// Message to target
if (IsClient() && caster != this) {
FilteredMessageString(caster, Chat::NonMelee,
FilterSpellDamage, YOU_HEALED, caster->GetCleanName(),
itoa(acthealed));
}
}
} else if (
CastToClient()->GetFilter(FilterHealOverTime) != FilterShowSelfOnly ||
+14 -31
View File
@@ -58,16 +58,10 @@ void Mob::CalcBonuses()
void NPC::CalcBonuses()
{
memset(&itembonuses, 0, sizeof(StatBonuses));
if (RuleB(NPC, UseItemBonusesForNonPets)) {
memset(&itembonuses, 0, sizeof(StatBonuses));
if (GetOwner() || RuleB(NPC, UseItemBonusesForNonPets)) {
CalcItemBonuses(&itembonuses);
}
else {
if (GetOwner()) {
memset(&itembonuses, 0, sizeof(StatBonuses));
CalcItemBonuses(&itembonuses);
}
}
// This has to happen last, so we actually take the item bonuses into account.
Mob::CalcBonuses();
@@ -152,18 +146,7 @@ void Mob::CalcItemBonuses(StatBonuses* b) {
int16 i;
for (i = EQ::invslot::BONUS_BEGIN; i <= EQ::invslot::BONUS_SKILL_END; i++) {
const EQ::ItemInstance* inst = nullptr;
if (IsOfClientBotMerc()) {
inst = GetInv().GetItem(i);
} else {
const auto* item = CastToNPC()->GetItem(i);
if (!item) {
continue;
}
inst = database.CreateItem(item->item_id);
}
const EQ::ItemInstance* inst = GetInv().GetItem(i);
if (!inst) {
continue;
}
@@ -268,7 +251,7 @@ void Mob::AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_a
return;
}
if (!is_tribute && !inst->IsEquipable(GetBaseRace(), GetClass())) {
if (IsClient() && !is_tribute && !inst->IsEquipable(GetBaseRace(), GetClass())) {
if (item->ItemType != EQ::item::ItemTypeFood && item->ItemType != EQ::item::ItemTypeDrink) {
return;
}
@@ -276,14 +259,14 @@ void Mob::AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_a
const auto current_level = GetLevel();
if (current_level < inst->GetItemRequiredLevel(true)) {
if (IsClient() && current_level < inst->GetItemRequiredLevel(true)) {
return;
}
if (!is_ammo_item) {
const auto recommended_level = is_augment ? recommended_level_override : inst->GetItemRecommendedLevel(true);
if (current_level >= recommended_level) {
if (IsNPC() || current_level >= recommended_level) {
b->HP += item->HP;
b->Mana += item->Mana;
b->Endurance += item->Endur;
@@ -5965,26 +5948,26 @@ void Mob::CalcHeroicBonuses(StatBonuses* newbon)
void Mob::SetHeroicWisBonuses(StatBonuses* n)
{
n->heroic_max_mana += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) * 10 : 0;
n->heroic_mana_regen += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 : 0;
n->heroic_max_mana += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) * 10 : 0;
n->heroic_mana_regen += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * RuleR(Character, HeroicWisdomMultiplier) / 25 : 0;
n->HealAmt += GetHeroicWIS() * RuleR(Character, HeroicWisdomIncreaseHealAmtMultiplier);
if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) {
n->heroic_max_mana += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisMaxMana) * 10 : 0;
n->heroic_mana_regen += IsWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisManaRegen) / 25 : 0;
n->heroic_max_mana += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisMaxMana) * 10 : 0;
n->heroic_mana_regen += IsHeroicWISCasterClass(GetClass()) ? GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisManaRegen) / 25 : 0;
n->HealAmt += GetHeroicWIS() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::WisHealAmt);
}
}
void Mob::SetHeroicIntBonuses(StatBonuses* n)
{
n->heroic_max_mana += IsINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10 : 0;
n->heroic_mana_regen += IsINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25 : 0;
n->heroic_max_mana += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) * 10 : 0;
n->heroic_mana_regen += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * RuleR(Character, HeroicIntelligenceMultiplier) / 25 : 0;
n->SpellDmg += GetHeroicINT() * RuleR(Character, HeroicIntelligenceIncreaseSpellDmgMultiplier);
if (RuleB(Character, HeroicStatsUseDataBucketsToScale)) {
n->heroic_max_mana += IsINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntMaxMana) * 10 : 0;
n->heroic_mana_regen += IsINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntManaRegen) / 25 : 0;
n->heroic_max_mana += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntMaxMana) * 10 : 0;
n->heroic_mana_regen += IsHeroicINTCasterClass(GetClass()) ? GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntManaRegen) / 25 : 0;
n->SpellDmg += GetHeroicINT() * CheckHeroicBonusesDataBuckets(HeroicBonusBucket::IntSpellDmg);
}
}
+4 -27
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];
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);
}
@@ -3605,19 +3605,6 @@ void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) {
}
}
void Bot::SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color) {
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto wc = (WearChange_Struct*)outapp->pBuffer;
wc->spawn_id = GetID();
wc->material = material;
wc->color.Color = color;
wc->wear_slot_id = material_slot;
entity_list.QueueClients(this, outapp);
safe_delete(outapp);
}
// Returns the item id that is in the bot inventory collection for the specified slot.
EQ::ItemInstance* Bot::GetBotItem(uint16 slot_id) {
EQ::ItemInstance* item = m_inv.GetItem(slot_id);
@@ -4903,7 +4890,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max
if (botweapon->ItemType == EQ::item::ItemTypeShield)
hate += botweapon->AC;
hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100);
hate = (hate * (100 + GetSpellFuriousBash(botweapon->Focus.Effect)) / 100);
}
}
@@ -5549,7 +5536,7 @@ int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) {
increase += 20;
}
if (IsMezSpell(spell_id))
if (IsMesmerizeSpell(spell_id))
tic_inc += GetAA(aaMesmerizationMastery);
return (((duration * increase) / 100) + tic_inc);
@@ -5867,16 +5854,6 @@ void Bot::GenerateSpecialAttacks() {
SetSpecialAbility(SPECATK_TRIPLE, 1);
}
bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
if (GetClass() == BARD) {
if (!ApplyBardPulse(bardsong, this, bardsong_slot))
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
stopLogic = true;
}
return true;
}
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
if (
@@ -6349,7 +6326,7 @@ void Bot::CalcRestState() {
for (unsigned int j = 0; j < buff_count; j++) {
if (IsValidSpell(buffs[j].spellid)) {
if (IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
if (!DetrimentalSpellAllowsRest(buffs[j].spellid))
if (!IsRestAllowedSpell(buffs[j].spellid))
return;
}
}
-2
View File
@@ -196,10 +196,8 @@ public:
void SetAttackTimer() override;
uint64 GetClassHPFactor();
int64 CalcMaxHP() override;
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
void Camp(bool save_to_database = true);
void SetTarget(Mob* mob) override;
void Zone();
+10 -10
View File
@@ -110,7 +110,7 @@ bool Bot::BotCastSong(Mob* tar, uint8 botLevel) {
continue;
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue;
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType()))
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue;
switch (spells[iter.SpellId].target_type) {
case ST_AEBard:
@@ -144,7 +144,7 @@ bool Bot::BotCastCombatSong(Mob* tar, uint8 botLevel) {
continue;
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue;
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType()))
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue;
switch (spells[iter.SpellId].target_type) {
case ST_AEBard:
@@ -176,7 +176,7 @@ bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpel
continue;
if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue;
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType()))
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue;
if (spells[iter.SpellId].target_type != ST_Target)
continue;
@@ -316,7 +316,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
continue;
}
if (!IsSpellUsableThisZoneType(iter.SpellId, zone->GetZoneType())) {
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType())) {
continue;
}
@@ -582,7 +582,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
if (
((IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())) &&
(botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType()))
(botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
) {
continue;
}
@@ -892,7 +892,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
(IsEffectInSpell(s.SpellId, SE_Levitate) && !zone->CanLevitate()) ||
(IsEffectInSpell(s.SpellId, SE_MovementSpeed) && !zone->CanCastOutdoor())
) &&
(botClass != BARD || !IsSpellUsableThisZoneType(s.SpellId, zone->GetZoneType()))
(botClass != BARD || !IsSpellUsableInThisZoneType(s.SpellId, zone->GetZoneType()))
) {
continue;
}
@@ -1902,7 +1902,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEff
continue;
}
if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) {
if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetSpellTriggerSpellID(botSpellList[i].spellid, spellEffect)) {
BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i;
@@ -1940,7 +1940,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
if (
(
IsEffectInSpell(botSpellList[i].spellid, spellEffect) ||
GetTriggerSpellID(botSpellList[i].spellid, spellEffect)
GetSpellTriggerSpellID(botSpellList[i].spellid, spellEffect)
) &&
spells[botSpellList[i].spellid].target_type == targetType
) {
@@ -2313,7 +2313,7 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* botCaster) {
for (std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if (
IsMezSpell(botSpellListItr->SpellId) &&
IsMesmerizeSpell(botSpellListItr->SpellId) &&
CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) {
result.SpellId = botSpellListItr->SpellId;
@@ -2388,7 +2388,7 @@ BotSpell Bot::GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster) {
Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) {
Mob* result = 0;
if (botCaster && IsMezSpell(botSpell.SpellId)) {
if (botCaster && IsMesmerizeSpell(botSpell.SpellId)) {
std::list<NPC*> npc_list;
entity_list.GetNPCList(npc_list);
+80 -25
View File
@@ -656,10 +656,10 @@ bool Client::Save(uint8 iCommitNow) {
/* Save Character Currency */
database.SaveCharacterCurrency(CharacterID(), &m_pp);
/* Save Current Bind Points */
for (int i = 0; i < 5; i++)
if (m_pp.binds[i].zone_id)
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i);
// save character binds
// this may not need to be called in Save() but it's here for now
// to maintain the current behavior
database.SaveCharacterBinds(this);
/* Save Character Buffs */
database.SaveBuffs(this);
@@ -713,7 +713,7 @@ bool Client::Save(uint8 iCommitNow) {
p_timers.Store(&database);
database.SaveCharacterTribute(CharacterID(), &m_pp);
database.SaveCharacterTribute(this);
SaveTaskState(); /* Save Character Task */
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
if (m_pp.intoxication > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) {
GarbleMessage(message, (int)(m_pp.intoxication / 3));
if (GetIntoxication() > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) {
GarbleMessage(message, (int)(GetIntoxication() / 3));
language = 0; // No need for language when drunk
lang_skill = 100;
}
@@ -1062,7 +1062,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
if(!global_channel_timer.Check())
{
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
return;
}
@@ -2783,25 +2783,64 @@ void Client::GMKill() {
safe_delete(outapp);
}
bool Client::CheckAccess(int16 iDBLevel, int16 iDefaultLevel) {
if ((admin >= iDBLevel) || (iDBLevel == AccountStatus::Max && admin >= iDefaultLevel))
return true;
else
return false;
}
void Client::MemorizeSpell(uint32 slot, uint32 spell_id, uint32 scribing, uint32 reduction){
if (
!EQ::ValueWithin(
slot,
0,
(EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize - 1)
)
) {
return;
}
void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing, uint32 reduction){
if (slot < 0 || slot >= EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize)
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;
}
auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct));
MemorizeSpell_Struct* mss=(MemorizeSpell_Struct*)outapp->pBuffer;
mss->scribing=scribing;
mss->slot=slot;
mss->spell_id=spellid;
auto* mss = (MemorizeSpell_Struct*) outapp->pBuffer;
mss->scribing = scribing;
mss->slot = slot;
mss->spell_id = spell_id;
mss->reduction = reduction;
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);
safe_delete(outapp);
}
@@ -8347,6 +8386,11 @@ void Client::SetThirst(int32 in_thirst)
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)
{
EQApplicationPacket *outapp = nullptr;
@@ -8545,7 +8589,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
AddMoneyToPP(copper, silver, gold, platinum);
if (itemid > 0)
SummonItem(itemid, -1, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
SummonItem(itemid, -1, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
if (faction)
{
@@ -8581,7 +8625,7 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac
for (int i = 0; i < QUESTREWARD_COUNT; ++i)
if (reward.item_id[i] > 0)
SummonItem(reward.item_id[i], -1, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
SummonItem(reward.item_id[i], -1, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
// only process if both are valid
// if we don't have a target here, we want to just reward, but if there is a target, need to check charm
@@ -9432,6 +9476,7 @@ void Client::ShowDevToolsMenu()
menu_reload_five += Saylink::Silent("#reload merchants", "Merchants");
menu_reload_five += " | " + Saylink::Silent("#reload npc_emotes", "NPC Emotes");
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 quest", "Quests");
@@ -11240,7 +11285,7 @@ void Client::ReconnectUCS()
{
EQApplicationPacket *outapp = nullptr;
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;
// chat server packet
@@ -11439,6 +11484,16 @@ void Client::SendReloadCommandMessages() {
).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");
Message(
+14 -10
View File
@@ -67,6 +67,7 @@ namespace EQ
#include "task_client_state.h"
#include "cheat_manager.h"
#include "../common/events/player_events.h"
#include "../common/data_verification.h"
#ifdef _WINDOWS
// since windows defines these within windef.h (which windows.h include)
@@ -306,7 +307,6 @@ public:
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0);
void TradeRequestFailed(const EQApplicationPacket* app);
void BuyTraderItem(TraderBuy_Struct* tbs,Client* trader,const EQApplicationPacket* app);
void TraderUpdate(uint16 slot_id,uint32 trader_id);
void FinishTrade(Mob* with, bool finalizer = false, void* event_entry = nullptr, std::list<void*>* event_details = nullptr);
void SendZonePoints();
@@ -322,7 +322,6 @@ public:
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
bool ShouldISpawnFor(Client *c) { return !GMHideMe(c) && !IsHoveringForRespawn(); }
virtual bool Process();
void ProcessPackets();
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname = nullptr, bool is_silent = false);
@@ -379,12 +378,8 @@ public:
void SetPetCommandState(int button, int state);
bool CheckAccess(int16 iDBLevel, int16 iDefaultLevel);
void CheckQuests(const char* zonename, const char* message, uint32 npc_id, uint32 item_id, Mob* other);
bool AutoAttackEnabled() const { return auto_attack; }
bool AutoFireEnabled() const { return auto_fire; }
void MakeCorpse(uint32 exploss);
bool ChangeFirstName(const char* in_firstname,const char* gmname);
@@ -394,7 +389,6 @@ public:
virtual void SetMaxHP();
int32 LevelRegen();
void HPTick();
void SetGM(bool toggle);
void SetPVP(bool toggle, bool message = true);
@@ -938,7 +932,7 @@ public:
inline uint32 GetAAPercent() const { return m_epp.perAA; }
void SetAATitle(std::string title);
void SetTitleSuffix(std::string suffix);
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing, uint32 reduction = 0);
void MemorizeSpell(uint32 slot, uint32 spell_id, uint32 scribing, uint32 reduction = 0);
// Item methods
void UseAugmentContainer(int container_slot);
@@ -972,6 +966,8 @@ public:
void DropItem(int16 slot_id, bool recurse = true);
void DropItemQS(EQ::ItemInstance* inst, bool pickup);
bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction);
int GetItemLinkHash(const EQ::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field
void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false);
@@ -999,6 +995,7 @@ public:
void SetThirst(int32 in_thirst);
void SetConsumption(int32 in_hunger, int32 in_thirst);
bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; }
int32 GetIntoxication() const { return m_pp.intoxication; }
bool CheckTradeLoreConflict(Client* other);
bool CheckTradeNonDroppable();
@@ -1588,6 +1585,7 @@ public:
void SetEnvironmentDamageModifier(int32 val) { environment_damage_modifier = val; }
inline bool GetInvulnerableEnvironmentDamage() const { return invulnerable_environment_damage; }
void SetInvulnerableEnvironmentDamage(bool val) { invulnerable_environment_damage = val; }
void SetIntoxication(int32 in_intoxication);
void ShowNumHits(); // work around function for numhits not showing on buffs
@@ -1643,6 +1641,7 @@ public:
PlayerEvent::PlayerEvent GetPlayerEvent();
void RecordKilledNPCEvent(NPC *n);
uint32 GetEXPForLevel(uint16 check_level);
protected:
friend class Mob;
void CalcEdibleBonuses(StatBonuses* newbon);
@@ -1719,7 +1718,6 @@ private:
int64 CalcHPRegen(bool bCombat = false);
int64 CalcManaRegen(bool bCombat = false);
int64 CalcBaseManaRegen();
uint64 GetClassHPFactor();
void DoHPRegen();
void DoManaRegen();
void DoStaminaHungerUpdate();
@@ -1819,7 +1817,6 @@ private:
bool temp_pvp;
void NPCSpawn(const Seperator* sep);
uint32 GetEXPForLevel(uint16 level);
void SendLogoutPackets();
void SendZoneInPackets();
@@ -2040,6 +2037,13 @@ private:
bool CanTradeFVNoDropItem();
void SendMobPositions();
void PlayerTradeEventLog(Trade *t, Trade *t2);
// full and partial mail key cache
std::string m_mail_key_full;
std::string m_mail_key;
public:
const std::string &GetMailKeyFull() const;
const std::string &GetMailKey() const;
};
#endif
+7 -51
View File
@@ -288,7 +288,7 @@ int64 Client::CalcHPRegen(bool bCombat)
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
auto max_hp = GetMaxHP();
int fast_regen = 6 * (max_hp / zone->newzone_data.fast_regen_hp);
int64 fast_regen = 6 * (max_hp / (zone ? zone->newzone_data.fast_regen_hp : 180));
if (base < fast_regen) // weird, but what the client is doing
base = fast_regen;
}
@@ -506,50 +506,6 @@ int64 Client::CalcBaseHP()
return base_hp;
}
// This is for calculating Base HPs + STA bonus for SoD or later clients.
uint64 Client::GetClassHPFactor()
{
int factor;
// Note: Base HP factor under level 41 is equal to factor / 12, and from level 41 to 80 is factor / 6.
// Base HP over level 80 is factor / 10
// HP per STA point per level is factor / 30 for level 80+
// HP per STA under level 40 is the level 80 HP Per STA / 120, and for over 40 it is / 60.
switch (GetClass()) {
case DRUID:
case ENCHANTER:
case NECROMANCER:
case MAGICIAN:
case WIZARD:
factor = 240;
break;
case BEASTLORD:
case BERSERKER:
case MONK:
case ROGUE:
case SHAMAN:
factor = 255;
break;
case BARD:
case CLERIC:
factor = 264;
break;
case SHADOWKNIGHT:
case PALADIN:
factor = 288;
break;
case RANGER:
factor = 276;
break;
case WARRIOR:
factor = 300;
break;
default:
factor = 240;
break;
}
return factor;
}
// This should return the combined AC of all the items the player is wearing.
int32 Client::GetRawItemAC()
{
@@ -841,10 +797,10 @@ uint32 Client::CalcCurrentWeight()
int32 Client::CalcAlcoholPhysicalEffect()
{
if (m_pp.intoxication <= 55) {
if (GetIntoxication() <= 55) {
return 0;
}
return (m_pp.intoxication - 40) / 16;
return (GetIntoxication() - 40) / 16;
}
int32 Client::CalcSTR()
@@ -922,8 +878,8 @@ int32 Client::CalcINT()
int32 val = m_pp.INT + itembonuses.INT + spellbonuses.INT;
int32 mod = aabonuses.INT;
INT = val + mod;
if (m_pp.intoxication) {
int32 AlcINT = INT - (int32)((float)m_pp.intoxication / 200.0f * (float)INT) - 1;
if (GetIntoxication()) {
int32 AlcINT = INT - (int32)((float)GetIntoxication() / 200.0f * (float)INT) - 1;
if ((AlcINT < (int)(0.2 * INT))) {
INT = (int)(0.2f * (float)INT);
}
@@ -946,8 +902,8 @@ int32 Client::CalcWIS()
int32 val = m_pp.WIS + itembonuses.WIS + spellbonuses.WIS;
int32 mod = aabonuses.WIS;
WIS = val + mod;
if (m_pp.intoxication) {
int32 AlcWIS = WIS - (int32)((float)m_pp.intoxication / 200.0f * (float)WIS) - 1;
if (GetIntoxication()) {
int32 AlcWIS = WIS - (int32)((float)GetIntoxication() / 200.0f * (float)WIS) - 1;
if ((AlcWIS < (int)(0.2 * WIS))) {
WIS = (int)(0.2f * (float)WIS);
}
+55 -49
View File
@@ -656,7 +656,7 @@ void Client::CompleteConnect()
const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid];
int NimbusEffect = GetNimbusEffect(buffs[j1].spellid);
int NimbusEffect = GetSpellNimbusEffect(buffs[j1].spellid);
if (NimbusEffect) {
if (!IsNimbusEffectActive(NimbusEffect))
SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true);
@@ -721,17 +721,17 @@ void Client::CompleteConnect()
case SE_AddMeleeProc:
case SE_WeaponProc:
{
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
break;
}
case SE_DefensiveProc:
{
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
break;
}
case SE_RangedProc:
{
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
break;
}
}
@@ -1265,7 +1265,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */
database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */
database.LoadCharacterTribute(this); /* Load CharacterTribute */
// this pattern is strange
// this is remnants of the old way of doing things
auto mail_keys = database.GetMailKey(CharacterID());
m_mail_key_full = mail_keys.mail_key_full;
m_mail_key = mail_keys.mail_key;
/* Load AdventureStats */
AdventureStats_Struct as;
@@ -1309,7 +1315,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/* If we can maintain intoxication across zones, check for it */
if (!RuleB(Character, MaintainIntoxicationAcrossZones))
m_pp.intoxication = 0;
SetIntoxication(0);
strcpy(name, m_pp.name);
strcpy(lastname, m_pp.last_name);
@@ -1508,30 +1514,31 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
}
if (group) {
// If the group leader is not set, pull the group leader infomrmation from the database.
if (!group->GetLeader()) {
char ln[64];
char MainTankName[64];
char AssistName[64];
char PullerName[64];
char NPCMarkerName[64];
char mentoree_name[64];
int mentor_percent;
GroupLeadershipAA_Struct GLAA;
memset(ln, 0, 64);
database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA);
Client *c = entity_list.GetClientByName(ln);
if (c)
group->SetLeader(c);
group->SetMainTank(MainTankName);
group->SetMainAssist(AssistName);
group->SetPuller(PullerName);
group->SetNPCMarker(NPCMarkerName);
group->SetGroupAAs(&GLAA);
group->SetGroupMentor(mentor_percent, mentoree_name);
}
char ln[64];
char MainTankName[64];
char AssistName[64];
char PullerName[64];
char NPCMarkerName[64];
char mentoree_name[64];
int mentor_percent;
GroupLeadershipAA_Struct GLAA;
memset(ln, 0, 64);
database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, mentoree_name, &mentor_percent, &GLAA);
group->LearnMembers();
if (!group->GetLeader()) {
Client *c = entity_list.GetClientByName(ln);
if (c) {
group->SetLeader(c);
}
}
group->SetMainTank(MainTankName);
group->SetMainAssist(AssistName);
group->SetPuller(PullerName);
group->SetNPCMarker(NPCMarkerName);
group->SetGroupAAs(&GLAA);
group->SetGroupMentor(mentor_percent, mentoree_name);
JoinGroupXTargets(group);
group->UpdatePlayer(this);
LFG = false;
@@ -5568,10 +5575,8 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app)
if (IntoxicationIncrease < 0)
IntoxicationIncrease = 1;
m_pp.intoxication += IntoxicationIncrease;
SetIntoxication(GetIntoxication()+IntoxicationIncrease);
if (m_pp.intoxication > 200)
m_pp.intoxication = 200;
}
DeleteItemInInventory(alc->from_slot, 1);
@@ -6466,27 +6471,28 @@ void Client::Handle_OP_GMFind(const EQApplicationPacket *app)
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"});
return;
}
if (app->size != sizeof(GMSummon_Struct)) {
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMSummon_Struct));
if (app->size != sizeof(GMFind_Struct)) {
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMFind_Struct));
return;
}
//Break down incoming
GMSummon_Struct* request = (GMSummon_Struct*)app->pBuffer;
auto* request = (GMFind_Struct*) app->pBuffer;
//Create a new outgoing
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMSummon_Struct));
GMSummon_Struct* foundplayer = (GMSummon_Struct*)outapp->pBuffer;
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMFind_Struct));
auto* foundplayer = (GMFind_Struct*) outapp->pBuffer;
//Copy the constants
strcpy(foundplayer->charname, request->charname);
strcpy(foundplayer->gmname, request->gmname);
//Check if the NPC exits intrazone...
Mob* gt = entity_list.GetMob(request->charname);
if (gt != 0) {
auto* gt = entity_list.GetMob(request->charname);
if (gt) {
foundplayer->success = 1;
foundplayer->x = (int32)gt->GetX();
foundplayer->y = (int32)gt->GetY();
foundplayer->z = (int32)gt->GetZ();
foundplayer->zoneID = zone->GetZoneID();
foundplayer->x = gt->GetX();
foundplayer->y = gt->GetY();
foundplayer->z = gt->GetZ();
foundplayer->zoneID = zone->GetZoneID();
}
//Send the packet...
FastQueuePacket(&outapp);
@@ -9227,7 +9233,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
return;
}
if (i == 0) {
if (!IsCastWhileInvis(item->Click.Effect)) {
if (!IsCastWhileInvisibleSpell(item->Click.Effect)) {
CommonBreakInvisible(); // client can't do this for us :(
}
if (GetClass() == BARD){
@@ -9299,7 +9305,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
}
if (i == 0) {
if (!IsCastWhileInvis(augitem->Click.Effect)) {
if (!IsCastWhileInvisibleSpell(augitem->Click.Effect)) {
CommonBreakInvisible(); // client can't do this for us :(
}
if (GetClass() == BARD) {
@@ -11464,7 +11470,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY)) {
response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY);
if (!response.empty()) {
ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true);
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
}
}
break;
@@ -11473,7 +11479,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY)) {
response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY);
if (!response.empty()) {
ChannelMessageReceived(8, 0, 100, response.c_str(), nullptr, true);
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
}
}
break;
@@ -11679,7 +11685,7 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app)
EQApplicationPacket* outapp = nullptr;
std::string buffer;
std::string MailKey = database.GetMailKey(CharacterID(), true);
std::string MailKey = GetMailKey();
EQ::versions::UCSVersion ConnectionType = EQ::versions::ucsUnknown;
// chat server packet
+4 -4
View File
@@ -518,9 +518,9 @@ bool Client::Process() {
Save(0);
}
if (m_pp.intoxication > 0)
if (GetIntoxication() > 0)
{
--m_pp.intoxication;
SetIntoxication(GetIntoxication()-1);
CalcBonuses();
}
@@ -1035,7 +1035,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
BuffFadeNonPersistDeath();
}
int SpellEffectDescNum = GetSpellEffectDescNum(SpellID);
int SpellEffectDescNum = GetSpellEffectDescriptionNumber(SpellID);
// Rez spells with Rez effects have this DescNum (first is Titanium, second is 6.2 Client)
if(RuleB(Character, UseResurrectionSickness) && SpellEffectDescNum == 82 || SpellEffectDescNum == 39067) {
SetHP(GetMaxHP() / 5);
@@ -1968,7 +1968,7 @@ void Client::CalcRestState()
for (unsigned int j = 0; j < buff_count; j++) {
if(IsValidSpell(buffs[j].spellid)) {
if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
if(!DetrimentalSpellAllowsRest(buffs[j].spellid))
if(!IsRestAllowedSpell(buffs[j].spellid))
return;
}
}
-10
View File
@@ -71,13 +71,3 @@ float CombatRecord::GetHealedReceivedPerSecond() const
double time_in_combat = TimeInCombat();
return time_in_combat > 0 ? (m_heal_received / time_in_combat) : m_heal_received;
}
int64 CombatRecord::GetDamageReceived() const
{
return m_damage_received;
}
int64 CombatRecord::GetHealReceived() const
{
return m_heal_received;
}
-2
View File
@@ -12,8 +12,6 @@ public:
bool InCombat() const;
void ProcessHPEvent(int64 hp, int64 current_hp);
double TimeInCombat() const;
int64 GetDamageReceived() const;
int64 GetHealReceived() const;
float GetDamageReceivedPerSecond() const;
float GetHealedReceivedPerSecond() const;
private:
+5 -2
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("enablerecipe", "[Recipe ID] - Enables a Recipe", AccountStatus::QuestTroupe, command_enablerecipe) ||
command_add("endurance", "Restores your or your target's endurance.", AccountStatus::Guide, command_endurance) ||
command_add("entityvariable", "[clear|delete|set|view] - Modify entity variables for yourself or your target", AccountStatus::GMAdmin, command_entityvariable) ||
command_add("exptoggle", "[Toggle] - Toggle your or your target's experience gain.", AccountStatus::QuestTroupe, command_exptoggle) ||
command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) ||
command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) ||
@@ -140,6 +141,7 @@ int command_init(void)
command_add("findaliases", "[Search Criteria]- Searches for available command aliases, by alias or command", AccountStatus::Player, command_findaliases) ||
command_add("findcharacter", "[Search Criteria] - Search for a character", AccountStatus::Guide, command_findcharacter) ||
command_add("findclass", "[Search Criteria] - Search for a class", AccountStatus::Guide, command_findclass) ||
command_add("findcurrency", "[Search Criteria] - Search for an alternate currency", AccountStatus::Guide, command_findcurrency) ||
command_add("findfaction", "[Search Criteria] - Search for a faction", AccountStatus::Guide, command_findfaction) ||
command_add("findnpctype", "[Search Criteria] - Search database NPC types", AccountStatus::GMAdmin, command_findnpctype) ||
command_add("findrace", "[Search Criteria] - Search for a race", AccountStatus::Guide, command_findrace) ||
@@ -230,7 +232,7 @@ int command_init(void)
command_add("nukeitem", "[Item ID] - Removes the specified Item ID from you or your player target's inventory", AccountStatus::GMLeadAdmin, command_nukeitem) ||
command_add("object", "List|Add|Edit|Move|Rotate|Copy|Save|Undo|Delete - Manipulate static and tradeskill objects within the zone", AccountStatus::GMAdmin, command_object) ||
command_add("oocmute", "[0|1] - Enable or Disable Server OOC", AccountStatus::GMMgmt, command_oocmute) ||
command_add("opcode", "Reloads all server patches", AccountStatus::GMImpossible, command_opcode) ||
command_add("opcode", "Reloads all opcodes from server patch files", AccountStatus::GMMgmt, command_reload) ||
command_add("path", "view and edit pathing", AccountStatus::GMMgmt, command_path) ||
command_add("peekinv", "[equip/gen/cursor/poss/limbo/curlim/trib/bank/shbank/allbank/trade/world/all] - Print out contents of your player target's inventory", AccountStatus::GMAdmin, command_peekinv) ||
command_add("peqzone", "[Zone ID|Zone Short Name] - Teleports you to the specified zone if you meet the requirements.", AccountStatus::Player, command_peqzone) ||
@@ -976,12 +978,14 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/emptyinventory.cpp"
#include "gm_commands/enablerecipe.cpp"
#include "gm_commands/endurance.cpp"
#include "gm_commands/entityvariable.cpp"
#include "gm_commands/exptoggle.cpp"
#include "gm_commands/faction.cpp"
#include "gm_commands/feature.cpp"
#include "gm_commands/findaa.cpp"
#include "gm_commands/findcharacter.cpp"
#include "gm_commands/findclass.cpp"
#include "gm_commands/findcurrency.cpp"
#include "gm_commands/findfaction.cpp"
#include "gm_commands/findnpctype.cpp"
#include "gm_commands/findrace.cpp"
@@ -1069,7 +1073,6 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/nukeitem.cpp"
#include "gm_commands/object.cpp"
#include "gm_commands/oocmute.cpp"
#include "gm_commands/opcode.cpp"
#include "gm_commands/path.cpp"
#include "gm_commands/peekinv.cpp"
#include "gm_commands/peqzone.cpp"
+2 -1
View File
@@ -82,6 +82,7 @@ void command_emoteview(Client *c, const Seperator *sep);
void command_emptyinventory(Client *c, const Seperator *sep);
void command_enablerecipe(Client *c, const Seperator *sep);
void command_endurance(Client *c, const Seperator *sep);
void command_entityvariable(Client *c, const Seperator *sep);
void command_exptoggle(Client *c, const Seperator *sep);
void command_faction(Client *c, const Seperator *sep);
void command_faction_association(Client *c, const Seperator *sep);
@@ -90,6 +91,7 @@ void command_findaa(Client *c, const Seperator *sep);
void command_findaliases(Client *c, const Seperator *sep);
void command_findcharacter(Client *c, const Seperator *sep);
void command_findclass(Client *c, const Seperator *sep);
void command_findcurrency(Client *c, const Seperator *sep);
void command_findfaction(Client *c, const Seperator *sep);
void command_findnpctype(Client *c, const Seperator *sep);
void command_findrace(Client *c, const Seperator *sep);
@@ -180,7 +182,6 @@ void command_nukebuffs(Client *c, const Seperator *sep);
void command_nukeitem(Client *c, const Seperator *sep);
void command_object(Client *c, const Seperator *sep);
void command_oocmute(Client *c, const Seperator *sep);
void command_opcode(Client *c, const Seperator *sep);
#ifdef PACKET_PROFILER
void command_packetprofile(Client *c, const Seperator *sep);
-6
View File
@@ -14,13 +14,10 @@
#define _CLIENTCORPSE(x) (x && x->IsCorpse() && x->CastToCorpse()->IsPlayerCorpse() && !x->CastToCorpse()->IsBecomeNPCCorpse())
#define _NPCCORPSE(x) (x && x->IsCorpse() && (x->CastToCorpse()->IsNPCCorpse() || x->CastToCorpse()->IsBecomeNPCCorpse()))
#define _CLIENTPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient())
#define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC())
#define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC())
//LOS Parameters:
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
#define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS
#define CHECK_LOS_STEP 1.0f
#define ARCHETYPE_HYBRID 1
#define ARCHETYPE_CASTER 2
@@ -44,7 +41,6 @@
//Spell specialization parameters, not sure of a better place for them
#define SPECIALIZE_FIZZLE 11 //% fizzle chance reduce at 200 specialized
#define SPECIALIZE_MANA_REDUCE 12 //% mana cost reduction at 200 specialized
//these are large right now because the x,y,z coords of the zone
//lines do not make a lot of sense
@@ -232,7 +228,6 @@ enum GravityBehavior {
LevitateWhileRunning
};
struct TradeEntity;
class Trade;
enum TradeState {
TradeNone,
@@ -846,7 +841,6 @@ public:
virtual ~Trade();
void Reset();
void SetTradeCash(uint32 in_pp, uint32 in_gp, uint32 in_sp, uint32 in_cp);
// Initiate a trade with another mob
// Also puts other mob into trader mode with this mob
+3 -3
View File
@@ -623,13 +623,13 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
if (!alt_mode) { // original function
if (!m_is_open) {
if (!m_disable_timer) {
LogDoorsDetail("door_id [{}] starting timer", md->doorid);
LogDoorsDetail("door_id [{}] starting timer", m_door_id);
m_close_timer.Start();
}
m_is_open = true;
}
else {
LogDoorsDetail("door_id [{}] disable timer", md->doorid);
LogDoorsDetail("door_id [{}] disable timer", m_door_id);
m_close_timer.Disable();
if (!m_disable_timer) {
m_is_open = false;
@@ -638,7 +638,7 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
}
else { // alternative function
if (!m_disable_timer) {
LogDoorsDetail("door_id [{}] alt starting timer", md->doorid);
LogDoorsDetail("door_id [{}] alt starting timer", m_door_id);
m_close_timer.Start();
}
m_is_open = true;
+3 -3
View File
@@ -810,9 +810,9 @@ void Client::SendDisciplineUpdate() {
bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
// Dont let client waste a reuse timer if they can't use the disc
if ((IsStunned() && !IgnoreCastingRestriction(spell_id))||
if ((IsStunned() && !IsCastNotStandingSpell(spell_id))||
IsFeared() ||
(IsMezzed() && !IgnoreCastingRestriction(spell_id)) ||
(IsMezzed() && !IsCastNotStandingSpell(spell_id)) ||
IsAmnesiad() ||
IsPet())
{
@@ -837,7 +837,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
return false;
}
if (DivineAura() && !IgnoreCastingRestriction(spell_id)) {
if (DivineAura() && !IsCastNotStandingSpell(spell_id)) {
return false;
}
+17
View File
@@ -179,6 +179,10 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_ITEM_CLICK_CAST_CLIENT",
"EVENT_DESTROY_ITEM_CLIENT",
"EVENT_DROP_ITEM_CLIENT",
"EVENT_MEMORIZE_SPELL",
"EVENT_UNMEMORIZE_SPELL",
"EVENT_SCRIBE_SPELL",
"EVENT_UNSCRIBE_SPELL",
// Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT",
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT"
@@ -2160,6 +2164,19 @@ void PerlembParser::ExportEventVariables(
break;
}
case EVENT_MEMORIZE_SPELL:
case EVENT_UNMEMORIZE_SPELL:
case EVENT_SCRIBE_SPELL:
case EVENT_UNSCRIBE_SPELL: {
Seperator sep(data);
ExportVar(package_name.c_str(), "slot_id", sep.arg[0]);
ExportVar(package_name.c_str(), "spell_id", sep.arg[1]);
if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[1]))) {
ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[1])]);
}
break;
}
default: {
break;
}
+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,
bool ignore_sender, uint8 minstatus, uint8 maxstatus)
{
@@ -2180,21 +2165,6 @@ Group *EntityList::GetGroupByClient(Client *client)
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)
{
std::list<Raid *>::iterator iterator;
@@ -2274,26 +2244,6 @@ Raid* EntityList::GetRaidByBot(const Bot* bot)
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)
{
auto it = client_list.begin();
@@ -2833,31 +2783,6 @@ bool EntityList::RemoveMob(uint16 delete_id)
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
* @return
@@ -3109,18 +3034,6 @@ bool EntityList::RemoveGroup(uint32 delete_id)
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()
{
RemoveAllClients();
@@ -3205,21 +3118,6 @@ void EntityList::Process()
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)
{
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
@@ -3554,15 +3452,6 @@ void EntityList::ClearClientPetitionQueue()
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)
{
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
void EntityList::ClearAggro(Mob* targ)
{
@@ -4388,35 +4259,6 @@ bool EntityList::LimitCheckGroup(uint32 spawngroup_id, int count)
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)
{
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)
{
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(
Mob *sender, float dist, const char *mobname, const char *message,
Journal::Options &opts
@@ -5201,17 +4998,6 @@ uint32 EntityList::CheckNPCsClose(Mob *center)
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)
{
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)
{
m_list.clear();
-19
View File
@@ -50,7 +50,6 @@ class Raid;
class Spawn2;
class Trap;
struct DynamicZoneSafeReturn;
struct GuildBankItemUpdate_Struct;
struct NewSpawn_Struct;
struct QGlobal;
@@ -115,7 +114,6 @@ public:
inline const time_t& GetSpawnTimeStamp() const { return spawn_timestamp; }
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();
const Bot* CastToBot() const;
@@ -129,7 +127,6 @@ protected:
initial_id = set_id;
}
}
uint32 pDBAsyncWorkID;
private:
uint16 id;
uint16 initial_id;
@@ -186,7 +183,6 @@ public:
Client *GetClientByCharID(uint32 iCharID);
Client *GetClientByWID(uint32 iWID);
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);
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);
Group* GetGroupByMob(Mob* mob);
Group* GetGroupByMobName(const char* name);
Group* GetGroupByBot(Bot* bot);
bool IsInSameGroupOrRaidGroup(Client *client1, Client *client2);
Group *GetGroupByClient(Client* client);
Group *GetGroupByID(uint32 id);
Group *GetGroupByLeaderName(const char* leader);
Raid *GetRaidByMob(Mob* mob);
Raid *GetRaidByClient(Client* client);
Raid *GetRaidByID(uint32 id);
Raid *GetRaidByLeaderName(const char *leader);
Raid* GetRaidByBotName(const char* name);
Raid* GetRaidByBot(const Bot* bot);
@@ -268,7 +261,6 @@ public:
void ClearAreas();
void ReloadMerchants();
void ProcessProximitySay(const char *message, Client *c, uint8 language = 0);
void SendAATimer(uint32 charid,UseAA_Struct* uaa);
Doors *FindDoor(uint8 door_id);
Object *FindObject(uint32 object_id);
Object* FindNearbyObject(float x, float y, float z, float radius);
@@ -291,13 +283,11 @@ public:
void AddProximity(NPC *proximity_for);
void Clear();
bool RemoveMob(uint16 delete_id);
bool RemoveMob(Mob* delete_mob);
bool RemoveClient(uint16 delete_id);
bool RemoveClient(Client* delete_client);
bool RemoveNPC(uint16 delete_id);
bool RemoveMerc(uint16 delete_id);
bool RemoveGroup(uint32 delete_id);
bool RemoveRaid(uint32 delete_id);
bool RemoveCorpse(uint16 delete_id);
bool RemoveDoor(uint16 delete_id);
bool RemoveTrap(uint16 delete_id);
@@ -321,7 +311,6 @@ public:
void RemoveAllRaids();
void RemoveAllEncounters();
void DestroyTempPets(Mob *owner);
int16 CountTempPets(Mob *owner);
void AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy = false);
void AddTempPetsToHateListOnOwnerDamage(Mob *owner, Mob* attacker, int32 spell_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 QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true);
void AEAttack(
Mob *attacker,
@@ -455,13 +443,11 @@ public:
Trap* FindNearbyTrap(Mob* searcher, float max_dist, float &curdist, bool detected = false);
void AddHealAggro(Mob* target, Mob* caster, uint16 hate);
Mob* FindDefenseNPC(uint32 npcid);
void OpenDoorsNear(Mob* opener);
void UpdateWho(bool iSendFullUpdate = false);
char* MakeNameUnique(char* name);
static char* RemoveNumbers(char* name);
void SignalMobsByNPCID(uint32 npc_type, int signal_id);
void CountNPC(uint32* NPCCount, uint32* NPCLootCount, uint32* gmspawntype_count);
void RemoveEntity(uint16 id);
void SendPetitionToAdmins(Petition* pet);
void SendPetitionToAdmins();
@@ -472,10 +458,8 @@ public:
uint32 DeleteNPCCorpses();
uint32 DeletePlayerCorpses();
void CorpseFix(Client* c);
void WriteEntityIDs();
void HalveAggro(Mob* who);
void DoubleAggro(Mob* who);
void Evade(Mob *who);
void UpdateHoTT(Mob* target);
void Process();
@@ -496,7 +480,6 @@ public:
void LimitRemoveNPC(NPC *npc);
bool LimitCheckType(uint32 npc_type, 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);
int GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con);
@@ -521,7 +504,6 @@ public:
void ZoneWho(Client *c, Who_All_Struct* Who);
void UnMarkNPC(uint16 ID);
void GateAllClients();
void SignalAllClients(int signal_id);
void UpdateQGlobal(uint32 qid, QGlobal newGlobal);
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
@@ -531,7 +513,6 @@ public:
void GateAllClientsToSafeReturn();
uint16 GetClientCount();
void GetMobList(std::list<Mob*> &m_list);
void GetNPCList(std::list<NPC*> &n_list);
void GetMercList(std::list<Merc*> &n_list);
+4
View File
@@ -124,6 +124,10 @@ typedef enum {
EVENT_ITEM_CLICK_CAST_CLIENT,
EVENT_DESTROY_ITEM_CLIENT,
EVENT_DROP_ITEM_CLIENT,
EVENT_MEMORIZE_SPELL,
EVENT_UNMEMORIZE_SPELL,
EVENT_SCRIBE_SPELL,
EVENT_UNSCRIBE_SPELL,
// Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT,
EVENT_SPELL_EFFECT_BUFF_TIC_BOT,
+3 -3
View File
@@ -783,8 +783,6 @@ void Client::SetEXP(uint64 set_exp, uint64 set_aaxp, bool isrezzexp) {
if (check_level == RuleI(Character, DeathExpLossLevel))
MessageString(Chat::Yellow, CORPSE_EXP_LOST);
}
else
MessageString(Chat::Experience, LOSE_LEVEL, ConvertArray(check_level, val1));
uint8 myoldlevel = GetLevel();
@@ -1256,8 +1254,10 @@ uint8 Client::GetCharMaxLevelFromQGlobal() {
std::list<QGlobal> global_map;
const uint32 zone_id = zone ? zone->GetZoneID() : 0;
if (char_cache) {
QGlobalCache::Combine(global_map, char_cache->GetBucket(), 0, CharacterID(), zone->GetZoneID());
QGlobalCache::Combine(global_map, char_cache->GetBucket(), 0, CharacterID(), zone_id);
}
for (const auto& global : global_map) {
+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 {}.",
effect_id,
slot_id,
c->GetTargetDescription(t, TargetDescriptionType::LCSelf)
c->GetTargetDescription(t)
).c_str()
);
} else if (is_remove) {
@@ -90,7 +90,7 @@ void command_appearanceeffects(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"Appearance Effects have been removed for {}.",
c->GetTargetDescription(t, TargetDescriptionType::LCSelf)
c->GetTargetDescription(t)
).c_str()
);
} else if (is_view) {
+1 -1
View File
@@ -21,7 +21,7 @@ void command_castspell(Client *c, const Seperator *sep)
else {
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.");
}
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,
fmt::format(
"Experience gain for {} is now {}abled.",
c->GetTargetDescription(t, TargetDescriptionType::LCSelf),
c->GetTargetDescription(t),
is_exp_enabled ? "en" : "dis"
).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()
);
}
+8 -14
View File
@@ -420,24 +420,18 @@ void command_npcedit(Client *c, const Seperator *sep)
} else if (!strcasecmp(sep->arg[1], "special_attacks")) {
std::string special_attacks = sep->argplus[2];
n.npcspecialattks = special_attacks;
c->Message(
Chat::Yellow,
fmt::format(
"{} is now using the following Special Attacks '{}'.",
npc_id_string,
special_attacks
).c_str()
d = fmt::format(
"{} is now using the following Special Attacks '{}'.",
npc_id_string,
special_attacks
);
} else if (!strcasecmp(sep->arg[1], "special_abilities")) {
std::string special_abilities = sep->argplus[2];
n.special_abilities = special_abilities;
c->Message(
Chat::Yellow,
fmt::format(
"{} is now using the following Special Abilities '{}'.",
npc_id_string,
special_abilities
).c_str()
d = fmt::format(
"{} is now using the following Special Abilities '{}'.",
npc_id_string,
special_abilities
);
} else if (!strcasecmp(sep->arg[1], "aggroradius")) {
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;
for (auto quest_error : quest_errors) {
if (error_index >= 30) {
c->Message(Chat::White, "Maximum of 30 errors shown.");
if (error_index >= RuleI(World, MaximumQuestErrors)) {
c->Message(
Chat::White,
fmt::format(
"Maximum of {} error{} shown.",
RuleI(World, MaximumQuestErrors),
RuleI(World, MaximumQuestErrors) != 1 ? "s" : ""
).c_str()
);
break;
}
+57 -81
View File
@@ -1,16 +1,18 @@
#include "../client.h"
#include "../../common/patches/patches.h"
void command_reload(Client *c, const Seperator *sep)
{
std::string command = sep->arg[0] ? sep->arg[0] : "";
int arguments = sep->argnum;
const auto arguments = sep->argnum;
if (!arguments && Strings::Contains(command, "#reload")) {
c->SendReloadCommandMessages();
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_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_alternate_currencies = !strcasecmp(sep->arg[1], "alternate_currencies");
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_npc_emotes = !strcasecmp(sep->arg[1], "npc_emotes");
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_quest = !strcasecmp(sep->arg[1], "quest") || (is_rq_alias);
bool is_rules = !strcasecmp(sep->arg[1], "rules");
@@ -51,6 +54,7 @@ void command_reload(Client *c, const Seperator *sep)
!is_merchants &&
!is_npc_emotes &&
!is_objects &&
!is_opcodes &&
!is_perl_export &&
!is_quest &&
!is_rules &&
@@ -63,7 +67,7 @@ void command_reload(Client *c, const Seperator *sep)
!is_world &&
!is_zone &&
!is_zone_points
) {
) {
c->SendReloadCommandMessages();
return;
}
@@ -73,36 +77,28 @@ void command_reload(Client *c, const Seperator *sep)
if (is_aa) {
c->Message(Chat::White, "Attempting to reload Alternate Advancement Data globally.");
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.");
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.");
pack = new ServerPacket(ServerOP_ReloadBlockedSpells, 0);
}
else if (is_commands) {
} else if (is_commands) {
c->Message(Chat::White, "Attempting to reload Commands globally.");
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.");
pack = new ServerPacket(ServerOP_ReloadContentFlags, 0);
}
else if (is_doors) {
} else if (is_doors) {
c->Message(Chat::White, "Attempting to reload Doors globally.");
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.");
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.");
pack = new ServerPacket(ServerOP_ReloadGroundSpawns, 0);
}
else if (is_level_mods) {
} else if (is_level_mods) {
if (!RuleB(Zone, LevelBasedEXPMods)) {
c->Message(Chat::White, "Level Based Experience Modifiers are disabled.");
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.");
pack = new ServerPacket(ServerOP_ReloadLevelEXPMods, 0);
}
else if (is_logs) {
} else if (is_logs) {
c->Message(Chat::White, "Attempting to reload Log Settings globally.");
pack = new ServerPacket(ServerOP_ReloadLogs, 0);
}
else if (is_merchants) {
} else if (is_merchants) {
c->Message(Chat::White, "Attempting to reload Merchants globally.");
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.");
pack = new ServerPacket(ServerOP_ReloadNPCEmotes, 0);
}
else if (is_objects) {
} else if (is_objects) {
c->Message(Chat::White, "Attempting to reload Objects globally.");
pack = new ServerPacket(ServerOP_ReloadObjects, 0);
}
else if (is_perl_export) {
} else if (is_opcodes) {
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.");
pack = new ServerPacket(ServerOP_ReloadPerlExportSettings, 0);
}
else if (is_quest) {
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" : "";
} else if (is_quest) {
const auto stop_timers = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
c->Message(
Chat::Yellow,
fmt::format(
"Quests reloaded{} for {}.",
stop_timers_message,
stop_timers ? " and timers stopped" : "",
zone->GetZoneDescription()
).c_str()
);
entity_list.ClearAreas();
parse->ReloadQuests(stop_timers);
}
else if (is_rules) {
} else if (is_rules) {
c->Message(Chat::White, "Attempting to reload Rules globally.");
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.");
pack = new ServerPacket(ServerOP_ReloadStaticZoneData, 0);
}
else if (is_tasks) {
} else if (is_tasks) {
uint32 task_id = 0;
if (!sep->IsNumber(2)) {
c->Message(Chat::White, "Attempting to reload Tasks globally.");
pack = new ServerPacket(ServerOP_ReloadTasks, sizeof(ReloadTasks_Struct));
}
else {
} else {
task_id = Strings::ToUnsignedInt(sep->arg[2]);
}
auto rts = (ReloadTasks_Struct *) pack->pBuffer;
rts->reload_type = RELOADTASKS;
rts->task_id = task_id;
}
else if (is_titles) {
} else if (is_titles) {
c->Message(Chat::White, "Attempting to reload Titles globally.");
pack = new ServerPacket(ServerOP_ReloadTitles, 0);
}
else if (is_traps) {
} else if (is_traps) {
if (arguments < 2 || !sep->IsNumber(2)) {
entity_list.UpdateAllTraps(true, true);
c->Message(
@@ -191,7 +172,7 @@ void command_reload(Client *c, const Seperator *sep)
return;
}
bool global = Strings::ToInt(sep->arg[2]) ? true : false;
const auto global = Strings::ToBool(sep->arg[2]);
if (!global) {
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.");
pack = new ServerPacket(ServerOP_ReloadTraps, 0);
}
else if (is_variables) {
} else if (is_variables) {
c->Message(Chat::White, "Attempting to reload Variables globally.");
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.");
pack = new ServerPacket(ServerOP_ReloadVeteranRewards, 0);
}
else if (is_world) {
} else if (is_world) {
uint8 global_repop = ReloadWorld::NoRepop;
if (sep->IsNumber(2)) {
@@ -233,12 +211,12 @@ void command_reload(Client *c, const Seperator *sep)
"Attempting to reload Quests {}worldwide.",
(
global_repop ?
(
global_repop == ReloadWorld::Repop ?
"and repop NPCs " :
"and forcefully repop NPCs "
) :
""
(
global_repop == ReloadWorld::Repop ?
"and repop NPCs " :
"and forcefully repop NPCs "
) :
""
)
).c_str()
);
@@ -246,8 +224,7 @@ void command_reload(Client *c, const Seperator *sep)
pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
auto RW = (ReloadWorld_Struct *) pack->pBuffer;
RW->global_repop = global_repop;
}
else if (is_zone) {
} else if (is_zone) {
zone_store.LoadZones(content_db);
if (arguments < 2) {
@@ -257,8 +234,8 @@ void command_reload(Client *c, const Seperator *sep)
"Zone Header Load {} | Zone: {}",
(
zone->LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion()) ?
"Succeeded" :
"Failed"
"Succeeded" :
"Failed"
),
zone->GetZoneDescription()
).c_str()
@@ -268,8 +245,8 @@ void command_reload(Client *c, const Seperator *sep)
auto zone_id = (
sep->IsNumber(2) ?
Strings::ToUnsignedInt(sep->arg[2]) :
ZoneID(sep->arg[2])
Strings::ToUnsignedInt(sep->arg[2]) :
ZoneID(sep->arg[2])
);
if (!zone_id) {
c->Message(
@@ -286,8 +263,8 @@ void command_reload(Client *c, const Seperator *sep)
auto zone_long_name = ZoneLongName(zone_id);
auto version = (
sep->IsNumber(3) ?
Strings::ToUnsignedInt(sep->arg[3]) :
0
Strings::ToUnsignedInt(sep->arg[3]) :
0
);
auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
@@ -301,23 +278,22 @@ void command_reload(Client *c, const Seperator *sep)
"Zone Header Load {} | Zone: {} ({}){}",
(
zone->LoadZoneCFG(zone_short_name, version) ?
"Succeeded" :
"Failed"
"Succeeded" :
"Failed"
),
zone_long_name,
zone_short_name,
(
version ?
fmt::format(
" Version: {}",
version
) :
""
fmt::format(
" Version: {}",
version
) :
""
)
).c_str()
);
}
else if (is_zone_points) {
} else if (is_zone_points) {
c->Message(Chat::White, "Attempting to reloading Zone Points globally.");
pack = new ServerPacket(ServerOP_ReloadZonePoints, 0);
}
+41 -19
View File
@@ -2,9 +2,24 @@
void command_setanim(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
const auto arguments = sep->argnum;
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;
}
@@ -13,29 +28,36 @@ void command_setanim(Client *c, const Seperator *sep)
target = c->GetTarget();
}
int animation_id = Strings::ToInt(sep->arg[1]);
const auto animation_id = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1]));
if (
animation_id < 0 ||
animation_id > eaLooting
!EQ::ValueWithin(
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;
}
target->SetAppearance(static_cast<EmuAppearance>(animation_id), false);
std::string animation_name;
if (animation_id == eaStanding) {
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";
}
const auto animation_name = EQ::constants::GetSpawnAnimationName(animation_id);
c->Message(
Chat::White,
+35 -44
View File
@@ -2,54 +2,45 @@
void command_setskill(Client *c, const Seperator *sep)
{
Client *target = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient();
}
const auto arguments = sep->argnum;
auto skill_id = sep->IsNumber(1) ? Strings::ToInt(sep->arg[1]) : -1;
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
) {
if (arguments < 2 || !sep->IsNumber(1) || !sep->IsNumber(2)) {
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());
c->Message(Chat::White, fmt::format("Skill Value = 0 to {}", HIGHEST_CAN_SET_SKILL).c_str());
return;
}
else {
LogInfo(
"Set skill request from [{}], Target: [{}] Skill ID: [{}] Skill Value: [{}]",
c->GetCleanName(),
c->GetTargetDescription(target),
skill_id,
skill_value
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
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 (c != t) {
c->Message(
Chat::White,
fmt::format(
"Set {} ({}) to {} for {}.",
EQ::skills::GetSkillName(skill_type),
skill_id,
skill_value > t->MaxSkill(skill_type) ? t->MaxSkill(skill_type) : skill_value,
c->GetTargetDescription(t)
).c_str()
);
if (
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(
Chat::White,
fmt::format(
"Set {} ({}) to {} for {}.",
EQ::skills::GetSkillName((EQ::skills::SkillType) skill_id),
skill_id,
skill_value,
c->GetTargetDescription(target)
).c_str()
);
}
}
}
}
+27 -30
View File
@@ -2,45 +2,42 @@
void command_setskillall(Client *c, const Seperator *sep)
{
auto target = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient();
const auto arguments = sep->argnum;
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)) {
c->Message(Chat::White, "Usage: #setskillall [Skill Level] - Set all of your or your target's skills to the specified skill level");
c->Message(
Chat::White,
fmt::format(
"Note: Skill Level ranges from 0 to {}",
HIGHEST_CAN_SET_SKILL
).c_str()
);
} else {
if (c->Admin() >= commandSetSkillsOther || c->GetTarget() == c) {
LogInfo(
"Set ALL skill request from [{}], target:[{}]",
c->GetCleanName(),
c->GetTargetDescription(target)
);
auto t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
auto skill_level = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[1]));
if (c->Admin() < commandSetSkillsOther && t != c) {
c->Message(Chat::White, "Your status is not high enough to set another player's skills.");
return;
}
auto skill_level = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[1]));
for (const auto& s : EQ::skills::GetSkillTypeMap()) {
if (c != t) {
c->Message(
Chat::White,
fmt::format(
"Setting all skills to {} for {}.",
skill_level,
c->GetTargetDescription(target)
"Setting {} ({}) to {} for {}.",
s.second,
s.first,
skill_level > t->MaxSkill(s.first) ? t->MaxSkill(s.first) : skill_level,
c->GetTargetDescription(t)
).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
);
}
}
+28 -11
View File
@@ -2,19 +2,36 @@
void command_spawn(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] != 0) {
Client *client = entity_list.GetClientByName(sep->arg[1]);
if (client) {
c->Message(Chat::White, "You cannot spawn a mob with the same name as a character!");
return;
}
}
NPC *npc = NPC::SpawnNPC(sep->argplus[1], c->GetPosition(), c);
if (!npc) {
const auto arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #spawn [Name]");
c->Message(
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(
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!");
return;
}
const auto* n = NPC::SpawnNPC(sep->argplus[1], c->GetPosition(), c);
if (!n) {
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,
+10 -10
View File
@@ -3,18 +3,18 @@
void command_unscribespell(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
const auto arguments = sep->argnum;
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");
return;
}
auto target = c;
auto t = c;
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)) {
c->Message(
@@ -29,16 +29,16 @@ void command_unscribespell(Client *c, const Seperator *sep)
auto spell_name = GetSpellName(spell_id);
if (target->HasSpellScribed(spell_id)) {
target->UnscribeSpellBySpellID(spell_id);
if (t->HasSpellScribed(spell_id)) {
t->UnscribeSpellBySpellID(spell_id);
c->Message(
Chat::White,
fmt::format(
"Unscribing {} ({}) for {}.",
"Unscribing {} ({}) from {}.",
spell_name,
spell_id,
c->GetTargetDescription(target)
c->GetTargetDescription(t, TargetDescriptionType::LCSelf)
).c_str()
);
} else {
@@ -46,8 +46,8 @@ void command_unscribespell(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"{} {} not have {} ({}) scribed.",
c->GetTargetDescription(target),
c == target ? "do" : "does",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "do" : "does",
spell_name,
spell_id
).c_str()
+1 -1
View File
@@ -34,7 +34,7 @@ void command_xtargets(Client *c, const Seperator *sep)
fmt::format(
"Max number of XTargets set to {} for {}.",
new_max,
c->GetTargetDescription(t, TargetDescriptionType::LCSelf)
c->GetTargetDescription(t)
).c_str()
);
}
+8 -8
View File
@@ -2,16 +2,16 @@
void command_zheader(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
const auto arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #zheader [Zone ID|Zone Short Name] [Version]");
return;
}
auto zone_id = (
sep->IsNumber(2) ?
Strings::ToUnsignedInt(sep->arg[2]) :
ZoneID(sep->arg[2])
const auto zone_id = (
sep->IsNumber(1) ?
Strings::ToUnsignedInt(sep->arg[1]) :
ZoneID(sep->arg[1])
);
if (!zone_id) {
c->Message(
@@ -26,9 +26,9 @@ void command_zheader(Client *c, const Seperator *sep)
auto zone_short_name = ZoneName(zone_id);
auto zone_long_name = ZoneLongName(zone_id);
auto version = (
sep->IsNumber(3) ?
Strings::ToUnsignedInt(sep->arg[3]) :
const auto version = (
sep->IsNumber(2) ?
Strings::ToUnsignedInt(sep->arg[2]) :
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;
for (const auto& member : rows) {
if (memberIndex >= MAX_GROUP_MEMBERS) {
+37 -47
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()
{
auto iterator = list.begin();
@@ -155,28 +142,54 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater)
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;
float close_distance = 99999.9f;
float this_distance;
auto iterator = list.begin();
while (iterator != list.end()) {
if (skip_mezzed && (*iterator)->entity_on_hatelist->IsMezzed()) {
++iterator;
for (const auto& e : list) {
if (!e->entity_on_hatelist) {
continue;
}
this_distance = DistanceSquaredNoZ((*iterator)->entity_on_hatelist->GetPosition(), hater->GetPosition());
if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) {
close_distance = this_distance;
close_entity = (*iterator)->entity_on_hatelist;
if (skip_mezzed && e->entity_on_hatelist->IsMezzed()) {
continue;
}
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;
}
++iterator;
}
if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura()))
if (
(!close_entity && hater->IsNPC()) ||
(close_entity && close_entity->DivineAura())
) {
close_entity = hater->CastToNPC()->GetHateTop();
}
return close_entity;
}
@@ -591,29 +604,6 @@ Mob *HateList::GetRandomEntOnHateList(bool skip_mezzed)
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) {
// function is still in design stage
+1 -3
View File
@@ -41,12 +41,11 @@ public:
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 *GetEntWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false);
Mob *GetRandomEntOnHateList(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);
Bot* GetRandomBotOnHateList(bool skip_mezzed = false);
@@ -85,7 +84,6 @@ public:
bool add_to_hate_list_if_not_exist = true
);
void DoFactionHits(int64 npc_faction_level_id, int32 faction_id, int32 faction_value);
void IsEntityInFrenzyMode();
void PrintHateListToClient(Client *c);
void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage);
void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; }
+154 -166
View File
@@ -415,173 +415,10 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
}
// check for augment to item restriction
if(enforce_restrictions) {
bool is_restricted = false;
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 (enforce_restrictions) {
bool is_restricted = IsAugmentRestricted(item->ItemType, augtest->AugRestrict);
if(is_restricted) {
if (is_restricted) {
Message(
Chat::Red,
fmt::format(
@@ -4766,3 +4603,154 @@ int32 Bot::GetAugmentIDAt(int16 slot_id, uint8 augslot) {
// None found
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;
}
+13 -3
View File
@@ -361,11 +361,12 @@ void NPC::AddLootDrop(
SetArrowEquipped(true);
}
bool found = false; // track if we found an empty slot we fit into
if (loot_drop.equip_item > 0) {
uint8 eslot = 0xFF;
char newid[20];
const EQ::ItemData* compitem = nullptr;
bool found = false; // track if we found an empty slot we fit into
int32 foundslot = -1; // for multi-slot items
// Equip rules are as follows:
@@ -394,9 +395,15 @@ void NPC::AddLootDrop(
foundslot = i;
}
else {
// Unequip old item
auto* olditem = GetItem(i);
olditem->equip_slot = EQ::invslot::SLOT_INVALID;
equipment[i] = item2->ID;
foundslot = i;
found = true;
found = true;
}
} // end if ac
}
@@ -500,7 +507,6 @@ void NPC::AddLootDrop(
}
if (found) {
CalcBonuses(); // This is less than ideal for bulk adding of items
item->equip_slot = foundslot;
}
}
@@ -510,6 +516,10 @@ void NPC::AddLootDrop(
}
else safe_delete(item);
if (found) {
CalcBonuses();
}
if (IsRecordLootStats()) {
m_rolled_items.emplace_back(item->item_id);
}
+12
View File
@@ -2504,6 +2504,10 @@ int Lua_Client::GetSpellDamage() {
Lua_Safe_Call_Int();
return self->GetSpellDmg();
}
int Lua_Client::GetIntoxication() {
Lua_Safe_Call_Int();
return self->GetIntoxication();
}
void Lua_Client::TaskSelector(luabind::adl::object table) {
TaskSelector(table, false);
@@ -3050,6 +3054,12 @@ bool Lua_Client::ReloadDataBuckets() {
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() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@@ -3213,6 +3223,7 @@ luabind::scope lua_register_client() {
.def("GetDisciplineTimer", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetDisciplineTimer)
.def("GetDuelTarget", (int(Lua_Client::*)(void))&Lua_Client::GetDuelTarget)
.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,int16))&Lua_Client::GetEXPModifier)
.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("GetIPString", (std::string(Lua_Client::*)(void))&Lua_Client::GetIPString)
.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("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage)
.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);
int GetHunger();
int GetThirst();
int GetIntoxication();
void SetHunger(int in_hunger);
void SetThirst(int in_thirst);
void SetConsumption(int in_hunger, int in_thirst);
@@ -467,6 +468,7 @@ public:
void UseAugmentContainer(int container_slot);
bool IsAutoAttackEnabled();
bool IsAutoFireEnabled();
uint32 GetEXPForLevel(uint16 check_level);
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);
+1458 -1
View File
File diff suppressed because it is too large Load Diff
+62 -2
View File
@@ -2376,6 +2376,41 @@ Lua_Mob Lua_Mob::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_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
@@ -2875,6 +2910,16 @@ float Lua_Mob::GetDefaultRaceSize() {
return self->GetDefaultRaceSize();
}
float Lua_Mob::GetDefaultRaceSize(int race_id) {
Lua_Safe_Call_Real();
return self->GetDefaultRaceSize(race_id);
}
float Lua_Mob::GetDefaultRaceSize(int race_id, int gender_id) {
Lua_Safe_Call_Real();
return self->GetDefaultRaceSize(race_id, gender_id);
}
float Lua_Mob::GetActSpellRange(uint16 spell_id, float range) {
Lua_Safe_Call_Real();
return self->GetActSpellRange(spell_id, range);
@@ -3000,6 +3045,11 @@ luabind::object Lua_Mob::GetBuffSpellIDs(lua_State* L) {
return t;
}
bool Lua_Mob::HasSpellEffect(int effect_id) {
Lua_Safe_Call_Bool();
return self->HasSpellEffect(effect_id);
}
luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>())
@@ -3212,7 +3262,9 @@ luabind::scope lua_register_mob() {
.def("GetDEX", &Lua_Mob::GetDEX)
.def("GetDR", &Lua_Mob::GetDR)
.def("GetDamageAmount", (uint32(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetDamageAmount)
.def("GetDefaultRaceSize", &Lua_Mob::GetDefaultRaceSize)
.def("GetDefaultRaceSize", (float(Lua_Mob::*)(void))&Lua_Mob::GetDefaultRaceSize)
.def("GetDefaultRaceSize", (float(Lua_Mob::*)(int))&Lua_Mob::GetDefaultRaceSize)
.def("GetDefaultRaceSize", (float(Lua_Mob::*)(int,int))&Lua_Mob::GetDefaultRaceSize)
.def("GetDeity", &Lua_Mob::GetDeity)
.def("GetDisplayAC", &Lua_Mob::GetDisplayAC)
.def("GetDrakkinDetails", &Lua_Mob::GetDrakkinDetails)
@@ -3236,7 +3288,14 @@ luabind::scope lua_register_mob() {
.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,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("GetHateList", &Lua_Mob::GetHateList)
.def("GetHateListBots", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListBots)
@@ -3338,6 +3397,7 @@ luabind::scope lua_register_mob() {
.def("HasPet", (bool(Lua_Mob::*)(void))&Lua_Mob::HasPet)
.def("HasProcs", &Lua_Mob::HasProcs)
.def("HasShieldEquipped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasShieldEquipped)
.def("HasSpellEffect", &Lua_Mob::HasSpellEffect)
.def("HasTimer", &Lua_Mob::HasTimer)
.def("HasTwoHandBluntEquipped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHandBluntEquipped)
.def("HasTwoHanderEquipped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHanderEquipped)
+10
View File
@@ -227,6 +227,13 @@ public:
Lua_Client GetHateRandomClient();
Lua_NPC GetHateRandomNPC();
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, int64 hate);
void AddToHateList(Lua_Mob other, int64 hate, int64 damage);
@@ -516,6 +523,8 @@ public:
bool IsFindable();
bool IsTrackable();
float GetDefaultRaceSize();
float GetDefaultRaceSize(int race_id);
float GetDefaultRaceSize(int race_id, int gender_id);
int64 GetActDoTDamage(uint16 spell_id, int64 value, Lua_Mob target);
int64 GetActDoTDamage(uint16 spell_id, int64 value, Lua_Mob target, bool from_buff_tic);
int64 GetActReflectedSpellDamage(uint16 spell_id, int64 value, int effectiveness);
@@ -539,6 +548,7 @@ public:
void StopAllTimers();
void StopTimer(const char* timer_name);
luabind::object GetBuffSpellIDs(lua_State* L);
bool HasSpellEffect(int effect_id);
};
#endif
+9 -1
View File
@@ -164,7 +164,11 @@ const char *LuaEvents[_LargestEventID] = {
"event_item_click_client",
"event_item_click_cast_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;
@@ -292,6 +296,10 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_DESTROY_ITEM_CLIENT] = handle_player_destroy_item;
PlayerArgumentDispatch[EVENT_TARGET_CHANGE] = handle_player_target_change;
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_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
void handle_item_click(
QuestInterface *parse,
+9
View File
@@ -734,6 +734,15 @@ void handle_player_drop_item(
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
void handle_item_click(
QuestInterface *parse,
+3 -3
View File
@@ -770,7 +770,7 @@ void Merc::CalcRestState() {
for (unsigned int j = 0; j < buff_count; j++) {
if(IsValidSpell(buffs[j].spellid)) {
if(IsDetrimentalSpell(buffs[j].spellid) && (buffs[j].ticsremaining > 0))
if(!DetrimentalSpellAllowsRest(buffs[j].spellid))
if(!IsRestAllowedSpell(buffs[j].spellid))
return;
}
}
@@ -4299,10 +4299,10 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
if(merc_template)
{
//TODO: Maybe add a way of updating client merc stats in a seperate function? like, for example, on leveling up.
const NPCType* npc_type_to_copy = nullptr;
if (c) {
const NPCType* npc_type_to_copy = content_db.GetMercType(merc_template->MercNPCID, merc_template->RaceID, c->GetLevel());
npc_type_to_copy = content_db.GetMercType(merc_template->MercNPCID, merc_template->RaceID, c->GetLevel());
}
if(npc_type_to_copy != nullptr)
-1
View File
@@ -307,7 +307,6 @@ private:
int32 CalcCorrup();
int64 CalcMaxHP();
int64 CalcBaseHP();
int64 GetClassHPFactor();
int64 CalcHPRegen();
int64 CalcHPRegenCap();
int64 CalcMaxMana();
-7
View File
@@ -1,7 +0,0 @@
struct Msg {
int id;
char* Sender;
char* Subject;
char* Body;
char* Date;
};
+20 -13
View File
@@ -2483,8 +2483,12 @@ void Mob::SendIllusionPacket(
// update internal values for mob
size = (in_size <= 0.0f) ? GetRaceGenderDefaultHeight(race, gender) : in_size;
texture = new_texture;
helmtexture = new_helmtexture;
if (new_texture != 0xFF) {
texture = new_texture;
}
if (new_helmtexture != 0xFF) {
helmtexture = new_helmtexture;
}
haircolor = new_haircolor;
beardcolor = new_beardcolor;
eyecolor1 = new_eyecolor1;
@@ -4391,7 +4395,7 @@ int Mob::CountDispellableBuffs()
if(buffs[x].counters)
continue;
if(spells[buffs[x].spellid].good_effect == 0)
if(spells[buffs[x].spellid].good_effect == DETRIMENTAL_EFFECT)
continue;
if(IsValidSpell(buffs[x].spellid) && spells[buffs[x].spellid].buff_duration_formula != DF_Permanent) {
@@ -6227,20 +6231,20 @@ FACTION_VALUE Mob::GetSpecialFactionCon(Mob* iOther) {
bool Mob::HasSpellEffect(int effect_id)
{
int i;
const auto buff_count = GetMaxTotalSlots();
for (int i = 0; i < buff_count; i++) {
const auto spell_id = buffs[i].spellid;
int buff_count = GetMaxTotalSlots();
for(i = 0; i < buff_count; i++)
{
if (!IsValidSpell(buffs[i].spellid)) {
if (!IsValidSpell(spell_id)) {
continue;
}
if (IsEffectInSpell(buffs[i].spellid, effect_id)) {
return(1);
if (IsEffectInSpell(spell_id, effect_id)) {
return true;
}
}
return(0);
return false;
}
int Mob::GetSpecialAbility(int ability)
@@ -6724,8 +6728,11 @@ void Mob::CommonBreakInvisible()
CancelSneakHide();
}
float Mob::GetDefaultRaceSize() const {
return GetRaceGenderDefaultHeight(race, gender);
float Mob::GetDefaultRaceSize(int race_id, int gender_id) const {
return GetRaceGenderDefaultHeight(
race_id > 0 ? race_id : race,
gender_id >= 0 ? gender_id : gender
);
}
bool Mob::ShieldAbility(uint32 target_id, int shielder_max_distance, int shield_duration, int shield_target_mitigation, int shielder_mitigation, bool use_aa, bool can_shield_npc)
+5 -2
View File
@@ -732,7 +732,10 @@ public:
NPC* GetHateRandomNPC() { return hate_list.GetRandomNPCOnHateList(); }
Bot* GetHateRandomBot() { return hate_list.GetRandomBotOnHateList(); }
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 HasPrimaryAggro() { return PrimaryAggro; }
bool HasAssistAggro() { return AssistAggro; }
@@ -1205,7 +1208,7 @@ public:
void SendTo(float new_x, float new_y, float new_z);
void SendToFixZ(float new_x, float new_y, float new_z);
float GetZOffset() const;
float GetDefaultRaceSize() const;
float GetDefaultRaceSize(int race_id = -1, int gender_id = -1) const;
void FixZ(int32 z_find_offset = 5, bool fix_client_z = false);
float GetFixedZ(const glm::vec3 &destination, int32 z_find_offset = 5);
virtual int GetStuckBehavior() const { return 0; }
+1 -1
View File
@@ -653,7 +653,7 @@ void Client::AI_SpellCast()
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);
if(!tar)
+66 -28
View File
@@ -832,14 +832,6 @@ void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_
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() {
copper = 0;
silver = 0;
@@ -1194,7 +1186,7 @@ bool NPC::DatabaseCastAccepted(int spell_id) {
break;
}
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 false;
}
@@ -1378,7 +1370,7 @@ NPC * NPC::SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4
}
NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client) {
if(spawncommand == 0 || spawncommand[0] == 0) {
if (spawncommand == 0 || spawncommand[0] == 0) {
return 0;
}
else {
@@ -1387,42 +1379,54 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
if (!sep.IsNumber(1)) {
sprintf(sep.arg[1], "1");
}
if (!sep.IsNumber(2)) {
sprintf(sep.arg[2], "1");
}
if (!sep.IsNumber(3)) {
sprintf(sep.arg[3], "0");
}
if (Strings::ToInt(sep.arg[4]) > 2100000000 || Strings::ToInt(sep.arg[4]) <= 0) {
sprintf(sep.arg[4], " ");
}
if (!strcmp(sep.arg[5], "-")) {
sprintf(sep.arg[5], " ");
}
if (!sep.IsNumber(5)) {
sprintf(sep.arg[5], " ");
}
if (!sep.IsNumber(6)) {
sprintf(sep.arg[6], "1");
}
if (!sep.IsNumber(8)) {
sprintf(sep.arg[8], "0");
}
if (!sep.IsNumber(9)) {
sprintf(sep.arg[9], "0");
}
if (!sep.IsNumber(7)) {
sprintf(sep.arg[7], "0");
}
if (!strcmp(sep.arg[4], "-")) {
sprintf(sep.arg[4], " ");
}
if (!sep.IsNumber(10)) { // bodytype
sprintf(sep.arg[10], "0");
}
//Calc MaxHP if client neglected to enter it...
if (sep.arg[4] && !sep.IsNumber(4)) {
sprintf(sep.arg[4], "0");
sprintf(sep.arg[4], "1");
}
// Autoselect NPC Gender
@@ -1435,6 +1439,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
memset(npc_type, 0, sizeof(NPCType));
strncpy(npc_type->name, sep.arg[0], 60);
npc_type->current_hp = Strings::ToInt(sep.arg[4]);
npc_type->max_hp = Strings::ToInt(sep.arg[4]);
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->loottable_id = 0;
npc_type->texture = Strings::ToInt(sep.arg[3]);
npc_type->light = 0; // spawncommand needs update
npc_type->runspeed = 1.25;
npc_type->light = 0;
npc_type->runspeed = 1.25f;
npc_type->d_melee_texture1 = Strings::ToInt(sep.arg[7]);
npc_type->d_melee_texture2 = Strings::ToInt(sep.arg[8]);
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->prim_melee_type = 28;
npc_type->sec_melee_type = 28;
npc_type->prim_melee_type = static_cast<uint8>(EQ::skills::SkillHandtoHand);
npc_type->sec_melee_type = static_cast<uint8>(EQ::skills::SkillHandtoHand);
auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Water);
npc->GiveNPCTypeData(npc_type);
@@ -1472,17 +1477,34 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
if (client) {
// Notify client of spawn data
client->Message(Chat::White, "New spawn:");
client->Message(Chat::White, "Name: %s", npc->name);
client->Message(Chat::White, "Race: %u", npc->race);
client->Message(Chat::White, "Level: %u", npc->level);
client->Message(Chat::White, "Material: %u", npc->texture);
client->Message(Chat::White, "Current/Max HP: %i", npc->max_hp);
client->Message(Chat::White, "Gender: %u", npc->gender);
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);
client->Message(Chat::White, "MerchantID: %u", npc->MerchantType);
client->Message(Chat::White, "Bodytype: %u", npc->bodytype);
client->Message(Chat::White, fmt::format("Name | {}", npc->name).c_str());
client->Message(Chat::White, fmt::format("Level | {}", npc->level).c_str());
client->Message(Chat::White, fmt::format("Health | {}", npc->max_hp).c_str());
client->Message(Chat::White, fmt::format("Race | {} ({})", GetRaceIDName(npc->race), npc->race).c_str());
client->Message(Chat::White, fmt::format("Class | {} ({})", GetClassIDName(npc->class_), npc->class_).c_str());
client->Message(Chat::White, fmt::format("Gender | {} ({})", GetGenderName(npc->gender), npc->gender).c_str());
client->Message(Chat::White, fmt::format("Texture | {}", npc->texture).c_str());
if (npc->d_melee_texture1 || npc->d_melee_texture2) {
client->Message(
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;
@@ -2611,15 +2633,31 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value)
return;
}
else if (stat_lower == "min_hit") {
min_dmg = Strings::ToInt(value);
min_dmg = Strings::ToInt(value);
// 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);
min_damage = min_dmg - round(base_damage / 10.0);
return;
}
else if (stat_lower == "max_hit") {
max_dmg = Strings::ToInt(value);
max_dmg = Strings::ToInt(value);
// 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);
min_damage = min_dmg - round(base_damage / 10.0);
return;
-4
View File
@@ -191,8 +191,6 @@ public:
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
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 FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
@@ -208,7 +206,6 @@ public:
inline const ItemList &GetItemList() { return itemlist; }
ServerLootItem_Struct* GetItem(int slot_id);
void AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum);
void AddCash();
void RemoveCash();
void QueryLoot(Client* to, bool is_pet_query = false);
bool HasItem(uint32 item_id);
@@ -584,7 +581,6 @@ protected:
uint32 npc_spells_id;
uint8 casting_spell_AIindex;
uint32* pDontCastBefore_casting_spell;
std::vector<AISpells_Struct> AIspells;
bool HasAISpell;
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates = false);
+4 -1
View File
@@ -135,6 +135,8 @@ void NpcScaleManager::ScaleNPC(
npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist));
}
auto min_damage_set = false;
if (always_scale || npc->GetMinDMG() == 0) {
int64 min_dmg = scale_data.min_dmg;
if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
@@ -145,9 +147,10 @@ void NpcScaleManager::ScaleNPC(
}
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;
if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
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 HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac);
static EQ::skills::SkillType TypeToSkill(uint32 type);
// Packet functions
void CreateSpawnPacket(EQApplicationPacket* app);
void CreateDeSpawnPacket(EQApplicationPacket* app);
+2 -2
View File
@@ -7,9 +7,9 @@
class OrientedBoundingBox
{
public:
OrientedBoundingBox() { }
OrientedBoundingBox() = default;
OrientedBoundingBox(const glm::vec3 &pos, const glm::vec3 &rot, const glm::vec3 &scale, const glm::vec3 &extents);
~OrientedBoundingBox() { }
~OrientedBoundingBox() = default;
bool ContainsPoint(const glm::vec3 &p) const;
private:
+13 -1
View File
@@ -1522,6 +1522,11 @@ int Perl_Client_GetThirst(Client* self) // @categories Account and Character, St
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
{
self->SetHunger(in_hunger);
@@ -1550,7 +1555,7 @@ void Perl_Client_SilentMessage(Client* self, const char* message) // @categories
if (self->GetTarget()->CastToNPC()->IsMoving() &&
!self->GetTarget()->CastToNPC()->IsOnHatelist(self->GetTarget()))
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);
}
uint32 Perl_Client_GetEXPForLevel(Client* self, uint16 check_level)
{
return self->GetEXPForLevel(check_level);
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3070,6 +3080,7 @@ void perl_register_client()
package.add("GetDuelTarget", &Perl_Client_GetDuelTarget);
package.add("GetEnvironmentDamageModifier", &Perl_Client_GetEnvironmentDamageModifier);
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, int16))&Perl_Client_GetEXPModifier);
package.add("GetEbonCrystals", &Perl_Client_GetEbonCrystals);
@@ -3093,6 +3104,7 @@ void perl_register_client()
package.add("GetHorseId", &Perl_Client_GetHorseId);
package.add("GetHealAmount", &Perl_Client_GetHealAmount);
package.add("GetHunger", &Perl_Client_GetHunger);
package.add("GetIntoxication", &Perl_Client_GetIntoxication);
package.add("GetIP", &Perl_Client_GetIP);
package.add("GetIPExemption", &Perl_Client_GetIPExemption);
package.add("GetIPString", &Perl_Client_GetIPString);
+68 -2
View File
@@ -1054,6 +1054,11 @@ void Perl_Mob_SetPetID(Mob* self, uint16 new_pet_id) // @categories Pet
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
{
return self->GetPetID();
@@ -2432,6 +2437,41 @@ Mob* Perl_Mob_GetHateClosest(Mob* self) // @categories Hate and Aggro
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
{
return self->GetLastName();
@@ -2887,6 +2927,16 @@ float Perl_Mob_GetDefaultRaceSize(Mob* self) // @categories Script Utility
return self->GetDefaultRaceSize();
}
float Perl_Mob_GetDefaultRaceSize(Mob* self, int race_id) // @categories Script Utility
{
return self->GetDefaultRaceSize(race_id);
}
float Perl_Mob_GetDefaultRaceSize(Mob* self, int race_id, int gender_id) // @categories Script Utility
{
return self->GetDefaultRaceSize(race_id, gender_id);
}
uint32 Perl_Mob_GetRemainingTimeMS(Mob* self, const char* timer_name)
{
return quest_manager.getremainingtimeMS(timer_name, self);
@@ -2950,6 +3000,11 @@ perl::array Perl_Mob_GetBuffSpellIDs(Mob* self)
return l;
}
bool Perl_Mob_HasSpellEffect(Mob* self, int effect_id)
{
return self->HasSpellEffect(effect_id);
}
void perl_register_mob()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3141,7 +3196,9 @@ void perl_register_mob()
package.add("GetClassName", &Perl_Mob_GetClassName);
package.add("GetCleanName", &Perl_Mob_GetCleanName);
package.add("GetCorruption", &Perl_Mob_GetCorruption);
package.add("GetDefaultRaceSize", &Perl_Mob_GetDefaultRaceSize);
package.add("GetDefaultRaceSize", (float(*)(Mob*))&Perl_Mob_GetDefaultRaceSize);
package.add("GetDefaultRaceSize", (float(*)(Mob*, int))&Perl_Mob_GetDefaultRaceSize);
package.add("GetDefaultRaceSize", (float(*)(Mob*, int, int))&Perl_Mob_GetDefaultRaceSize);
package.add("GetDEX", &Perl_Mob_GetDEX);
package.add("GetDR", &Perl_Mob_GetDR);
package.add("GetDamageAmount", &Perl_Mob_GetDamageAmount);
@@ -3171,7 +3228,14 @@ void perl_register_mob()
package.add("GetHaste", &Perl_Mob_GetHaste);
package.add("GetHateAmount", (int64_t(*)(Mob*, Mob*))&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("GetHateList", &Perl_Mob_GetHateList);
package.add("GetHateListBots", (perl::array(*)(Mob*))&Perl_Mob_GetHateListBots);
@@ -3225,6 +3289,7 @@ void perl_register_mob()
package.add("GetOwner", &Perl_Mob_GetOwner);
package.add("GetOwnerID", &Perl_Mob_GetOwnerID);
package.add("GetPR", &Perl_Mob_GetPR);
package.add("GetPet", &Perl_Mob_GetPet);
package.add("GetPetID", &Perl_Mob_GetPetID);
package.add("GetPetOrder", &Perl_Mob_GetPetOrder);
package.add("GetPetType", &Perl_Mob_GetPetType);
@@ -3272,6 +3337,7 @@ void perl_register_mob()
package.add("HasPet", &Perl_Mob_HasPet);
package.add("HasProcs", &Perl_Mob_HasProcs);
package.add("HasShieldEquipped", &Perl_Mob_HasShieldEquipped);
package.add("HasSpellEffect", &Perl_Mob_HasSpellEffect);
package.add("HasTimer", &Perl_Mob_HasTimer);
package.add("HasTwoHandBluntEquipped", &Perl_Mob_HasTwoHandBluntEquipped);
package.add("HasTwoHanderEquipped", &Perl_Mob_HasTwoHanderEquipped);

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