void CBulletInfo::Update(const double dt) { // check if the bullet is active if(getStatus() == true) { // Update the position of the bullet SetPosition(getPosition() + getDirection() * getSpeed() * static_cast<float>(dt)); // Update the lifetime SetLifetime(getLifetime() - static_cast<float>(dt)); // check if the lifetime is gone if(getLifetime() < 0) { SetStatus( false); } } }
// VectorPuffParticle2D //--------------------------------------------------------------------------- VectorPuffParticle2D::VectorPuffParticle2D( const fXYZ &pos, const fXYZ &direction, float scaleMin, float scaleRand, float speedMin, float speedRand, float waitMin, float waitRand, float lifetimeMin, float lifetimeRand, float windScale) : WindParticle2D(pos, windScale) { VectorPuffParticle2D::scaleMin = scaleMin; VectorPuffParticle2D::scaleRand = scaleRand; VectorPuffParticle2D::isFarAway = isFarAway; wait = ((float(rand()) / float(RAND_MAX)) * waitRand + waitMin); velocity = direction * ((float(rand()) / float(RAND_MAX)) * speedRand + speedMin); lifetime = getLifetime(lifetimeMin, lifetimeRand); waitTime = 0.0f; } // end VectorPuffParticle2D::VectorPuffParticle2D
bool Garage::shouldClose() { auto player = engine->getPlayer(); auto plyChar = player->getCharacter(); auto playerPosition = plyChar->getPosition(); auto playerVehicle = plyChar->getCurrentVehicle(); bool playerIsInVehicle = playerVehicle != nullptr; switch (type) { case Type::Mission: { if (!isObjectInsideGarage(static_cast<GameObject*>(plyChar)) && isObjectInsideGarage(target) && !playerIsInVehicle && getDistanceToGarage(playerPosition) >= 2.f) { return true; } return false; } case Type::BombShop1: case Type::BombShop2: case Type::BombShop3: { if (playerIsInVehicle) { if (isObjectInsideGarage( static_cast<GameObject*>(playerVehicle)) && playerVehicle->isStopped()) { return true; } } return false; } case Type::Respray: { if (playerIsInVehicle) { if (isObjectInsideGarage( static_cast<GameObject*>(playerVehicle)) && playerVehicle->isStopped() && !resprayDone) { return true; } else if (!isObjectInsideGarage( static_cast<GameObject*>(playerVehicle)) && getDistanceToGarage(playerVehicle->getPosition()) >= 2.f && resprayDone) { resprayDone = false; } } return false; } case Type::CollectCars1: case Type::CollectCars2: { if (playerIsInVehicle) { if (isObjectInsideGarage( static_cast<GameObject*>(playerVehicle))) { if (playerVehicle->getLifetime() != GameObject::MissionLifetime) { return true; } else { // @todo show message "come back when youre not busy" } } } return false; } case Type::MissionForCarToComeOut: { // @todo unimplemented return false; } case Type::Crusher: { // @todo unimplemented return false; } case Type::MissionKeepCar: { // @todo unimplemented return false; } case Type::Hideout1: case Type::Hideout2: case Type::Hideout3: { // Not sure about these values if ((!playerIsInVehicle && getDistanceToGarage(playerPosition) >= 5.f) || (playerIsInVehicle && getDistanceToGarage(playerPosition) >= 10.f)) { return true; } return false; } case Type::MissionToOpenAndClose: { // @todo unimplemented return false; } case Type::MissionForSpecificCar: { // @todo unimplemented return false; } case Type::MissionKeepCarAndRemainClosed: { // @todo unimplemented return false; } default: { return false; } } return false; }
bool EntityItem::lifetimeHasExpired() const { return isMortal() && (getAge() > getLifetime()); }
void EntityItem::update(const quint64& updateTime) { bool wantDebug = false; if (_lastUpdated == 0) { _lastUpdated = updateTime; } float timeElapsed = (float)(updateTime - _lastUpdated) / (float)(USECS_PER_SECOND); if (wantDebug) { qDebug() << "********** EntityItem::update()"; qDebug() << " entity ID=" << getEntityItemID(); qDebug() << " updateTime=" << updateTime; qDebug() << " _lastUpdated=" << _lastUpdated; qDebug() << " timeElapsed=" << timeElapsed; qDebug() << " hasVelocity=" << hasVelocity(); qDebug() << " hasGravity=" << hasGravity(); qDebug() << " isRestingOnSurface=" << isRestingOnSurface(); qDebug() << " hasAngularVelocity=" << hasAngularVelocity(); qDebug() << " getAngularVelocity=" << getAngularVelocity(); qDebug() << " isMortal=" << isMortal(); qDebug() << " getAge()=" << getAge(); qDebug() << " getLifetime()=" << getLifetime(); if (hasVelocity() || (hasGravity() && !isRestingOnSurface())) { qDebug() << " MOVING...="; qDebug() << " hasVelocity=" << hasVelocity(); qDebug() << " hasGravity=" << hasGravity(); qDebug() << " isRestingOnSurface=" << isRestingOnSurface(); qDebug() << " hasAngularVelocity=" << hasAngularVelocity(); qDebug() << " getAngularVelocity=" << getAngularVelocity(); } if (hasAngularVelocity()) { qDebug() << " CHANGING...="; qDebug() << " hasAngularVelocity=" << hasAngularVelocity(); qDebug() << " getAngularVelocity=" << getAngularVelocity(); } if (isMortal()) { qDebug() << " MORTAL...="; qDebug() << " isMortal=" << isMortal(); qDebug() << " getAge()=" << getAge(); qDebug() << " getLifetime()=" << getLifetime(); } } _lastUpdated = updateTime; if (wantDebug) { qDebug() << " ********** EntityItem::update() .... SETTING _lastUpdated=" << _lastUpdated; } if (hasAngularVelocity()) { glm::quat rotation = getRotation(); glm::vec3 angularVelocity = glm::radians(getAngularVelocity()); float angularSpeed = glm::length(angularVelocity); if (angularSpeed < EPSILON_VELOCITY_LENGTH) { setAngularVelocity(NO_ANGULAR_VELOCITY); } else { float angle = timeElapsed * angularSpeed; glm::quat dQ = glm::angleAxis(angle, glm::normalize(angularVelocity)); rotation = dQ * rotation; setRotation(rotation); // handle damping for angular velocity if (getAngularDamping() > 0.0f) { glm::vec3 dampingResistance = getAngularVelocity() * getAngularDamping(); glm::vec3 newAngularVelocity = getAngularVelocity() - (dampingResistance * timeElapsed); setAngularVelocity(newAngularVelocity); if (wantDebug) { qDebug() << " getDamping():" << getDamping(); qDebug() << " dampingResistance:" << dampingResistance; qDebug() << " newAngularVelocity:" << newAngularVelocity; } } } } if (hasVelocity() || hasGravity()) { glm::vec3 position = getPosition(); glm::vec3 velocity = getVelocity(); glm::vec3 newPosition = position + (velocity * timeElapsed); if (wantDebug) { qDebug() << " EntityItem::update()...."; qDebug() << " timeElapsed:" << timeElapsed; qDebug() << " old AACube:" << getMaximumAACube(); qDebug() << " old position:" << position; qDebug() << " old velocity:" << velocity; qDebug() << " old getAABox:" << getAABox(); qDebug() << " getDistanceToBottomOfEntity():" << getDistanceToBottomOfEntity() * (float)TREE_SCALE << " in meters"; qDebug() << " newPosition:" << newPosition; qDebug() << " glm::distance(newPosition, position):" << glm::distance(newPosition, position); } position = newPosition; // handle bounces off the ground... We bounce at the distance to the bottom of our entity if (position.y <= getDistanceToBottomOfEntity()) { velocity = velocity * glm::vec3(1,-1,1); // if we've slowed considerably, then just stop moving if (glm::length(velocity) <= EPSILON_VELOCITY_LENGTH) { velocity = NO_VELOCITY; } position.y = getDistanceToBottomOfEntity(); } // handle gravity.... if (hasGravity() && !isRestingOnSurface()) { velocity += getGravity() * timeElapsed; } // handle resting on surface case, this is definitely a bit of a hack, and it only works on the // "ground" plane of the domain, but for now it if (hasGravity() && isRestingOnSurface()) { velocity.y = 0.0f; position.y = getDistanceToBottomOfEntity(); } // handle damping for velocity glm::vec3 dampingResistance = velocity * getDamping(); if (wantDebug) { qDebug() << " getDamping():" << getDamping(); qDebug() << " dampingResistance:" << dampingResistance; qDebug() << " dampingResistance * timeElapsed:" << dampingResistance * timeElapsed; } velocity -= dampingResistance * timeElapsed; if (wantDebug) { qDebug() << " velocity AFTER dampingResistance:" << velocity; qDebug() << " glm::length(velocity):" << glm::length(velocity); qDebug() << " EPSILON_VELOCITY_LENGTH:" << EPSILON_VELOCITY_LENGTH; } // round velocity to zero if it's close enough... if (glm::length(velocity) <= EPSILON_VELOCITY_LENGTH) { velocity = NO_VELOCITY; } setPosition(position); // this will automatically recalculate our collision shape setVelocity(velocity); if (wantDebug) { qDebug() << " new position:" << position; qDebug() << " new velocity:" << velocity; qDebug() << " new AACube:" << getMaximumAACube(); qDebug() << " old getAABox:" << getAABox(); } } }
OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const { // ALL this fits... // object ID [16 bytes] // ByteCountCoded(type code) [~1 byte] // last edited [8 bytes] // ByteCountCoded(last_edited to last_updated delta) [~1-8 bytes] // PropertyFlags<>( everything ) [1-2 bytes] // ~27-35 bytes... OctreeElement::AppendState appendState = OctreeElement::COMPLETED; // assume the best // encode our ID as a byte count coded byte stream QByteArray encodedID = getID().toRfc4122(); // encode our type as a byte count coded byte stream ByteCountCoded<quint32> typeCoder = getType(); QByteArray encodedType = typeCoder; quint64 updateDelta = getLastUpdated() <= getLastEdited() ? 0 : getLastUpdated() - getLastEdited(); ByteCountCoded<quint64> updateDeltaCoder = updateDelta; QByteArray encodedUpdateDelta = updateDeltaCoder; EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = getEntityProperties(params); EntityPropertyFlags propertiesDidntFit = requestedProperties; // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, // then our entityTreeElementExtraEncodeData should include data about which properties we need to append. if (entityTreeElementExtraEncodeData && entityTreeElementExtraEncodeData->entities.contains(getEntityItemID())) { requestedProperties = entityTreeElementExtraEncodeData->entities.value(getEntityItemID()); } LevelDetails entityLevel = packetData->startLevel(); quint64 lastEdited = getLastEdited(); const bool wantDebug = false; if (wantDebug) { float editedAgo = getEditedAgo(); QString agoAsString = formatSecondsElapsed(editedAgo); qDebug() << "Writing entity " << getEntityItemID() << " to buffer, lastEdited =" << lastEdited << " ago=" << editedAgo << "seconds - " << agoAsString; } bool successIDFits = false; bool successTypeFits = false; bool successCreatedFits = false; bool successLastEditedFits = false; bool successLastUpdatedFits = false; bool successPropertyFlagsFits = false; int propertyFlagsOffset = 0; int oldPropertyFlagsLength = 0; QByteArray encodedPropertyFlags; int propertyCount = 0; successIDFits = packetData->appendValue(encodedID); if (successIDFits) { successTypeFits = packetData->appendValue(encodedType); } if (successTypeFits) { successCreatedFits = packetData->appendValue(_created); } if (successCreatedFits) { successLastEditedFits = packetData->appendValue(lastEdited); } if (successLastEditedFits) { successLastUpdatedFits = packetData->appendValue(encodedUpdateDelta); } if (successLastUpdatedFits) { propertyFlagsOffset = packetData->getUncompressedByteOffset(); encodedPropertyFlags = propertyFlags; oldPropertyFlagsLength = encodedPropertyFlags.length(); successPropertyFlagsFits = packetData->appendValue(encodedPropertyFlags); } bool headerFits = successIDFits && successTypeFits && successCreatedFits && successLastEditedFits && successLastUpdatedFits && successPropertyFlagsFits; int startOfEntityItemData = packetData->getUncompressedByteOffset(); if (headerFits) { bool successPropertyFits; propertyFlags -= PROP_LAST_ITEM; // clear the last item for now, we may or may not set it as the actual item // These items would go here once supported.... // PROP_PAGED_PROPERTY, // PROP_CUSTOM_PROPERTIES_INCLUDED, APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition()); APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete if (wantDebug) { qDebug() << " APPEND_ENTITY_PROPERTY() PROP_DIMENSIONS:" << getDimensions(); } APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation()); APPEND_ENTITY_PROPERTY(PROP_MASS, appendValue, getMass()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity()); APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, getAngularVelocity()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, appendValue, getAngularDamping()); APPEND_ENTITY_PROPERTY(PROP_VISIBLE, appendValue, getVisible()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, getIgnoreForCollisions()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove()); appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); encodedPropertyFlags = propertyFlags; int newPropertyFlagsLength = encodedPropertyFlags.length(); packetData->updatePriorBytes(propertyFlagsOffset, (const unsigned char*)encodedPropertyFlags.constData(), encodedPropertyFlags.length()); // if the size of the PropertyFlags shrunk, we need to shift everything down to front of packet. if (newPropertyFlagsLength < oldPropertyFlagsLength) { int oldSize = packetData->getUncompressedSize(); const unsigned char* modelItemData = packetData->getUncompressedData(propertyFlagsOffset + oldPropertyFlagsLength); int modelItemDataLength = endOfEntityItemData - startOfEntityItemData; int newEntityItemDataStart = propertyFlagsOffset + newPropertyFlagsLength; packetData->updatePriorBytes(newEntityItemDataStart, modelItemData, modelItemDataLength); int newSize = oldSize - (oldPropertyFlagsLength - newPropertyFlagsLength); packetData->setUncompressedSize(newSize); } else { assert(newPropertyFlagsLength == oldPropertyFlagsLength); // should not have grown } packetData->endLevel(entityLevel); } else { packetData->discardLevel(entityLevel); appendState = OctreeElement::NONE; // if we got here, then we didn't include the item } // If any part of the model items didn't fit, then the element is considered partial if (appendState != OctreeElement::COMPLETED) { // add this item into our list for the next appendElementData() pass entityTreeElementExtraEncodeData->entities.insert(getEntityItemID(), propertiesDidntFit); } return appendState; }
void ExternalLoader::reloadAndUpdate(bool throw_on_error) { reloadFromConfigFiles(throw_on_error); /// list of recreated loadable objects to perform delayed removal from unordered_map std::list<std::string> recreated_failed_loadable_objects; std::unique_lock<std::mutex> all_lock(all_mutex); /// retry loading failed loadable objects for (auto & failed_loadable_object : failed_loadable_objects) { if (std::chrono::system_clock::now() < failed_loadable_object.second.next_attempt_time) continue; const auto & name = failed_loadable_object.first; try { auto loadable_ptr = failed_loadable_object.second.loadable->clone(); if (const auto exception_ptr = loadable_ptr->getCreationException()) { /// recalculate next attempt time std::uniform_int_distribution<UInt64> distribution( 0, static_cast<UInt64>(std::exp2(failed_loadable_object.second.error_count))); std::chrono::seconds delay(std::min<UInt64>( update_settings.backoff_max_sec, update_settings.backoff_initial_sec + distribution(rnd_engine))); failed_loadable_object.second.next_attempt_time = std::chrono::system_clock::now() + delay; ++failed_loadable_object.second.error_count; std::rethrow_exception(exception_ptr); } else { const std::lock_guard<std::mutex> lock{map_mutex}; const auto & lifetime = loadable_ptr->getLifetime(); std::uniform_int_distribution<UInt64> distribution{lifetime.min_sec, lifetime.max_sec}; update_times[name] = std::chrono::system_clock::now() + std::chrono::seconds{distribution(rnd_engine)}; const auto dict_it = loadable_objects.find(name); dict_it->second.loadable.reset(); dict_it->second.loadable = std::move(loadable_ptr); /// clear stored exception on success dict_it->second.exception = std::exception_ptr{}; recreated_failed_loadable_objects.push_back(name); } } catch (...) { tryLogCurrentException(log, "Failed reloading '" + name + "' " + object_name); if (throw_on_error) throw; } } /// do not undertake further attempts to recreate these loadable objects for (const auto & name : recreated_failed_loadable_objects) failed_loadable_objects.erase(name); /// periodic update for (auto & loadable_object : loadable_objects) { const auto & name = loadable_object.first; try { /// If the loadable objects failed to load or even failed to initialize from the config. if (!loadable_object.second.loadable) continue; auto current = loadable_object.second.loadable; const auto & lifetime = current->getLifetime(); /// do not update loadable objects with zero as lifetime if (lifetime.min_sec == 0 || lifetime.max_sec == 0) continue; if (current->supportUpdates()) { auto & update_time = update_times[current->getName()]; /// check that timeout has passed if (std::chrono::system_clock::now() < update_time) continue; SCOPE_EXIT({ /// calculate next update time std::uniform_int_distribution<UInt64> distribution{lifetime.min_sec, lifetime.max_sec}; update_time = std::chrono::system_clock::now() + std::chrono::seconds{distribution(rnd_engine)}; }); /// check source modified if (current->isModified()) { /// create new version of loadable object auto new_version = current->clone(); if (const auto exception_ptr = new_version->getCreationException()) std::rethrow_exception(exception_ptr); loadable_object.second.loadable.reset(); loadable_object.second.loadable = std::move(new_version); } } /// erase stored exception on success loadable_object.second.exception = std::exception_ptr{}; }
void ExternalDictionaries::reloadImpl(const bool throw_on_error) { const auto config_paths = getDictionariesConfigPaths(Poco::Util::Application::instance().config()); for (const auto & config_path : config_paths) { try { reloadFromFile(config_path, throw_on_error); } catch (...) { tryLogCurrentException(log, "reloadFromFile has thrown while reading from " + config_path); if (throw_on_error) throw; } } /// list of recreated dictionaries to perform delayed removal from unordered_map std::list<std::string> recreated_failed_dictionaries; /// retry loading failed dictionaries for (auto & failed_dictionary : failed_dictionaries) { if (std::chrono::system_clock::now() < failed_dictionary.second.next_attempt_time) continue; const auto & name = failed_dictionary.first; try { auto dict_ptr = failed_dictionary.second.dict->clone(); if (const auto exception_ptr = dict_ptr->getCreationException()) { /// recalculate next attempt time std::uniform_int_distribution<UInt64> distribution( 0, std::exp2(failed_dictionary.second.error_count)); failed_dictionary.second.next_attempt_time = std::chrono::system_clock::now() + std::chrono::seconds{ std::min<UInt64>(backoff_max_sec, backoff_initial_sec + distribution(rnd_engine))}; ++failed_dictionary.second.error_count; std::rethrow_exception(exception_ptr); } else { const std::lock_guard<std::mutex> lock{dictionaries_mutex}; const auto & lifetime = dict_ptr->getLifetime(); std::uniform_int_distribution<UInt64> distribution{lifetime.min_sec, lifetime.max_sec}; update_times[name] = std::chrono::system_clock::now() + std::chrono::seconds{distribution(rnd_engine)}; const auto dict_it = dictionaries.find(name); if (dict_it->second.dict) dict_it->second.dict->set(dict_ptr.release()); else dict_it->second.dict = std::make_shared<MultiVersion<IDictionaryBase>>(dict_ptr.release()); /// erase stored exception on success dict_it->second.exception = std::exception_ptr{}; recreated_failed_dictionaries.push_back(name); } } catch (...) { tryLogCurrentException(log, "Failed reloading '" + name + "' dictionary"); if (throw_on_error) throw; } } /// do not undertake further attempts to recreate these dictionaries for (const auto & name : recreated_failed_dictionaries) failed_dictionaries.erase(name); /// periodic update for (auto & dictionary : dictionaries) { const auto & name = dictionary.first; try { /// If the dictionary failed to load or even failed to initialize from the config. if (!dictionary.second.dict) continue; auto current = dictionary.second.dict->get(); const auto & lifetime = current->getLifetime(); /// do not update dictionaries with zero as lifetime if (lifetime.min_sec == 0 || lifetime.max_sec == 0) continue; /// update only non-cached dictionaries if (!current->isCached()) { auto & update_time = update_times[current->getName()]; /// check that timeout has passed if (std::chrono::system_clock::now() < update_time) continue; SCOPE_EXIT({ /// calculate next update time std::uniform_int_distribution<UInt64> distribution{lifetime.min_sec, lifetime.max_sec}; update_time = std::chrono::system_clock::now() + std::chrono::seconds{distribution(rnd_engine)}; }); /// check source modified if (current->getSource()->isModified()) { /// create new version of dictionary auto new_version = current->clone(); if (const auto exception_ptr = new_version->getCreationException()) std::rethrow_exception(exception_ptr); dictionary.second.dict->set(new_version.release()); } } /// erase stored exception on success dictionary.second.exception = std::exception_ptr{}; }