Merge branch 'master' of github.com:EQEmu/Server into wp

This commit is contained in:
KimLS 2017-08-31 17:47:33 -07:00
commit 6a79694fa1
22 changed files with 717 additions and 552 deletions

View File

@ -617,7 +617,7 @@ struct NewZone_Struct {
/*0704*/ char zone_short_name2[32]; //zone file name? excludes instance number which can be in previous version.
/*0736*/ char WeatherString[32];
/*0768*/ char SkyString2[32];
/*0800*/ int32 SkyRelated2; //seen -1
/*0800*/ int32 SkyRelated2; //seen -1 -- maybe some default sky time?
/*0804*/ char WeatherString2[32]; //
/*0836*/ float WeatherChangeTime; // not sure :P
/*0840*/ uint32 Climate;

View File

@ -563,6 +563,8 @@ RULE_INT(Range, DamageMessages, 50)
RULE_INT(Range, SpellMessages, 75)
RULE_INT(Range, SongMessages, 75)
RULE_INT(Range, MobPositionUpdates, 600)
RULE_INT(Range, ClientPositionUpdates, 300)
RULE_INT(Range, ClientForceSpawnUpdateRange, 1000)
RULE_INT(Range, CriticalDamage, 80)
RULE_INT(Range, ClientNPCScan, 300)
RULE_CATEGORY_END()

View File

@ -357,7 +357,7 @@
9101|2016_12_01_pcnpc_only.sql|SHOW COLUMNS FROM `spells_new` LIKE 'pcnpc_only_flag'|empty|
9102|2017_01_10_book_languages.sql|SHOW COLUMNS FROM `books` LIKE 'language'|empty|
9103|2017_01_30_book_languages_fix.sql|SELECT `language` from `books` WHERE `language` IS NULL|not_empty|
9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE `type`|contains|smallint(5) unsigned
9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE 'type'|contains|smallint(5) unsigned
9105|2017_02_15_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty|
9106|2017_02_26_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty|
9107|2017_03_09_inventory_version.sql|SHOW TABLES LIKE 'inventory_version'|empty|

View File

@ -1003,6 +1003,15 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
case SE_RiposteChance:
newbon->RiposteChance += base1;
break;
case SE_DodgeChance:
newbon->DodgeChance += base1;
break;
case SE_ParryChance:
newbon->ParryChance += base1;
break;
case SE_IncreaseBlockChance:
newbon->IncreaseBlockChance += base1;
break;
case SE_Flurry:
newbon->FlurryChance += base1;
break;
@ -2495,7 +2504,12 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
break;
case SE_IncreaseBlockChance:
new_bonus->IncreaseBlockChance += effect_value;
if (AdditiveWornBonus)
new_bonus->IncreaseBlockChance += effect_value;
else if (effect_value < 0 && new_bonus->IncreaseBlockChance > effect_value)
new_bonus->IncreaseBlockChance = effect_value;
else if (new_bonus->IncreaseBlockChance < effect_value)
new_bonus->IncreaseBlockChance = effect_value;
break;
case SE_PersistantCasting:

View File

@ -1489,7 +1489,9 @@ private:
Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */
Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
glm::vec3 m_Proximity;
glm::vec3 m_Proximity;
glm::vec4 last_major_update_position;
void BulkSendInventoryItems();

File diff suppressed because it is too large Load Diff

View File

@ -243,15 +243,21 @@ bool Client::Process() {
/* Build a close range list of NPC's */
if (npc_close_scan_timer.Check()) {
close_mobs.clear();
auto &mob_list = entity_list.GetMobList();
float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan));
float client_update_range = (RuleI(Range, MobPositionUpdates) * RuleI(Range, MobPositionUpdates));
/* Force spawn updates when traveled far */
bool force_spawn_updates = false;
float client_update_range = (RuleI(Range, ClientForceSpawnUpdateRange) * RuleI(Range, ClientForceSpawnUpdateRange));
if (DistanceSquared(last_major_update_position, m_Position) >= client_update_range) {
last_major_update_position = m_Position;
force_spawn_updates = true;
}
float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan));
auto &mob_list = entity_list.GetMobList();
for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) {
Mob* mob = itr->second;
float distance = DistanceSquared(m_Position, mob->GetPosition());
if (mob->IsNPC()) {
if (distance <= scan_range) {
@ -261,6 +267,10 @@ bool Client::Process() {
close_mobs.insert(std::pair<Mob *, float>(mob, distance));
}
}
if (force_spawn_updates && mob != this && distance <= client_update_range)
mob->SendPositionUpdateToClient(this);
}
}

View File

@ -3894,6 +3894,8 @@ void command_depopzone(Client *c, const Seperator *sep)
void command_repop(Client *c, const Seperator *sep)
{
int timearg = 1;
int delay = 0;
if (sep->arg[1] && strcasecmp(sep->arg[1], "force") == 0) {
timearg++;
@ -3912,13 +3914,19 @@ void command_repop(Client *c, const Seperator *sep)
}
if (!sep->IsNumber(timearg)) {
c->Message(0, "Zone depoped. Repoping now.");
c->Message(0, "Zone depopped - repopping now.");
zone->Repop();
/* Force a spawn2 timer trigger so we don't delay actually spawning the NPC's */
zone->spawn2_timer.Trigger();
return;
}
c->Message(0, "Zone depoped. Repop in %i seconds", atoi(sep->arg[timearg]));
zone->Repop(atoi(sep->arg[timearg])*1000);
zone->Repop(atoi(sep->arg[timearg]) * 1000);
zone->spawn2_timer.Trigger();
}
void command_repopclose(Client *c, const Seperator *sep)

View File

@ -613,7 +613,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
//Check the disc timer
pTimerType DiscTimer = pTimerDisciplineReuseStart + spell.EndurTimerIndex;
if(!p_timers.Expired(&database, DiscTimer)) {
if(!p_timers.Expired(&database, DiscTimer, false)) { // lets not set the reuse timer in case CastSpell fails (or we would have to turn off the timer, but CastSpell will set it as well)
/*char val1[20]={0};*/ //unused
/*char val2[20]={0};*/ //unused
uint32 remain = p_timers.GetRemainingTime(DiscTimer);

View File

@ -119,7 +119,7 @@ void Embperl::DoInit() {
perl_run(my_perl);
//a little routine we use a lot.
eval_pv("sub my_eval {eval $_[0];}", TRUE); //dies on error
eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error
//ruin the perl exit and command:
eval_pv("sub my_exit {}",TRUE);
@ -149,7 +149,7 @@ void Embperl::DoInit() {
//make a tieable class to capture IO and pass it into EQEMuLog
eval_pv(
"package EQEmuIO; "
"sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '.$me); return($me); } "
"sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '. $me); return($me); } "
"sub WRITE { } "
//dunno why I need to shift off fmt here, but it dosent like without it
"sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } "
@ -237,6 +237,7 @@ void Embperl::init_eval_file(void)
{
eval_pv(
"our %Cache;"
"no warnings;"
"use Symbol qw(delete_package);"
"sub eval_file {"
"my($package, $filename) = @_;"
@ -246,8 +247,9 @@ void Embperl::init_eval_file(void)
"if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){"
" return;"
"} else {"
//we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here.
" eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require '$filename'; \");"
// we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here.
" eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require './$filename'; \");"
// " print $@ if $@;"
/* "local *FH;open FH, $filename or die \"open '$filename' $!\";"
"local($/) = undef;my $sub = <FH>;close FH;"
"my $eval = qq{package $package; sub handler { $sub; }};"

View File

@ -99,6 +99,10 @@ XS(XS_EQEmuIO_PRINT)
/* Strip newlines from log message 'str' */
*std::remove(str, str + strlen(str), '\n') = '\0';
std::string log_string = str;
if (log_string.find("did not return a true") != std::string::npos)
return;;
int i;
int pos = 0;
int len = 0;

View File

@ -648,6 +648,8 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
npc->FixZ();
uint16 emoteid = npc->GetEmoteID();
if (emoteid != 0)
npc->DoNPCEmote(ONSPAWN, emoteid);

View File

@ -2464,3 +2464,30 @@ bool Group::HasRole(Mob *m, uint8 Role)
return false;
}
void Group::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/) {
if (sender && sender->IsClient()) {
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (!members[i])
continue;
if (ignore_sender && members[i] == sender)
continue;
/* If we don't have a distance requirement - send to all members */
if (distance == 0) {
members[i]->CastToClient()->QueuePacket(app, ack_required);
}
else {
/* If negative distance - we check if current distance is greater than X */
if (distance <= 0 && DistanceSquared(sender->GetPosition(), members[i]->GetPosition()) >= (distance * distance)) {
members[i]->CastToClient()->QueuePacket(app, ack_required);
}
/* If positive distance - we check if current distance is less than X */
else if (distance >= 0 && DistanceSquared(sender->GetPosition(), members[i]->GetPosition()) <= (distance * distance)) {
members[i]->CastToClient()->QueuePacket(app, ack_required);
}
}
}
}
}

View File

@ -140,6 +140,7 @@ public:
inline int GetLeadershipAA(int AAID) { return LeaderAbilities.ranks[AAID]; }
void ClearAllNPCMarks();
void QueueHPPacketsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
void QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required = true, bool ignore_sender = true, float distance = 0);
void ChangeLeader(Mob* newleader);
const char *GetClientNameByIndex(uint8 index);
void UpdateXTargetMarkedNPC(uint32 Number, Mob *m);

View File

@ -1375,7 +1375,7 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
if(IsClient()){
Raid *raid = entity_list.GetRaidByClient(CastToClient());
if (raid)
raid->SendHPPacketsFrom(this);
raid->SendHPManaEndPacketsFrom(this);
}
/* Pet - Update master - group and raid if exists */
@ -1388,7 +1388,7 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
Raid *raid = entity_list.GetRaidByClient(GetOwner()->CastToClient());
if(raid)
raid->SendHPPacketsFrom(this);
raid->SendHPManaEndPacketsFrom(this);
}
/* Send to pet */
@ -1447,6 +1447,20 @@ void Mob::SendPosition() {
safe_delete(app);
}
void Mob::SendPositionUpdateToClient(Client *client) {
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
if(this->IsMoving())
MakeSpawnUpdate(spawn_update);
else
MakeSpawnUpdateNoDelta(spawn_update);
client->QueuePacket(app, false);
safe_delete(app);
}
/* Position updates for mobs on the move */
void Mob::SendPositionUpdate(uint8 iSendToSelf) {
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));

View File

@ -543,6 +543,7 @@ public:
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true);
void SetDelta(const glm::vec4& delta);
void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; }
void SendPositionUpdateToClient(Client *client);
void SendPositionUpdate(uint8 iSendToSelf = 0);
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);

View File

@ -997,10 +997,9 @@ void Mob::AI_Process() {
if (this->GetTarget()) {
/* If we are engaged, moving and following client, let's look for best Z more often */
float target_distance = DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition());
if (target_distance >= 25) {
this->FixZ();
}
else if (!this->CheckLosFN(this->GetTarget())) {
this->FixZ();
if (target_distance <= 15 && !this->CheckLosFN(this->GetTarget())) {
Mob* target = this->GetTarget();
m_Position.x = target->GetX();

View File

@ -149,7 +149,7 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
raid_update = c->GetRaid();
if (raid_update) {
raid_update->SendHPManaEndPacketsTo(c);
raid_update->SendHPPacketsFrom(c);
raid_update->SendHPManaEndPacketsFrom(c);
}
auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct));
@ -1591,7 +1591,7 @@ void Raid::SendHPManaEndPacketsTo(Client *client)
}
}
void Raid::SendHPPacketsFrom(Mob *mob)
void Raid::SendHPManaEndPacketsFrom(Mob *mob)
{
if(!mob)
return;
@ -1779,3 +1779,42 @@ void Raid::SetDirtyAutoHaters()
}
void Raid::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/, bool group_only /*= true*/) {
if (sender && sender->IsClient()) {
uint32 group_id = this->GetGroup(sender->CastToClient());
/* If this is a group only packet and we're not in a group -- return */
if (!group_id == 0xFFFFFFFF && group_only)
return;
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++) {
if (!members[i].member)
continue;
if (!members[i].member->IsClient())
continue;
if (ignore_sender && members[i].member == sender)
continue;
if (group_only && members[i].GroupNumber != group_id)
continue;
/* If we don't have a distance requirement - send to all members */
if (distance == 0) {
members[i].member->CastToClient()->QueuePacket(app, ack_required);
}
else {
/* If negative distance - we check if current distance is greater than X */
if (distance <= 0 && DistanceSquared(sender->GetPosition(), members[i].member->GetPosition()) >= (distance * distance)) {
members[i].member->CastToClient()->QueuePacket(app, ack_required);
}
/* If positive distance - we check if current distance is less than X */
else if (distance >= 0 && DistanceSquared(sender->GetPosition(), members[i].member->GetPosition()) <= (distance * distance)) {
members[i].member->CastToClient()->QueuePacket(app, ack_required);
}
}
}
}
}

View File

@ -174,7 +174,7 @@ public:
void VerifyRaid();
void MemberZoned(Client *c);
void SendHPManaEndPacketsTo(Client *c);
void SendHPPacketsFrom(Mob *mob);
void SendHPManaEndPacketsFrom(Mob *mob);
void SendManaPacketFrom(Mob *mob);
void SendEndurancePacketFrom(Mob *mob);
void RaidSay(const char *msg, Client *c);
@ -237,6 +237,8 @@ public:
void SetDirtyAutoHaters();
inline XTargetAutoHaters *GetXTargetAutoMgr() { return &m_autohatermgr; }
void QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required = true, bool ignore_sender = true, float distance = 0, bool group_only = true);
RaidMember members[MAX_RAID_MEMBERS];
char leadername[64];
protected:

View File

@ -1427,8 +1427,10 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
ZeroCastingVars();
// set the rapid recast timer for next time around
// Why do we have this? It mostly just causes issues when things are working correctly
// It also needs to be <users's ping to not cause issues
delaytimer = true;
spellend_timer.Start(400,true);
spellend_timer.Start(10, true);
Log(Logs::Detail, Logs::Spells, "Spell casting of %d is finished.", spell_id);

View File

@ -1170,10 +1170,13 @@ bool Zone::Process() {
spawn_conditions.Process();
if(spawn2_timer.Check()) {
LinkedListIterator<Spawn2*> iterator(spawn2_list);
EQEmu::InventoryProfile::CleanDirty();
Log(Logs::Detail, Logs::Spawns, "Running Zone::Process -> Spawn2::Process");
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->Process()) {
@ -1183,10 +1186,10 @@ bool Zone::Process() {
iterator.RemoveCurrent();
}
}
if(adv_data && !did_adventure_actions)
{
DoAdventureActions();
}
}
if(initgrids_timer.Check()) {
//delayed grid loading stuff.

View File

@ -106,6 +106,7 @@ public:
inline const uint8 GetZoneType() const { return zone_type; }
inline Timer* GetInstanceTimer() { return Instance_Timer; }
Timer spawn2_timer;
inline glm::vec3 GetSafePoint() { return m_SafePoint; }
inline const uint32& graveyard_zoneid() { return pgraveyard_zoneid; }
@ -336,7 +337,6 @@ private:
Timer autoshutdown_timer;
Timer clientauth_timer;
Timer spawn2_timer;
Timer qglobal_purge_timer;
Timer* Weather_Timer;
Timer* Instance_Timer;