Merge fix

This commit is contained in:
KimLS 2017-03-14 21:18:35 -07:00
commit db210ba70e
11 changed files with 148 additions and 49 deletions

View File

@ -163,6 +163,8 @@ RULE_INT(Mercs, AggroRadius, 100) // Determines the distance from which a merc
RULE_INT(Mercs, AggroRadiusPuller, 25) // Determines the distance from which a merc will aggro group member's target, if they have the group role of puller (also used to determine the distance at which a healer merc will begin healing a group member, if they have the group role of puller) RULE_INT(Mercs, AggroRadiusPuller, 25) // Determines the distance from which a merc will aggro group member's target, if they have the group role of puller (also used to determine the distance at which a healer merc will begin healing a group member, if they have the group role of puller)
RULE_INT(Mercs, ResurrectRadius, 50) // Determines the distance from which a healer merc will attempt to resurrect a group member's corpse RULE_INT(Mercs, ResurrectRadius, 50) // Determines the distance from which a healer merc will attempt to resurrect a group member's corpse
RULE_INT(Mercs, ScaleRate, 100) RULE_INT(Mercs, ScaleRate, 100)
RULE_BOOL(Mercs, MercsUsePathing, true) // Mercs will use node pathing when moving
RULE_BOOL(Mercs, AllowMercSuspendInCombat, true)
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Guild) RULE_CATEGORY(Guild)
@ -225,6 +227,7 @@ RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Ral
RULE_BOOL (World, IsGMPetitionWindowEnabled, false) RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items. RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
RULE_BOOL (World, IPLimitDisconnectAll, false) RULE_BOOL (World, IPLimitDisconnectAll, false)
RULE_BOOL(World, MaxClientsSimplifiedLogic, false) // New logic that only uses ExemptMaxClientsStatus and MaxClientsPerIP. Done on the loginserver. This mimics the P99-style special IP rules.
RULE_INT (World, TellQueueSize, 20) RULE_INT (World, TellQueueSize, 20)
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind? RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind?
RULE_CATEGORY_END() RULE_CATEGORY_END()

View File

@ -655,6 +655,7 @@ struct UsertoWorldRequest_Struct {
uint32 worldid; uint32 worldid;
uint32 FromID; uint32 FromID;
uint32 ToID; uint32 ToID;
char IPAddr[64];
}; };
struct UsertoWorldResponse_Struct { struct UsertoWorldResponse_Struct {

View File

@ -940,7 +940,7 @@ bool IsRegularSingleTargetHealSpell(uint16 spell_id)
{ {
if(spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && if(spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 &&
spells[spell_id].targettype == ST_Target && spells[spell_id].buffduration == 0 && spells[spell_id].targettype == ST_Target && spells[spell_id].buffduration == 0 &&
!IsFastHealSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsCompleteHealSpell(spell_id) &&
!IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id))
return true; return true;

View File

@ -0,0 +1 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Mercs:MercsUsePathing', 'false', 'Mercs will use node pathing when moving');

View File

@ -1017,6 +1017,12 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
eqs->Close(); eqs->Close();
return true; return true;
} }
case OP_WorldLogout:
{
eqs->Close();
cle->SetOnline(CLE_Status_Offline); //allows this player to log in again without an ip restriction.
return false;
}
case OP_ZoneChange: case OP_ZoneChange:
{ {
// HoT sends this to world while zoning and wants it echoed back. // HoT sends this to world while zoning and wants it echoed back.

View File

@ -219,6 +219,24 @@ void ClientList::GetCLEIP(uint32 iIP) {
} }
} }
uint32 ClientList::GetCLEIPCount(uint32 iIP) {
ClientListEntry* countCLEIPs = 0;
LinkedListIterator<ClientListEntry*> iterator(clientlist);
int IPInstances = 0;
iterator.Reset();
while (iterator.MoreElements()) {
countCLEIPs = iterator.GetData();
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status_Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt)
IPInstances++; // Increment the occurences of this IP address
}
iterator.Advance();
}
return IPInstances;
}
void ClientList::DisconnectByIP(uint32 iIP) { void ClientList::DisconnectByIP(uint32 iIP) {
ClientListEntry* countCLEIPs = 0; ClientListEntry* countCLEIPs = 0;
LinkedListIterator<ClientListEntry*> iterator(clientlist); LinkedListIterator<ClientListEntry*> iterator(clientlist);
@ -257,7 +275,6 @@ ClientListEntry* ClientList::FindCharacter(const char* name) {
return 0; return 0;
} }
ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) { ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) {
LinkedListIterator<ClientListEntry*> iterator(clientlist); LinkedListIterator<ClientListEntry*> iterator(clientlist);

View File

@ -57,6 +57,7 @@ public:
ClientListEntry* FindCLEByCharacterID(uint32 iCharID); ClientListEntry* FindCLEByCharacterID(uint32 iCharID);
ClientListEntry* GetCLE(uint32 iID); ClientListEntry* GetCLE(uint32 iID);
void GetCLEIP(uint32 iIP); void GetCLEIP(uint32 iIP);
uint32 GetCLEIPCount(uint32 iLSAccountID);
void DisconnectByIP(uint32 iIP); void DisconnectByIP(uint32 iIP);
void EnforceSessionLimit(uint32 iLSAccountID); void EnforceSessionLimit(uint32 iLSAccountID);
void CLCheckStale(); void CLCheckStale();

View File

@ -737,7 +737,7 @@ private:
bool _hasBeenSummoned; bool _hasBeenSummoned;
glm::vec3 m_PreSummonLocation; glm::vec3 m_PreSummonLocation;
Timer evade_timer; Timer evade_timer; // can be moved to pTimers at some point
BotCastingRoles m_CastingRoles; BotCastingRoles m_CastingRoles;

View File

@ -69,6 +69,9 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
SetStance(MercStanceBalanced); SetStance(MercStanceBalanced);
rest_timer.Disable(); rest_timer.Disable();
if (GetClass() == ROGUE)
evade_timer.Start();
int r; int r;
for (r = 0; r <= EQEmu::skills::HIGHEST_SKILL; r++) { for (r = 0; r <= EQEmu::skills::HIGHEST_SKILL; r++) {
skills[r] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)r, GetLevel()); skills[r] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)r, GetLevel());
@ -1459,7 +1462,7 @@ void Merc::AI_Process() {
// Let's check if we have a los with our target. // Let's check if we have a los with our target.
// If we don't, our hate_list is wiped. // If we don't, our hate_list is wiped.
// Else, it was causing the merc to aggro behind wall etc... causing massive trains. // Else, it was causing the merc to aggro behind wall etc... causing massive trains.
if(!CheckLosFN(GetTarget()) || GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) { if(GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) {
WipeHateList(); WipeHateList();
if(IsMoving()) { if(IsMoving()) {
@ -1474,6 +1477,26 @@ void Merc::AI_Process() {
return; return;
} }
else if (!CheckLosFN(GetTarget())) {
if (RuleB(Mercs, MercsUsePathing) && zone->pathing) {
bool WaypointChanged, NodeReached;
glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(),
GetRunspeed(), WaypointChanged, NodeReached);
if (WaypointChanged)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed());
}
else {
Mob* follow = entity_list.GetMob(GetFollowID());
if (follow)
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed());
}
return;
}
if (!(m_PlayerState & static_cast<uint32>(PlayerState::Aggressive))) if (!(m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)))
SendAddPlayerState(PlayerState::Aggressive); SendAddPlayerState(PlayerState::Aggressive);
@ -1508,32 +1531,60 @@ void Merc::AI_Process() {
} }
} }
if(AI_movement_timer->Check()) if(AI_movement_timer->Check()) {
{ if (!IsMoving()) {
if(!IsMoving() && GetClass() == ROGUE && !BehindMob(GetTarget(), GetX(), GetY())) if (GetClass() == ROGUE) {
{ if (HasTargetReflection() && !GetTarget()->IsFeared() && !GetTarget()->IsStunned()) {
// Move the rogue to behind the mob // Hate redux actions
float newX = 0; if (evade_timer.Check(false)) {
float newY = 0; // Attempt to evade
float newZ = 0; int timer_duration = (HideReuseTime - GetSkillReuseTime(EQEmu::skills::SkillHide)) * 1000;
if (timer_duration < 0)
timer_duration = 0;
evade_timer.Start(timer_duration);
if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) if (zone->random.Int(0, 260) < (int)GetSkill(EQEmu::skills::SkillHide))
{ RogueEvade(GetTarget());
CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
return; return;
}
else if (GetTarget()->IsRooted()) {
// Move rogue back from rooted mob - out of combat range, if necessary
float melee_distance = GetMaxMeleeRangeToTarget(GetTarget());
float current_distance = DistanceSquared(static_cast<glm::vec3>(m_Position), static_cast<glm::vec3>(GetTarget()->GetPosition()));
if (current_distance <= melee_distance) {
float newX = 0;
float newY = 0;
float newZ = 0;
FaceTarget(GetTarget());
if (PlotPositionAroundTarget(this, newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
return;
}
}
}
}
else if (!BehindMob(GetTarget(), GetX(), GetY())) {
// Move the rogue to behind the mob
float newX = 0;
float newY = 0;
float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
return;
}
}
} }
} else if (GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) {
else if(!IsMoving() && GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) // If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up
{ float newX = 0;
// If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up float newY = 0;
float newX = 0; float newZ = 0;
float newY = 0; if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
float newZ = 0; CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
return;
if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) }
{
CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
return;
} }
} }
@ -1707,34 +1758,42 @@ void Merc::AI_Process() {
} }
} }
if(AI_movement_timer->Check()) if(AI_movement_timer->Check()) {
{ if(GetFollowID()) {
if(GetFollowID())
{
Mob* follow = entity_list.GetMob(GetFollowID()); Mob* follow = entity_list.GetMob(GetFollowID());
if(follow) if (follow) {
{
float dist = DistanceSquared(m_Position, follow->GetPosition()); float dist = DistanceSquared(m_Position, follow->GetPosition());
int speed = GetRunspeed(); int speed = GetRunspeed();
if(dist < GetFollowDistance() + 1000) if (dist < GetFollowDistance() + 1000)
speed = GetWalkspeed(); speed = GetWalkspeed();
SetRunAnimSpeed(0); SetRunAnimSpeed(0);
if(dist > GetFollowDistance()) { if (dist > GetFollowDistance()) {
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); if (RuleB(Mercs, MercsUsePathing) && zone->pathing) {
if(rest_timer.Enabled()) bool WaypointChanged, NodeReached;
glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(),
speed, WaypointChanged, NodeReached);
if (WaypointChanged)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed);
}
else {
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
}
if (rest_timer.Enabled())
rest_timer.Disable(); rest_timer.Disable();
return;
} }
else else {
{ if (moved) {
if(moved) moved = false;
{ SetCurrentSpeed(0);
SetCurrentSpeed(0);
moved = false;
} }
} }
} }
@ -5468,7 +5527,7 @@ void Client::SuspendMercCommand() {
Merc* merc = Merc::LoadMerc(this, &zone->merc_templates[GetMercInfo().MercTemplateID], 0, true); Merc* merc = Merc::LoadMerc(this, &zone->merc_templates[GetMercInfo().MercTemplateID], 0, true);
if(merc) if(merc)
{ {
SpawnMerc(merc, true); SpawnMerc(merc, false);
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Unsuspend for %s.", GetName()); Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Unsuspend for %s.", GetName());
} }
else else
@ -5482,6 +5541,15 @@ void Client::SuspendMercCommand() {
{ {
Merc* CurrentMerc = GetMerc(); Merc* CurrentMerc = GetMerc();
if (!RuleB(Mercs, AllowMercSuspendInCombat))
{
if (!CheckCanSpawnMerc(GetMercInfo().MercTemplateID))
{
return;
}
}
if(CurrentMerc && GetMercID()) if(CurrentMerc && GetMercID())
{ {
CurrentMerc->Suspend(); CurrentMerc->Suspend();

View File

@ -250,7 +250,7 @@ public:
inline virtual int32 GetStringMod() const { return itembonuses.stringedMod; } inline virtual int32 GetStringMod() const { return itembonuses.stringedMod; }
inline virtual int32 GetWindMod() const { return itembonuses.windMod; } inline virtual int32 GetWindMod() const { return itembonuses.windMod; }
inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; } inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath; }
// "SET" Class Methods // "SET" Class Methods
void SetMercData (uint32 templateID ); void SetMercData (uint32 templateID );
@ -290,6 +290,8 @@ protected:
std::vector<MercSpell> merc_spells; std::vector<MercSpell> merc_spells;
std::map<uint32,MercTimer> timers; std::map<uint32,MercTimer> timers;
Timer evade_timer; // can be moved to pTimers at some point
uint16 skills[EQEmu::skills::HIGHEST_SKILL + 1]; uint16 skills[EQEmu::skills::HIGHEST_SKILL + 1];
uint32 equipment[EQEmu::legacy::EQUIPMENT_SIZE]; //this is an array of item IDs uint32 equipment[EQEmu::legacy::EQUIPMENT_SIZE]; //this is an array of item IDs
uint16 d_melee_texture1; //this is an item Material value uint16 d_melee_texture1; //this is an item Material value

View File

@ -1793,8 +1793,8 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
} }
while(AtkRounds > 0) { while(AtkRounds > 0) {
if (GetTarget()) if (ca_target!=this)
DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, dmg, 0, dmg, ReuseTime); DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillFrenzy, dmg, 0, dmg, ReuseTime);
AtkRounds--; AtkRounds--;
} }