void MOTransport::Update(uint32 update_diff, uint32 p_time) { UpdateSplineMovement(p_time); if (!movespline->Finalized()) return; if (m_WayPoints.size() <= 1) return; bool anchorage = !m_anchorageTimer.Passed(); if (anchorage) m_anchorageTimer.Update(update_diff); m_timer = WorldTimer::getMSTime() % GetPeriod(true); while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime)) { DoEventIfAny(*m_curr,true); MoveToNextWayPoint(); // delay detect if (m_next->second.delay > 0) { m_anchorageTimer.SetInterval(m_next->first - m_next->second.delay); m_anchorageTimer.Reset(); } DoEventIfAny(*m_curr,false); if (!SetPosition(m_curr->second.loc, m_curr->second.teleport)) { if (m_curr->second.loc.GetMapId() == m_next->second.loc.GetMapId() && !m_curr->second.teleport && m_anchorageTimer.Passed() && !(m_curr->second.loc == m_next->second.loc)) { // FIXME - use MovementGenerator instead this DEBUG_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES,"Transport::Update %s start spline movement to %f %f %f",GetObjectGuid().GetString().c_str(), m_next->second.loc.x, m_next->second.loc.y, m_next->second.loc.z); Movement::MoveSplineInit<GameObject*> init(*this); init.MoveTo((Vector3)m_next->second.loc); init.SetVelocity(GetGOInfo()->moTransport.moveSpeed); init.Launch(); } } m_nextNodeTime = m_curr->first; DEBUG_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES, "Transport::Update %s moved to %f %f %f %d %s, next keyframe %u", GetObjectGuid().GetString().c_str(), m_curr->second.loc.x, m_curr->second.loc.y, m_curr->second.loc.z, m_curr->second.loc.GetMapId(), m_curr == m_WayPoints.begin() ? "begin move" : "", m_nextNodeTime); } }
void Transport::Update( uint32 update_diff, uint32 /*p_time*/) { if (m_WayPoints.size() <= 1) return; m_timer = WorldTimer::getMSTime() % m_period; while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime)) { DoEventIfAny(*m_curr,true); MoveToNextWayPoint(); DoEventIfAny(*m_curr,false); // first check help in case client-server transport coordinates de-synchronization if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport) { TeleportTransport(m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z); } else { Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z); } /* for(PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) { PlayerSet::const_iterator it2 = itr; ++itr; //(*it2)->SetPosition( m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO() ); } */ m_nextNodeTime = m_curr->first; if (m_curr == m_WayPoints.begin()) DETAIL_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES, " ************ BEGIN ************** %s", GetName()); DETAIL_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES, "%s moved to %f %f %f %d", GetName(), m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); } }
void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) { Map const* oldMap = GetMap(); Relocate(x, y, z); // we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference... // player far teleport would try to create same instance, but we need it NOW for transport... RemoveFromWorld(); ResetMap(); Map* newMap = sMapMgr->CreateBaseMap(newMapid); SetMap(newMap); ASSERT(GetMap()); AddToWorld(); for (UnitSet::iterator itr = _passengers.begin(); itr != _passengers.end();) { Unit* passenger = *itr; ++itr; switch (passenger->GetTypeId()) { case TYPEID_UNIT: passenger->ToCreature()->FarTeleportTo(newMap, x, y, z, passenger->GetOrientation()); break; case TYPEID_PLAYER: if (passenger->isDead() && !passenger->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) passenger->ToPlayer()->ResurrectPlayer(1.0f); passenger->ToPlayer()->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT); break; } } if (oldMap != newMap) { UpdateForMap(oldMap); UpdateForMap(newMap); } MoveToNextWayPoint(); }
bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids) { if (pathid >= sTaxiPathNodesByPath.size()) return false; TaxiPathNodeList const& path = sTaxiPathNodesByPath[pathid]; std::vector<keyFrame> keyFrames; int mapChange = 0; mapids.clear(); for (size_t i = 1; i < path.size() - 1; ++i) { if (mapChange == 0) { TaxiPathNodeEntry const& node_i = path[i]; if (node_i.mapid == path[i+1].mapid) { keyFrame k(node_i); keyFrames.push_back(k); mapids.insert(k.node->mapid); } else { mapChange = 1; } } else { --mapChange; } } int lastStop = -1; int firstStop = -1; // first cell is arrived at by teleportation :S keyFrames[0].distFromPrev = 0; if (keyFrames[0].node->actionFlag == 2) { lastStop = 0; } // find the rest of the distances between key points for (size_t i = 1; i < keyFrames.size(); ++i) { if ((keyFrames[i].node->actionFlag == 1) || (keyFrames[i].node->mapid != keyFrames[i-1].node->mapid)) { keyFrames[i].distFromPrev = 0; } else { keyFrames[i].distFromPrev = sqrt(pow(keyFrames[i].node->x - keyFrames[i - 1].node->x, 2) + pow(keyFrames[i].node->y - keyFrames[i - 1].node->y, 2) + pow(keyFrames[i].node->z - keyFrames[i - 1].node->z, 2)); } if (keyFrames[i].node->actionFlag == 2) { // remember first stop frame if(firstStop == -1) firstStop = i; lastStop = i; } } float tmpDist = 0; for (size_t i = 0; i < keyFrames.size(); ++i) { int j = (i + lastStop) % keyFrames.size(); if (keyFrames[j].node->actionFlag == 2) tmpDist = 0; else tmpDist += keyFrames[j].distFromPrev; keyFrames[j].distSinceStop = tmpDist; } for (int i = int(keyFrames.size()) - 1; i >= 0; i--) { int j = (i + (firstStop+1)) % keyFrames.size(); tmpDist += keyFrames[(j + 1) % keyFrames.size()].distFromPrev; keyFrames[j].distUntilStop = tmpDist; if (keyFrames[j].node->actionFlag == 2) tmpDist = 0; } for (size_t i = 0; i < keyFrames.size(); ++i) { if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f)) keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop); else keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30; if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f)) keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop); else keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30; keyFrames[i].tFrom *= 1000; keyFrames[i].tTo *= 1000; } // for (int i = 0; i < keyFrames.size(); ++i) { // sLog.outString("%f, %f, %f, %f, %f, %f, %f", keyFrames[i].x, keyFrames[i].y, keyFrames[i].distUntilStop, keyFrames[i].distSinceStop, keyFrames[i].distFromPrev, keyFrames[i].tFrom, keyFrames[i].tTo); // } // Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals // speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2 int t = 0; bool teleport = false; if (keyFrames[keyFrames.size() - 1].node->mapid != keyFrames[0].node->mapid) teleport = true; WayPoint pos(keyFrames[0].node->mapid, keyFrames[0].node->x, keyFrames[0].node->y, keyFrames[0].node->z, teleport, keyFrames[0].node->arrivalEventID, keyFrames[0].node->departureEventID); m_WayPoints[0] = pos; t += keyFrames[0].node->delay * 1000; uint32 cM = keyFrames[0].node->mapid; for (size_t i = 0; i < keyFrames.size() - 1; ++i) { float d = 0; float tFrom = keyFrames[i].tFrom; float tTo = keyFrames[i].tTo; // keep the generation of all these points; we use only a few now, but may need the others later if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0))) { while ((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)) { tFrom += 100; tTo -= 100; if (d > 0) { float newX, newY, newZ; newX = keyFrames[i].node->x + (keyFrames[i + 1].node->x - keyFrames[i].node->x) * d / keyFrames[i + 1].distFromPrev; newY = keyFrames[i].node->y + (keyFrames[i + 1].node->y - keyFrames[i].node->y) * d / keyFrames[i + 1].distFromPrev; newZ = keyFrames[i].node->z + (keyFrames[i + 1].node->z - keyFrames[i].node->z) * d / keyFrames[i + 1].distFromPrev; bool teleport = false; if (keyFrames[i].node->mapid != cM) { teleport = true; cM = keyFrames[i].node->mapid; } // sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ); WayPoint pos(keyFrames[i].node->mapid, newX, newY, newZ, teleport); if (teleport) m_WayPoints[t] = pos; } if (tFrom < tTo) // caught in tFrom dock's "gravitational pull" { if (tFrom <= 30000) { d = 0.5f * (tFrom / 1000) * (tFrom / 1000); } else { d = 0.5f * 30 * 30 + 30 * ((tFrom - 30000) / 1000); } d = d - keyFrames[i].distSinceStop; } else { if (tTo <= 30000) { d = 0.5f * (tTo / 1000) * (tTo / 1000); } else { d = 0.5f * 30 * 30 + 30 * ((tTo - 30000) / 1000); } d = keyFrames[i].distUntilStop - d; } t += 100; } t -= 100; } if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo) t += 100 - ((long)keyFrames[i + 1].tTo % 100); else t += (long)keyFrames[i + 1].tTo % 100; bool teleport = false; if ((keyFrames[i + 1].node->actionFlag == 1) || (keyFrames[i + 1].node->mapid != keyFrames[i].node->mapid)) { teleport = true; cM = keyFrames[i + 1].node->mapid; } WayPoint pos(keyFrames[i + 1].node->mapid, keyFrames[i + 1].node->x, keyFrames[i + 1].node->y, keyFrames[i + 1].node->z, teleport, keyFrames[i + 1].node->arrivalEventID, keyFrames[i + 1].node->departureEventID); // sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport); //if (teleport) m_WayPoints[t] = pos; t += keyFrames[i + 1].node->delay * 1000; // sLog.outString("------"); } uint32 timer = t; // sLog.outDetail(" Generated %lu waypoints, total time %u.", (unsigned long)m_WayPoints.size(), timer); m_next = m_WayPoints.begin(); // will used in MoveToNextWayPoint for init m_curr MoveToNextWayPoint(); // m_curr -> first point MoveToNextWayPoint(); // skip first point m_pathTime = timer; m_nextNodeTime = m_curr->first; return true; }
void Transport::Update(uint32 diff) { if (!AI()) { if (!AIM_Initialize()) sLog->outError("Could not initialize GameObjectAI for Transport"); } else AI()->UpdateAI(diff); if (_isStopped) return; if (GetKeyFrames().size() <= 1) return; //_moveTimer = getMSTime() % _transportInfo->pathTime; _moveTimer += diff; _moveTimer %= _transportInfo->pathTime; // need restart path from beginning /* if (m_timer < m_curr->pathTime) { m_curr = keyFrames.begin(); m_next = m_curr + 1; } */ while (_moveTimer > _nextFrame->pathTime || _moveTimer < _currentFrame->departureTime) { // arrived at next stop point if (_transportInfo->pathTime > _nextFrame->pathTime && _moveTimer < _nextFrame->departureTime) { if (IsMoving()) { SetMoving(false); DoEventIfAny(*_currentFrame, false); } break; } MoveToNextWayPoint(); SetMoving(true); DoEventIfAny(*_currentFrame, true); // first check help in case client-server transport coordinates de-synchronization if (_currentFrame->IsTeleportFrame()) TeleportTransport(_nextFrame->node->mapid, _nextFrame->node->x, _nextFrame->node->y, _nextFrame->node->z); ASSERT(_nextFrame != GetKeyFrames().begin()); sScriptMgr->OnRelocate(this, _currentFrame->node->index, _currentFrame->node->mapid, _currentFrame->node->x, _currentFrame->node->y, _currentFrame->node->z); sLog->outDebug(LOG_FILTER_TRANSPORTS, "%s moved to %f %f %f %d", GetName(), GetPositionX(), GetPositionY(), GetPositionZ(), _currentFrame->node->mapid); } if (IsMoving()) { if (_moveTimer < _currentFrame->departureTime || _moveTimer > _nextFrame->pathTime) sLog->outError("strange times, c.dep:%u, n.pt:%u (%s, %u)", _currentFrame->departureTime, _nextFrame->pathTime, GetName(), m_goInfo->moTransport.mapID); float t = CalculateSegmentPos((float)_moveTimer/(float)IN_MILLISECONDS); //if (t < -0.01f || t > 1.01f) // sLog.outError("strange t=%f (%s, %u)", t, GetName(), m_goInfo->moTransport.mapID); //G3D::Vector3 pos; //m_spline->Evaluate(m_curr->node->index - 1, t, pos); //G3D::Vector3 dir; //m_spline->EvaluateDerivative(m_curr->node->index - 1, t, dir); //dir.z = 0.0f; //dir = -dir.direction(); //Relocate(pos.x, pos.y, pos.z); float x = _currentFrame->node->x * (1.0f - t) + _nextFrame->node->x * t; float y = _currentFrame->node->y * (1.0f - t) + _nextFrame->node->y * t; float z = _currentFrame->node->z * (1.0f - t) + _nextFrame->node->z * t; float o = GetAngle(_nextFrame->node->x, _nextFrame->node->y) + float(M_PI); Relocate(x, y, z, o); UpdatePassengerPositions(); } sScriptMgr->OnTransportUpdate(this, diff); }