mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-11 11:48:37 +00:00
Merge remote-tracking branch 'upstream/master' into spa382update2
This commit is contained in:
@@ -12198,7 +12198,8 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
|
||||
tr.name,
|
||||
tr.trivial,
|
||||
SUM(tre.componentcount),
|
||||
tr.tradeskill
|
||||
tr.tradeskill,
|
||||
tr.must_learn
|
||||
FROM
|
||||
tradeskill_recipe AS tr
|
||||
LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id
|
||||
@@ -12298,7 +12299,8 @@ void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app)
|
||||
tr.name,
|
||||
tr.trivial,
|
||||
SUM(tre.componentcount),
|
||||
tr.tradeskill
|
||||
tr.tradeskill,
|
||||
tr.must_learn
|
||||
FROM
|
||||
tradeskill_recipe AS tr
|
||||
LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id
|
||||
|
||||
@@ -846,6 +846,7 @@ public:
|
||||
bool HarmonySpellLevelCheck(int32 spell_id, Mob* target = nullptr);
|
||||
bool CanFocusUseRandomEffectivenessByType(focusType type);
|
||||
int GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool best_focus = 0);
|
||||
int GetMemoryBlurChance(int base_chance);
|
||||
|
||||
bool TryDoubleMeleeRoundEffect();
|
||||
bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; }
|
||||
@@ -1534,6 +1535,7 @@ protected:
|
||||
bool endur_upkeep;
|
||||
bool degenerating_effects; // true if we have a buff that needs to be recalced every tick
|
||||
bool spawned_in_water;
|
||||
|
||||
public:
|
||||
bool GetWasSpawnedInWater() const;
|
||||
|
||||
|
||||
+59
-19
@@ -63,6 +63,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
if (spell.disallow_sit && IsBuffSpell(spell_id) && IsClient() && (CastToClient()->IsSitting() || CastToClient()->GetHorseId() != 0))
|
||||
return false;
|
||||
|
||||
bool CanMemoryBlurFromMez = true;
|
||||
if (IsMezzed()) { //Check for special memory blur behavior when on mez, this needs to be before buff override.
|
||||
CanMemoryBlurFromMez = false;
|
||||
}
|
||||
|
||||
bool c_override = false;
|
||||
if (caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) {
|
||||
const EQ::ItemInstance *inst = caster->CastToClient()->GetInv().GetItem(GetCastedSpellInvSlot());
|
||||
@@ -1530,16 +1535,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Memory Blur: %d", effect_value);
|
||||
#endif
|
||||
int wipechance = spells[spell_id].base[i];
|
||||
int bonus = 0;
|
||||
|
||||
if (caster){
|
||||
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
|
||||
caster->itembonuses.IncreaseChanceMemwipe +
|
||||
caster->aabonuses.IncreaseChanceMemwipe;
|
||||
//Memory blur component of Mez spells is not checked again if Mez is recast on a target that is already mezed
|
||||
if (!CanMemoryBlurFromMez && IsEffectInSpell(spell_id, SE_Mez)) {
|
||||
break;
|
||||
}
|
||||
|
||||
int wipechance = 0;
|
||||
|
||||
if (caster) {
|
||||
wipechance = caster->GetMemoryBlurChance(effect_value);
|
||||
}
|
||||
|
||||
wipechance += wipechance*bonus/100;
|
||||
|
||||
if(zone->random.Roll(wipechance))
|
||||
{
|
||||
@@ -3859,19 +3864,15 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
}
|
||||
|
||||
case SE_WipeHateList: {
|
||||
if (IsMezSpell(buff.spellid))
|
||||
if (IsMezSpell(buff.spellid)) {
|
||||
break;
|
||||
|
||||
int wipechance = spells[buff.spellid].base[i];
|
||||
int bonus = 0;
|
||||
|
||||
if (caster) {
|
||||
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
|
||||
caster->itembonuses.IncreaseChanceMemwipe +
|
||||
caster->aabonuses.IncreaseChanceMemwipe;
|
||||
}
|
||||
|
||||
wipechance += wipechance * bonus / 100;
|
||||
int wipechance = 0;
|
||||
|
||||
if (caster) {
|
||||
wipechance = caster->GetMemoryBlurChance(effect_value);
|
||||
}
|
||||
|
||||
if (zone->random.Roll(wipechance)) {
|
||||
if (IsAIControlled()) {
|
||||
@@ -8544,3 +8545,42 @@ bool Mob::NegateSpellEffect(uint16 spell_id, int effect_id)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Mob::GetMemoryBlurChance(int base_chance)
|
||||
{
|
||||
/*
|
||||
Memory Blur mechanic for SPA 62
|
||||
Chance formula is effect chance + charisma modifer + caster level modifier
|
||||
Effect chance is base value of spell
|
||||
Charisma modifier is CHA/10 = %, with MAX of 15% (thus 150 cha gives you max bonus)
|
||||
Caster level modifier. +100% if caster < level 17 which scales down to 25% at > 53. **
|
||||
(Yes the above gets worse as you level. Behavior was confirmed on live.)
|
||||
Memory blur is applied to mez on initial cast using same formula. However, recasting on a target that
|
||||
is already mezed will not give a chance to memory blur. The blur is not checked on buff ticks.
|
||||
|
||||
SPA 242 SE_IncreaseChanceMemwipe modifies the final chance after all bonuses are applied.
|
||||
This is also applied to memory blur from mez spells.
|
||||
|
||||
this = caster
|
||||
*/
|
||||
int cha_mod = int(GetCHA() / 10);
|
||||
cha_mod = std::min(cha_mod, 15);
|
||||
|
||||
int lvl_mod = 0;
|
||||
if (GetLevel() < 17) {
|
||||
lvl_mod = 100;
|
||||
}
|
||||
else if (GetLevel() > 53) {
|
||||
lvl_mod = 25;
|
||||
}
|
||||
else {
|
||||
lvl_mod = 100 + ((GetLevel() - 16)*-2);//Derived from above range of values.**
|
||||
}
|
||||
|
||||
int chance = cha_mod + lvl_mod + base_chance;
|
||||
|
||||
int chance_mod = spellbonuses.IncreaseChanceMemwipe + itembonuses.IncreaseChanceMemwipe + aabonuses.IncreaseChanceMemwipe;
|
||||
|
||||
chance += chance * chance_mod / 100;
|
||||
return chance;
|
||||
}
|
||||
|
||||
+1
-1
@@ -3406,7 +3406,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
buffs[emptyslot].focusproclimit_procamt = 0;
|
||||
buffs[emptyslot].instrument_mod = caster ? caster->GetInstrumentMod(spell_id) : 10;
|
||||
|
||||
if (level_override > 0) {
|
||||
if (level_override > 0 || buffs[emptyslot].numhits > 0) {
|
||||
buffs[emptyslot].UpdateClient = true;
|
||||
} else {
|
||||
if (buffs[emptyslot].ticsremaining > (1 + CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration)))
|
||||
|
||||
+17
-8
@@ -782,7 +782,7 @@ void Client::SendTradeskillSearchResults(
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (row == nullptr || row[0] == nullptr || row[1] == nullptr || row[2] == nullptr || row[3] == nullptr ||
|
||||
row[5] == nullptr) {
|
||||
row[4] == nullptr || row[5] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -790,27 +790,36 @@ void Client::SendTradeskillSearchResults(
|
||||
const char *name = row[1];
|
||||
uint32 trivial = (uint32) atoi(row[2]);
|
||||
uint32 comp_count = (uint32) atoi(row[3]);
|
||||
uint32 tradeskill = (uint16) atoi(row[5]);
|
||||
uint32 tradeskill = (uint16) atoi(row[4]);
|
||||
uint32 must_learn = (uint16) atoi(row[5]);
|
||||
|
||||
|
||||
// Skip the recipes that exceed the threshold in skill difference
|
||||
// Recipes that have either been made before or were
|
||||
// explicitly learned are excempt from that limit
|
||||
|
||||
auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe(
|
||||
character_learned_recipe_list,
|
||||
recipe_id
|
||||
);
|
||||
|
||||
if (RuleB(Skills, UseLimitTradeskillSearchSkillDiff) &&
|
||||
((int32) trivial - (int32) GetSkill((EQ::skills::SkillType) tradeskill)) >
|
||||
RuleI(Skills, MaxTradeskillSearchSkillDiff)) {
|
||||
|
||||
LogTradeskills("Checking limit recipe_id [{}] name [{}]", recipe_id, name);
|
||||
|
||||
auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe(
|
||||
character_learned_recipe_list,
|
||||
recipe_id
|
||||
);
|
||||
|
||||
if (character_learned_recipe.made_count == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//Skip recipes that must be learned
|
||||
if ((must_learn & 0xf) && !character_learned_recipe.recipe_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RecipeReply, sizeof(RecipeReply_Struct));
|
||||
RecipeReply_Struct *reply = (RecipeReply_Struct *) outapp->pBuffer;
|
||||
|
||||
@@ -1489,7 +1498,7 @@ bool ZoneDatabase::GetTradeRecipe(
|
||||
recipe_id
|
||||
);
|
||||
|
||||
if (character_learned_recipe.made_count > 0) {
|
||||
if (character_learned_recipe.recipe_id) { //If this exists we learned it
|
||||
LogTradeskills("[GetTradeRecipe] made_count [{}]", character_learned_recipe.made_count);
|
||||
|
||||
spec->has_learnt = true;
|
||||
|
||||
+2
-2
@@ -153,7 +153,6 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
|
||||
LogInfo("Zone Bootup: [{}] ([{}]: [{}])", zonename, iZoneID, iInstanceID);
|
||||
parse->Init();
|
||||
UpdateWindowTitle(nullptr);
|
||||
zone->GetTimeSync();
|
||||
|
||||
zone->RequestUCSServerStatus();
|
||||
|
||||
@@ -1818,7 +1817,8 @@ void Zone::Repop(uint32 delay)
|
||||
|
||||
void Zone::GetTimeSync()
|
||||
{
|
||||
if (worldserver.Connected() && !zone_has_current_time) {
|
||||
if (!zone_has_current_time) {
|
||||
LogInfo("Requesting world time");
|
||||
auto pack = new ServerPacket(ServerOP_GetWorldTime, 1);
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
|
||||
+5
-1
@@ -167,7 +167,9 @@ bool ZoneDatabase::GetZoneCFG(
|
||||
"fast_regen_endurance, " // 59
|
||||
"npc_max_aggro_dist, " // 60
|
||||
"max_movement_update_range, " // 61
|
||||
"underworld_teleport_index " // 62
|
||||
"underworld_teleport_index, " // 62
|
||||
"lava_damage, " // 63
|
||||
"min_lava_damage " // 64
|
||||
"FROM zone WHERE zoneidnumber = %i AND version = %i %s",
|
||||
zoneid,
|
||||
instance_id,
|
||||
@@ -220,6 +222,8 @@ bool ZoneDatabase::GetZoneCFG(
|
||||
zone_data->FastRegenEndurance = atoi(row[59]);
|
||||
zone_data->NPCAggroMaxDist = atoi(row[60]);
|
||||
zone_data->underworld_teleport_index = atoi(row[62]);
|
||||
zone_data->LavaDamage = atoi(row[63]);
|
||||
zone_data->MinLavaDamage = atoi(row[64]);
|
||||
|
||||
int bindable = 0;
|
||||
bindable = atoi(row[31]);
|
||||
|
||||
Reference in New Issue
Block a user