mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 09:31:30 +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)
|
||||
-------------------------------------------------------
|
||||
== 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 ==
|
||||
Uleat: Implemented 'Inventory Snapshot' feature to track online player inventories at timed intervals.
|
||||
rules:
|
||||
|
||||
@ -478,7 +478,7 @@ typedef enum {
|
||||
#define SE_GateToHomeCity 322 // implemented
|
||||
#define SE_DefensiveProc 323 // 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_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
|
||||
|
||||
@ -1382,7 +1382,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0)
|
||||
TrySkillProc(other, skillinuse, 0, true, Hand);
|
||||
|
||||
CommonBreakInvisible();
|
||||
CommonBreakInvisibleFromCombat();
|
||||
|
||||
if(GetTarget())
|
||||
TriggerDefensiveProcs(weapon, other, Hand, damage);
|
||||
@ -1940,7 +1940,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
||||
|
||||
MeleeLifeTap(damage);
|
||||
|
||||
CommonBreakInvisible();
|
||||
CommonBreakInvisibleFromCombat();
|
||||
|
||||
//I doubt this works...
|
||||
if (!GetTarget())
|
||||
@ -4487,7 +4487,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes s
|
||||
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||
}
|
||||
|
||||
void Mob::CommonBreakInvisible()
|
||||
void Mob::CommonBreakInvisibleFromCombat()
|
||||
{
|
||||
//break invis when you attack
|
||||
if(invisible) {
|
||||
|
||||
@ -1452,6 +1452,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
newbon->TradeSkillMastery = base1;
|
||||
break;
|
||||
|
||||
case SE_NoBreakAESneak:
|
||||
if (newbon->NoBreakAESneak < base1)
|
||||
newbon->NoBreakAESneak = base1;
|
||||
break;
|
||||
|
||||
// to do
|
||||
case SE_PetDiscipline:
|
||||
break;
|
||||
@ -3189,6 +3194,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
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
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
|
||||
@ -878,6 +878,7 @@ public:
|
||||
void SetFilter(eqFilterType filter_id, eqFilterMode value) { ClientFilters[filter_id]=value; }
|
||||
|
||||
void BreakInvis();
|
||||
void BreakSneakWhenCastOn(Mob* caster, bool IsResisted);
|
||||
void LeaveGroup();
|
||||
|
||||
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
|
||||
int32 ReduceTradeskillFail[HIGHEST_SKILL+1]; // Reduces chance for trade skills to fail by percent.
|
||||
uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill.
|
||||
int16 NoBreakAESneak; // Percent value
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
||||
@ -164,7 +164,8 @@ public:
|
||||
virtual inline bool IsBerserk() { return false; } // only clients
|
||||
void RogueEvade(Mob *other);
|
||||
void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse);
|
||||
void CommonBreakInvisible();
|
||||
void BreakInvisibleSpells();
|
||||
void CommonBreakInvisibleFromCombat();
|
||||
bool HasDied();
|
||||
virtual bool CheckDualWield();
|
||||
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);
|
||||
CommonBreakInvisible();
|
||||
CommonBreakInvisibleFromCombat();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
CommonBreakInvisible();
|
||||
CommonBreakInvisibleFromCombat();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1433,7 +1433,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
//consume ammo
|
||||
DeleteItemInInventory(ammo_slot, 1, true);
|
||||
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)
|
||||
|
||||
@ -6707,3 +6707,67 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster)
|
||||
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
|
||||
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))
|
||||
spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resisttype, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override);
|
||||
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);
|
||||
CheckNumHitsRemaining(NumHit::OutgoingSpells);
|
||||
|
||||
@ -3719,6 +3724,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (spelltar->IsClient()){
|
||||
spelltar->CastToClient()->BreakSneakWhenCastOn(this, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -384,6 +384,8 @@
|
||||
#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_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 ALREADY_CASTING 12442 //You are already casting a spell!
|
||||
#define SHIMMERS_BRIEFLY 12444 //Your %1 shimmers briefly.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user