bool game_character_stoped_in_volume(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<T>(0)); glm::vec3 vec1(args[1].real, args[2].real, args[3].real); glm::vec3 vec2(args[4].real, args[5].real, args[6].real); bool drawCylinder = !!args[7].integer; glm::vec3 min = glm::min(vec1, vec2); glm::vec3 max = glm::max(vec1, vec2); glm::vec3 pp = character->getPosition(); if( pp.x >= min.x && pp.y >= min.y && pp.z >= min.z && pp.x <= max.x && pp.y <= max.y && pp.z <= max.z ) { if( character->getCurrentVehicle() != nullptr ) { return character->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f; } else { return character->controller->getCurrentActivity() == nullptr; } } if( drawCylinder ) { args.getWorld()->drawAreaIndicator(AreaIndicatorInfo::Cylinder, (max+min)/2.f, (max-min)/2.f); } return false; }
void CharacterObject::resetToAINode() { auto nodes = engine->aigraph.nodes; bool vehicleNode = !! getCurrentVehicle(); AIGraphNode* nearest = nullptr; float d = std::numeric_limits<float>::max(); for(auto it = nodes.begin(); it != nodes.end(); ++it) { if(vehicleNode) { if((*it)->type == AIGraphNode::Pedestrian) continue; } else { if((*it)->type == AIGraphNode::Vehicle) continue; } float dist = glm::length((*it)->position - getPosition()); if(dist < d) { nearest = *it; d = dist; } } if(nearest) { if(vehicleNode) { getCurrentVehicle()->setPosition(nearest->position + glm::vec3(0.f, 0.f, 2.5f)); } else { setPosition(nearest->position + glm::vec3(0.f, 0.f, 2.5f)); } } }
bool game_locate_player_stopped_in_vehicle_2d(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getPlayerCharacter(0)); glm::vec2 position(args[1].real, args[2].real); glm::vec2 radius(args[3].real, args[4].real); bool drawCylinder = args[5].integer; if( character->getCurrentVehicle() == nullptr ) { return false; } auto vp = character->getCurrentVehicle()->getPosition(); glm::vec2 distance = glm::abs(position - glm::vec2(vp)); if(distance.x <= radius.x && distance.y <= radius.y && character->isStopped()) { return true; } if( drawCylinder ) { auto ground = args.getWorld()->getGroundAtPosition(glm::vec3(position, 100.f)); args.getWorld()->drawAreaIndicator(AreaIndicatorInfo::Cylinder, ground, glm::vec3(radius, 5.f)); } return false; }
bool game_is_character_stopped(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<T>(0)); if( character && character->getCurrentVehicle() != nullptr ) { return character->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f; } return true; }
bool game_player_in_any_vehicle(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getPlayerCharacter(0)); auto vehicle = character->getCurrentVehicle(); return vehicle != nullptr; }
bool game_player_in_taxi(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getPlayerCharacter(0)); auto vehicle = character->getCurrentVehicle(); return (vehicle && (vehicle->vehicle->classType & VehicleData::TAXI) == VehicleData::TAXI); }
void game_character_exit_vehicle(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1)); auto cvehcile = character->getCurrentVehicle(); if( cvehcile && cvehcile == vehicle ) { character->controller->setNextActivity(new Activities::ExitVehicle()); } }
bool game_player_pressing_horn(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getPlayerCharacter(0)); if ( character->getCurrentVehicle() != nullptr ) { /// @todo Respect actual horn key. return true; } return false; }
void Garage::doOnStartClosingEvent() { auto player = engine->getPlayer(); auto plyChar = player->getCharacter(); auto playerPosition = plyChar->getPosition(); auto playerVehicle = plyChar->getCurrentVehicle(); bool playerIsInVehicle = playerVehicle != nullptr; RW_UNUSED(playerPosition); RW_UNUSED(playerIsInVehicle); switch (type) { case Type::Mission: case Type::CollectCars1: case Type::CollectCars2: { player->setInputEnabled(false); break; } case Type::BombShop1: case Type::BombShop2: case Type::BombShop3: case Type::Respray: { player->setInputEnabled(false); playerVehicle->setHandbraking(true); break; } case Type::MissionForCarToComeOut: { break; } case Type::Crusher: { break; } case Type::MissionKeepCar: { break; } case Type::MissionToOpenAndClose: { break; } case Type::MissionForSpecificCar: { break; } case Type::MissionKeepCarAndRemainClosed: { break; } default: { break; } } }
bool game_character_in_vehicle(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<T>(0)); auto vehicle = args.getObject<VehicleObject>(1); if( character == nullptr || vehicle == nullptr ) { return false; } return character->getCurrentVehicle() == vehicle; }
bool game_player_in_model(const ScriptArguments& args) { auto vdata = args.getWorld()->data->findObjectType<VehicleData>(args[1].integer); if( vdata ) { auto character = static_cast<CharacterObject*>(args.getPlayerCharacter(0)); auto vehicle = character->getCurrentVehicle(); if ( vehicle ) { return vehicle->model && vdata->modelName == vehicle->model->name; } } return false; }
void game_navigate_on_foot(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0)); glm::vec3 target(args[1].real, args[2].real, 0.f); target = args.getWorld()->getGroundAtPosition(target); character->controller->skipActivity(); if( character->getCurrentVehicle() ) { // Since we just cleared the Activities, this will become current immediatley. character->controller->setNextActivity(new Activities::ExitVehicle); } character->controller->setNextActivity(new Activities::GoTo(target)); }
bool game_player_near_point_in_vehicle_3D(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getPlayerCharacter(0)); glm::vec3 center(args[1].real, args[2].real, args[3].real); glm::vec3 size(args[4].real, args[5].real, args[6].real); bool unkown = !!args[7].integer; RW_UNUSED(unkown); auto vehicle = character->getCurrentVehicle(); if( vehicle ) { auto distance = center - character->getPosition(); distance /= size; if( glm::length( distance ) < 1.f ) return true; } return false; }
bool game_character_near_point_on_foot_2D(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0)); glm::vec2 center(args[1].real, args[2].real); glm::vec2 size(args[3].real, args[4].real); bool unkown = !!args[5].integer; RW_UNUSED(unkown); auto vehicle = character->getCurrentVehicle(); if( !vehicle ) { auto distance = center - glm::vec2(character->getPosition()); distance /= size; if( glm::length( distance ) < 1.f ) return true; } return false; }
bool game_character_near_car_2d(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1)); glm::vec2 radius(args[2].real, args[3].real); bool drawMarker = !!args[4].integer; RW_UNUSED(drawMarker); RW_UNIMPLEMENTED("Draw marker in game_character_near_car_2D"); auto charVehicle = character->getCurrentVehicle(); if( charVehicle ) { auto dist = charVehicle->getPosition() - vehicle->getPosition(); if( dist.x <= radius.x && dist.y <= radius.y ) { return true; } } return false; }
bool game_player_near_point_on_foot_3D(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getPlayerCharacter(0)); glm::vec3 center(args[1].real, args[2].real, args[3].real); glm::vec3 size(args[4].real, args[5].real, args[6].real); bool drawCylinder = !!args[7].integer; auto vehicle = character->getCurrentVehicle(); if( ! vehicle ) { auto distance = center - character->getPosition(); distance /= size; if( glm::length( distance ) < 1.f ) return true; } if( drawCylinder ) { args.getWorld()->drawAreaIndicator(AreaIndicatorInfo::Cylinder, center, size); } return false; }
glm::vec3 CharacterObject::getPosition() const { if(physCharacter) { btVector3 Pos = physCharacter->getGhostObject()->getWorldTransform().getOrigin(); return glm::vec3(Pos.x(), Pos.y(), Pos.z()); } if(currentVehicle) { /// @todo this is hacky. if( animator->getAnimation(AnimIndexAction) == animations.car_getout_lhs ) { return currentVehicle->getSeatEntryPosition(currentSeat); } auto v = getCurrentVehicle(); auto R = glm::mat3_cast(v->getRotation()); glm::vec3 offset; auto o = (animator->getAnimation(AnimIndexAction) == animations.car_getin_lhs) ? enter_offset : glm::vec3(); if(getCurrentSeat() < v->info->seats.size()) { offset = R * (v->info->seats[getCurrentSeat()].offset - o); } return currentVehicle->getPosition() + offset; } return position; }
void game_get_character_vehicle(const ScriptArguments& args) { auto character = static_cast<CharacterObject*>(args.getObject<T>(0)); *args[1].globalInteger = character->getCurrentVehicle()->getGameObjectID(); }
void Garage::doOnCloseEvent() { auto player = engine->getPlayer(); auto plyChar = player->getCharacter(); auto playerPosition = plyChar->getPosition(); auto playerVehicle = plyChar->getCurrentVehicle(); bool playerIsInVehicle = playerVehicle != nullptr; RW_UNUSED(playerPosition); RW_UNUSED(playerIsInVehicle); switch (type) { case Type::Mission: { player->setInputEnabled(true); break; } case Type::BombShop1: case Type::BombShop2: case Type::BombShop3: { // Find out real value garageTimer = engine->getGameTime() + 1.5f; break; } case Type::Respray: { // Find out real value garageTimer = engine->getGameTime() + 2.f; playerVehicle->setHealth(1000.f); break; } case Type::CollectCars1: case Type::CollectCars2: { break; } case Type::MissionForCarToComeOut: { break; } case Type::Crusher: { break; } case Type::MissionKeepCar: { break; } case Type::Hideout1: case Type::Hideout2: case Type::Hideout3: { break; } case Type::MissionToOpenAndClose: { break; } case Type::MissionForSpecificCar: { break; } case Type::MissionKeepCarAndRemainClosed: { break; } default: { break; } } }
void Garage::doOnOpenEvent() { auto player = engine->getPlayer(); auto plyChar = player->getCharacter(); auto playerPosition = plyChar->getPosition(); auto playerVehicle = plyChar->getCurrentVehicle(); bool playerIsInVehicle = playerVehicle != nullptr; RW_UNUSED(playerPosition); RW_UNUSED(playerIsInVehicle); switch (type) { case Type::Mission: { break; } case Type::BombShop1: { break; } case Type::BombShop2: { break; } case Type::BombShop3: { break; } case Type::Respray: { break; } case Type::CollectCars1: case Type::CollectCars2: { break; } case Type::MissionForCarToComeOut: { break; } case Type::Crusher: { break; } case Type::MissionKeepCar: { break; } case Type::Hideout1: case Type::Hideout2: case Type::Hideout3: { break; } case Type::MissionToOpenAndClose: { break; } case Type::MissionForSpecificCar: { break; } case Type::MissionKeepCarAndRemainClosed: { break; } default: { break; } } }
bool Garage::shouldStopOpening() { 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: case Type::BombShop1: case Type::BombShop2: case Type::BombShop3: case Type::Respray: case Type::CollectCars1: case Type::CollectCars2: { 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 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; }
glm::vec3 CharacterObject::updateMovementAnimation(float dt) { glm::vec3 animTranslate; if (motionBlockedByActivity) { // Clear any residual motion animation animator->playAnimation(AnimIndexMovement, nullptr, 1.f, false); return glm::vec3(); } // Things are simpler if we're in a vehicle if (getCurrentVehicle()) { animator->playAnimation(0, animations.car_sit, 1.f, true); return glm::vec3(); } Animation* movementAnimation = animations.idle; Animation* currentAnim = animator->getAnimation(AnimIndexMovement); bool isActionHappening = (animator->getAnimation(AnimIndexAction) != nullptr); float animationSpeed = 1.f; bool repeat = true; constexpr float movementEpsilon = 0.1f; float movementLength = glm::length(movement); if (!isAlive()) { movementAnimation = animations.ko_shot_front; repeat = false; } else if (jumped) { repeat = false; if (currentAnim == animations.jump_start && animator->isCompleted(AnimIndexMovement)) { movementAnimation = animations.jump_start; } if (isOnGround()) { if (currentAnim != animations.jump_land || !animator->isCompleted(AnimIndexMovement)) { movementAnimation = animations.jump_land; } else { // We are done jumping jumped = false; } } else { movementAnimation = animations.jump_glide; } } else if (movementLength > movementEpsilon) { if (running && !isActionHappening) { // No slow running movementAnimation = animations.run; animationSpeed = 1.f; } else { animationSpeed = 1.f / movementLength; // Determine if we need to play the walk start animation if (currentAnim != animations.walk) { if (currentAnim != animations.walk_start || !animator->isCompleted(AnimIndexMovement)) { movementAnimation = animations.walk_start; } else { movementAnimation = animations.walk; } } else { // Keep walkin movementAnimation = animations.walk; } } } // Check if we need to change the animation or change speed if (animator->getAnimation(AnimIndexMovement) != movementAnimation) { animator->playAnimation(AnimIndexMovement, movementAnimation, animationSpeed, repeat); } else { animator->setAnimationSpeed(AnimIndexMovement, animationSpeed); } // If we have to, interrogate the movement animation if (movementAnimation != animations.idle) { if(! model->resource->frames[0]->getChildren().empty() ) { ModelFrame* root = model->resource->frames[0]->getChildren()[0]; auto it = movementAnimation->bones.find(root->getName()); if (it != movementAnimation->bones.end()) { AnimationBone* rootBone = it->second; float step = dt; const float duration = animator->getAnimation(AnimIndexMovement)->duration; float animTime = fmod(animator->getAnimationTime(AnimIndexMovement), duration); // Handle any remaining transformation before the end of the keyframes if ((animTime+step) > duration) { glm::vec3 a = rootBone->getInterpolatedKeyframe(animTime).position; glm::vec3 b = rootBone->getInterpolatedKeyframe(duration).position; glm::vec3 d = (b-a); animTranslate.y += d.y; step -= (duration - animTime); animTime = 0.f; } glm::vec3 a = rootBone->getInterpolatedKeyframe(animTime).position; glm::vec3 b = rootBone->getInterpolatedKeyframe(animTime+step).position; glm::vec3 d = (b-a); animTranslate.y += d.y; Skeleton::FrameData fd = skeleton->getData(root->getIndex()); fd.a.translation.y = 0.f; skeleton->setData(root->getIndex(), fd); } } } return animTranslate; }