Allow changing spectate target with analog input

This commit is contained in:
Benau 2019-02-02 01:20:52 +08:00
parent 75bc25d2ff
commit 0cb12ea124
7 changed files with 65 additions and 65 deletions

View File

@ -790,11 +790,16 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
}
}
auto cl = LobbyProtocol::get<ClientLobby>();
bool is_nw_spectator = cl && cl->isSpectator() &&
StateManager::get()->getGameState() == GUIEngine::GAME &&
!GUIEngine::ModalDialog::isADialogActive();
// ... when in-game
if (StateManager::get()->getGameState() == GUIEngine::GAME &&
!GUIEngine::ModalDialog::isADialogActive() &&
!GUIEngine::ScreenKeyboard::isActive() &&
!race_manager->isWatchingReplay() )
!race_manager->isWatchingReplay() && !is_nw_spectator)
{
if (player == NULL)
{
@ -807,14 +812,6 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
if (pk == NULL)
{
if (auto cl = LobbyProtocol::get<ClientLobby>())
{
if (cl->isSpectator())
{
cl->changeSpectateTarget(action, value);
return;
}
}
Log::error("InputManager::dispatchInput", "Trying to process "
"action for an unknown player");
return;
@ -842,7 +839,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
// When in master-only mode, we can safely assume that players
// are set up, contrarly to early menus where we accept every
// input because players are not set-up yet
if (m_master_player_only && player == NULL)
if (m_master_player_only && player == NULL && !is_nw_spectator)
{
if (type == Input::IT_STICKMOTION ||
type == Input::IT_STICKBUTTON)
@ -872,6 +869,12 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
m_timer = 0.25;
}
if (is_nw_spectator)
{
cl->changeSpectateTarget(action, abs(value), type);
return;
}
// player may be NULL in early menus, before player setup has
// been performed
int playerID = (player == NULL ? 0 : player->getID());

View File

@ -39,12 +39,10 @@
#include "graphics/irr_driver.hpp"
#endif
#include "graphics/camera.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/max_speed.hpp"
#include "karts/rescue_animation.hpp"
#include "modes/linear_world.hpp"
#include "network/protocols/client_lobby.hpp"
#include "race/race_manager.hpp"
#include "states_screens/race_result_gui.hpp"
#include "tracks/drive_graph.hpp"
@ -57,8 +55,6 @@ EndController::EndController(AbstractKart *kart,
Controller *prev_controller)
: AIBaseLapController(kart)
{
m_network_spectate_time = std::numeric_limits<uint64_t>::max();
m_use_normal_camera_spectating = false;
m_previous_controller = prev_controller;
if(!race_manager->isBattleMode() &&
race_manager->getMinorMode()!=RaceManager::MINOR_MODE_SOCCER)
@ -168,18 +164,6 @@ void EndController::newLap(int lap)
*/
bool EndController::action(PlayerAction action, int value, bool dry_run)
{
auto cl = LobbyProtocol::get<ClientLobby>();
if (StkTime::getRealTimeMs() > m_network_spectate_time && cl)
{
if (!m_use_normal_camera_spectating)
{
// Only 1 local player will be able to change target
m_use_normal_camera_spectating = true;
Camera::changeCamera(0, Camera::CM_TYPE_NORMAL);
}
cl->changeSpectateTarget(action, value);
return true;
}
if(action!=PA_FIRE) return true;
RaceResultGUI *race_result_gui =
dynamic_cast<RaceResultGUI*>(World::getWorld()->getRaceGUI());

View File

@ -69,10 +69,6 @@ private:
* is targeting at. */
irr::scene::ISceneNode *m_debug_sphere;
uint64_t m_network_spectate_time;
bool m_use_normal_camera_spectating;
/*Functions called directly from update(). They all represent an action
*that can be done, and end up setting their respective m_controls
*variable.
@ -118,9 +114,7 @@ public:
/** Returns the name of the previous controller (which has the right
* player name associated). */
core::stringw getName() const { return m_previous_controller->getName(); }
// ------------------------------------------------------------------------
void setNetworkSpectateTime(uint64_t time)
{ m_network_spectate_time = time; }
}; // EndKart
#endif

View File

@ -322,6 +322,7 @@ void Kart::reset()
}
m_network_finish_check_ticks = 0;
m_enabled_network_spectator = false;
// Add karts back in case that they have been removed (i.e. in battle
// mode) - but only if they actually have a body (e.g. ghost karts
// don't have one).
@ -988,29 +989,6 @@ void Kart::finishedRace(float time, bool from_server)
}
} // !from_server
#ifndef ANDROID
auto cl = LobbyProtocol::get<ClientLobby>();
if (cl && m_controller->isLocalPlayerController() &&
race_manager->getNumLocalPlayers() == 1 &&
race_manager->modeHasLaps() && from_server)
{
static bool msg_shown = false;
if (!msg_shown)
{
msg_shown = true;
cl->addSpectateHelperMessage();
}
EndController* ec = dynamic_cast<EndController*>(m_controller);
if (ec)
{
// Enable spectate mode after 3 seconds which allow player to
// release left / right button if they keep pressing it during
// finishing line
ec->setNetworkSpectateTime(StkTime::getRealTimeMs() + 3000);
}
}
#endif
m_finished_race = true;
m_finish_time = time;
@ -1380,6 +1358,31 @@ void Kart::update(int ticks)
m_saved_controller = NULL;
}
#ifndef ANDROID
auto cl = LobbyProtocol::get<ClientLobby>();
// Enable spectate mode after 2 seconds which allow player to
// release left / right button if they keep pressing it during
// finishing line (1 second here because m_network_finish_check_ticks is
// already 1 second ahead of time when crossing finished line)
if (cl && m_finished_race && m_controller->isLocalPlayerController() &&
race_manager->getNumLocalPlayers() == 1 &&
race_manager->modeHasLaps() &&
World::getWorld()->getTicksSinceStart() >
m_network_finish_check_ticks + stk_config->time2Ticks(1.0f) &&
!m_enabled_network_spectator)
{
static bool msg_shown = false;
if (!msg_shown)
{
msg_shown = true;
cl->addSpectateHelperMessage();
}
m_enabled_network_spectator = true;
cl->setSpectator(true);
}
#endif
m_powerup->update(ticks);
// Reset any instant speed increase in the bullet kart

View File

@ -97,6 +97,8 @@ protected:
/** Is time flying activated */
bool m_is_jumping;
bool m_enabled_network_spectator;
protected:
/** Handles speed increase and capping due to powerup, terrain, ... */
MaxSpeed *m_max_speed;

View File

@ -1227,12 +1227,25 @@ void ClientLobby::sendChat(irr::core::stringw text)
} // sendChat
// ----------------------------------------------------------------------------
void ClientLobby::changeSpectateTarget(PlayerAction action, int value) const
void ClientLobby::changeSpectateTarget(PlayerAction action, int value,
Input::InputType type) const
{
Camera* cam = Camera::getActiveCamera();
if (!cam)
return;
if (action == PA_LOOK_BACK && value == 0)
// Only 1 local player will be able to change target, and this will replace
// the end camera with normal
if (cam->getType() != Camera::CM_TYPE_NORMAL)
Camera::changeCamera(0, Camera::CM_TYPE_NORMAL);
// Copied from EventHandler::processGUIAction
const bool pressed_down = value > Input::MAX_VALUE * 2 / 3;
if (!pressed_down && type == Input::IT_STICKMOTION)
return;
if (action == PA_LOOK_BACK)
{
if (cam->getMode() == Camera::CM_REVERSE)
cam->setMode(Camera::CM_NORMAL);
@ -1245,17 +1258,16 @@ void ClientLobby::changeSpectateTarget(PlayerAction action, int value) const
if (cam->getKart())
current_idx = cam->getKart()->getWorldKartId();
bool up = false;
if (action == PA_STEER_LEFT && value == 0)
if (action == PA_STEER_LEFT)
up = false;
else if (action == PA_STEER_RIGHT && value == 0)
else if (action == PA_STEER_RIGHT)
up = true;
else
return;
const int num_karts = World::getWorld()->getNumKarts();
for (int i = 0;i < num_karts; i++)
for (int i = 0; i < num_karts; i++)
{
current_idx = up ? current_idx+1 : current_idx-1;
current_idx = up ? current_idx + 1 : current_idx - 1;
// Handle looping
if (current_idx == -1)
current_idx = num_karts - 1;

View File

@ -147,13 +147,15 @@ public:
virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
void requestKartInfo(uint8_t kart_id);
void setSpectator(bool val) { m_spectator = val; }
bool isSpectator() const { return m_spectator; }
bool isSpectator() const
{ return m_spectator && m_state.load() != RACE_FINISHED; }
void startLiveJoinKartSelection();
void sendChat(irr::core::stringw text);
const std::vector<LobbyPlayer>& getLobbyPlayers() const
{ return m_lobby_players; }
bool isServerLiveJoinable() const { return m_server_live_joinable; }
void changeSpectateTarget(PlayerAction action, int value) const;
void changeSpectateTarget(PlayerAction action, int value,
Input::InputType type) const;
void addSpectateHelperMessage() const;
};