PDA

View Full Version : Ubound characters that die seem to get sent to -3,-3,-3


vesuvias
02-11-2004, 02:59 AM
I am not sure if this has been reported before. I am using the latest code from CVS running the MW 053 alpha3 DB.

Apprently If you die while not having been bound yet (perhaps we should make a startingbindpoints db table) you get sent to -3,-3,-3 in the same zone. This is a problem in some zones but in others (ie vahlshar) it can lead to repeated falling death loops.

I inspected the code and traced the problem to handlepacket inside client_process.cpp. The offending bug I believe is centered on this section:
if (!database.GetSafePoints(target_zone, &tarx, &tary, &tarz, &minstatus, &minlevel)) {
target_zone[0] = 0;
}
int8 tmpzonesummon_ignorerestrictions = zonesummon_ignorerestrictions;
if (zonesummon_ignorerestrictions) {
minstatus = 0;
minlevel = 0;
}
zonesummon_ignorerestrictions = 0;

ZonePoint* zone_point = zone->GetClosestZonePoint(x_pos, y_pos, z_pos, zc->zoneID);

tarx=zonesummon_x;
tary=zonesummon_y;
tarz=zonesummon_z;

// -1, -1, -1 = code for zone safe point
if ((x_pos == -1 && y_pos == -1 && (z_pos == -1 || z_pos == -10)) ||
(zonesummon_x == -1 && zonesummon_y == -1 && (zonesummon_z == -1 || zonesummon_z == -10))) {
cout << "Zoning to safe coords: " << target_zone << " (" << database.GetZoneID(target_zone) << ")" << endl;
tarx=database.GetSafePoint(target_zone, "x");
tary=database.GetSafePoint(target_zone, "y");
tarz=database.GetSafePoint(target_zone, "z");
zonesummon_x = -2;
zonesummon_y = -2;
zonesummon_z = -2;
}
// -3 -3 -3 = bind point
else if (zonesummon_x == -3 && zonesummon_y == -3 && (zonesummon_z == -3 || zonesummon_z == -30) && database.GetZoneName(m_pp.bind_zone_id)) {
strcpy(target_zone, database.GetZoneName(m_pp.bind_zone_id));
tarx = m_pp.bind_x;
tary = m_pp.bind_y;
tarz = m_pp.bind_z;
zonesummon_x = -2;
zonesummon_y = -2;
zonesummon_z = -2;
minstatus = 0;
minlevel = 0;
}
else if (zone_point != 0) {
if(zone_point->target_x==999999)
tarx=GetX();
else
tarx = zone_point->target_x;
if(zone_point->target_y==999999)
tary=GetY();
else
tary = zone_point->target_y;
if(zone_point->target_z==999999)
tarz=GetZ();
else
tarz = zone_point->target_z;
tarheading = zone_point->target_heading;
}
// if not -2 -2 -2, zone to these coords. -2, -2, -2 = not a zonesummon zonerequest
else if (!(zonesummon_x == -2 && zonesummon_y == -2 && (zonesummon_z == -2 || zonesummon_z == -20))) {
tarx = zonesummon_x;
tary = zonesummon_y;
tarz = zonesummon_z;
zonesummon_x = -2;
zonesummon_y = -2;
zonesummon_z = -2;
}
else {
cout << "WARNING: No target coords for this zone in DB found" << endl;
cout << "Zoning to safe coords: " << target_zone << " (" << database.GetZoneID(target_zone) << ")" << ", x=" << tarx << ", y=" << tary << ", z=" << tarz << endl;
tarx=-1;
tary=-1;
tarz=-1;
zonesummon_x = -2;
zonesummon_y = -2;
zonesummon_z = -2;
}

Now my C++ is rather rusty (but its coming back, I am a Java guy by trade) but this else {
cout << "WARNING: No target coords for this zone in DB found" << endl;
cout << "Zoning to safe coords: " << target_zone << " (" << database.GetZoneID(target_zone) << ")" << ", x=" << tarx << ", y=" << tary << ", z=" << tarz << endl;
tarx=-1;
tary=-1;
tarz=-1;
zonesummon_x = -2;
zonesummon_y = -2;
zonesummon_z = -2;
}
Seems really strange. Why would you print out the correct loc of the safe area and then proceed to wipe out your only record of those coords? Anyway like I said I am still a little rusty so I was hoping some more code experienced devs might be able to shed some light on the situation.

Try not to give me too much shit, at least I took the time to track down where I think the problem lies as oppossed to just whinning about it. :D

Ves

farce
02-11-2004, 03:07 AM
I agree that looks fishy.

toolh3
02-11-2004, 05:00 AM
Have you tried changing that else block to this:

else
{
cout << "WARNING: No target coords for this zone in DB found" << endl;
cout << "Zoning to safe coords: " << target_zone << " (" << database.GetZoneID(target_zone) << ")" << ", x=" << tarx << ", y=" << tary << ", z=" << tarz << endl;
tarx=database.GetSafePoint(target_zone, "x");
tary=database.GetSafePoint(target_zone, "y");
tarz=database.GetSafePoint(target_zone, "z");
zonesummon_x = -2;
zonesummon_y = -2;
zonesummon_z = -2;
}

If it is truly supposed to send you to the safe point in the zone (which the cout message certainly explains) then I believe this is the code to do it. I just took the code from the first if block which does send you to the safe point.

I think the original idea the devs have here is that this OP_ZoneChange case block is going to be hit again because of this code block:

if (m_pp.zone_id == zone->GetZoneID())
{
// No need to ask worldserver if we're zoning to ourselves (most
// likely to a bind point), also fixes a bug since the default response was failure
APPLAYER* outapp = new APPLAYER(OP_ZoneChange,sizeof(ZoneChange_Struct));
ZoneChange_Struct* zc2 = (ZoneChange_Struct*) outapp->pBuffer;
strcpy(zc2->char_name, GetName());
zc2->zoneID = m_pp.zone_id;
zc2->success = 1;
QueuePacket(outapp);
safe_delete(outapp);
zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
}

That block gets executed if you are zoning to the same zone, I believe. So then next time through the loop, x_pos, y_pos, and z_pos should equal 1 which should hit the first if block and send you to the zone safe points. Now this is all just speculation from looking at the code for about 10 minutes. A real dev would probably have a better answer to this.

vesuvias
02-11-2004, 06:10 AM
I think the original idea the devs have here is that this OP_ZoneChange case block is going to be hit again because of this code block:

if (m_pp.zone_id == zone->GetZoneID())
{
// No need to ask worldserver if we're zoning to ourselves (most
// likely to a bind point), also fixes a bug since the default response was failure
APPLAYER* outapp = new APPLAYER(OP_ZoneChange,sizeof(ZoneChange_Struct));
ZoneChange_Struct* zc2 = (ZoneChange_Struct*) outapp->pBuffer;
strcpy(zc2->char_name, GetName());
zc2->zoneID = m_pp.zone_id;
zc2->success = 1;
QueuePacket(outapp);
safe_delete(outapp);
zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
}


I think your right about that, however what prevents us from hitting this same block of code when we run through OP_ZoneChange a second time?

else
{
cout << "WARNING: No target coords for this zone in DB found" << endl;
cout << "Zoning to safe coords: " << target_zone << " (" << database.GetZoneID(target_zone) << ")" << ", x=" << tarx << ", y=" << tary << ", z=" << tarz << endl;
tarx=database.GetSafePoint(target_zone, "x");
tary=database.GetSafePoint(target_zone, "y");
tarz=database.GetSafePoint(target_zone, "z");
zonesummon_x = -2;
zonesummon_y = -2;
zonesummon_z = -2;
}
When I get home today I think I will try this out. But actually since
if (!database.GetSafePoints(target_zone, &tarx, &tary, &tarz, &minstatus, &minlevel)) {
target_zone[0] = 0;
}

was called before we even enter that compound branch I don't think I even have to specify what tarx, tary and tarz are, they should already have the right values (and we just cout'd them :) )

Interesting... thanks for the input.
Ves

toolh3
02-11-2004, 08:01 AM
I think your right about that, however what prevents us from hitting this same block of code when we run through OP_ZoneChange a second time?

I was thinking the same thing, but it was the only way I could explain what was happening. The block of code looks kinda messed up anyway. I agree with you that I see no point in calling the function GetSafePoints() and then overwriting them about 5 lines later. And then when we actually want the safe points we call GetSafePoint() for each variable. We are doing two hits on the database when there only needs to be one.