mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
Merge remote-tracking branch 'refs/remotes/origin/master' into 2002_fixes
This commit is contained in:
commit
67a95b59a7
@ -1,5 +1,21 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 03/12/2017 ==
|
||||
Akkadius:
|
||||
- Implemented range rules for packets and other functions
|
||||
RULE_INT ( Range, Say, 135 )
|
||||
RULE_INT ( Range, Emote, 135 )
|
||||
RULE_INT ( Range, BeginCast, 200)
|
||||
RULE_INT ( Range, Anims, 135)
|
||||
RULE_INT ( Range, SpellParticles, 135)
|
||||
RULE_INT ( Range, DamageMessages, 50)
|
||||
RULE_INT ( Range, SpellMessages, 75)
|
||||
RULE_INT ( Range, SongMessages, 75)
|
||||
RULE_INT ( Range, MobPositionUpdates, 600)
|
||||
RULE_INT ( Range, CriticalDamage, 80)
|
||||
|
||||
- (Readability) Also cleaned up some formatting in messaging and packets so it is easier to understand what is going on with the code
|
||||
|
||||
== 03/09/2017 ==
|
||||
Uleat: Fixed a few glitches related to bot trading and other affected code
|
||||
- Added a temporary fail clause for partial stack transfers to prevent client item overwrites
|
||||
|
||||
@ -207,3 +207,21 @@ bool EQEmu::ItemData::IsTypeShield() const
|
||||
{
|
||||
return (ItemType == item::ItemTypeShield);
|
||||
}
|
||||
|
||||
bool EQEmu::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item)
|
||||
{
|
||||
if (!l_item || !r_item)
|
||||
return false;
|
||||
|
||||
if (!l_item->LoreGroup || !r_item->LoreGroup)
|
||||
return false;
|
||||
|
||||
if (l_item->LoreGroup == r_item->LoreGroup) {
|
||||
if ((l_item->LoreGroup == -1) && (l_item->ID != r_item->ID))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -538,6 +538,9 @@ namespace EQEmu
|
||||
bool IsType1HWeapon() const;
|
||||
bool IsType2HWeapon() const;
|
||||
bool IsTypeShield() const;
|
||||
|
||||
static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item);
|
||||
bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); }
|
||||
};
|
||||
|
||||
} /*EQEmu*/
|
||||
|
||||
@ -545,6 +545,20 @@ RULE_BOOL(TaskSystem, KeepOneRecordPerCompletedTask, true)
|
||||
RULE_BOOL(TaskSystem, EnableTaskProximity, true)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Range)
|
||||
RULE_INT(Range, Say, 135)
|
||||
RULE_INT(Range, Emote, 135)
|
||||
RULE_INT(Range, BeginCast, 200)
|
||||
RULE_INT(Range, Anims, 135)
|
||||
RULE_INT(Range, SpellParticles, 135)
|
||||
RULE_INT(Range, DamageMessages, 50)
|
||||
RULE_INT(Range, SpellMessages, 75)
|
||||
RULE_INT(Range, SongMessages, 75)
|
||||
RULE_INT(Range, MobPositionUpdates, 600)
|
||||
RULE_INT(Range, CriticalDamage, 80)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
|
||||
#ifdef BOTS
|
||||
RULE_CATEGORY(Bots)
|
||||
RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:SongMessages', '75', 'The packet range in which song messages are sent');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:Emote', '135', 'The packet range in which emote messages are sent');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:BeginCast', '200', 'The packet range in which begin cast messages are sent');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:Anims', '135', 'The packet range in which animations are sent');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:DamageMessages', '50', 'The packet range in which damage messages are sent (non-crit)');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:SpellMessages', '75', 'The packet range in which spell damage messages are sent');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:Say', '135', 'The range that is required before /say or hail messages will work to an NPC');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:SpellParticles', '135', 'The packet range in which spell particles are sent');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:MobPositionUpdates', '600', 'The packet range in which mob position updates are sent');
|
||||
INSERT INTO `rule_values` VALUES (1, 'Range:CriticalDamage', '80', 'The packet range in which critical hit messages are sent');
|
||||
189
zone/attack.cpp
189
zone/attack.cpp
@ -1480,9 +1480,18 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk
|
||||
}
|
||||
|
||||
if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||
char val1[20]={0};
|
||||
entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE,
|
||||
killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
||||
char val1[20] = { 0 };
|
||||
|
||||
entity_list.MessageClose_StringID(
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, DamageMessages),
|
||||
MT_NonMelee, /* 283 */
|
||||
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
|
||||
killerMob->GetCleanName(), /* Message1 */
|
||||
GetCleanName(), /* Message2 */
|
||||
ConvertArray(damage, val1)/* Message3 */
|
||||
);
|
||||
}
|
||||
|
||||
int exploss = 0;
|
||||
@ -2009,8 +2018,17 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil
|
||||
|
||||
if (killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||
char val1[20] = { 0 };
|
||||
entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE,
|
||||
killer_mob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
||||
|
||||
entity_list.MessageClose_StringID(
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, DamageMessages),
|
||||
MT_NonMelee, /* 283 */
|
||||
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
|
||||
killer_mob->GetCleanName(), /* Message1 */
|
||||
GetCleanName(), /* Message2 */
|
||||
ConvertArray(damage, val1) /* Message3 */
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3229,7 +3247,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
|
||||
//we used to do a message to the client, but its gone now.
|
||||
// emote goes with every one ... even npcs
|
||||
entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() );
|
||||
entity_list.MessageClose(this, true, RuleI(Range, SpellMessages), MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() );
|
||||
}
|
||||
} //end `if there is some damage being done and theres anattacker person involved`
|
||||
|
||||
@ -3309,8 +3327,15 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
//fade mez if we are mezzed
|
||||
if (IsMezzed() && attacker) {
|
||||
Log.Out(Logs::Detail, Logs::Combat, "Breaking mez due to attack.");
|
||||
entity_list.MessageClose_StringID(this, true, 100, MT_WornOff,
|
||||
HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName());
|
||||
entity_list.MessageClose_StringID(
|
||||
this, /* Sender */
|
||||
true, /* Skip Sender */
|
||||
RuleI(Range, SpellMessages),
|
||||
MT_WornOff, /* 284 */
|
||||
HAS_BEEN_AWAKENED, // %1 has been awakened by %2.
|
||||
GetCleanName(), /* Message1 */
|
||||
attacker->GetCleanName() /* Message2 */
|
||||
);
|
||||
BuffFadeByEffect(SE_Mez);
|
||||
}
|
||||
|
||||
@ -3454,8 +3479,8 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
else
|
||||
filter = FilterPetMisses;
|
||||
|
||||
if(!FromDamageShield)
|
||||
owner->CastToClient()->QueuePacket(outapp,true,CLIENT_CONNECTED,filter);
|
||||
if (!FromDamageShield)
|
||||
owner->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter);
|
||||
}
|
||||
}
|
||||
skip = owner;
|
||||
@ -3469,9 +3494,18 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
char val1[20] = {0};
|
||||
if (FromDamageShield) {
|
||||
if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide)
|
||||
attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1));
|
||||
attacker->Message_StringID(MT_DS, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1));
|
||||
} else {
|
||||
entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee, HIT_NON_MELEE, attacker->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
||||
entity_list.MessageClose_StringID(
|
||||
this, /* Sender */
|
||||
true, /* Skip Sender */
|
||||
RuleI(Range, SpellMessages),
|
||||
MT_NonMelee, /* 283 */
|
||||
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
|
||||
attacker->GetCleanName(), /* Message1 */
|
||||
GetCleanName(), /* Message2 */
|
||||
ConvertArray(damage, val1) /* Message3 */
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if(damage > 0) {
|
||||
@ -3505,7 +3539,17 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
// If this is Damage Shield damage, the correct OP_Damage packets will be sent from Mob::DamageShield, so
|
||||
// we don't send them here.
|
||||
if(!FromDamageShield) {
|
||||
entity_list.QueueCloseClients(this, outapp, true, 200, skip, true, filter);
|
||||
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* packet */
|
||||
true, /* Skip Sender */
|
||||
RuleI(Range, SpellMessages),
|
||||
skip, /* Skip this mob */
|
||||
true, /* Packet ACK */
|
||||
filter /* eqFilterType filter */
|
||||
);
|
||||
|
||||
//send the damage to ourself if we are a client
|
||||
if(IsClient()) {
|
||||
//I dont think any filters apply to damage affecting us
|
||||
@ -3521,10 +3565,20 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
//might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it
|
||||
attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT,
|
||||
YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name);
|
||||
// older clients don't have the below String ID, but it will be filtered
|
||||
entity_list.FilteredMessageClose_StringID(attacker, true, 200,
|
||||
MT_DoTDamage, FilterDOT, OTHER_HIT_DOT, GetCleanName(),
|
||||
itoa(damage), attacker->GetCleanName(), spells[spell_id].name);
|
||||
|
||||
/* older clients don't have the below String ID, but it will be filtered */
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
attacker, /* Sender */
|
||||
true, /* Skip Sender */
|
||||
RuleI(Range, SpellMessages),
|
||||
MT_DoTDamage, /* Type: 325 */
|
||||
FilterDOT, /* FilterType: 19 */
|
||||
OTHER_HIT_DOT, /* MessageFormat: %1 has taken %2 damage from %3 by %4. */
|
||||
GetCleanName(), /* Message1 */
|
||||
itoa(damage), /* Message2 */
|
||||
attacker->GetCleanName(), /* Message3 */
|
||||
spells[spell_id].name /* Message4 */
|
||||
);
|
||||
}
|
||||
} //end packet sending
|
||||
|
||||
@ -3853,7 +3907,7 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w
|
||||
begincast->spell_id = SpellProcs[i].spellID;
|
||||
begincast->cast_time = 0;
|
||||
outapp->priority = 3;
|
||||
entity_list.QueueCloseClients(this, outapp, false, 200, 0, true);
|
||||
entity_list.QueueCloseClients(this, outapp, false, RuleI(Range, SpellMessages), 0, true);
|
||||
safe_delete(outapp);
|
||||
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on, SpellProcs[i].level_override);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
|
||||
@ -3932,8 +3986,18 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit)
|
||||
critMod += GetCritDmgMob(hit.skill);
|
||||
hit.damage_done += 5;
|
||||
hit.damage_done = (hit.damage_done * critMod) / 100;
|
||||
entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, FilterMeleeCrits,
|
||||
CRITICAL_HIT, GetCleanName(), itoa(hit.damage_done + hit.min_damage));
|
||||
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, CriticalDamage),
|
||||
MT_CritMelee, /* Type: 301 */
|
||||
FilterMeleeCrits, /* FilterType: 12 */
|
||||
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
|
||||
GetCleanName(), /* Message1 */
|
||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3971,14 +4035,33 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
{aabonuses.SlayUndead[1], itembonuses.SlayUndead[1], spellbonuses.SlayUndead[1]});
|
||||
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
||||
hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100;
|
||||
if (GetGender() == 1) // female
|
||||
|
||||
/* Female */
|
||||
if (GetGender() == 1) {
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, false, 200, MT_CritMelee, FilterMeleeCrits, FEMALE_SLAYUNDEAD,
|
||||
GetCleanName(), itoa(hit.damage_done + hit.min_damage));
|
||||
else // males and neuter I guess
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, CriticalDamage),
|
||||
MT_CritMelee, /* Type: 301 */
|
||||
FilterMeleeCrits, /* FilterType: 12 */
|
||||
FEMALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses her target!(%2) */
|
||||
GetCleanName(), /* Message1 */
|
||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
||||
);
|
||||
}
|
||||
/* Males and Neuter */
|
||||
else {
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, false, 200, MT_CritMelee, FilterMeleeCrits, MALE_SLAYUNDEAD,
|
||||
GetCleanName(), itoa(hit.damage_done + hit.min_damage));
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, CriticalDamage),
|
||||
MT_CritMelee, /* Type: 301 */
|
||||
FilterMeleeCrits, /* FilterType: 12 */
|
||||
MALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses his target!(%2) */
|
||||
GetCleanName(), /* Message1 */
|
||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -4047,9 +4130,17 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
return;
|
||||
}
|
||||
hit.damage_done = hit.damage_done * 200 / 100;
|
||||
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, false, 200, MT_CritMelee, FilterMeleeCrits, DEADLY_STRIKE,
|
||||
GetCleanName(), itoa(hit.damage_done + hit.min_damage));
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, CriticalDamage),
|
||||
MT_CritMelee, /* Type: 301 */
|
||||
FilterMeleeCrits, /* FilterType: 12 */
|
||||
DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */
|
||||
GetCleanName(), /* Message1 */
|
||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -4067,9 +4158,18 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
if (IsBerserk() || berserk) {
|
||||
hit.damage_done += og_damage * 119 / 100;
|
||||
Log.Out(Logs::Detail, Logs::Combat, "Crip damage %d", hit.damage_done);
|
||||
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, false, 200, MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, GetCleanName(),
|
||||
itoa(hit.damage_done + hit.min_damage));
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, CriticalDamage),
|
||||
MT_CritMelee, /* Type: 301 */
|
||||
FilterMeleeCrits, /* FilterType: 12 */
|
||||
CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */
|
||||
GetCleanName(), /* Message1 */
|
||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
||||
);
|
||||
|
||||
// Crippling blows also have a chance to stun
|
||||
// Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a
|
||||
// staggers message.
|
||||
@ -4079,10 +4179,18 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
}
|
||||
return;
|
||||
}
|
||||
// okay, critted but didn't do anything else, just normal message now
|
||||
entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, FilterMeleeCrits,
|
||||
CRITICAL_HIT, GetCleanName(),
|
||||
itoa(hit.damage_done + hit.min_damage));
|
||||
|
||||
/* Normal Critical hit message */
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, CriticalDamage),
|
||||
MT_CritMelee, /* Type: 301 */
|
||||
FilterMeleeCrits, /* FilterType: 12 */
|
||||
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
|
||||
GetCleanName(), /* Message1 */
|
||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4108,7 +4216,18 @@ bool Mob::TryFinishingBlow(Mob *defender, int &damage)
|
||||
|
||||
if (FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) &&
|
||||
(ProcChance >= zone->random.Int(1, 1000))) {
|
||||
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
|
||||
|
||||
/* Finishing Blow Critical Message */
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, /* Sender */
|
||||
false, /* Skip Sender */
|
||||
RuleI(Range, CriticalDamage),
|
||||
MT_CritMelee, /* Type: 301 */
|
||||
FilterMeleeCrits, /* FilterType: 12 */
|
||||
FINISHING_BLOW, /* MessageFormat: %1 scores a Finishing Blow!!) */
|
||||
GetCleanName() /* Message1 */
|
||||
);
|
||||
|
||||
damage = FB_Dmg;
|
||||
return true;
|
||||
}
|
||||
|
||||
74
zone/bot.cpp
74
zone/bot.cpp
@ -1724,7 +1724,7 @@ bool Bot::LoadPet()
|
||||
|
||||
bool Bot::SavePet()
|
||||
{
|
||||
if (!GetPet() || GetPet()->IsFamiliar() /*|| dead*/)
|
||||
if (!GetPet() || GetPet()->IsFamiliar()) // dead?
|
||||
return true;
|
||||
|
||||
NPC *pet_inst = GetPet()->CastToNPC();
|
||||
@ -3505,8 +3505,8 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
|
||||
continue;
|
||||
|
||||
auto trade_instance = trade_iterator.tradeItemInstance;
|
||||
/*if ((stage_loop == stageStackable) && !trade_instance->IsStackable())
|
||||
continue;*/
|
||||
//if ((stage_loop == stageStackable) && !trade_instance->IsStackable())
|
||||
// continue;
|
||||
|
||||
for (auto index : bot_equip_order) {
|
||||
if (!(trade_instance->GetItem()->Slots & (1 << index)))
|
||||
@ -3849,7 +3849,8 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillT
|
||||
}
|
||||
}
|
||||
|
||||
void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/) {
|
||||
//void Bot::AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false)
|
||||
void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) {
|
||||
Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic);
|
||||
}
|
||||
|
||||
@ -4261,24 +4262,23 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16
|
||||
value = base1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case SE_SympatheticProc:
|
||||
{
|
||||
if(type == focusSympatheticProc)
|
||||
{
|
||||
float ProcChance, ProcBonus;
|
||||
int16 ProcRateMod = base1; //Baseline is 100 for most Sympathetic foci
|
||||
int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time);
|
||||
GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod);
|
||||
//case SE_SympatheticProc:
|
||||
//{
|
||||
// if(type == focusSympatheticProc)
|
||||
// {
|
||||
// float ProcChance, ProcBonus;
|
||||
// int16 ProcRateMod = base1; //Baseline is 100 for most Sympathetic foci
|
||||
// int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time);
|
||||
// GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod);
|
||||
|
||||
if(zone->random.Real(0, 1) <= ProcChance)
|
||||
value = focus_id;
|
||||
// if(zone->random.Real(0, 1) <= ProcChance)
|
||||
// value = focus_id;
|
||||
|
||||
else
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
}*/
|
||||
// else
|
||||
// value = 0;
|
||||
// }
|
||||
// break;
|
||||
//}
|
||||
case SE_FcDamageAmt: {
|
||||
if(type == focusFcDamageAmt)
|
||||
value = base1;
|
||||
@ -5069,14 +5069,14 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32
|
||||
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||
|
||||
//[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill
|
||||
/* if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){
|
||||
int kb_chance = 25;
|
||||
kb_chance += (kb_chance * (100 - aabonuses.SpecialAttackKBProc[0]) / 100);
|
||||
//if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){
|
||||
// int kb_chance = 25;
|
||||
// kb_chance += (kb_chance * (100 - aabonuses.SpecialAttackKBProc[0]) / 100);
|
||||
|
||||
if (zone->random.Int(0, 99) < kb_chance)
|
||||
SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff);
|
||||
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
|
||||
}*/
|
||||
// if (zone->random.Int(0, 99) < kb_chance)
|
||||
// SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff);
|
||||
// //who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
|
||||
//}
|
||||
|
||||
if (HasSkillProcs())
|
||||
TrySkillProc(who, skill, (ReuseTime * 1000));
|
||||
@ -7648,7 +7648,7 @@ void Bot::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, b
|
||||
|
||||
switch(item->BardType)
|
||||
{
|
||||
case 51: /* All (e.g. Singing Short Sword) */
|
||||
case EQEmu::item::ItemTypeAllInstrumentTypes: // (e.g. Singing Short Sword)
|
||||
{
|
||||
if(item->BardValue > newbon->singingMod)
|
||||
newbon->singingMod = item->BardValue;
|
||||
@ -7662,31 +7662,31 @@ void Bot::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, b
|
||||
newbon->windMod = item->BardValue;
|
||||
break;
|
||||
}
|
||||
case 50: /* Singing */
|
||||
case EQEmu::item::ItemTypeSinging:
|
||||
{
|
||||
if(item->BardValue > newbon->singingMod)
|
||||
newbon->singingMod = item->BardValue;
|
||||
break;
|
||||
}
|
||||
case 23: /* Wind */
|
||||
case EQEmu::item::ItemTypeWindInstrument:
|
||||
{
|
||||
if(item->BardValue > newbon->windMod)
|
||||
newbon->windMod = item->BardValue;
|
||||
break;
|
||||
}
|
||||
case 24: /* stringed */
|
||||
case EQEmu::item::ItemTypeStringedInstrument:
|
||||
{
|
||||
if(item->BardValue > newbon->stringedMod)
|
||||
newbon->stringedMod = item->BardValue;
|
||||
break;
|
||||
}
|
||||
case 25: /* brass */
|
||||
case EQEmu::item::ItemTypeBrassInstrument:
|
||||
{
|
||||
if(item->BardValue > newbon->brassMod)
|
||||
newbon->brassMod = item->BardValue;
|
||||
break;
|
||||
}
|
||||
case 26: /* Percussion */
|
||||
case EQEmu::item::ItemTypePercussionInstrument:
|
||||
{
|
||||
if(item->BardValue > newbon->percussionMod)
|
||||
newbon->percussionMod = item->BardValue;
|
||||
@ -7768,10 +7768,10 @@ void Bot::CalcBotStats(bool showtext) {
|
||||
GetSkill(EQEmu::skills::SkillBrassInstruments), GetSkill(EQEmu::skills::SkillPercussionInstruments), GetSkill(EQEmu::skills::SkillSinging), GetSkill(EQEmu::skills::SkillStringedInstruments), GetSkill(EQEmu::skills::SkillWindInstruments));
|
||||
}
|
||||
|
||||
/*if(this->Save())
|
||||
this->GetBotOwner()->CastToClient()->Message(0, "%s saved.", this->GetCleanName());
|
||||
else
|
||||
this->GetBotOwner()->CastToClient()->Message(13, "%s save failed!", this->GetCleanName());*/
|
||||
//if(this->Save())
|
||||
// this->GetBotOwner()->CastToClient()->Message(0, "%s saved.", this->GetCleanName());
|
||||
//else
|
||||
// this->GetBotOwner()->CastToClient()->Message(13, "%s save failed!", this->GetCleanName());
|
||||
|
||||
CalcBonuses();
|
||||
|
||||
|
||||
@ -1099,7 +1099,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
CheckLDoNHail(GetTarget());
|
||||
CheckEmoteHail(GetTarget(), message);
|
||||
|
||||
if(DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= 200) {
|
||||
if(DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) {
|
||||
NPC *tar = GetTarget()->CastToNPC();
|
||||
parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language);
|
||||
|
||||
@ -1111,7 +1111,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= 200) {
|
||||
if (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) {
|
||||
parse->EventNPC(EVENT_AGGRO_SAY, GetTarget()->CastToNPC(), this, message, language);
|
||||
}
|
||||
}
|
||||
@ -1140,7 +1140,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
char *Buffer = (char *)es;
|
||||
Buffer += 4;
|
||||
snprintf(Buffer, sizeof(Emote_Struct) - 4, "%s %s", GetName(), message);
|
||||
entity_list.QueueCloseClients(this, outapp, true, 100, 0, true, FilterSocials);
|
||||
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, Emote), 0, true, FilterSocials);
|
||||
safe_delete(outapp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4372,7 +4372,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
|
||||
new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct* ppus = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
|
||||
boat->MakeSpawnUpdate(ppus);
|
||||
entity_list.QueueCloseClients(boat,outapp,true,300,this,false);
|
||||
entity_list.QueueCloseClients(boat, outapp, true, 300, this, false);
|
||||
safe_delete(outapp);
|
||||
// update the boat's position on the server, without sending an update
|
||||
boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ19toFloat(ppu->heading), false);
|
||||
@ -4606,9 +4606,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
|
||||
PlayerPositionUpdateServer_Struct* ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
|
||||
MakeSpawnUpdate(ppu);
|
||||
if (gmhideme)
|
||||
entity_list.QueueClientsStatus(this,outapp,true,Admin(),250);
|
||||
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250);
|
||||
else
|
||||
entity_list.QueueCloseClients(this,outapp,true,300,nullptr,false);
|
||||
entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, false);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -5488,7 +5488,7 @@ void Client::Handle_OP_Emote(const EQApplicationPacket *app)
|
||||
}
|
||||
else
|
||||
*/
|
||||
entity_list.QueueCloseClients(this, outapp, true, 100, 0, true, FilterSocials);
|
||||
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, Emote), 0, true, FilterSocials);
|
||||
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
|
||||
19
zone/mob.cpp
19
zone/mob.cpp
@ -1426,7 +1426,7 @@ void Mob::SendPosUpdate(uint8 iSendToSelf) {
|
||||
}
|
||||
else if(move_tic_count % 2 == 0)
|
||||
{
|
||||
entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), 700, nullptr, false);
|
||||
entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false);
|
||||
move_tic_count++;
|
||||
}
|
||||
else {
|
||||
@ -1529,15 +1529,26 @@ void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter)
|
||||
auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct));
|
||||
Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer;
|
||||
anim->spawnid = GetID();
|
||||
|
||||
if(type == 0){
|
||||
anim->action = animnum;
|
||||
anim->speed = 10;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
anim->action = animnum;
|
||||
anim->speed = type;
|
||||
}
|
||||
entity_list.QueueCloseClients(this, outapp, false, 200, 0, ackreq, filter);
|
||||
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* Packet */
|
||||
false, /* Ignore Sender */
|
||||
RuleI(Range, Anims),
|
||||
0, /* Skip this mob */
|
||||
ackreq, /* Packet ACK */
|
||||
filter /* eqFilterType filter */
|
||||
);
|
||||
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -1581,7 +1592,7 @@ void Mob::ShowBuffList(Client* client) {
|
||||
client->Message(0, "Buffs on: %s", this->GetCleanName());
|
||||
uint32 i;
|
||||
uint32 buff_count = GetMaxTotalSlots();
|
||||
for (i=0; i < buff_count; i++) {
|
||||
for (i = 0; i < buff_count; i++) {
|
||||
if (buffs[i].spellid != SPELL_UNKNOWN) {
|
||||
if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent)
|
||||
client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name);
|
||||
|
||||
@ -1791,8 +1791,8 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
}
|
||||
|
||||
while(AtkRounds > 0) {
|
||||
if (GetTarget())
|
||||
DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, dmg, 0, dmg, ReuseTime);
|
||||
if (ca_target!=this)
|
||||
DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillFrenzy, dmg, 0, dmg, ReuseTime);
|
||||
AtkRounds--;
|
||||
}
|
||||
|
||||
|
||||
@ -363,9 +363,22 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
StopCasting();
|
||||
|
||||
Message_StringID(MT_SpellFailure, fizzle_msg);
|
||||
|
||||
/* Song Failure Messages */
|
||||
entity_list.FilteredMessageClose_StringID(
|
||||
this, true, 200, MT_SpellFailure, IsClient() ? FilterPCSpells : FilterNPCSpells,
|
||||
fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER, GetName());
|
||||
this, /* Sender */
|
||||
true, /* Skip Sender */
|
||||
RuleI(Range, SpellMessages),
|
||||
MT_SpellFailure, /* Type: 289 */
|
||||
(IsClient() ? FilterPCSpells : FilterNPCSpells), /* FilterType: 8 or 9 depending on client/npc */
|
||||
(fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER),
|
||||
/*
|
||||
MessageFormat: You miss a note, bringing your song to a close! (if missed note)
|
||||
MessageFormat: A missed note brings %1's song to a close!
|
||||
MessageFormat: %1's spell fizzles!
|
||||
*/
|
||||
GetName() /* Message1 */
|
||||
);
|
||||
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
return(false);
|
||||
@ -469,7 +482,14 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
begincast->spell_id = spell_id;
|
||||
begincast->cast_time = orgcasttime; // client calculates reduced time by itself
|
||||
outapp->priority = 3;
|
||||
entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS);
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* Packet */
|
||||
false, /* Ignore Sender */
|
||||
RuleI(Range, BeginCast),
|
||||
0, /* Skip this Mob */
|
||||
true /* Packet ACK */
|
||||
); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@ -886,7 +906,7 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid)
|
||||
ic->messageid = message_other;
|
||||
ic->spawnid = GetID();
|
||||
strcpy(ic->message, GetCleanName());
|
||||
entity_list.QueueCloseClients(this, outapp, true, 200, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
safe_delete(outapp);
|
||||
|
||||
}
|
||||
@ -1096,7 +1116,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
|
||||
// if we got here, we regained concentration
|
||||
regain_conc = true;
|
||||
Message_StringID(MT_Spells,REGAIN_AND_CONTINUE);
|
||||
entity_list.MessageClose_StringID(this, true, 200, MT_Spells, OTHER_REGAIN_CAST, this->GetCleanName());
|
||||
entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_Spells, OTHER_REGAIN_CAST, this->GetCleanName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2609,7 +2629,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
||||
action->buff_unknown = 0;
|
||||
action->level = buffs[buffs_i].casterlevel;
|
||||
action->type = DamageTypeSpell;
|
||||
entity_list.QueueCloseClients(this, packet, false, 200, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
entity_list.QueueCloseClients(this, packet, false, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
|
||||
action->buff_unknown = 4;
|
||||
|
||||
@ -2681,7 +2701,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
||||
cd->damage = 0;
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||
{
|
||||
entity_list.QueueCloseClients(this, message_packet, false, 200, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
entity_list.QueueCloseClients(this, message_packet, false, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
}
|
||||
safe_delete(message_packet);
|
||||
safe_delete(packet);
|
||||
@ -3484,8 +3504,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
spelltar->CastToClient()->QueuePacket(action_packet);
|
||||
if(IsClient()) // send to caster
|
||||
CastToClient()->QueuePacket(action_packet);
|
||||
|
||||
// send to people in the area, ignoring caster and target
|
||||
entity_list.QueueCloseClients(spelltar, action_packet, true, 200, this, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
entity_list.QueueCloseClients(
|
||||
spelltar, /* Sender */
|
||||
action_packet, /* Packet */
|
||||
true, /* Ignore Sender */
|
||||
RuleI(Range, SpellMessages),
|
||||
this, /* Skip this Mob */
|
||||
true, /* Packet ACK */
|
||||
(spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) /* EQ Filter Type: (8 or 9) */
|
||||
);
|
||||
|
||||
/* Send the EVENT_CAST_ON event */
|
||||
if(spelltar->IsNPC())
|
||||
@ -3954,9 +3983,16 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
cd->spellid = action->spell;
|
||||
cd->meleepush_xy = action->sequence;
|
||||
cd->damage = 0;
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||
{
|
||||
entity_list.QueueCloseClients(spelltar, message_packet, false, 200, 0, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity)){
|
||||
entity_list.QueueCloseClients(
|
||||
spelltar, /* Sender */
|
||||
message_packet, /* Packet */
|
||||
false, /* Ignore Sender */
|
||||
RuleI(Range, SpellMessages),
|
||||
0, /* Skip this mob */
|
||||
true, /* Packet ACK */
|
||||
(spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */
|
||||
);
|
||||
}
|
||||
safe_delete(action_packet);
|
||||
safe_delete(message_packet);
|
||||
@ -5610,7 +5646,7 @@ void Client::SendSpellAnim(uint16 targetid, uint16 spell_id)
|
||||
a->sequence = 231;
|
||||
|
||||
app.priority = 1;
|
||||
entity_list.QueueCloseClients(this, &app);
|
||||
entity_list.QueueCloseClients(this, &app, false, RuleI(Range, SpellParticles));
|
||||
}
|
||||
|
||||
void Mob::CalcDestFromHeading(float heading, float distance, float MaxZDiff, float StartX, float StartY, float &dX, float &dY, float &dZ)
|
||||
|
||||
@ -720,7 +720,7 @@ void Client::Gate(uint8 bindnum) {
|
||||
}
|
||||
|
||||
void NPC::Gate(uint8 bindnum) {
|
||||
entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName());
|
||||
entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_Spells, GATES, GetCleanName());
|
||||
|
||||
Mob::Gate(bindnum);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user