Merge remote-tracking branch 'remotes/origin/master' into web_interface

Conflicts:
	common/shareddb.cpp
	zone/attack.cpp
This commit is contained in:
akkadius
2014-12-11 22:22:34 -06:00
38 changed files with 560 additions and 487 deletions
+3 -3
View File
@@ -893,7 +893,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
//turn on an AA effect
//duration == 0 means no time limit, used for one-shot deals, etc..
void Client::EnableAAEffect(aaEffectType type, uint32 duration) {
if(type > 32)
if(type > _maxaaEffectType)
return; //for now, special logic needed.
m_epp.aa_effects |= 1 << (type-1);
@@ -905,7 +905,7 @@ void Client::EnableAAEffect(aaEffectType type, uint32 duration) {
}
void Client::DisableAAEffect(aaEffectType type) {
if(type > 32)
if(type > _maxaaEffectType)
return; //for now, special logic needed.
uint32 bit = 1 << (type-1);
if(m_epp.aa_effects & bit) {
@@ -919,7 +919,7 @@ By default an AA effect is a one shot deal, unless
a duration timer is set.
*/
bool Client::CheckAAEffect(aaEffectType type) {
if(type > 32)
if(type > _maxaaEffectType)
return(false); //for now, special logic needed.
if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled?
//has our timer expired?
+2 -1
View File
@@ -51,7 +51,8 @@ typedef enum { //AA Effect IDs
aaEffectFrostArrows,
aaEffectWarcry,
aaEffectLeechTouch,
aaEffectProjectIllusion // unused - Handled via spell effect
aaEffectProjectIllusion, // unused - Handled via spell effect
_maxaaEffectType = 32
} aaEffectType;
+86 -112
View File
@@ -198,7 +198,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
pvpmode = true;
if (chance_mod >= 10000)
return true;
return true;
float avoidanceBonus = 0;
float hitBonus = 0;
@@ -269,21 +269,21 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
}
//Avoidance Bonuses on defender decreases baseline hit chance by percent.
avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect +
defender->itembonuses.AvoidMeleeChanceEffect +
avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect +
defender->itembonuses.AvoidMeleeChanceEffect +
defender->aabonuses.AvoidMeleeChanceEffect +
(defender->itembonuses.AvoidMeleeChance / 10.0f); //Item Mod 'Avoidence'
Mob *owner = nullptr;
if (defender->IsPet())
if (defender->IsPet())
owner = defender->GetOwner();
else if ((defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner()))
owner = entity_list.GetMobID(defender->CastToNPC()->GetSwarmOwner());
if (owner)
avoidanceBonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance;
if(defender->IsNPC())
if(defender->IsNPC())
avoidanceBonus += (defender->CastToNPC()->GetAvoidanceRating() / 10.0f); //Modifier from database
//Hit Chance Bonuses on attacker increases baseline hit chance by percent.
@@ -294,7 +294,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] +
attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1];
//Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect
//Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim)
hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] +
@@ -307,7 +306,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
if(attacker->IsNPC())
hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database
if(skillinuse == SkillArchery)
hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty);
@@ -327,11 +326,10 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
else if(chancetohit < RuleR(Combat,MinChancetoHit)) {
chancetohit = RuleR(Combat,MinChancetoHit);
}
//I dont know the best way to handle a garunteed hit discipline being used
//agains a garunteed riposte (for example) discipline... for now, garunteed hit wins
#if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit);
#endif
@@ -347,7 +345,6 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
return(tohit_roll <= chancetohit);
}
bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
{
/* solar: called when a mob is attacked, does the checks to see if it's a hit
@@ -563,7 +560,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
armor = (armor / RuleR(Combat, NPCACFactor));
Mob *owner = nullptr;
if (IsPet())
if (IsPet())
owner = GetOwner();
else if ((CastToNPC()->GetSwarmOwner()))
owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner());
@@ -1165,7 +1162,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if (GetFeigned())
return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code.
ItemInst* weapon;
if (Hand == MainSecondary){ // Kaiyodo - Pick weapon from the attacking hand
weapon = GetInv().GetItem(MainSecondary);
@@ -1226,7 +1222,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
CheckIncreaseSkill(skillinuse, other, -15);
CheckIncreaseSkill(SkillOffense, other, -15);
// ***************************************************************
// *** Calculate the damage bonus, if applicable, for this hit ***
// ***************************************************************
@@ -1420,7 +1415,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
if(dead)
return false; //cant die more than once...
if(!spell)
if(!spell)
spell = SPELL_UNKNOWN;
char buffer[48] = { 0 };
@@ -1445,7 +1440,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
#1: Send death packet to everyone
*/
uint8 killed_level = GetLevel();
SendLogoutPackets();
/* Make self become corpse packet */
@@ -1523,7 +1518,6 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
hate_list.RemoveEnt(this);
RemoveAutoXTargets();
//remove ourself from all proximities
ClearAllProximities();
@@ -1599,7 +1593,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
else
UnmemSpellAll(false);
if(RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel) || RuleB(Character, LeaveNakedCorpses))
if((RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) || RuleB(Character, LeaveNakedCorpses))
{
// creating the corpse takes the cash/items off the player too
Corpse *new_corpse = new Corpse(this, exploss);
@@ -1658,8 +1652,8 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
{
ClearDraggedCorpses();
RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000);
ClearDraggedCorpses();
RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000);
SendRespawnBinds();
}
else
@@ -1676,19 +1670,19 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
if(r)
r->MemberZoned(this);
dead_timer.Start(5000, true);
dead_timer.Start(5000, true);
m_pp.zone_id = m_pp.binds[0].zoneId;
m_pp.zoneInstance = m_pp.binds[0].instance_id;
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
Save();
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
Save();
GoToDeath();
}
/* QS: PlayerLogDeaths */
if (RuleB(QueryServ, PlayerLogDeaths)){
const char * killer_name = "";
if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); }
std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", this->GetZoneID(), this->GetInstanceID(), killer_name, spell, damage);
if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); }
std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", this->GetZoneID(), this->GetInstanceID(), killer_name, spell, damage);
QServ->PlayerLogEvent(Player_Log_Deaths, this->CharacterID(), event_desc);
}
@@ -1837,7 +1831,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
else
damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane));
//check if we're hitting above our max or below it.
if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) {
mlog(COMBAT__DAMAGE, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane));
@@ -1847,7 +1840,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
mlog(COMBAT__DAMAGE, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane));
damage = (max_dmg+eleBane);
}
damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other);
int32 hate = damage;
@@ -1926,7 +1919,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
return false;
MeleeLifeTap(damage);
CommonBreakInvisible();
//I doubt this works...
@@ -1935,15 +1928,15 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if(!bRiposte && !other->HasDied()) {
TryWeaponProc(nullptr, weapon, other, Hand); //no weapon
if (!other->HasDied())
TrySpellProc(nullptr, weapon, other, Hand);
if (damage > 0 && HasSkillProcSuccess() && !other->HasDied())
TrySkillProc(other, skillinuse, 0, true, Hand);
}
if(GetHP() > 0 && !other->HasDied())
if(GetHP() > 0 && !other->HasDied())
TriggerDefensiveProcs(nullptr, other, Hand, damage);
// now check ripostes
@@ -2003,8 +1996,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack
bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) {
mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill);
bool MadeCorpse = false;
uint16 OrigEntID = this->GetID();
Mob *oos = nullptr;
if(killerMob) {
oos = killerMob->GetOwnerOrSelf();
@@ -2059,7 +2051,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if(p_depop == true)
return false;
HasAISpellEffects = false;
BuffFadeAll();
uint8 killed_level = GetLevel();
@@ -2120,8 +2112,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
Group *kg = entity_list.GetGroupByClient(give_exp_client);
Raid *kr = entity_list.GetRaidByClient(give_exp_client);
int32 finalxp = EXP_FORMULA;
finalxp = give_exp_client->mod_client_xp(finalxp, this);
int32 finalxp = EXP_FORMULA;
finalxp = give_exp_client->mod_client_xp(finalxp, this);
if(kr)
{
@@ -2232,7 +2224,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0);
if(RuleB(NPC, EnableMeritBasedFaction))
give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(),
give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(),
give_exp_client->GetBaseRace(), give_exp_client->GetDeity());
mod_npc_killed_merit(give_exp_client);
@@ -2405,9 +2397,9 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
}
void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) {
assert(other != nullptr);
if (other == this)
return;
@@ -2424,12 +2416,12 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if(other){
AddRampage(other);
int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod;
int32 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod;
if (shieldhatemod && other->HasShieldEquiped())
hatemod += shieldhatemod;
if(hatemod < 1)
hatemod = 1;
hate = ((hate * (hatemod))/100);
@@ -2446,7 +2438,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0))
TryTriggerOnValueAmount(false, false, false, true);
if(IsClient() && !IsAIControlled())
return;
@@ -2488,9 +2480,9 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if(damage > GetHP())
damage = GetHP();
if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0])
if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0])
&& other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID()))
hate = (hate*spellbonuses.ImprovedTaunt[1])/100;
hate = (hate*spellbonuses.ImprovedTaunt[1])/100;
hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic);
@@ -2510,7 +2502,6 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
}
#endif //BOTS
// if other is a merc, add the merc client to the hate list
if(other->IsMerc()) {
if(other->CastToMerc()->GetMercOwner() && other->CastToMerc()->GetMercOwner()->CastToClient()->GetFeigned()) {
@@ -2649,7 +2640,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
// This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon".
// Modified 9/21/2008 by Cantus
// Assert: This function should only be called for hits by the mainhand, as damage bonuses apply only to the
// weapon in the primary slot. Be sure to check that Hand == MainPrimary before calling.
@@ -2661,7 +2651,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
// Assert: This function should not be called unless the player is a melee class, as casters do not receive a damage bonus.
if( Weapon == nullptr || Weapon->ItemType == ItemType1HSlash || Weapon->ItemType == ItemType1HBlunt || Weapon->ItemType == ItemTypeMartial || Weapon->ItemType == ItemType1HPiercing )
{
// The weapon in the player's main (primary) hand is a one-handed weapon, or there is no item equipped at all.
@@ -2689,7 +2678,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
// as I suspect, then please feel free to delete the following line, and replace all occurences of "ucPlayerLevel" with "GetLevel()".
uint8 ucPlayerLevel = (uint8) GetLevel();
// The following may look cleaner, and would certainly be easier to understand, if it was
// a simple 53x150 cell matrix.
//
@@ -2707,7 +2695,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
// lookup table. In cases where a formula is the best bet, I use a formula. In other places
// where a formula would be ugly, I use a lookup table in the interests of speed.
if( Weapon->Delay <= 27 )
{
// Damage Bonuses for all 2H weapons with delays of 27 or less are identical.
@@ -2719,7 +2706,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
return (ucPlayerLevel - 22) / 3;
}
if( ucPlayerLevel == 65 && Weapon->Delay <= 59 )
{
// Consider these two facts:
@@ -2738,7 +2724,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
return ucLevel65DamageBonusesForDelays28to59[Weapon->Delay-28];
}
if( ucPlayerLevel > 65 )
{
if( ucPlayerLevel > 80 )
@@ -2877,7 +2862,6 @@ uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon )
}
}
// If we've gotten to this point in the function without hitting a return statement,
// we know that the character's level is between 28 and 65, and that the 2H weapon's
// delay is 28 or higher.
@@ -3123,7 +3107,6 @@ int Mob::GetMonkHandToHandDelay(void)
}
}
int32 Mob::ReduceDamage(int32 damage)
{
if(damage <= 0)
@@ -3136,7 +3119,7 @@ int32 Mob::ReduceDamage(int32 damage)
slot = spellbonuses.NegateAttacks[1];
if(slot >= 0) {
if(--buffs[slot].numhits == 0) {
if(!TryFadeEffect(slot))
BuffFadeBySlot(slot , true);
}
@@ -3151,8 +3134,8 @@ int32 Mob::ReduceDamage(int32 damage)
//Only mitigate if damage is above the minimium specified.
if (spellbonuses.MeleeThresholdGuard[0]){
slot = spellbonuses.MeleeThresholdGuard[1];
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
{
DisableMeleeRune = true;
int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100;
@@ -3174,7 +3157,6 @@ int32 Mob::ReduceDamage(int32 damage)
}
}
if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune){
slot = spellbonuses.MitigateMeleeRune[1];
if(slot >= 0)
@@ -3183,7 +3165,7 @@ int32 Mob::ReduceDamage(int32 damage)
if (spellbonuses.MitigateMeleeRune[2] && (damage_to_reduce > spellbonuses.MitigateMeleeRune[2]))
damage_to_reduce = spellbonuses.MitigateMeleeRune[2];
if(spellbonuses.MitigateMeleeRune[3] && (damage_to_reduce >= buffs[slot].melee_rune))
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
@@ -3196,10 +3178,10 @@ int32 Mob::ReduceDamage(int32 damage)
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].melee_rune);
if (spellbonuses.MitigateMeleeRune[3])
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
@@ -3230,7 +3212,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
slot = spellbonuses.NegateAttacks[1];
if(slot >= 0) {
if(--buffs[slot].numhits == 0) {
if(!TryFadeEffect(slot))
BuffFadeBySlot(slot , true);
}
@@ -3244,8 +3226,8 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
// If this is a DoT, use DoT Shielding...
if(iBuffTic) {
damage -= (damage * itembonuses.DoTShielding / 100);
damage -= (damage * itembonuses.DoTShielding / 100);
if (spellbonuses.MitigateDotRune[0]){
slot = spellbonuses.MitigateDotRune[1];
if(slot >= 0)
@@ -3265,7 +3247,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
{
if (spellbonuses.MitigateDotRune[3])
buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
@@ -3278,12 +3260,11 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
// Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
damage -= (damage * itembonuses.SpellShield / 100);
//Only mitigate if damage is above the minimium specified.
if (spellbonuses.SpellThresholdGuard[0]){
slot = spellbonuses.SpellThresholdGuard[1];
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
{
DisableSpellRune = true;
int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100;
@@ -3300,8 +3281,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
}
}
}
// Do runes now.
if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune){
slot = spellbonuses.MitigateSpellRune[1];
@@ -3324,10 +3304,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
if (spellbonuses.MitigateSpellRune[3])
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
@@ -3335,14 +3315,14 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
if(damage < 1)
return 0;
//Regular runes absorb spell damage (except dots) - Confirmed on live.
if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0)
damage = RuneAbsorb(damage, SE_Rune);
damage = RuneAbsorb(damage, SE_Rune);
if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0)
damage = RuneAbsorb(damage, SE_AbsorbMagicAtt);
if(damage < 1)
return 0;
}
@@ -3362,7 +3342,7 @@ int32 Mob::ReduceAllDamage(int32 damage)
TryTriggerOnValueAmount(false, true);
}
}
CheckNumHitsRemaining(NUMHIT_IncomingDamage);
return(damage);
@@ -3569,7 +3549,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
attacker->CastToClient()->sneaking = false;
attacker->SendAppearancePacket(AT_Sneak, 0);
}
//final damage has been determined.
SetHP(GetHP() - damage);
@@ -3601,7 +3581,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
entity_list.MessageClose_StringID(this, true, 100, MT_WornOff,
HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName());
BuffFadeByEffect(SE_Mez);
}
}
//check stun chances if bashing
if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) {
@@ -3734,18 +3714,15 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
//if the attacker is a client, try them with the correct filter
if(attacker && attacker->IsClient()) {
if (((spell_id != SPELL_UNKNOWN)||(FromDamageShield)) && damage>0) {
if ((spell_id != SPELL_UNKNOWN || FromDamageShield) && damage > 0) {
//special crap for spell damage, looks hackish to me
char val1[20]={0};
if (FromDamageShield)
{
if(!attacker->CastToClient()->GetFilter(FilterDamageShields) == FilterHide)
{
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));
char val1[20] = {0};
if (FromDamageShield) {
if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide)
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));
}
} else {
if(damage > 0) {
if(spell_id != SPELL_UNKNOWN)
@@ -3803,7 +3780,6 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
}
void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
{
int32 maxhp = GetMaxHP();
@@ -3892,7 +3868,7 @@ float Mob::GetProcChances(float ProcBonus, uint16 hand)
}
float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand, Mob* on) {
if (!on)
return ProcChance;
@@ -3948,7 +3924,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!");
return;
}
if (!IsAttackAllowed(on)) {
mlog(COMBAT__PROCS, "Preventing procing off of unattackable things.");
return;
@@ -3975,7 +3951,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand)
{
if (!weapon)
return;
uint16 skillinuse = 28;
@@ -4136,7 +4112,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
uint16 skillinuse = 28;
if (weapon)
skillinuse = GetSkillByItemType(weapon->ItemType);
TrySkillProc(on, skillinuse, 0, false, hand);
}
@@ -4203,7 +4179,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
// decided to branch this into it's own function since it's going to be duplicating a lot of the
// code in here, but could lead to some confusion otherwise
if (IsPet() && GetOwner()->IsClient() || (IsNPC() && CastToNPC()->GetSwarmOwner())) {
if ((IsPet() && GetOwner()->IsClient()) || (IsNPC() && CastToNPC()->GetSwarmOwner())) {
TryPetCriticalHit(defender,skill,damage);
return;
}
@@ -4247,7 +4223,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
//are defined you will have an innate chance to hit at Level 1 regardless of bonuses.
//Warning: Do not define these rules if you want live like critical hits.
critChance += RuleI(Combat, MeleeBaseCritChance);
if (IsClient()) {
critChance += RuleI(Combat, ClientBaseCritChance);
@@ -4348,7 +4324,6 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
}
}
bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
{
if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){
@@ -4497,8 +4472,8 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill])
return;
/*Allow one proc from each (Spell/Item/AA)
Kayen: Due to limited avialability of effects on live it is too difficult
/*Allow one proc from each (Spell/Item/AA)
Kayen: Due to limited avialability of effects on live it is too difficult
to confirm how they stack at this time, will adjust formula when more data is avialablle to test.*/
bool CanProc = true;
@@ -4516,9 +4491,9 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e]))
|| (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e]))) {
((!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e]))
|| (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e])))) {
if (Success)
base_spell_id = spellbonuses.SkillProcSuccess[e];
else
@@ -4560,8 +4535,8 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
CanProc = true;
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e]))
|| (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e]))) {
((!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e]))
|| (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e])))) {
if (Success)
base_spell_id = itembonuses.SkillProcSuccess[e];
@@ -4602,15 +4577,15 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
CanProc = true;
uint32 effect = 0;
int32 base1 = 0;
int32 base2 = 0;
int32 base2 = 0;
uint32 slot = 0;
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && aabonuses.SkillProc[e])
|| (Success && aabonuses.SkillProcSuccess[e])){
((!Success && aabonuses.SkillProc[e])
|| (Success && aabonuses.SkillProcSuccess[e]))) {
int aaid = 0;
if (Success)
base_spell_id = aabonuses.SkillProcSuccess[e];
else
@@ -4683,7 +4658,7 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
General Mechanics
- Check buffslot to make sure damage from a root does not cancel the root
- If multiple roots on target, always and only checks first root slot and if broken only removes that slots root.
- If multiple roots on target, always and only checks first root slot and if broken only removes that slots root.
- Only roots on determental spells can be broken by damage.
- Root break chance values obtained from live parses.
*/
@@ -4744,7 +4719,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
{
if(melee_rune_left > 0)
damage -= melee_rune_left;
if(!TryFadeEffect(slot))
BuffFadeBySlot(slot);
}
@@ -4752,7 +4727,6 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
}
}
else{
for(uint32 slot = 0; slot < buff_max; slot++) {
if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){
@@ -4768,7 +4742,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
{
if(magic_rune_left > 0)
damage -= magic_rune_left;
if(!TryFadeEffect(slot))
BuffFadeBySlot(slot);
}
@@ -4781,7 +4755,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse)
{
if (!defender)
if (!defender)
return;
ApplyMeleeDamageBonus(skillInUse, damage);
+29 -92
View File
@@ -4361,7 +4361,8 @@ void Bot::SetLevel(uint8 in_level, bool command) {
}
void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
if(ns) {
if(ns)
{
Mob::FillSpawnStruct(ns, ForWho);
ns->spawn.afk = 0;
@@ -4389,98 +4390,34 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
uint32 spawnedbotid = 0;
spawnedbotid = this->GetBotID();
inst = GetBotItem(MainHands);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialHands] = item->Material;
ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands);
}
}
for (int i = 0; i < _MaterialCount; i++)
{
inst = GetBotItem(i);
if (inst)
{
item = inst->GetItem();
if (item != 0)
{
ns->spawn.equipment[i].material = item->Material;
ns->spawn.equipment[i].elitematerial = item->EliteMaterial;
ns->spawn.equipment[i].heroforgemodel = item->HerosForgeModel;
if (armor_tint[i])
{
ns->spawn.colors[i].color = armor_tint[i];
inst = GetBotItem(MainHead);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialHead] = item->Material;
ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead);
}
}
inst = GetBotItem(MainArms);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialArms] = item->Material;
ns->spawn.colors[MaterialArms].color = GetEquipmentColor(MaterialArms);
}
}
inst = GetBotItem(MainWrist1);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialWrist] = item->Material;
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist);
}
}
/*
// non-live behavior
inst = GetBotItem(MainWrist2);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialWrist] = item->Material;
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist);
}
}
*/
inst = GetBotItem(MainChest);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialChest] = item->Material;
ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest);
}
}
inst = GetBotItem(MainLegs);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialLegs] = item->Material;
ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs);
}
}
inst = GetBotItem(MainFeet);
if(inst) {
item = inst->GetItem();
if(item) {
ns->spawn.equipment[MaterialFeet] = item->Material;
ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet);
}
}
inst = GetBotItem(MainPrimary);
if(inst) {
item = inst->GetItem();
if(item) {
if(strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
ns->spawn.colors[MaterialPrimary].color = GetEquipmentColor(MaterialPrimary);
}
}
inst = GetBotItem(MainSecondary);
if(inst) {
item = inst->GetItem();
if(item) {
if(strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
ns->spawn.colors[MaterialSecondary].color = GetEquipmentColor(MaterialSecondary);
}
else
{
ns->spawn.colors[i].color = item->Color;
}
}
else
{
if (armor_tint[i])
{
ns->spawn.colors[i].color = armor_tint[i];
}
}
}
}
}
+89 -56
View File
@@ -1823,80 +1823,113 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
// (update: i think pp should do it, as this holds LoY dye - plus, this is ugly code with Inventory!)
const Item_Struct* item = nullptr;
const ItemInst* inst = nullptr;
if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialHands] = item->Material;
ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands);
}
if ((inst = m_inv[MainHead]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialHead] = item->Material;
ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead);
}
if ((inst = m_inv[MainArms]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialArms] = item->Material;
ns->spawn.colors[MaterialArms].color = GetEquipmentColor(MaterialArms);
}
if ((inst = m_inv[MainWrist1]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialWrist]= item->Material;
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist);
}
/*
// non-live behavior
if ((inst = m_inv[SLOT_BRACER02]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialWrist]= item->Material;
ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist);
}
*/
// Only Player Races Wear Armor
if (IsPlayerRace(race))
{
if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
ns->spawn.equipment[MaterialHands].material = item->Material;
ns->spawn.equipment[MaterialHands].elitematerial = item->EliteMaterial;
ns->spawn.equipment[MaterialHands].heroforgemodel = item->HerosForgeModel;
ns->spawn.colors[MaterialHands].color = m_pp.item_tint[MaterialHands].rgb.use_tint ? m_pp.item_tint[MaterialHands].color : item->Color;
}
if ((inst = m_inv[MainHead]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
ns->spawn.equipment[MaterialHead].material = item->Material;
ns->spawn.equipment[MaterialHead].elitematerial = item->EliteMaterial;
ns->spawn.equipment[MaterialHead].heroforgemodel = item->HerosForgeModel;
ns->spawn.colors[MaterialHead].color = m_pp.item_tint[MaterialHead].rgb.use_tint ? m_pp.item_tint[MaterialHead].color : item->Color;
}
if ((inst = m_inv[MainArms]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
ns->spawn.equipment[MaterialArms].material = item->Material;
ns->spawn.equipment[MaterialArms].elitematerial = item->EliteMaterial;
ns->spawn.equipment[MaterialArms].heroforgemodel = item->HerosForgeModel;
ns->spawn.colors[MaterialArms].color = m_pp.item_tint[MaterialArms].rgb.use_tint ? m_pp.item_tint[MaterialArms].color : item->Color;
}
if ((inst = m_inv[MainWrist1]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
ns->spawn.equipment[MaterialWrist].material = item->Material;
ns->spawn.equipment[MaterialWrist].elitematerial = item->EliteMaterial;
ns->spawn.equipment[MaterialWrist].heroforgemodel = item->HerosForgeModel;
ns->spawn.colors[MaterialWrist].color = m_pp.item_tint[MaterialWrist].rgb.use_tint ? m_pp.item_tint[MaterialWrist].color : item->Color;
}
if ((inst = m_inv[MainChest]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialChest] = item->Material;
ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest);
}
if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialLegs] = item->Material;
ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs);
}
if ((inst = m_inv[MainFeet]) && inst->IsType(ItemClassCommon)) {
item = inst->GetItem();
ns->spawn.equipment[MaterialFeet] = item->Material;
ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet);
if ((inst = m_inv[MainChest]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
ns->spawn.equipment[MaterialChest].material = item->Material;
ns->spawn.equipment[MaterialChest].elitematerial = item->EliteMaterial;
ns->spawn.equipment[MaterialChest].heroforgemodel = item->HerosForgeModel;
ns->spawn.colors[MaterialChest].color = m_pp.item_tint[MaterialChest].rgb.use_tint ? m_pp.item_tint[MaterialChest].color : item->Color;
}
if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
ns->spawn.equipment[MaterialLegs].material = item->Material;
ns->spawn.equipment[MaterialLegs].elitematerial = item->EliteMaterial;
ns->spawn.equipment[MaterialLegs].heroforgemodel = item->HerosForgeModel;
ns->spawn.colors[MaterialLegs].color = m_pp.item_tint[MaterialLegs].rgb.use_tint ? m_pp.item_tint[MaterialLegs].color : item->Color;
}
if ((inst = m_inv[MainFeet]) && inst->IsType(ItemClassCommon))
{
item = inst->GetItem();
ns->spawn.equipment[MaterialFeet].material = item->Material;
ns->spawn.equipment[MaterialFeet].elitematerial = item->EliteMaterial;
ns->spawn.equipment[MaterialFeet].heroforgemodel = item->HerosForgeModel;
ns->spawn.colors[MaterialFeet].color = m_pp.item_tint[MaterialFeet].rgb.use_tint ? m_pp.item_tint[MaterialFeet].color : item->Color;
}
}
int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon)) {
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon))
{
if (inst->GetOrnamentationAug(ornamentationAugtype))
{
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
{
ns->spawn.equipment[MaterialPrimary].material = atoi(&item->IDFile[2]);
}
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
ns->spawn.equipment[MaterialPrimary] = inst->GetOrnamentationIDFile();
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile())
{
ns->spawn.equipment[MaterialPrimary].material = inst->GetOrnamentationIDFile();
}
else {
else
{
item = inst->GetItem();
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
{
ns->spawn.equipment[MaterialPrimary].material = atoi(&item->IDFile[2]);
}
}
}
if ((inst = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon)) {
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
if ((inst = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon))
{
if (inst->GetOrnamentationAug(ornamentationAugtype))
{
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
{
ns->spawn.equipment[MaterialSecondary].material = atoi(&item->IDFile[2]);
}
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
ns->spawn.equipment[MaterialSecondary] = inst->GetOrnamentationIDFile();
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile())
{
ns->spawn.equipment[MaterialSecondary].material = inst->GetOrnamentationIDFile();
}
else {
else
{
item = inst->GetItem();
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
{
ns->spawn.equipment[MaterialSecondary].material = atoi(&item->IDFile[2]);
}
}
}
+1 -1
View File
@@ -8372,7 +8372,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app)
outapp->WriteUInt32(item->Material);
outapp->WriteUInt32(0); //unknown
outapp->WriteUInt32(item->EliteMaterial);
outapp->WriteUInt32(0); // unknown
outapp->WriteUInt32(item->HerosForgeModel);
outapp->WriteUInt32(0); // unknown
outapp->WriteUInt32(0); //This is unknown057 from lucy
for (spacer = 0; spacer < 77; spacer++) { //More Item stats, but some seem to be off based on packet check
+10 -2
View File
@@ -5598,7 +5598,11 @@ void command_itemsearch(Client *c, const Seperator *sep)
if (Seperator::IsNumber(search_criteria)) {
item = database.GetItem(atoi(search_criteria));
if (item)
if (c->GetClientVersion() >= EQClientRoF)
if (c->GetClientVersion() >= EQClientRoF2)
{
c->Message(0, " %i: %c%06X00000000000000000000000000000000000000000000000000%s%c", (int)item->ID, 0x12, item->ID, item->Name, 0x12);
}
else if (c->GetClientVersion() >= EQClientRoF)
{
c->Message(0, " %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12);
}
@@ -5627,7 +5631,11 @@ void command_itemsearch(Client *c, const Seperator *sep)
strupr(sName);
pdest = strstr(sName, sCriteria);
if (pdest != nullptr) {
if (c->GetClientVersion() >= EQClientRoF)
if (c->GetClientVersion() >= EQClientRoF2)
{
c->Message(0, " %i: %c%06X00000000000000000000000000000000000000000000000000%s%c", (int)item->ID, 0x12, item->ID, item->Name, 0x12);
}
else if (c->GetClientVersion() >= EQClientRoF)
{
c->Message(0, " %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(int) item->ID,0x12, item->ID, item->Name, 0x12);
}
+20 -5
View File
@@ -1196,18 +1196,32 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse
ns->spawn.IsMercenary = 1;
/*
// Wear Slots are not setup for Mercs yet
unsigned int i;
//should not include 21 (SLOT_AMMO)
for (i = 0; i < MainAmmo; i++) {
if(equipment[i] == 0)
for (i = 0; i < _MaterialCount; i++)
{
if (equipment[i] == 0)
{
continue;
}
const Item_Struct* item = database.GetItem(equipment[i]);
if(item)
{
ns->spawn.equipment[i] = item->Material;
ns->spawn.colors[i].color = item->Color;
ns->spawn.equipment[i].material = item->Material;
ns->spawn.equipment[i].elitematerial = item->EliteMaterial;
ns->spawn.equipment[i].heroforgemodel = item->HerosForgeModel;
if (armor_tint[i])
{
ns->spawn.colors[i].color = armor_tint[i];
}
else
{
ns->spawn.colors[i].color = item->Color;
}
}
}
*/
}
}
@@ -4758,6 +4772,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
npc_type->npc_id = 0; //NPC ID has to be 0, otherwise db gets all confuzzled.
npc_type->class_ = merc_template->ClassID;
npc_type->maxlevel = 0; //We should hard-set this to override scalerate's functionality in the NPC class when it is constructed.
npc_type->no_target_hotkey = 1;
Merc* merc = new Merc(npc_type, c->GetX(), c->GetY(), c->GetZ(), 0);
+64 -12
View File
@@ -923,7 +923,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
ns->spawn.NPC = IsClient() ? 0 : 1;
ns->spawn.IsMercenary = (IsMerc() || no_target_hotkey) ? 1 : 0;
ns->spawn.IsMercenary = IsMerc() ? 1 : 0;
ns->spawn.targetable_with_hotkey = no_target_hotkey ? 0 : 1; // opposite logic!
ns->spawn.petOwnerId = ownerid;
@@ -963,22 +964,44 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0;
}
else
{
ns->spawn.flymode = flymode;
}
ns->spawn.lastName[0] = '\0';
strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName));
for(i = 0; i < _MaterialCount; i++)
const Item_Struct *item;
for (i = 0; i < _MaterialCount; i++)
{
ns->spawn.equipment[i] = GetEquipmentMaterial(i);
if (armor_tint[i])
// Only Player Races Wear Armor
if (IsPlayerRace(race) || i > 6)
{
ns->spawn.colors[i].color = armor_tint[i];
}
else
{
ns->spawn.colors[i].color = GetEquipmentColor(i);
ns->spawn.equipment[i].material = GetEquipmentMaterial(i);
item = database.GetItem(GetEquipment(i));
if (item != 0)
{
ns->spawn.equipment[i].elitematerial = item->EliteMaterial;
ns->spawn.equipment[i].heroforgemodel = item->HerosForgeModel;
if (armor_tint[i])
{
ns->spawn.colors[i].color = armor_tint[i];
}
else
{
ns->spawn.colors[i].color = item->Color;
}
}
else
{
if (armor_tint[i])
{
ns->spawn.colors[i].color = armor_tint[i];
}
}
}
}
@@ -2617,8 +2640,20 @@ void Mob::SendWearChange(uint8 material_slot)
wc->spawn_id = GetID();
wc->material = GetEquipmentMaterial(material_slot);
wc->elite_material = IsEliteMaterialItem(material_slot);
wc->color.color = GetEquipmentColor(material_slot);
const Item_Struct *item;
item = database.GetItem(GetEquipment(material_slot));
if (item != 0)
{
wc->elite_material = item->EliteMaterial;
wc->hero_forge_model = item->HerosForgeModel;
wc->color.color = item->Color;
}
else
{
wc->elite_material = 0;
wc->hero_forge_model = 0;
wc->color.color = 0;
}
wc->wear_slot_id = material_slot;
entity_list.QueueClients(this, outapp);
@@ -2662,6 +2697,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
wc->spawn_id = this->GetID();
wc->material = GetEquipmentMaterial(material_slot);
wc->hero_forge_model = GetHeroForgeModel(material_slot);
wc->color.color = color;
wc->wear_slot_id = material_slot;
@@ -2669,7 +2705,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin
safe_delete(outapp);
}
void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color)
void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model)
{
armor_tint[material_slot] = color;
@@ -2678,6 +2714,7 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color)
wc->spawn_id = this->GetID();
wc->material = texture;
wc->hero_forge_model = hero_forge_model;
wc->color.color = color;
wc->wear_slot_id = material_slot;
@@ -2757,6 +2794,19 @@ uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const
return 0;
}
uint32 Mob::GetHeroForgeModel(uint8 material_slot) const
{
const Item_Struct *item;
item = database.GetItem(GetEquipment(material_slot));
if (item != 0)
{
return item->HerosForgeModel;
}
return 0;
}
// works just like a printf
void Mob::Say(const char *format, ...)
{
@@ -3813,6 +3863,8 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier)
stat = int32(item->CastTime);
if (id == "elitematerial")
stat = int32(item->EliteMaterial);
if (id == "herosforgemodel")
stat = int32(item->HerosForgeModel);
if (id == "procrate")
stat = int32(item->ProcRate);
if (id == "combateffects")
+2 -1
View File
@@ -171,7 +171,7 @@ public:
virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0,
uint32 unknown06 = 0, uint32 unknown18 = 0);
virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint);
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color);
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model = 0);
void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone);
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0,
float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, SkillUseTypes skillInUse = SkillArchery);
@@ -314,6 +314,7 @@ public:
virtual int32 GetEquipmentMaterial(uint8 material_slot) const;
virtual uint32 GetEquipmentColor(uint8 material_slot) const;
virtual uint32 IsEliteMaterialItem(uint8 material_slot) const;
virtual uint32 GetHeroForgeModel(uint8 material_slot) const;
bool AffectedBySpellExcludingSlot(int slot, int effect);
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0;
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill,
+8 -7
View File
@@ -1854,27 +1854,28 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns)
{
swarmOwner = entity_list.GetMobID(GetSwarmOwner());
}
if (swarmOwner != nullptr)
{
if(swarmOwner->IsClient())
{
SetPetOwnerClient(true); //Simple flag to determine if pet belongs to a client
SetAllowBeneficial(1);//Allow temp pets to receive buffs and heals if owner is client.
//This is a hack to allow CLIENT swarm pets NOT to be targeted with F8. Warning: Will turn name 'Yellow'!
if (RuleB(Pets, SwarmPetNotTargetableWithHotKey))
ns->spawn.IsMercenary = 1;
//This will allow CLIENT swarm pets NOT to be targeted with F8.
ns->spawn.targetable_with_hotkey = 0;
no_target_hotkey = 1;
}
else
{
//NPC cast swarm pets should still be targetable with F8.
ns->spawn.IsMercenary = 0;
ns->spawn.targetable_with_hotkey = 1;
no_target_hotkey = 0;
}
SetTempPet(true); //Simple mob flag for checking if temp pet
swarmOwner->SetTempPetsActive(true); //Necessary fail safe flag set if mob ever had a swarm pet to ensure they are removed.
swarmOwner->SetTempPetCount(swarmOwner->GetTempPetCount() + 1);
//Not recommended if using above (However, this will work better on older clients).
if (RuleB(Pets, UnTargetableSwarmPet))
{
@@ -1882,7 +1883,7 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns)
if(!IsCharmed() && swarmOwner->IsClient())
sprintf(ns->spawn.lastName, "%s's Pet", swarmOwner->GetName());
}
}
}
else if(GetOwnerID())
{
ns->spawn.is_pet = 1;
+1 -1
View File
@@ -269,7 +269,7 @@ public:
void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false);
virtual void DoClassAttacks(Mob *target);
void CheckSignal();
inline bool IsTargetableWithHotkey() const { return no_target_hotkey; }
inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; }
int32 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
inline const char* GetAmmoIDfile() const { return ammo_idfile; }
+7 -3
View File
@@ -7460,12 +7460,13 @@ XS(XS_Mob_WearChange)
{
dXSARGS;
if (items < 3 || items > 4)
Perl_croak(aTHX_ "Usage: Mob::WearChange(THIS, material_slot, texture, color)");
Perl_croak(aTHX_ "Usage: Mob::WearChange(THIS, material_slot, texture, [color, hero_forge_model])");
{
Mob * THIS;
uint8 material_slot = (uint8)SvIV(ST(1));
uint16 texture = (uint16)SvUV(ST(2));
uint32 color = 0;
uint32 hero_forge_model = 0;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -7479,8 +7480,11 @@ XS(XS_Mob_WearChange)
if (items > 3) {
color = (uint32)SvUV(ST(3));
}
if (items > 4) {
hero_forge_model = (uint32)SvUV(ST(3));
}
THIS->WearChange(material_slot, texture, color);
THIS->WearChange(material_slot, texture, color, hero_forge_model);
}
XSRETURN_EMPTY;
}
@@ -8614,7 +8618,7 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "TarGlobal"), XS_Mob_TarGlobal, file, "$$$$$$$");
newXSproto(strcpy(buf, "DelGlobal"), XS_Mob_DelGlobal, file, "$$");
newXSproto(strcpy(buf, "SetSlotTint"), XS_Mob_SetSlotTint, file, "$$$$$");
newXSproto(strcpy(buf, "WearChange"), XS_Mob_WearChange, file, "$$$;$");
newXSproto(strcpy(buf, "WearChange"), XS_Mob_WearChange, file, "$$$;$$");
newXSproto(strcpy(buf, "DoKnockback"), XS_Mob_DoKnockback, file, "$$$$");
newXSproto(strcpy(buf, "RemoveNimbusEffect"), XS_Mob_RemoveNimbusEffect, file, "$$");
newXSproto(strcpy(buf, "IsRunning"), XS_Mob_IsRunning, file, "$");