Have you tried changing that else block to this:
	Code:
	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:
	Code:
	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.