mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 13:41:31 +00:00
Merge pull request #463 from KayenEQ/Development
Invisible/Hide mechanics when cast on
This commit is contained in:
commit
b923c69f39
@ -1,5 +1,12 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 10/10/2015 ==
|
||||||
|
Kayen: Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell.
|
||||||
|
Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE.
|
||||||
|
Hide skill now also follows the same rules as above.
|
||||||
|
Implemented support for Rogue AA - Nerves of Steel which gives a chance for hide NOT to break
|
||||||
|
when client is hit with an AOE spell.
|
||||||
|
|
||||||
== 09/25/2015 ==
|
== 09/25/2015 ==
|
||||||
Uleat: Implemented 'Inventory Snapshot' feature to track online player inventories at timed intervals.
|
Uleat: Implemented 'Inventory Snapshot' feature to track online player inventories at timed intervals.
|
||||||
rules:
|
rules:
|
||||||
|
|||||||
@ -478,7 +478,7 @@ typedef enum {
|
|||||||
#define SE_GateToHomeCity 322 // implemented
|
#define SE_GateToHomeCity 322 // implemented
|
||||||
#define SE_DefensiveProc 323 // implemented
|
#define SE_DefensiveProc 323 // implemented
|
||||||
#define SE_HPToMana 324 // implemented
|
#define SE_HPToMana 324 // implemented
|
||||||
//#define SE_NoBreakAESneak 325 // *not implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
|
#define SE_NoBreakAESneak 325 // implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
|
||||||
#define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability
|
#define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability
|
||||||
#define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have
|
#define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have
|
||||||
#define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die
|
#define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die
|
||||||
|
|||||||
@ -1382,7 +1382,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
|||||||
if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0)
|
if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0)
|
||||||
TrySkillProc(other, skillinuse, 0, true, Hand);
|
TrySkillProc(other, skillinuse, 0, true, Hand);
|
||||||
|
|
||||||
CommonBreakInvisible();
|
CommonBreakInvisibleFromCombat();
|
||||||
|
|
||||||
if(GetTarget())
|
if(GetTarget())
|
||||||
TriggerDefensiveProcs(weapon, other, Hand, damage);
|
TriggerDefensiveProcs(weapon, other, Hand, damage);
|
||||||
@ -1940,7 +1940,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
|||||||
|
|
||||||
MeleeLifeTap(damage);
|
MeleeLifeTap(damage);
|
||||||
|
|
||||||
CommonBreakInvisible();
|
CommonBreakInvisibleFromCombat();
|
||||||
|
|
||||||
//I doubt this works...
|
//I doubt this works...
|
||||||
if (!GetTarget())
|
if (!GetTarget())
|
||||||
@ -4487,7 +4487,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes s
|
|||||||
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::CommonBreakInvisible()
|
void Mob::CommonBreakInvisibleFromCombat()
|
||||||
{
|
{
|
||||||
//break invis when you attack
|
//break invis when you attack
|
||||||
if(invisible) {
|
if(invisible) {
|
||||||
|
|||||||
@ -1452,6 +1452,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
|||||||
newbon->TradeSkillMastery = base1;
|
newbon->TradeSkillMastery = base1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SE_NoBreakAESneak:
|
||||||
|
if (newbon->NoBreakAESneak < base1)
|
||||||
|
newbon->NoBreakAESneak = base1;
|
||||||
|
break;
|
||||||
|
|
||||||
// to do
|
// to do
|
||||||
case SE_PetDiscipline:
|
case SE_PetDiscipline:
|
||||||
break;
|
break;
|
||||||
@ -3188,6 +3193,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
|||||||
new_bonus->RaiseSkillCap[base2] = effect_value;
|
new_bonus->RaiseSkillCap[base2] = effect_value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SE_NoBreakAESneak:
|
||||||
|
if (new_bonus->NoBreakAESneak < effect_value)
|
||||||
|
new_bonus->NoBreakAESneak = effect_value;
|
||||||
|
break;
|
||||||
|
|
||||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||||
if (IsAISpellEffect) {
|
if (IsAISpellEffect) {
|
||||||
|
|||||||
@ -878,6 +878,7 @@ public:
|
|||||||
void SetFilter(eqFilterType filter_id, eqFilterMode value) { ClientFilters[filter_id]=value; }
|
void SetFilter(eqFilterType filter_id, eqFilterMode value) { ClientFilters[filter_id]=value; }
|
||||||
|
|
||||||
void BreakInvis();
|
void BreakInvis();
|
||||||
|
void BreakSneakWhenCastOn(Mob* caster, bool IsResisted);
|
||||||
void LeaveGroup();
|
void LeaveGroup();
|
||||||
|
|
||||||
bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;}
|
bool Hungry() const {if (GetGM()) return false; return m_pp.hunger_level <= 3000;}
|
||||||
|
|||||||
@ -471,6 +471,7 @@ struct StatBonuses {
|
|||||||
uint16 ReduceFallDamage; // reduce fall damage by percent
|
uint16 ReduceFallDamage; // reduce fall damage by percent
|
||||||
int32 ReduceTradeskillFail[HIGHEST_SKILL+1]; // Reduces chance for trade skills to fail by percent.
|
int32 ReduceTradeskillFail[HIGHEST_SKILL+1]; // Reduces chance for trade skills to fail by percent.
|
||||||
uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill.
|
uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill.
|
||||||
|
int16 NoBreakAESneak; // Percent value
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
@ -164,7 +164,8 @@ public:
|
|||||||
virtual inline bool IsBerserk() { return false; } // only clients
|
virtual inline bool IsBerserk() { return false; } // only clients
|
||||||
void RogueEvade(Mob *other);
|
void RogueEvade(Mob *other);
|
||||||
void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse);
|
void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse);
|
||||||
void CommonBreakInvisible();
|
void BreakInvisibleSpells();
|
||||||
|
void CommonBreakInvisibleFromCombat();
|
||||||
bool HasDied();
|
bool HasDied();
|
||||||
virtual bool CheckDualWield();
|
virtual bool CheckDualWield();
|
||||||
void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0);
|
void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0);
|
||||||
|
|||||||
@ -805,7 +805,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CheckIncreaseSkill(SkillArchery, GetTarget(), -15);
|
CheckIncreaseSkill(SkillArchery, GetTarget(), -15);
|
||||||
CommonBreakInvisible();
|
CommonBreakInvisibleFromCombat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime,
|
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime,
|
||||||
@ -1237,7 +1237,7 @@ void NPC::RangedAttack(Mob* other)
|
|||||||
|
|
||||||
DoRangedAttackDmg(other);
|
DoRangedAttackDmg(other);
|
||||||
|
|
||||||
CommonBreakInvisible();
|
CommonBreakInvisibleFromCombat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1433,7 +1433,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
|||||||
//consume ammo
|
//consume ammo
|
||||||
DeleteItemInInventory(ammo_slot, 1, true);
|
DeleteItemInInventory(ammo_slot, 1, true);
|
||||||
CheckIncreaseSkill(SkillThrowing, GetTarget());
|
CheckIncreaseSkill(SkillThrowing, GetTarget());
|
||||||
CommonBreakInvisible();
|
CommonBreakInvisibleFromCombat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed)
|
void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed)
|
||||||
|
|||||||
@ -6707,3 +6707,67 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster)
|
|||||||
SetSpellPowerDistanceMod(static_cast<int>(mod));
|
SetSpellPowerDistanceMod(static_cast<int>(mod));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mob::BreakInvisibleSpells()
|
||||||
|
{
|
||||||
|
if(invisible) {
|
||||||
|
BuffFadeByEffect(SE_Invisibility);
|
||||||
|
BuffFadeByEffect(SE_Invisibility2);
|
||||||
|
invisible = false;
|
||||||
|
}
|
||||||
|
if(invisible_undead) {
|
||||||
|
BuffFadeByEffect(SE_InvisVsUndead);
|
||||||
|
BuffFadeByEffect(SE_InvisVsUndead2);
|
||||||
|
invisible_undead = false;
|
||||||
|
}
|
||||||
|
if(invisible_animals){
|
||||||
|
BuffFadeByEffect(SE_InvisVsAnimals);
|
||||||
|
invisible_animals = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::BreakSneakWhenCastOn(Mob* caster, bool IsResisted)
|
||||||
|
{
|
||||||
|
bool IsCastersTarget = false; //Chance to avoid only applies to AOE spells when not targeted.
|
||||||
|
if(hidden || improved_hidden){
|
||||||
|
|
||||||
|
if (caster){
|
||||||
|
Mob* target = nullptr;
|
||||||
|
target = caster->GetTarget();
|
||||||
|
if (target && target == this){
|
||||||
|
IsCastersTarget = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsCastersTarget){
|
||||||
|
|
||||||
|
int chance = spellbonuses.NoBreakAESneak + itembonuses.NoBreakAESneak + aabonuses.NoBreakAESneak;
|
||||||
|
|
||||||
|
if (IsResisted)
|
||||||
|
chance *= 2;
|
||||||
|
|
||||||
|
if(chance && (zone->random.Roll(chance)))
|
||||||
|
return; // Do not drop Sneak/Hide
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: The skill buttons should reset when this occurs. Not sure how to force that yet. - Kayen
|
||||||
|
hidden = false;
|
||||||
|
improved_hidden = false;
|
||||||
|
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
||||||
|
SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer;
|
||||||
|
sa_out->spawn_id = GetID();
|
||||||
|
sa_out->type = 0x03;
|
||||||
|
sa_out->parameter = 0;
|
||||||
|
entity_list.QueueClients(this, outapp, false);
|
||||||
|
safe_delete(outapp);
|
||||||
|
|
||||||
|
Message_StringID(MT_Skills,NO_LONGER_HIDDEN);
|
||||||
|
|
||||||
|
//Sneaking alone will not be disabled from spells, only hide+sneak.
|
||||||
|
if (sneaking){
|
||||||
|
sneaking = false;
|
||||||
|
SendAppearancePacket(AT_Sneak, 0);
|
||||||
|
Message_StringID(MT_Skills,STOP_SNEAKING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3679,6 +3679,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
|||||||
// not all unresistable, so changing this to only check certain spells
|
// not all unresistable, so changing this to only check certain spells
|
||||||
if(IsResistableSpell(spell_id))
|
if(IsResistableSpell(spell_id))
|
||||||
{
|
{
|
||||||
|
spelltar->BreakInvisibleSpells(); //Any detrimental spell cast on you will drop invisible (can be AOE, non damage ect).
|
||||||
|
|
||||||
if (IsCharmSpell(spell_id) || IsMezSpell(spell_id) || IsFearSpell(spell_id))
|
if (IsCharmSpell(spell_id) || IsMezSpell(spell_id) || IsFearSpell(spell_id))
|
||||||
spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override);
|
spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override);
|
||||||
else
|
else
|
||||||
@ -3712,6 +3714,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spelltar->IsClient())
|
||||||
|
spelltar->CastToClient()->BreakSneakWhenCastOn(this, true);
|
||||||
|
|
||||||
spelltar->CheckNumHitsRemaining(NumHit::IncomingSpells);
|
spelltar->CheckNumHitsRemaining(NumHit::IncomingSpells);
|
||||||
CheckNumHitsRemaining(NumHit::OutgoingSpells);
|
CheckNumHitsRemaining(NumHit::OutgoingSpells);
|
||||||
|
|
||||||
@ -3719,6 +3724,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (spelltar->IsClient()){
|
||||||
|
spelltar->CastToClient()->BreakSneakWhenCastOn(this, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -384,6 +384,8 @@
|
|||||||
#define TARGET_PLAYER_FOR_GUILD_STATUS 12260
|
#define TARGET_PLAYER_FOR_GUILD_STATUS 12260
|
||||||
#define GROUP_INVITEE_NOT_FOUND 12268 //You must target a player or use /invite <name> to invite someone to your group.
|
#define GROUP_INVITEE_NOT_FOUND 12268 //You must target a player or use /invite <name> to invite someone to your group.
|
||||||
#define GROUP_INVITEE_SELF 12270 //12270 You cannot invite yourself.
|
#define GROUP_INVITEE_SELF 12270 //12270 You cannot invite yourself.
|
||||||
|
#define NO_LONGER_HIDDEN 12337 //You are no longer hidden.
|
||||||
|
#define STOP_SNEAKING 12338 //You stop sneaking
|
||||||
#define NOT_IN_CONTROL 12368 //You do not have control of yourself right now.
|
#define NOT_IN_CONTROL 12368 //You do not have control of yourself right now.
|
||||||
#define ALREADY_CASTING 12442 //You are already casting a spell!
|
#define ALREADY_CASTING 12442 //You are already casting a spell!
|
||||||
#define SHIMMERS_BRIEFLY 12444 //Your %1 shimmers briefly.
|
#define SHIMMERS_BRIEFLY 12444 //Your %1 shimmers briefly.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user