mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-17 03:08:26 +00:00
[Bug Fix] Zone Heading for Binds, Summons, Teleports, and Zoning. (#1328)
* For as long as I can remember people have had issues with zoning in, facing the wrong way, and walking through a zone line. With this we will be able to set zone's safe heading as well as preserve heading on summon (NPC or GM) and teleports between zones. This affects several pre-existing quest methods and extends their parameters to allow for the addition of heading. The following functions have had heading added. Lua - client:SetBindPoint() - client:SetStartZone() Perl - $client->SetBindPoint() - $client->SetStartZone() - quest::rebind() SetStartZone parameter list was fixed also. This converts some pre-existing methods from glm::vec3() to glm::vec4() and has an overload where necessary to use a glm::vec3() method versus glm::vec4() method. This shouldn't affect any pre-existing servers and will allow PEQ and others to document safe headings for zones properly. * Removed possible memory leaks. * Fix SQL. * Fix client message. * Fix debug log. * Fix log message. * Fix call in rebind overload. * Fix floats. * Add default to column.
This commit is contained in:
+2
-2
@@ -1655,7 +1655,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
|
||||
d->spawn_id = GetID();
|
||||
d->killer_id = killerMob ? killerMob->GetID() : 0;
|
||||
d->corpseid = GetID();
|
||||
d->bindzoneid = m_pp.binds[0].zoneId;
|
||||
d->bindzoneid = m_pp.binds[0].zone_id;
|
||||
d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell;
|
||||
d->attack_skill = spell != SPELL_UNKNOWN ? 0xe7 : attack_skill;
|
||||
d->damage = damage;
|
||||
@@ -1892,7 +1892,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
|
||||
r->MemberZoned(this);
|
||||
|
||||
dead_timer.Start(5000, true);
|
||||
m_pp.zone_id = m_pp.binds[0].zoneId;
|
||||
m_pp.zone_id = m_pp.binds[0].zone_id;
|
||||
m_pp.zoneInstance = m_pp.binds[0].instance_id;
|
||||
database.MoveCharacterToZone(this->CharacterID(), m_pp.zone_id);
|
||||
Save();
|
||||
|
||||
+19
-11
@@ -163,7 +163,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
helm_toggle_timer(250),
|
||||
aggro_meter_timer(AGGRO_METER_UPDATE_MS),
|
||||
m_Proximity(FLT_MAX, FLT_MAX, FLT_MAX), //arbitrary large number
|
||||
m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f),
|
||||
m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f,-2.0f),
|
||||
m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f),
|
||||
last_region_type(RegionTypeUnsupported),
|
||||
@@ -441,7 +441,7 @@ Client::~Client() {
|
||||
|
||||
if(IsHoveringForRespawn())
|
||||
{
|
||||
m_pp.zone_id = m_pp.binds[0].zoneId;
|
||||
m_pp.zone_id = m_pp.binds[0].zone_id;
|
||||
m_pp.zoneInstance = m_pp.binds[0].instance_id;
|
||||
m_Position.x = m_pp.binds[0].x;
|
||||
m_Position.y = m_pp.binds[0].y;
|
||||
@@ -658,7 +658,7 @@ bool Client::Save(uint8 iCommitNow) {
|
||||
|
||||
/* Save Current Bind Points */
|
||||
for (int i = 0; i < 5; i++)
|
||||
if (m_pp.binds[i].zoneId)
|
||||
if (m_pp.binds[i].zone_id)
|
||||
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i);
|
||||
|
||||
/* Save Character Buffs */
|
||||
@@ -3959,7 +3959,7 @@ void Client::Sacrifice(Client *caster)
|
||||
Death_Struct *d = (Death_Struct *)app.pBuffer;
|
||||
d->spawn_id = GetID();
|
||||
d->killer_id = caster ? caster->GetID() : 0;
|
||||
d->bindzoneid = GetPP().binds[0].zoneId;
|
||||
d->bindzoneid = GetPP().binds[0].zone_id;
|
||||
d->spell_id = SPELL_UNKNOWN;
|
||||
d->attack_skill = 0xe7;
|
||||
d->damage = 0;
|
||||
@@ -4007,7 +4007,7 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) {
|
||||
PendingTranslocateData.spell_id = ts->SpellID = SpellID;
|
||||
|
||||
if((SpellID == 1422) || (SpellID == 1334) || (SpellID == 3243)) {
|
||||
PendingTranslocateData.zone_id = ts->ZoneID = m_pp.binds[0].zoneId;
|
||||
PendingTranslocateData.zone_id = ts->ZoneID = m_pp.binds[0].zone_id;
|
||||
PendingTranslocateData.instance_id = m_pp.binds[0].instance_id;
|
||||
PendingTranslocateData.x = ts->x = m_pp.binds[0].x;
|
||||
PendingTranslocateData.y = ts->y = m_pp.binds[0].y;
|
||||
@@ -4892,7 +4892,7 @@ void Client::SendRespawnBinds()
|
||||
BindStruct* b = &m_pp.binds[0];
|
||||
RespawnOption opt;
|
||||
opt.name = "Bind Location";
|
||||
opt.zone_id = b->zoneId;
|
||||
opt.zone_id = b->zone_id;
|
||||
opt.instance_id = b->instance_id;
|
||||
opt.x = b->x;
|
||||
opt.y = b->y;
|
||||
@@ -5289,11 +5289,11 @@ void Client::NotifyNewTitlesAvailable()
|
||||
|
||||
}
|
||||
|
||||
void Client::SetStartZone(uint32 zoneid, float x, float y, float z)
|
||||
void Client::SetStartZone(uint32 zoneid, float x, float y, float z, float heading)
|
||||
{
|
||||
// setting city to zero allows the player to use /setstartcity to set the city themselves
|
||||
if(zoneid == 0) {
|
||||
m_pp.binds[4].zoneId = 0;
|
||||
m_pp.binds[4].zone_id = 0;
|
||||
this->Message(Chat::Yellow,"Your starting city has been reset. Use /setstartcity to choose a new one");
|
||||
return;
|
||||
}
|
||||
@@ -5303,24 +5303,32 @@ void Client::SetStartZone(uint32 zoneid, float x, float y, float z)
|
||||
if(target_zone_name == nullptr)
|
||||
return;
|
||||
|
||||
m_pp.binds[4].zoneId = zoneid;
|
||||
m_pp.binds[4].zone_id = zoneid;
|
||||
if(zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) {
|
||||
m_pp.binds[4].instance_id = zone->GetInstanceID();
|
||||
}
|
||||
|
||||
if (x == 0 && y == 0 && z == 0) {
|
||||
content_db.GetSafePoints(ZoneName(m_pp.binds[4].zoneId), 0, &m_pp.binds[4].x, &m_pp.binds[4].y, &m_pp.binds[4].z);
|
||||
content_db.GetSafePoints(
|
||||
ZoneName(m_pp.binds[4].zone_id),
|
||||
0,
|
||||
&m_pp.binds[4].x,
|
||||
&m_pp.binds[4].y,
|
||||
&m_pp.binds[4].z,
|
||||
&m_pp.binds[4].heading
|
||||
);
|
||||
}
|
||||
else {
|
||||
m_pp.binds[4].x = x;
|
||||
m_pp.binds[4].y = y;
|
||||
m_pp.binds[4].z = z;
|
||||
m_pp.binds[4].heading = heading;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Client::GetStartZone()
|
||||
{
|
||||
return m_pp.binds[4].zoneId;
|
||||
return m_pp.binds[4].zone_id;
|
||||
}
|
||||
|
||||
void Client::ShowSkillsWindow()
|
||||
|
||||
+4
-3
@@ -426,7 +426,7 @@ public:
|
||||
inline const float GetBindY(uint32 index = 0) const { return m_pp.binds[index].y; }
|
||||
inline const float GetBindZ(uint32 index = 0) const { return m_pp.binds[index].z; }
|
||||
inline const float GetBindHeading(uint32 index = 0) const { return m_pp.binds[index].heading; }
|
||||
inline uint32 GetBindZoneID(uint32 index = 0) const { return m_pp.binds[index].zoneId; }
|
||||
inline uint32 GetBindZoneID(uint32 index = 0) const { return m_pp.binds[index].zone_id; }
|
||||
inline uint32 GetBindInstanceID(uint32 index = 0) const { return m_pp.binds[index].instance_id; }
|
||||
int32 CalcMaxMana();
|
||||
int32 CalcBaseMana();
|
||||
@@ -644,7 +644,8 @@ public:
|
||||
void GoToSafeCoords(uint16 zone_id, uint16 instance_id);
|
||||
void Gate(uint8 bindnum = 0);
|
||||
void SetBindPoint(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3());
|
||||
void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f);
|
||||
void SetBindPoint2(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec4& location = glm::vec4());
|
||||
void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f, float heading = 0.0f);
|
||||
uint32 GetStartZone(void);
|
||||
void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
|
||||
void MovePC(uint32 zoneID, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
|
||||
@@ -1765,7 +1766,7 @@ private:
|
||||
void ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm);
|
||||
void ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
|
||||
|
||||
glm::vec3 m_ZoneSummonLocation;
|
||||
glm::vec4 m_ZoneSummonLocation;
|
||||
uint16 zonesummon_id;
|
||||
uint8 zonesummon_ignorerestrictions;
|
||||
ZoneMode zone_mode;
|
||||
|
||||
+79
-44
@@ -1332,10 +1332,11 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
strcpy(lastname, m_pp.last_name);
|
||||
/* If PP is set to weird coordinates */
|
||||
if ((m_pp.x == -1 && m_pp.y == -1 && m_pp.z == -1) || (m_pp.x == -2 && m_pp.y == -2 && m_pp.z == -2)) {
|
||||
auto safePoint = zone->GetSafePoint();
|
||||
m_pp.x = safePoint.x;
|
||||
m_pp.y = safePoint.y;
|
||||
m_pp.z = safePoint.z;
|
||||
auto zone_safe_point = zone->GetSafePoint();
|
||||
m_pp.x = zone_safe_point.x;
|
||||
m_pp.y = zone_safe_point.y;
|
||||
m_pp.z = zone_safe_point.z;
|
||||
m_pp.heading = zone_safe_point.w;
|
||||
}
|
||||
/* If too far below ground, then fix */
|
||||
// float ground_z = GetGroundZ(m_pp.x, m_pp.y, m_pp.z);
|
||||
@@ -6594,34 +6595,45 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
GMZoneRequest_Struct* gmzr = (GMZoneRequest_Struct*)app->pBuffer;
|
||||
float tarx = -1, tary = -1, tarz = -1;
|
||||
float target_x = -1, target_y = -1, target_z = -1, target_heading;
|
||||
|
||||
int16 minstatus = 0;
|
||||
uint8 minlevel = 0;
|
||||
char tarzone[32];
|
||||
uint16 zid = gmzr->zone_id;
|
||||
int16 min_status = 0;
|
||||
uint8 min_level = 0;
|
||||
char target_zone[32];
|
||||
uint16 zone_id = gmzr->zone_id;
|
||||
if (gmzr->zone_id == 0)
|
||||
zid = zonesummon_id;
|
||||
const char * zname = ZoneName(zid);
|
||||
if (zname == nullptr)
|
||||
tarzone[0] = 0;
|
||||
zone_id = zonesummon_id;
|
||||
|
||||
const char* zone_short_name = ZoneName(zone_id);
|
||||
if (zone_short_name == nullptr)
|
||||
target_zone[0] = 0;
|
||||
else
|
||||
strcpy(tarzone, zname);
|
||||
strcpy(target_zone, zone_short_name);
|
||||
|
||||
// this both loads the safe points and does a sanity check on zone name
|
||||
if (!content_db.GetSafePoints(tarzone, 0, &tarx, &tary, &tarz, &minstatus, &minlevel)) {
|
||||
tarzone[0] = 0;
|
||||
if (!content_db.GetSafePoints(
|
||||
target_zone,
|
||||
0,
|
||||
&target_x,
|
||||
&target_y,
|
||||
&target_z,
|
||||
&target_heading,
|
||||
&min_status,
|
||||
&min_level
|
||||
)) {
|
||||
target_zone[0] = 0;
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GMZoneRequest, sizeof(GMZoneRequest_Struct));
|
||||
GMZoneRequest_Struct* gmzr2 = (GMZoneRequest_Struct*)outapp->pBuffer;
|
||||
strcpy(gmzr2->charname, this->GetName());
|
||||
gmzr2->zone_id = gmzr->zone_id;
|
||||
gmzr2->x = tarx;
|
||||
gmzr2->y = tary;
|
||||
gmzr2->z = tarz;
|
||||
gmzr2->x = target_x;
|
||||
gmzr2->y = target_y;
|
||||
gmzr2->z = target_z;
|
||||
gmzr2->heading = target_heading;
|
||||
// Next line stolen from ZoneChange as well... - This gives us a nicer message than the normal "zone is down" message...
|
||||
if (tarzone[0] != 0 && admin >= minstatus && GetLevel() >= minlevel)
|
||||
if (target_zone[0] != 0 && admin >= min_status && GetLevel() >= min_level)
|
||||
gmzr2->success = 1;
|
||||
else {
|
||||
std::cout << "GetZoneSafeCoords failed. zoneid = " << gmzr->zone_id << "; czone = " << zone->GetZoneID() << std::endl;
|
||||
@@ -12663,8 +12675,8 @@ void Client::Handle_OP_SetServerFilter(const EQApplicationPacket *app)
|
||||
void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
|
||||
{
|
||||
// if the character has a start city, don't let them use the command
|
||||
if (m_pp.binds[4].zoneId != 0 && m_pp.binds[4].zoneId != 189) {
|
||||
Message(Chat::Yellow, "Your home city has already been set.", m_pp.binds[4].zoneId, ZoneName(m_pp.binds[4].zoneId));
|
||||
if (m_pp.binds[4].zone_id != 0 && m_pp.binds[4].zone_id != 189) {
|
||||
Message(Chat::Yellow, "Your home city has already been set.", m_pp.binds[4].zone_id, ZoneName(m_pp.binds[4].zone_id));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12674,13 +12686,22 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
float x(0), y(0), z(0);
|
||||
uint32 zoneid = 0;
|
||||
uint32 startCity = (uint32)strtol((const char*)app->pBuffer, nullptr, 10);
|
||||
|
||||
std::string query = StringFormat(
|
||||
"SELECT zone_id, bind_id, x, y, z FROM start_zones "
|
||||
"WHERE player_class=%i AND player_deity=%i AND player_race=%i %s",
|
||||
float x = 0.0f, y = 0.0f, z = 0.0f, heading = 0.0f;
|
||||
uint32 zone_id = 0;
|
||||
uint32 start_city = (uint32)strtol((const char*)app->pBuffer, nullptr, 10);
|
||||
std::string query = fmt::format(
|
||||
SQL(
|
||||
SELECT
|
||||
`zone_id`, `bind_id`, `x`, `y`, `z`, `heading`
|
||||
FROM
|
||||
`start_zones`
|
||||
WHERE
|
||||
player_class = {}
|
||||
AND
|
||||
player_deity = {}
|
||||
AND
|
||||
player_race = {} {}
|
||||
),
|
||||
m_pp.class_,
|
||||
m_pp.deity,
|
||||
m_pp.race,
|
||||
@@ -12692,31 +12713,46 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
bool validCity = false;
|
||||
bool valid_city = false;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (atoi(row[1]) != 0)
|
||||
zoneid = atoi(row[1]);
|
||||
zone_id = atoi(row[1]);
|
||||
else
|
||||
zoneid = atoi(row[0]);
|
||||
zone_id = atoi(row[0]);
|
||||
|
||||
if (zoneid != startCity)
|
||||
if (zone_id != start_city)
|
||||
continue;
|
||||
|
||||
validCity = true;
|
||||
valid_city = true;
|
||||
x = atof(row[2]);
|
||||
y = atof(row[3]);
|
||||
z = atof(row[4]);
|
||||
heading = atof(row[5]);
|
||||
}
|
||||
|
||||
if (validCity) {
|
||||
if (valid_city) {
|
||||
Message(Chat::Yellow, "Your home city has been set");
|
||||
SetStartZone(startCity, x, y, z);
|
||||
SetStartZone(start_city, x, y, z, heading);
|
||||
return;
|
||||
}
|
||||
|
||||
query = StringFormat("SELECT zone_id, bind_id FROM start_zones "
|
||||
"WHERE player_class=%i AND player_deity=%i AND player_race=%i",
|
||||
m_pp.class_, m_pp.deity, m_pp.race);
|
||||
query = fmt::format(
|
||||
SQL(
|
||||
SELECT
|
||||
`zone_id`, `bind_id`
|
||||
FROM
|
||||
`start_zones`
|
||||
WHERE
|
||||
player_class = {}
|
||||
AND
|
||||
player_deity = {}
|
||||
AND
|
||||
player_race = {}
|
||||
),
|
||||
m_pp.class_,
|
||||
m_pp.deity,
|
||||
m_pp.race
|
||||
);
|
||||
results = content_db.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return;
|
||||
@@ -12725,13 +12761,12 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (atoi(row[1]) != 0)
|
||||
zoneid = atoi(row[1]);
|
||||
zone_id = atoi(row[1]);
|
||||
else
|
||||
zoneid = atoi(row[0]);
|
||||
zone_id = atoi(row[0]);
|
||||
|
||||
char* name = nullptr;
|
||||
content_db.GetZoneLongName(ZoneName(zoneid), &name);
|
||||
Message(Chat::Yellow, "%d - %s", zoneid, name);
|
||||
std::string zone_long_name = zone_store.GetZoneLongName(zone_id);
|
||||
Message(Chat::Yellow, "%d - %s", zone_id, zone_long_name.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -131,9 +131,9 @@ bool Client::Process() {
|
||||
CheckManaEndUpdate();
|
||||
|
||||
if (dead && dead_timer.Check()) {
|
||||
database.MoveCharacterToZone(GetName(), m_pp.binds[0].zoneId);
|
||||
database.MoveCharacterToZone(GetName(), m_pp.binds[0].zone_id);
|
||||
|
||||
m_pp.zone_id = m_pp.binds[0].zoneId;
|
||||
m_pp.zone_id = m_pp.binds[0].zone_id;
|
||||
m_pp.zoneInstance = m_pp.binds[0].instance_id;
|
||||
m_pp.x = m_pp.binds[0].x;
|
||||
m_pp.y = m_pp.binds[0].y;
|
||||
@@ -1996,7 +1996,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
|
||||
BindStruct* b = &m_pp.binds[0];
|
||||
default_to_bind = new RespawnOption;
|
||||
default_to_bind->name = "Bind Location";
|
||||
default_to_bind->zone_id = b->zoneId;
|
||||
default_to_bind->zone_id = b->zone_id;
|
||||
default_to_bind->instance_id = b->instance_id;
|
||||
default_to_bind->x = b->x;
|
||||
default_to_bind->y = b->y;
|
||||
|
||||
+3
-2
@@ -5199,7 +5199,7 @@ void command_gmzone(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
if (instance_id > 0) {
|
||||
float target_x = -1, target_y = -1, target_z = -1;
|
||||
float target_x = -1, target_y = -1, target_z = -1, target_heading = -1;
|
||||
int16 min_status = 0;
|
||||
uint8 min_level = 0;
|
||||
|
||||
@@ -5209,6 +5209,7 @@ void command_gmzone(Client *c, const Seperator *sep)
|
||||
&target_x,
|
||||
&target_y,
|
||||
&target_z,
|
||||
&target_heading,
|
||||
&min_status,
|
||||
&min_level
|
||||
)) {
|
||||
@@ -5218,7 +5219,7 @@ void command_gmzone(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::Yellow, "Zoning to private GM instance (%s) (%u)", zone_short_name, instance_id);
|
||||
|
||||
c->AssignToInstance(instance_id);
|
||||
c->MovePC(zone_id, instance_id, target_x, target_y, target_z, 0, 1);
|
||||
c->MovePC(zone_id, instance_id, target_x, target_y, target_z, target_heading, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-7
@@ -1495,14 +1495,19 @@ XS(XS__ding) {
|
||||
XS(XS__rebind);
|
||||
XS(XS__rebind) {
|
||||
dXSARGS;
|
||||
if (items != 4)
|
||||
Perl_croak(aTHX_ "Usage: quest::rebind(int zone_id, float x, float y, float z)");
|
||||
|
||||
int zone_id = (int) SvIV(ST(0));
|
||||
auto location = glm::vec3((float) SvNV(ST(1)), (float) SvNV(ST(2)), (float) SvNV(ST(3)));
|
||||
|
||||
quest_manager.rebind(zone_id, location);
|
||||
if (items < 4 || items > 5)
|
||||
Perl_croak(aTHX_ "Usage: quest::rebind(int zone_id, float x, float y, float z, [float heading])");
|
||||
|
||||
int zone_id = (int) SvIV(ST(0));
|
||||
float target_x = (float) SvNV(ST(1));
|
||||
float target_y = (float) SvNV(ST(2));
|
||||
float target_z = (float) SvNV(ST(3));
|
||||
if (items > 4) {
|
||||
float target_heading = (float) SvNV(ST(4));
|
||||
quest_manager.rebind(zone_id, glm::vec4(target_x, target_y, target_z, target_heading));
|
||||
} else {
|
||||
quest_manager.rebind(zone_id, glm::vec3(target_x, target_y, target_z));
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -299,6 +299,11 @@ void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float n
|
||||
self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
|
||||
}
|
||||
|
||||
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z, float new_heading) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetBindPoint2(0, to_zone, to_instance, glm::vec4(new_x, new_y, new_z, new_heading));
|
||||
}
|
||||
|
||||
float Lua_Client::GetBindX() {
|
||||
Lua_Safe_Call_Real();
|
||||
return self->GetBindX();
|
||||
@@ -2116,7 +2121,8 @@ luabind::scope lua_register_client() {
|
||||
.def("SetBindPoint", (void(Lua_Client::*)(int,int))&Lua_Client::SetBindPoint)
|
||||
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float))&Lua_Client::SetBindPoint)
|
||||
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float))&Lua_Client::SetBindPoint)
|
||||
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float, float))&Lua_Client::SetBindPoint)
|
||||
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float,float))&Lua_Client::SetBindPoint)
|
||||
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float,float,float))&Lua_Client::SetBindPoint)
|
||||
.def("GetBindX", (float(Lua_Client::*)(void))&Lua_Client::GetBindX)
|
||||
.def("GetBindX", (float(Lua_Client::*)(int))&Lua_Client::GetBindX)
|
||||
.def("GetBindY", (float(Lua_Client::*)(void))&Lua_Client::GetBindY)
|
||||
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
void SetBindPoint(int to_zone, int to_instance, float new_x);
|
||||
void SetBindPoint(int to_zone, int to_instance, float new_x, float new_y);
|
||||
void SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z);
|
||||
void SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z, float new_heading);
|
||||
float GetBindX();
|
||||
float GetBindX(int index);
|
||||
float GetBindY();
|
||||
@@ -249,6 +250,7 @@ public:
|
||||
void SetStartZone(int zone_id, float x);
|
||||
void SetStartZone(int zone_id, float x, float y);
|
||||
void SetStartZone(int zone_id, float x, float y, float z);
|
||||
void SetStartZone(int zone_id, float x, float y, float z, float heading);
|
||||
void KeyRingAdd(uint32 item);
|
||||
bool KeyRingCheck(uint32 item);
|
||||
void AddPVPPoints(uint32 points);
|
||||
|
||||
+2
-2
@@ -178,8 +178,8 @@ public:
|
||||
FACTION_VALUE CheckNPCFactionAlly(int32 other_faction);
|
||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
||||
|
||||
void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
|
||||
void Gate(uint8 bindnum = 0);
|
||||
void GoToBind(uint8 bind_number = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
|
||||
void Gate(uint8 bind_number = 0);
|
||||
|
||||
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
|
||||
void SetPetState(SpellBuff_Struct *buffs, uint32 *items);
|
||||
|
||||
+24
-44
@@ -753,47 +753,28 @@ XS(XS_Client_SetEXP) {
|
||||
XS(XS_Client_SetBindPoint); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_SetBindPoint) {
|
||||
dXSARGS;
|
||||
if (items < 1 || items > 6)
|
||||
Perl_croak(aTHX_ "Usage: Client::SetBindPoint(THIS, int to_zone = -1, int to_instance = 0, float new_x = 0.0f, float new_y = 0.0f, float new_z = 0.0f)"); // @categories Account and Character, Stats and Attributes
|
||||
if (items < 1 || items > 7)
|
||||
Perl_croak(aTHX_ "Usage: Client::SetBindPoint(THIS, [int to_zone = -1, int to_instance = 0, float new_x = 0.0f, float new_y = 0.0f, float new_z = 0.0f, float new_heading = 0.0f])"); // @categories Account and Character, Stats and Attributes
|
||||
{
|
||||
Client *THIS;
|
||||
int to_zone;
|
||||
int to_instance;
|
||||
float new_x;
|
||||
float new_y;
|
||||
float new_z;
|
||||
int to_zone = -1;
|
||||
int to_instance = 0;
|
||||
float new_x = 0.0f, new_y = 0.0f, new_z = 0.0f, new_heading = 0.0f;
|
||||
VALIDATE_THIS_IS_CLIENT;
|
||||
if (items < 2)
|
||||
to_zone = -1;
|
||||
else {
|
||||
if (items > 1)
|
||||
to_zone = (int) SvIV(ST(1));
|
||||
}
|
||||
|
||||
if (items < 3)
|
||||
to_instance = 0;
|
||||
else {
|
||||
if (items > 2)
|
||||
to_instance = (int) SvIV(ST(2));
|
||||
}
|
||||
|
||||
if (items < 4)
|
||||
new_x = 0.0f;
|
||||
else {
|
||||
if (items > 3)
|
||||
new_x = (float) SvNV(ST(3));
|
||||
}
|
||||
|
||||
if (items < 5)
|
||||
new_y = 0.0f;
|
||||
else {
|
||||
if (items > 4)
|
||||
new_y = (float) SvNV(ST(4));
|
||||
}
|
||||
|
||||
if (items < 6)
|
||||
new_z = 0.0f;
|
||||
else {
|
||||
if (items > 5)
|
||||
new_z = (float) SvNV(ST(5));
|
||||
}
|
||||
if (items > 6)
|
||||
new_heading = (float) SvNV(ST(6));
|
||||
|
||||
THIS->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
|
||||
THIS->SetBindPoint2(0, to_zone, to_instance, glm::vec4(new_x, new_y, new_z, new_heading));
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
@@ -3258,23 +3239,22 @@ XS(XS_Client_GetStartZone) {
|
||||
XS(XS_Client_SetStartZone);
|
||||
XS(XS_Client_SetStartZone) {
|
||||
dXSARGS;
|
||||
if (items != 2 && items != 5)
|
||||
Perl_croak(aTHX_
|
||||
"Usage: Client::SetStartZone(THIS, uint32 zone_id, [float x = 0], [float y = 0], [float z = 0])");
|
||||
if (items != 2 && items != 5 && items != 6)
|
||||
Perl_croak(aTHX_ "Usage: Client::SetStartZone(THIS, uint32 zone_id, [float x = 0, float y = 0, float z = 0, [float heading = 0]])");
|
||||
{
|
||||
Client *THIS;
|
||||
uint32 zoneid = (uint32) SvUV(ST(1));
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
float x = 0.0f, y = 0.0f, z = 0.0f, heading = 0.0f;
|
||||
VALIDATE_THIS_IS_CLIENT;
|
||||
if (items == 5) {
|
||||
x = SvNV(ST(2));
|
||||
y = SvNV(ST(3));
|
||||
z = SvNV(ST(4));
|
||||
x = (float) SvNV(ST(2));
|
||||
y = (float) SvNV(ST(3));
|
||||
z = (float) SvNV(ST(4));
|
||||
}
|
||||
if (items == 6)
|
||||
heading = (float) SvNV(ST(5));
|
||||
|
||||
THIS->SetStartZone(zoneid, x, y, z);
|
||||
THIS->SetStartZone(zoneid, x, y, z, heading);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
@@ -5485,7 +5465,7 @@ XS(boot_Client) {
|
||||
newXSproto(strcpy(buf, "SetBaseRace"), XS_Client_SetBaseRace, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBecomeNPC"), XS_Client_SetBecomeNPC, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBecomeNPCLevel"), XS_Client_SetBecomeNPCLevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBindPoint"), XS_Client_SetBindPoint, file, "$;$$$$$");
|
||||
newXSproto(strcpy(buf, "SetBindPoint"), XS_Client_SetBindPoint, file, "$;$$$$$$");
|
||||
newXSproto(strcpy(buf, "SetConsumption"), XS_Client_SetConsumption, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetClientMaxLevel"), XS_Client_SetClientMaxLevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetCustomItemData"), XS_Client_SetCustomItemData, file, "$$$$");
|
||||
@@ -5509,7 +5489,7 @@ XS(boot_Client) {
|
||||
newXSproto(strcpy(buf, "SetSecondaryWeaponOrnamentation"), XS_Client_SetSecondaryWeaponOrnamentation, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetSkill"), XS_Client_SetSkill, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetSkillPoints"), XS_Client_SetSkillPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetStartZone"), XS_Client_SetStartZone, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetStartZone"), XS_Client_SetStartZone, file, "$$;$$$$");
|
||||
newXSproto(strcpy(buf, "SetStats"), XS_Client_SetStats, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetThirst"), XS_Client_SetThirst, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetTint"), XS_Client_SetTint, file, "$$$");
|
||||
|
||||
+10
-3
@@ -1673,10 +1673,17 @@ void QuestManager::ding() {
|
||||
|
||||
}
|
||||
|
||||
void QuestManager::rebind(int zoneid, const glm::vec3& location) {
|
||||
void QuestManager::rebind(int zone_id, const glm::vec3& location) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if(initiator && initiator->IsClient()) {
|
||||
initiator->SetBindPoint(0, zoneid, 0, location);
|
||||
initiator->SetBindPoint(0, zone_id, 0, location);
|
||||
}
|
||||
}
|
||||
|
||||
void QuestManager::rebind(int zone_id, const glm::vec4& location) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if(initiator && initiator->IsClient()) {
|
||||
initiator->SetBindPoint2(0, zone_id, 0, location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4285,4 +4292,4 @@ std::string QuestManager::secondstotime(int duration) {
|
||||
time_string = fmt::format("{} {}", seconds, second_string);
|
||||
}
|
||||
return time_string;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -151,7 +151,8 @@ public:
|
||||
void targlobal(const char *varname, const char *value, const char *duration, int npcid, int charid, int zoneid);
|
||||
void delglobal(const char *varname);
|
||||
void ding();
|
||||
void rebind(int zoneid, const glm::vec3& location);
|
||||
void rebind(int zone_id, const glm::vec3& location);
|
||||
void rebind(int zone_id, const glm::vec4& location);
|
||||
void start(int wp);
|
||||
void stop();
|
||||
void pause(int duration);
|
||||
|
||||
+1
-1
@@ -941,7 +941,7 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
||||
spawn2_timer(1000),
|
||||
hot_reload_timer(1000),
|
||||
qglobal_purge_timer(30000),
|
||||
m_SafePoint(0.0f,0.0f,0.0f),
|
||||
m_SafePoint(0.0f,0.0f,0.0f,0.0f),
|
||||
m_Graveyard(0.0f,0.0f,0.0f,0.0f)
|
||||
{
|
||||
zoneid = in_zoneid;
|
||||
|
||||
+2
-2
@@ -167,7 +167,7 @@ public:
|
||||
inline const uint32 &graveyard_zoneid() { return pgraveyard_zoneid; }
|
||||
inline const uint32 GetInstanceID() const { return instanceid; }
|
||||
inline const uint32 GetZoneID() const { return zoneid; }
|
||||
inline glm::vec3 GetSafePoint() { return m_SafePoint; }
|
||||
inline glm::vec4 GetSafePoint() { return m_SafePoint; }
|
||||
inline glm::vec4 GetGraveyardPoint() { return m_Graveyard; }
|
||||
inline std::vector<int> GetGlobalLootTables(NPC *mob) const { return m_global_loot.GetGlobalLootTables(mob); }
|
||||
inline Timer *GetInstanceTimer() { return Instance_Timer; }
|
||||
@@ -376,7 +376,7 @@ private:
|
||||
char *map_name;
|
||||
char *short_name;
|
||||
char file_name[16];
|
||||
glm::vec3 m_SafePoint;
|
||||
glm::vec4 m_SafePoint;
|
||||
glm::vec4 m_Graveyard;
|
||||
int default_ruleset;
|
||||
int zone_total_blocked_spells;
|
||||
|
||||
+3
-3
@@ -1470,7 +1470,7 @@ bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Str
|
||||
if (index < 0 || index > 4)
|
||||
continue;
|
||||
|
||||
pp->binds[index].zoneId = atoi(row[1]);
|
||||
pp->binds[index].zone_id = atoi(row[1]);
|
||||
pp->binds[index].instance_id = atoi(row[2]);
|
||||
pp->binds[index].x = atoi(row[3]);
|
||||
pp->binds[index].y = atoi(row[4]);
|
||||
@@ -1493,10 +1493,10 @@ bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, const BindStruct
|
||||
std::string query =
|
||||
StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot) VALUES (%u, "
|
||||
"%u, %u, %f, %f, %f, %f, %i)",
|
||||
character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
|
||||
character_id, bind.zone_id, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
|
||||
|
||||
LogDebug("ZoneDatabase::SaveCharacterBindPoint for character ID: [{}] zone_id: [{}] instance_id: [{}] position: [{}] [{}] [{}] [{}] bind_num: [{}]",
|
||||
character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
|
||||
character_id, bind.zone_id, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.RowsAffected())
|
||||
|
||||
+1
-1
@@ -319,7 +319,7 @@ public:
|
||||
|
||||
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges);
|
||||
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
|
||||
bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num);
|
||||
bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_number);
|
||||
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
|
||||
|
||||
+181
-112
@@ -78,11 +78,11 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
target_zone_id = zonesummon_id;
|
||||
break;
|
||||
case GateToBindPoint:
|
||||
target_zone_id = m_pp.binds[0].zoneId;
|
||||
target_zone_id = m_pp.binds[0].zone_id;
|
||||
target_instance_id = m_pp.binds[0].instance_id;
|
||||
break;
|
||||
case ZoneToBindPoint:
|
||||
target_zone_id = m_pp.binds[0].zoneId;
|
||||
target_zone_id = m_pp.binds[0].zone_id;
|
||||
target_instance_id = m_pp.binds[0].instance_id;
|
||||
break;
|
||||
case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going.
|
||||
@@ -170,11 +170,21 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
/* Load up the Safe Coordinates, restrictions and verify the zone name*/
|
||||
float safe_x, safe_y, safe_z;
|
||||
int16 minstatus = 0;
|
||||
uint8 minlevel = 0;
|
||||
float safe_x, safe_y, safe_z, safe_heading;
|
||||
int16 min_status = 0;
|
||||
uint8 min_level = 0;
|
||||
char flag_needed[128];
|
||||
if(!content_db.GetSafePoints(target_zone_name, database.GetInstanceVersion(target_instance_id), &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_needed)) {
|
||||
if(!content_db.GetSafePoints(
|
||||
target_zone_name,
|
||||
database.GetInstanceVersion(target_instance_id),
|
||||
&safe_x,
|
||||
&safe_y,
|
||||
&safe_z,
|
||||
&safe_heading,
|
||||
&min_status,
|
||||
&min_level,
|
||||
flag_needed
|
||||
)) {
|
||||
//invalid zone...
|
||||
Message(Chat::Red, "Invalid target zone while getting safe points.");
|
||||
LogError("Zoning [{}]: Unable to get safe coordinates for zone [{}]", GetName(), target_zone_name);
|
||||
@@ -189,41 +199,54 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
|
||||
//handle circumvention of zone restrictions
|
||||
//we need the value when creating the outgoing packet as well.
|
||||
uint8 ignorerestrictions = zonesummon_ignorerestrictions;
|
||||
uint8 ignore_restrictions = zonesummon_ignorerestrictions;
|
||||
zonesummon_ignorerestrictions = 0;
|
||||
|
||||
float dest_x=0, dest_y=0, dest_z=0, dest_h;
|
||||
dest_h = GetHeading();
|
||||
float target_x = 0, target_y = 0, target_z = 0, target_heading = 0;
|
||||
switch(zone_mode) {
|
||||
case EvacToSafeCoords:
|
||||
case ZoneToSafeCoords:
|
||||
LogDebug("Zoning [{}] to safe coords ([{}],[{}],[{}]) in [{}] ([{}])", GetName(), safe_x, safe_y, safe_z, target_zone_name, target_zone_id);
|
||||
dest_x = safe_x;
|
||||
dest_y = safe_y;
|
||||
dest_z = safe_z;
|
||||
LogDebug(
|
||||
"Zoning [{}] to safe coords ([{}], [{}], [{}], [{}]) in [{}] ([{}])",
|
||||
GetName(),
|
||||
safe_x,
|
||||
safe_y,
|
||||
safe_z,
|
||||
safe_heading,
|
||||
target_zone_name,
|
||||
target_zone_id
|
||||
);
|
||||
target_x = safe_x;
|
||||
target_y = safe_y;
|
||||
target_z = safe_z;
|
||||
target_heading = safe_heading;
|
||||
break;
|
||||
case GMSummon:
|
||||
dest_x = m_ZoneSummonLocation.x;
|
||||
dest_y = m_ZoneSummonLocation.y;
|
||||
dest_z = m_ZoneSummonLocation.z;
|
||||
ignorerestrictions = 1;
|
||||
target_x = m_ZoneSummonLocation.x;
|
||||
target_y = m_ZoneSummonLocation.y;
|
||||
target_z = m_ZoneSummonLocation.z;
|
||||
target_heading = m_ZoneSummonLocation.w;
|
||||
ignore_restrictions = 1;
|
||||
break;
|
||||
case GateToBindPoint:
|
||||
dest_x = m_pp.binds[0].x;
|
||||
dest_y = m_pp.binds[0].y;
|
||||
dest_z = m_pp.binds[0].z;
|
||||
target_x = m_pp.binds[0].x;
|
||||
target_x = m_pp.binds[0].y;
|
||||
target_x = m_pp.binds[0].z;
|
||||
target_x = m_pp.binds[0].heading;
|
||||
break;
|
||||
case ZoneToBindPoint:
|
||||
dest_x = m_pp.binds[0].x;
|
||||
dest_y = m_pp.binds[0].y;
|
||||
dest_z = m_pp.binds[0].z;
|
||||
ignorerestrictions = 1; //can always get to our bind point? seems exploitable
|
||||
target_x = m_pp.binds[0].x;
|
||||
target_y = m_pp.binds[0].y;
|
||||
target_z = m_pp.binds[0].z;
|
||||
target_heading = m_pp.binds[0].heading;
|
||||
ignore_restrictions = 1; //can always get to our bind point? seems exploitable
|
||||
break;
|
||||
case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going.
|
||||
//recycle zonesummon variables
|
||||
dest_x = m_ZoneSummonLocation.x;
|
||||
dest_y = m_ZoneSummonLocation.y;
|
||||
dest_z = m_ZoneSummonLocation.z;
|
||||
target_x = m_ZoneSummonLocation.x;
|
||||
target_y = m_ZoneSummonLocation.y;
|
||||
target_z = m_ZoneSummonLocation.z;
|
||||
target_heading = m_ZoneSummonLocation.w;
|
||||
break;
|
||||
case ZoneUnsolicited: //client came up with this on its own.
|
||||
//client requested a zoning... what are the cases when this could happen?
|
||||
@@ -234,21 +257,24 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
|
||||
//999999 is a placeholder for 'same as where they were from'
|
||||
if(zone_point->target_x == 999999)
|
||||
dest_x = GetX();
|
||||
target_x = GetX();
|
||||
else
|
||||
dest_x = zone_point->target_x;
|
||||
target_x = zone_point->target_x;
|
||||
|
||||
if(zone_point->target_y == 999999)
|
||||
dest_y = GetY();
|
||||
target_y = GetY();
|
||||
else
|
||||
dest_y = zone_point->target_y;
|
||||
target_y = zone_point->target_y;
|
||||
|
||||
if(zone_point->target_z == 999999)
|
||||
dest_z=GetZ();
|
||||
target_z = GetZ();
|
||||
else
|
||||
dest_z = zone_point->target_z;
|
||||
target_z = zone_point->target_z;
|
||||
|
||||
if(zone_point->target_heading == 999)
|
||||
dest_h = GetHeading();
|
||||
target_heading = GetHeading();
|
||||
else
|
||||
dest_h = zone_point->target_heading;
|
||||
target_heading = zone_point->target_heading;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -272,12 +298,12 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
//not sure when we would use ZONE_ERROR_NOTREADY
|
||||
|
||||
//enforce min status and level
|
||||
if (!ignorerestrictions && (Admin() < minstatus || GetLevel() < minlevel))
|
||||
if (!ignore_restrictions && (Admin() < min_status || GetLevel() < min_level))
|
||||
{
|
||||
myerror = ZONE_ERROR_NOEXPERIENCE;
|
||||
}
|
||||
|
||||
if(!ignorerestrictions && flag_needed[0] != '\0') {
|
||||
if(!ignore_restrictions && flag_needed[0] != '\0') {
|
||||
//the flag needed string is not empty, meaning a flag is required.
|
||||
if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id))
|
||||
{
|
||||
@@ -343,7 +369,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
|
||||
if(myerror == 1) {
|
||||
//we have successfully zoned
|
||||
DoZoneSuccess(zc, target_zone_id, target_instance_id, dest_x, dest_y, dest_z, dest_h, ignorerestrictions);
|
||||
DoZoneSuccess(zc, target_zone_id, target_instance_id, target_x, target_y, target_z, target_heading, ignore_restrictions);
|
||||
} else {
|
||||
LogError("Zoning [{}]: Rules prevent this char from zoning into [{}]", GetName(), target_zone_name);
|
||||
SendZoneError(zc, myerror);
|
||||
@@ -463,7 +489,7 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc
|
||||
|
||||
//reset to unsolicited.
|
||||
zone_mode = ZoneUnsolicited;
|
||||
m_ZoneSummonLocation = glm::vec3();
|
||||
m_ZoneSummonLocation = glm::vec4();
|
||||
zonesummon_id = 0;
|
||||
zonesummon_ignorerestrictions = 0;
|
||||
}
|
||||
@@ -647,29 +673,24 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
||||
return;
|
||||
}
|
||||
iZoneNameLength = strlen(pZoneName);
|
||||
glm::vec3 safePoint;
|
||||
|
||||
glm::vec4 zone_safe_point;
|
||||
switch(zm) {
|
||||
case EvacToSafeCoords:
|
||||
case ZoneToSafeCoords:
|
||||
safePoint = zone->GetSafePoint();
|
||||
x = safePoint.x;
|
||||
y = safePoint.y;
|
||||
z = safePoint.z;
|
||||
SetHeading(heading);
|
||||
zone_safe_point = zone->GetSafePoint();
|
||||
x = zone_safe_point.x;
|
||||
y = zone_safe_point.y;
|
||||
z = zone_safe_point.z;
|
||||
heading = zone_safe_point.w;
|
||||
break;
|
||||
case GMSummon:
|
||||
m_Position = glm::vec4(x, y, z, heading);
|
||||
m_ZoneSummonLocation = glm::vec3(m_Position);
|
||||
SetHeading(heading);
|
||||
|
||||
m_ZoneSummonLocation = m_Position;
|
||||
zonesummon_id = zoneID;
|
||||
zonesummon_ignorerestrictions = 1;
|
||||
break;
|
||||
case ZoneSolicited:
|
||||
m_ZoneSummonLocation = glm::vec3(x,y,z);
|
||||
SetHeading(heading);
|
||||
|
||||
m_ZoneSummonLocation = glm::vec4(x, y, z, heading);
|
||||
zonesummon_id = zoneID;
|
||||
zonesummon_ignorerestrictions = ignorerestrictions;
|
||||
break;
|
||||
@@ -684,23 +705,20 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
||||
y = m_Position.y = m_pp.binds[0].y;
|
||||
z = m_Position.z = m_pp.binds[0].z;
|
||||
heading = m_pp.binds[0].heading;
|
||||
|
||||
zonesummon_ignorerestrictions = 1;
|
||||
LogDebug("Player [{}] has died and will be zoned to bind point in zone: [{}] at LOC x=[{}], y=[{}], z=[{}], heading=[{}]",
|
||||
GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
|
||||
break;
|
||||
case SummonPC:
|
||||
m_ZoneSummonLocation = glm::vec3(x, y, z);
|
||||
m_Position = glm::vec4(m_ZoneSummonLocation, 0.0f);
|
||||
SetHeading(heading);
|
||||
m_ZoneSummonLocation = glm::vec4(x, y, z, heading);
|
||||
m_Position = m_ZoneSummonLocation;
|
||||
break;
|
||||
case Rewind:
|
||||
LogDebug("[{}] has requested a /rewind from [{}], [{}], [{}], to [{}], [{}], [{}] in [{}]", GetName(),
|
||||
m_Position.x, m_Position.y, m_Position.z,
|
||||
m_RewindLocation.x, m_RewindLocation.y, m_RewindLocation.z, zone->GetShortName());
|
||||
m_ZoneSummonLocation = glm::vec3(x, y, z);
|
||||
m_Position = glm::vec4(m_ZoneSummonLocation, 0.0f);
|
||||
SetHeading(heading);
|
||||
m_ZoneSummonLocation = glm::vec4(x, y, z, heading);
|
||||
m_Position = m_ZoneSummonLocation;
|
||||
break;
|
||||
default:
|
||||
LogError("Client::ZonePC() received a reguest to perform an unsupported client zone operation");
|
||||
@@ -847,7 +865,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
||||
{
|
||||
if(zm != EvacToSafeCoords && zm != ZoneToSafeCoords && zm != ZoneToBindPoint)
|
||||
{
|
||||
m_ZoneSummonLocation = glm::vec3();
|
||||
m_ZoneSummonLocation = glm::vec4();
|
||||
zonesummon_id = 0;
|
||||
zonesummon_ignorerestrictions = 0;
|
||||
zone_mode = ZoneUnsolicited;
|
||||
@@ -866,61 +884,100 @@ void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) {
|
||||
}
|
||||
|
||||
|
||||
void Mob::Gate(uint8 bindnum) {
|
||||
GoToBind(bindnum);
|
||||
void Mob::Gate(uint8 bind_number) {
|
||||
GoToBind(bind_number);
|
||||
if (RuleB(NPC, NPCHealOnGate) && this->IsNPC() && this->GetHPRatio() <= RuleR(NPC, NPCHealOnGateAmount)) {
|
||||
auto HealAmount = (RuleR(NPC, NPCHealOnGateAmount) / 100);
|
||||
SetHP(int(this->GetMaxHP() * HealAmount));
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Gate(uint8 bindnum) {
|
||||
Mob::Gate(bindnum);
|
||||
void Client::Gate(uint8 bind_number) {
|
||||
Mob::Gate(bind_number);
|
||||
}
|
||||
|
||||
void NPC::Gate(uint8 bindnum) {
|
||||
void NPC::Gate(uint8 bind_number) {
|
||||
entity_list.MessageCloseString(this, true, RuleI(Range, SpellMessages), Chat::Spells, GATES, GetCleanName());
|
||||
|
||||
Mob::Gate(bindnum);
|
||||
Mob::Gate(bind_number);
|
||||
}
|
||||
|
||||
void Client::SetBindPoint(int bind_num, int to_zone, int to_instance, const glm::vec3 &location)
|
||||
void Client::SetBindPoint(int bind_number, int to_zone, int to_instance, const glm::vec3 &location)
|
||||
{
|
||||
if (bind_num < 0 || bind_num >= 4)
|
||||
bind_num = 0;
|
||||
if (bind_number < 0 || bind_number >= 4)
|
||||
bind_number = 0;
|
||||
|
||||
if (to_zone == -1) {
|
||||
m_pp.binds[bind_num].zoneId = zone->GetZoneID();
|
||||
m_pp.binds[bind_num].instance_id =
|
||||
(zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0;
|
||||
m_pp.binds[bind_num].x = m_Position.x;
|
||||
m_pp.binds[bind_num].y = m_Position.y;
|
||||
m_pp.binds[bind_num].z = m_Position.z;
|
||||
m_pp.binds[bind_number].zone_id = zone->GetZoneID();
|
||||
m_pp.binds[bind_number].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0;
|
||||
m_pp.binds[bind_number].x = m_Position.x;
|
||||
m_pp.binds[bind_number].y = m_Position.y;
|
||||
m_pp.binds[bind_number].z = m_Position.z;
|
||||
} else {
|
||||
m_pp.binds[bind_num].zoneId = to_zone;
|
||||
m_pp.binds[bind_num].instance_id = to_instance;
|
||||
m_pp.binds[bind_num].x = location.x;
|
||||
m_pp.binds[bind_num].y = location.y;
|
||||
m_pp.binds[bind_num].z = location.z;
|
||||
m_pp.binds[bind_number].zone_id = to_zone;
|
||||
m_pp.binds[bind_number].instance_id = to_instance;
|
||||
m_pp.binds[bind_number].x = location.x;
|
||||
m_pp.binds[bind_number].y = location.y;
|
||||
m_pp.binds[bind_number].z = location.z;
|
||||
}
|
||||
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_num], bind_num);
|
||||
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_number], bind_number);
|
||||
}
|
||||
|
||||
void Client::GoToBind(uint8 bindnum) {
|
||||
void Client::SetBindPoint2(int bind_number, int to_zone, int to_instance, const glm::vec4 &location)
|
||||
{
|
||||
if (bind_number < 0 || bind_number >= 4)
|
||||
bind_number = 0;
|
||||
|
||||
if (to_zone == -1) {
|
||||
m_pp.binds[bind_number].zone_id = zone->GetZoneID();
|
||||
m_pp.binds[bind_number].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0;
|
||||
m_pp.binds[bind_number].x = m_Position.x;
|
||||
m_pp.binds[bind_number].y = m_Position.y;
|
||||
m_pp.binds[bind_number].z = m_Position.z;
|
||||
m_pp.binds[bind_number].heading = m_Position.w;
|
||||
} else {
|
||||
m_pp.binds[bind_number].zone_id = to_zone;
|
||||
m_pp.binds[bind_number].instance_id = to_instance;
|
||||
m_pp.binds[bind_number].x = location.x;
|
||||
m_pp.binds[bind_number].y = location.y;
|
||||
m_pp.binds[bind_number].z = location.z;
|
||||
m_pp.binds[bind_number].heading = location.w;
|
||||
}
|
||||
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_number], bind_number);
|
||||
}
|
||||
|
||||
void Client::GoToBind(uint8 bind_number) {
|
||||
// if the bind number is invalid, use the primary bind
|
||||
if(bindnum > 4)
|
||||
bindnum = 0;
|
||||
if(bind_number > 4)
|
||||
bind_number = 0;
|
||||
|
||||
// move the client, which will zone them if needed.
|
||||
// ignore restrictions on the zone request..?
|
||||
if(bindnum == 0)
|
||||
MovePC(m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, 0.0f, 0.0f, 0.0f, 0.0f, 1, GateToBindPoint);
|
||||
if(bind_number == 0)
|
||||
MovePC(
|
||||
m_pp.binds[0].zone_id,
|
||||
m_pp.binds[0].instance_id,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1,
|
||||
GateToBindPoint
|
||||
);
|
||||
else
|
||||
MovePC(m_pp.binds[bindnum].zoneId, m_pp.binds[bindnum].instance_id, m_pp.binds[bindnum].x, m_pp.binds[bindnum].y, m_pp.binds[bindnum].z, m_pp.binds[bindnum].heading, 1);
|
||||
MovePC(
|
||||
m_pp.binds[bind_number].zone_id,
|
||||
m_pp.binds[bind_number].instance_id,
|
||||
m_pp.binds[bind_number].x,
|
||||
m_pp.binds[bind_number].y,
|
||||
m_pp.binds[bind_number].z,
|
||||
m_pp.binds[bind_number].heading,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
void Client::GoToDeath() {
|
||||
MovePC(m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, 0.0f, 0.0f, 0.0f, 0.0f, 1, ZoneToBindPoint);
|
||||
MovePC(m_pp.binds[0].zone_id, m_pp.binds[0].instance_id, 0.0f, 0.0f, 0.0f, 0.0f, 1, ZoneToBindPoint);
|
||||
}
|
||||
|
||||
void Client::SetZoneFlag(uint32 zone_id) {
|
||||
@@ -982,26 +1039,28 @@ void Client::SendZoneFlagInfo(Client *to) const {
|
||||
to->Message(Chat::White, "Flags for %s:", GetName());
|
||||
|
||||
for(; cur != end; ++cur) {
|
||||
uint32 zoneid = *cur;
|
||||
|
||||
const char *short_name = ZoneName(zoneid);
|
||||
|
||||
char *long_name = nullptr;
|
||||
content_db.GetZoneLongName(short_name, &long_name);
|
||||
if(long_name == nullptr)
|
||||
long_name = empty;
|
||||
|
||||
float safe_x, safe_y, safe_z;
|
||||
int16 minstatus = 0;
|
||||
uint8 minlevel = 0;
|
||||
uint32 zone_id = *cur;
|
||||
const char* zone_short_name = ZoneName(zone_id);
|
||||
std::string zone_long_name = zone_store.GetZoneLongName(zone_id);
|
||||
float safe_x, safe_y, safe_z, safe_heading;
|
||||
int16 min_status = 0;
|
||||
uint8 min_level = 0;
|
||||
char flag_name[128];
|
||||
if(!content_db.GetSafePoints(short_name, 0, &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_name)) {
|
||||
if(!content_db.GetSafePoints(
|
||||
zone_short_name,
|
||||
0,
|
||||
&safe_x,
|
||||
&safe_y,
|
||||
&safe_z,
|
||||
&safe_heading,
|
||||
&min_status,
|
||||
&min_level,
|
||||
flag_name
|
||||
)) {
|
||||
strcpy(flag_name, "(ERROR GETTING NAME)");
|
||||
}
|
||||
|
||||
to->Message(Chat::White, "Has Flag %s for zone %s (%d,%s)", flag_name, long_name, zoneid, short_name);
|
||||
if(long_name != empty)
|
||||
delete[] long_name;
|
||||
to->Message(Chat::White, "Has Flag %s for zone %s (%d,%s)", flag_name, zone_long_name.c_str(), zone_id, zone_short_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1013,22 +1072,32 @@ bool Client::CanBeInZone() {
|
||||
if(Admin() >= RuleI(GM, MinStatusToZoneAnywhere))
|
||||
return(true);
|
||||
|
||||
float safe_x, safe_y, safe_z;
|
||||
int16 minstatus = 0;
|
||||
uint8 minlevel = 0;
|
||||
float safe_x, safe_y, safe_z, safe_heading;
|
||||
int16 min_status = 0;
|
||||
uint8 min_level = 0;
|
||||
char flag_needed[128];
|
||||
if(!content_db.GetSafePoints(zone->GetShortName(), zone->GetInstanceVersion(), &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_needed)) {
|
||||
if(!content_db.GetSafePoints(
|
||||
zone->GetShortName(),
|
||||
zone->GetInstanceVersion(),
|
||||
&safe_x,
|
||||
&safe_y,
|
||||
&safe_z,
|
||||
&safe_heading,
|
||||
&min_status,
|
||||
&min_level,
|
||||
flag_needed
|
||||
)) {
|
||||
//this should not happen...
|
||||
LogDebug("[CLIENT] Unable to query zone info for ourself [{}]", zone->GetShortName());
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(GetLevel() < minlevel) {
|
||||
LogDebug("[CLIENT] Character does not meet min level requirement ([{}] < [{}])!", GetLevel(), minlevel);
|
||||
if(GetLevel() < min_level) {
|
||||
LogDebug("[CLIENT] Character does not meet min level requirement ([{}] < [{}])!", GetLevel(), min_level);
|
||||
return(false);
|
||||
}
|
||||
if(Admin() < minstatus) {
|
||||
LogDebug("[CLIENT] Character does not meet min status requirement ([{}] < [{}])!", Admin(), minstatus);
|
||||
if(Admin() < min_status) {
|
||||
LogDebug("[CLIENT] Character does not meet min status requirement ([{}] < [{}])!", Admin(), min_status);
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user