mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Quest API] Add Instance ID/Version exports to EVENT_ZONE. (#2502)
# Perl - Add `$from_instance_id` to EVENT_ZONE in Perl. - Add `$from_instance_version` to EVENT_ZONE in Perl. - Add `$target_instance_id` to EVENT_ZONE in Perl. - Add `$target_instance_version` to EVENT_ZONE in Perl. # Lua - Add `e.from_instance_id` to EVENT_ZONE in Lua. - Add `e.from_instance_version` to EVENT_ZONE in Lua. - Add `e.instance_id` to EVENT_ZONE in Lua. - Add `e.instance_version` to EVENT_ZONE in Lua. # Notes - This will allow Operators to prevent people from entering zones by Instance ID or Instance Version.
This commit is contained in:
parent
9c7dd70b5f
commit
13b2af1a91
@ -1435,7 +1435,11 @@ void PerlembParser::ExportEventVariables(
|
||||
case EVENT_ZONE: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "from_zone_id", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "target_zone_id", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "from_instance_id", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "from_instance_version", sep.arg[2]);
|
||||
ExportVar(package_name.c_str(), "target_zone_id", sep.arg[3]);
|
||||
ExportVar(package_name.c_str(), "target_instance_id", sep.arg[4]);
|
||||
ExportVar(package_name.c_str(), "target_instance_version", sep.arg[5]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -434,7 +434,19 @@ void handle_player_zone(QuestInterface *parse, lua_State* L, Client* client, std
|
||||
lua_setfield(L, -2, "from_zone_id");
|
||||
|
||||
lua_pushinteger(L, std::stoi(sep.arg[1]));
|
||||
lua_setfield(L, -2, "from_instance_id");
|
||||
|
||||
lua_pushinteger(L, std::stoi(sep.arg[2]));
|
||||
lua_setfield(L, -2, "from_instance_version");
|
||||
|
||||
lua_pushinteger(L, std::stoi(sep.arg[3]));
|
||||
lua_setfield(L, -2, "zone_id");
|
||||
|
||||
lua_pushinteger(L, std::stoi(sep.arg[4]));
|
||||
lua_setfield(L, -2, "instance_id");
|
||||
|
||||
lua_pushinteger(L, std::stoi(sep.arg[5]));
|
||||
lua_setfield(L, -2, "instance_version");
|
||||
}
|
||||
|
||||
void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
|
||||
315
zone/zoning.cpp
315
zone/zoning.cpp
@ -56,80 +56,73 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
LogDebug("Zone request from [{}]", GetName());
|
||||
DumpPacket(app);
|
||||
#endif
|
||||
ZoneChange_Struct* zc=(ZoneChange_Struct*)app->pBuffer;
|
||||
auto* zc = (ZoneChange_Struct*)app->pBuffer;
|
||||
|
||||
uint16 target_zone_id = 0;
|
||||
uint16 target_instance_id = zc->instanceID;
|
||||
auto target_instance_id = zc->instanceID;
|
||||
ZonePoint* zone_point = nullptr;
|
||||
|
||||
//figure out where they are going.
|
||||
if(zc->zoneID == 0) {
|
||||
if (zc->zoneID == 0) {
|
||||
//client dosent know where they are going...
|
||||
//try to figure it out for them.
|
||||
|
||||
switch(zone_mode) {
|
||||
case EvacToSafeCoords:
|
||||
case ZoneToSafeCoords:
|
||||
//going to safe coords, but client dosent know where?
|
||||
//assume it is this zone for now.
|
||||
target_zone_id = zone->GetZoneID();
|
||||
break;
|
||||
case GMSummon:
|
||||
target_zone_id = zonesummon_id;
|
||||
break;
|
||||
case GateToBindPoint:
|
||||
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].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.
|
||||
target_zone_id = zonesummon_id;
|
||||
break;
|
||||
case ZoneUnsolicited: //client came up with this on its own.
|
||||
zone_point = zone->GetClosestZonePointWithoutZone(GetX(), GetY(), GetZ(), this, ZONEPOINT_NOZONE_RANGE);
|
||||
if(zone_point) {
|
||||
//we found a zone point, which is a reasonable distance away
|
||||
//assume that is the one were going with.
|
||||
target_zone_id = zone_point->target_zone_id;
|
||||
target_instance_id = zone_point->target_zone_instance;
|
||||
} else {
|
||||
//unable to find a zone point... is there anything else
|
||||
//that can be a valid un-zolicited zone request?
|
||||
case EvacToSafeCoords:
|
||||
case ZoneToSafeCoords:
|
||||
//going to safe coords, but client dosent know where?
|
||||
//assume it is this zone for now.
|
||||
target_zone_id = zone->GetZoneID();
|
||||
break;
|
||||
case GMSummon:
|
||||
target_zone_id = zonesummon_id;
|
||||
break;
|
||||
case GateToBindPoint:
|
||||
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].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.
|
||||
target_zone_id = zonesummon_id;
|
||||
break;
|
||||
case ZoneUnsolicited: //client came up with this on its own.
|
||||
zone_point = zone->GetClosestZonePointWithoutZone(GetX(), GetY(), GetZ(), this, ZONEPOINT_NOZONE_RANGE);
|
||||
if (zone_point) {
|
||||
//we found a zone point, which is a reasonable distance away
|
||||
//assume that is the one were going with.
|
||||
target_zone_id = zone_point->target_zone_id;
|
||||
target_instance_id = zone_point->target_zone_instance;
|
||||
} else {
|
||||
//unable to find a zone point... is there anything else
|
||||
//that can be a valid un-zolicited zone request?
|
||||
|
||||
Message(Chat::Red, "Invalid unsolicited zone request.");
|
||||
LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]", GetName(), target_zone_id);
|
||||
if (GetBindZoneID() == target_zone_id) {
|
||||
cheat_manager.CheatDetected(MQGate, glm::vec3(zc->x, zc->y, zc->z));
|
||||
Message(Chat::Red, "Invalid unsolicited zone request.");
|
||||
LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]", GetName(), target_zone_id);
|
||||
cheat_manager.CheatDetected(GetBindZoneID() == target_zone_id ? MQGate : MQZone, glm::vec3(zc->x, zc->y, zc->z));
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
cheat_manager.CheatDetected(MQZone, glm::vec3(zc->x, zc->y, zc->z));
|
||||
}
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// This is to allow both 6.2 and Titanium clients to perform a proper zoning of the client when evac/succor
|
||||
// WildcardX 27 January 2008
|
||||
if(zone_mode == EvacToSafeCoords && zonesummon_id > 0)
|
||||
if (zone_mode == EvacToSafeCoords && zonesummon_id) {
|
||||
target_zone_id = zonesummon_id;
|
||||
else
|
||||
} else {
|
||||
target_zone_id = zc->zoneID;
|
||||
}
|
||||
|
||||
//if we are zoning to a specific zone unsolicied,
|
||||
//then until otherwise determined, they must be zoning
|
||||
//on a zone line.
|
||||
if(zone_mode == ZoneUnsolicited)
|
||||
{
|
||||
if(target_zone_id == zone->GetZoneID())
|
||||
{
|
||||
if (zone_mode == ZoneUnsolicited) {
|
||||
if (target_zone_id == zone->GetZoneID()) {
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
}
|
||||
@ -137,41 +130,46 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
zone_point = zone->GetClosestZonePoint(glm::vec3(GetPosition()), target_zone_id, this, ZONEPOINT_ZONE_RANGE);
|
||||
//if we didnt get a zone point, or its to a different zone,
|
||||
//then we assume this is invalid.
|
||||
if(!zone_point || zone_point->target_zone_id != target_zone_id) {
|
||||
if (!zone_point || zone_point->target_zone_id != target_zone_id) {
|
||||
LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]", GetName(), target_zone_id);
|
||||
if (GetBindZoneID() == target_zone_id) {
|
||||
cheat_manager.CheatDetected(MQGate, glm::vec3(zc->x, zc->y, zc->z));
|
||||
}
|
||||
else {
|
||||
cheat_manager.CheatDetected(MQZone, glm::vec3(zc->x, zc->y, zc->z));
|
||||
}
|
||||
cheat_manager.CheatDetected(GetBindZoneID() == target_zone_id ? MQGate : MQZone, glm::vec3(zc->x, zc->y, zc->z));
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(target_instance_id > 0)
|
||||
{
|
||||
if (target_instance_id) {
|
||||
//make sure we are in it and it's unexpired.
|
||||
if(!database.VerifyInstanceAlive(target_instance_id, CharacterID()))
|
||||
{
|
||||
Message(Chat::Red, "Instance ID was expired or you were not in it.");
|
||||
if (!database.VerifyInstanceAlive(target_instance_id, CharacterID())) {
|
||||
Message(
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"Instance ID {} was expired or you were not a member of it.",
|
||||
target_instance_id
|
||||
).c_str()
|
||||
);
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!database.VerifyZoneInstance(target_zone_id, target_instance_id))
|
||||
{
|
||||
Message(Chat::Red, "Instance ID was %u does not go with zone id %u", target_instance_id, target_zone_id);
|
||||
if (!database.VerifyZoneInstance(target_zone_id, target_instance_id)) {
|
||||
Message(
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
"Instance ID was {}, this does not match Zone ID {}.",
|
||||
target_instance_id,
|
||||
target_zone_id
|
||||
).c_str()
|
||||
);
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for Valid Zone */
|
||||
const char *target_zone_name = ZoneName(target_zone_id);
|
||||
if(target_zone_name == nullptr) {
|
||||
auto* target_zone_name = ZoneName(target_zone_id);
|
||||
if (!target_zone_name) {
|
||||
//invalid zone...
|
||||
Message(Chat::Red, "Invalid target zone ID.");
|
||||
LogError("Zoning [{}]: Unable to get zone name for zone id [{}]", GetName(), target_zone_id);
|
||||
@ -179,9 +177,10 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto target_instance_version = database.GetInstanceVersion(target_instance_id);
|
||||
auto zone_data = GetZoneVersionWithFallback(
|
||||
ZoneID(target_zone_name),
|
||||
database.GetInstanceVersion(target_instance_id)
|
||||
target_instance_version
|
||||
);
|
||||
if (!zone_data) {
|
||||
Message(Chat::Red, "Invalid target zone while getting safe points.");
|
||||
@ -203,11 +202,16 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
min_status = zone_data->min_status;
|
||||
min_level = zone_data->min_level;
|
||||
|
||||
std::string export_string = fmt::format(
|
||||
"{} {}",
|
||||
const auto& export_string = fmt::format(
|
||||
"{} {} {} {} {} {}",
|
||||
zone->GetZoneID(),
|
||||
target_zone_id
|
||||
zone->GetInstanceID(),
|
||||
zone->GetInstanceVersion(),
|
||||
target_zone_id,
|
||||
target_instance_id,
|
||||
target_instance_version
|
||||
);
|
||||
|
||||
if (parse->EventPlayer(EVENT_ZONE, this, export_string, 0) != 0) {
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
@ -218,97 +222,77 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
uint8 ignore_restrictions = zonesummon_ignorerestrictions;
|
||||
zonesummon_ignorerestrictions = 0;
|
||||
|
||||
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,
|
||||
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:
|
||||
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:
|
||||
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;
|
||||
break;
|
||||
case ZoneToBindPoint:
|
||||
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
|
||||
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?
|
||||
|
||||
//Handle zone point case:
|
||||
if(zone_point != nullptr) {
|
||||
//they are zoning using a valid zone point, figure out coords
|
||||
|
||||
//999999 is a placeholder for 'same as where they were from'
|
||||
if(zone_point->target_x == 999999)
|
||||
target_x = GetX();
|
||||
else
|
||||
target_x = zone_point->target_x;
|
||||
|
||||
if(zone_point->target_y == 999999)
|
||||
target_y = GetY();
|
||||
else
|
||||
target_y = zone_point->target_y;
|
||||
|
||||
if(zone_point->target_z == 999999)
|
||||
target_z = GetZ();
|
||||
else
|
||||
target_z = zone_point->target_z;
|
||||
|
||||
if(zone_point->target_heading == 999)
|
||||
target_heading = GetHeading();
|
||||
else
|
||||
target_heading = zone_point->target_heading;
|
||||
|
||||
auto target_x = 0.0f, target_y = 0.0f, target_z = 0.0f, target_heading = 0.0f;
|
||||
switch (zone_mode) {
|
||||
case EvacToSafeCoords:
|
||||
case ZoneToSafeCoords:
|
||||
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:
|
||||
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:
|
||||
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;
|
||||
break;
|
||||
case ZoneToBindPoint:
|
||||
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
|
||||
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?
|
||||
|
||||
//for now, there are no other cases...
|
||||
//Handle zone point case:
|
||||
if (zone_point) {
|
||||
//they are zoning using a valid zone point, figure out coords
|
||||
|
||||
//could not find a valid reason for them to be zoning, stop it.
|
||||
if (GetBindZoneID() == target_zone_id) {
|
||||
cheat_manager.CheatDetected(MQGate, glm::vec3(zc->x, zc->y, zc->z));
|
||||
}
|
||||
else {
|
||||
cheat_manager.CheatDetected(MQZone, glm::vec3(zc->x, zc->y, zc->z));
|
||||
}
|
||||
LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]. Not near a zone point", GetName(), target_zone_name);
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
//999999 is a placeholder for 'same as where they were from'
|
||||
target_x = zone_point->target_x == 999999 ? GetX() : zone_point->target_x;
|
||||
target_y = zone_point->target_y == 999999 ? GetY() : zone_point->target_y;
|
||||
target_z = zone_point->target_z == 999999 ? GetZ() : zone_point->target_z;
|
||||
target_heading = zone_point->target_heading == 999 ? GetHeading() : zone_point->target_heading;
|
||||
break;
|
||||
}
|
||||
|
||||
//for now, there are no other cases...
|
||||
|
||||
//could not find a valid reason for them to be zoning, stop it.
|
||||
cheat_manager.CheatDetected(GetBindZoneID() == target_zone_id ? MQGate : MQZone, glm::vec3(zc->x, zc->y, zc->z));
|
||||
|
||||
LogError("Zoning [{}]: Invalid unsolicited zone request to zone id [{}]. Not near a zone point", GetName(), target_zone_name);
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
//OK, now we should know where were going...
|
||||
@ -319,8 +303,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
//not sure when we would use ZONE_ERROR_NOTREADY
|
||||
|
||||
//enforce min status and level
|
||||
if (!ignore_restrictions && (Admin() < min_status || GetLevel() < zone_data->min_level))
|
||||
{
|
||||
if (!ignore_restrictions && (Admin() < min_status || GetLevel() < zone_data->min_level)) {
|
||||
myerror = ZONE_ERROR_NOEXPERIENCE;
|
||||
}
|
||||
|
||||
@ -368,7 +351,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
LogInfo("[{}] Bypassing Expansion zone checks because GM status is set", GetCleanName());
|
||||
}
|
||||
|
||||
if(myerror == 1) {
|
||||
if (myerror == 1) {
|
||||
//we have successfully zoned
|
||||
DoZoneSuccess(zc, target_zone_id, target_instance_id, target_x, target_y, target_z, target_heading, ignore_restrictions);
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user