Added a very first version of a swatter (or inflatable hammer).
Details are in the wiki (http://supertuxkart.sourceforge.net/Items). Note that the model is _obviously_ a placeholder, and I used the icon for the bomb (which isn't used in game atm) for the swatter. I hope someone can provide a better model and icon. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9011 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
39ec2ffd74
commit
da8ec214ce
BIN
data/models/swatter-icon.png
Normal file
BIN
data/models/swatter-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
data/models/swatter.b3d
Normal file
BIN
data/models/swatter.b3d
Normal file
Binary file not shown.
@ -14,6 +14,7 @@
|
|||||||
<item name="anchor" icon="anchor-icon.png"
|
<item name="anchor" icon="anchor-icon.png"
|
||||||
model="anchor.b3d" />
|
model="anchor.b3d" />
|
||||||
<item name="switch" icon="swap-icon.png" />
|
<item name="switch" icon="swap-icon.png" />
|
||||||
|
<item name="swatter" icon="swatter-icon.png" />
|
||||||
<item name="parachute" icon="parachute-icon.png"
|
<item name="parachute" icon="parachute-icon.png"
|
||||||
model="parachute.b3d" />
|
model="parachute.b3d" />
|
||||||
<item name="plunger" icon="plunger-icon.png"
|
<item name="plunger" icon="plunger-icon.png"
|
||||||
@ -36,19 +37,19 @@
|
|||||||
be quite rare, since otherwise the item might be used
|
be quite rare, since otherwise the item might be used
|
||||||
too often (compared with many items which will only
|
too often (compared with many items which will only
|
||||||
affect a karts or two). -->
|
affect a karts or two). -->
|
||||||
<!-- bubble cake bowl zipper plunger switch para anvil -->
|
<!-- bubble cake bowl zipper plunger switch glove para anvil -->
|
||||||
<first w="25 5 15 5 10 10 0 0"
|
<first w="25 5 15 5 10 10 10 0 0"
|
||||||
w-multi=" 0 0 5 0 0 0 0 0" />
|
w-multi=" 0 0 5 0 0 0 5 0 0" />
|
||||||
<top33 w="30 30 30 30 30 10 30 0"
|
<top33 w="30 30 30 30 30 10 30 30 0"
|
||||||
w-multi=" 0 10 10 0 10 0 0 0" />
|
w-multi=" 0 10 10 0 10 0 10 0 0" />
|
||||||
<mid33 w="30 30 30 30 30 10 30 0"
|
<mid33 w="30 30 30 30 30 10 30 30 0"
|
||||||
w-multi=" 0 20 20 20 20 0 0 0" />
|
w-multi=" 0 20 20 20 20 0 0 20 0" />
|
||||||
<end33 w=" 0 30 30 30 30 10 30 30"
|
<end33 w=" 0 30 30 30 30 10 30 30 30"
|
||||||
w-multi=" 0 30 30 30 30 0 0 0" />
|
w-multi=" 0 30 30 30 30 0 30 0 0" />
|
||||||
<last w=" 0 30 30 60 60 0 60 60"
|
<last w=" 0 30 30 60 60 0 0 60 60"
|
||||||
w-multi=" 0 30 30 60 60 0 0 0" />
|
w-multi=" 0 30 30 60 60 0 0 0 0" />
|
||||||
<battle w=" 0 30 60 0 0 10 0 0"
|
<battle w=" 0 30 60 0 0 10 0 30 0"
|
||||||
w-multi=" 0 0 5 0 0 0 0 0" />
|
w-multi=" 0 0 5 0 0 0 0 5 0" />
|
||||||
|
|
||||||
</powerup>
|
</powerup>
|
||||||
|
|
||||||
|
@ -145,13 +145,13 @@
|
|||||||
<nitro power-boost="3" consumption="1" small-container="1" big-container="3"
|
<nitro power-boost="3" consumption="1" small-container="1" big-container="3"
|
||||||
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
||||||
|
|
||||||
<!-- time is the time a zipper is active. force is the additional
|
<!-- time is the time a zipper is active. force is the additional
|
||||||
zipper force. speed-gain is the one time additional speed.
|
zipper force. speed-gain is the one time additional speed.
|
||||||
max-speed-increase is the additional speed allowed on top
|
max-speed-increase is the additional speed allowed on top
|
||||||
of the kart-specific maximum kart speed. Fade-out time determines
|
of the kart-specific maximum kart speed. Fade-out time determines
|
||||||
how long it takes for a zipper to fade out (after 'time'). -->
|
how long it takes for a zipper to fade out (after 'time'). -->
|
||||||
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-increase="15"
|
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-increase="15"
|
||||||
fade-out-time="1.0" />
|
fade-out-time="1.0" />
|
||||||
|
|
||||||
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
|
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
|
||||||
decrease: multiplicative decrease of skidding factor in each frame.
|
decrease: multiplicative decrease of skidding factor in each frame.
|
||||||
@ -176,6 +176,20 @@
|
|||||||
add-power="3" min-speed="10"
|
add-power="3" min-speed="10"
|
||||||
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
||||||
|
|
||||||
|
<!-- Kart-specific settings for the swatter:
|
||||||
|
duration: how long can the swatter be readied.
|
||||||
|
count: how often can it be used.
|
||||||
|
distance: How close a kart must be before it can be hit.
|
||||||
|
animation-time: How long it takes for the swatter to hit a target.
|
||||||
|
item-animation-time: How long the swatter will swat when a
|
||||||
|
projectile hits.
|
||||||
|
squash-duration: How long a kart will remain squashed.
|
||||||
|
squash-slowdown: percentage of max speed that a kart is
|
||||||
|
restricted to. -->
|
||||||
|
<swatter duration="10" count="2" distance="3" animation-time="0.2"
|
||||||
|
item-animation-time="0.04" squash-duration="5"
|
||||||
|
squash-slowdown="0.5"/>
|
||||||
|
|
||||||
<!-- min-speed-radius and max-speed-radius define the smallest turn
|
<!-- min-speed-radius and max-speed-radius define the smallest turn
|
||||||
radius at lowest speed (4.64 m at speed 0) and at high speed
|
radius at lowest speed (4.64 m at speed 0) and at high speed
|
||||||
(13.5 m at speed 12 m/s). Maximum steering angles for speeds
|
(13.5 m at speed 12 m/s). Maximum steering angles for speeds
|
||||||
|
@ -115,7 +115,8 @@ void InputManager::handleStaticAction(int key, int value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEY_F1:
|
case KEY_F1:
|
||||||
if (UserConfigParams::m_artist_debug_mode && world && race_manager->getNumPlayers() ==1 )
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() ==1 )
|
||||||
{
|
{
|
||||||
Kart* kart = world->getLocalPlayerKart(0);
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
kart->setPowerup(PowerupManager::POWERUP_BUBBLEGUM, 10000);
|
kart->setPowerup(PowerupManager::POWERUP_BUBBLEGUM, 10000);
|
||||||
@ -127,42 +128,48 @@ void InputManager::handleStaticAction(int key, int value)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_F2:
|
case KEY_F2:
|
||||||
if (UserConfigParams::m_artist_debug_mode && world && race_manager->getNumPlayers() ==1 )
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() ==1 )
|
||||||
{
|
{
|
||||||
Kart* kart = world->getLocalPlayerKart(0);
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
kart->setPowerup(PowerupManager::POWERUP_PLUNGER, 10000);
|
kart->setPowerup(PowerupManager::POWERUP_PLUNGER, 10000);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_F3:
|
case KEY_F3:
|
||||||
if (UserConfigParams::m_artist_debug_mode && world && race_manager->getNumPlayers() ==1 )
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() ==1 )
|
||||||
{
|
{
|
||||||
Kart* kart = world->getLocalPlayerKart(0);
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
kart->setPowerup(PowerupManager::POWERUP_CAKE, 10000);
|
kart->setPowerup(PowerupManager::POWERUP_CAKE, 10000);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_F4:
|
case KEY_F4:
|
||||||
if (UserConfigParams::m_artist_debug_mode && world && race_manager->getNumPlayers() ==1 )
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() ==1 )
|
||||||
{
|
{
|
||||||
Kart* kart = world->getLocalPlayerKart(0);
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
kart->setPowerup(PowerupManager::POWERUP_SWITCH, 10000);
|
kart->setPowerup(PowerupManager::POWERUP_SWITCH, 10000);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_F5:
|
case KEY_F5:
|
||||||
if (UserConfigParams::m_artist_debug_mode && world && race_manager->getNumPlayers() ==1 )
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() ==1 )
|
||||||
{
|
{
|
||||||
Kart* kart = world->getLocalPlayerKart(0);
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
kart->setPowerup(PowerupManager::POWERUP_BOWLING, 10000);
|
kart->setPowerup(PowerupManager::POWERUP_BOWLING, 10000);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_F6:
|
case KEY_F6:
|
||||||
if (UserConfigParams::m_artist_debug_mode && world && race_manager->getNumPlayers() == 1)
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() == 1)
|
||||||
{
|
{
|
||||||
Kart* kart = world->getLocalPlayerKart(0);
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
kart->setPowerup(PowerupManager::POWERUP_PARACHUTE, 10000);
|
kart->setPowerup(PowerupManager::POWERUP_PARACHUTE, 10000);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_F7:
|
case KEY_F7:
|
||||||
if (UserConfigParams::m_artist_debug_mode && world && race_manager->getNumPlayers() == 1)
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() == 1)
|
||||||
{
|
{
|
||||||
Kart* kart = world->getLocalPlayerKart(0);
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
kart->setPowerup(PowerupManager::POWERUP_ZIPPER, 10000);
|
kart->setPowerup(PowerupManager::POWERUP_ZIPPER, 10000);
|
||||||
@ -180,7 +187,8 @@ void InputManager::handleStaticAction(int key, int value)
|
|||||||
const int count = World::getWorld()->getNumKarts();
|
const int count = World::getWorld()->getNumKarts();
|
||||||
for (int n=0; n<count; n++)
|
for (int n=0; n<count; n++)
|
||||||
{
|
{
|
||||||
World::getWorld()->getKart(n)->getNode()->setVisible(gui->m_enabled);
|
World::getWorld()->getKart(n)->getNode()
|
||||||
|
->setVisible(gui->m_enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -191,8 +199,17 @@ void InputManager::handleStaticAction(int key, int value)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KEY_F9:
|
||||||
|
if (UserConfigParams::m_artist_debug_mode && world &&
|
||||||
|
race_manager->getNumPlayers() == 1)
|
||||||
|
{
|
||||||
|
Kart* kart = world->getLocalPlayerKart(0);
|
||||||
|
kart->setPowerup(PowerupManager::POWERUP_SWATTER, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
case KEY_F11:
|
case KEY_F11:
|
||||||
if (UserConfigParams::m_artist_debug_mode && value && control_is_pressed)
|
if (UserConfigParams::m_artist_debug_mode && value &&
|
||||||
|
control_is_pressed)
|
||||||
{
|
{
|
||||||
if (world != NULL)
|
if (world != NULL)
|
||||||
{
|
{
|
||||||
@ -203,17 +220,9 @@ void InputManager::handleStaticAction(int key, int value)
|
|||||||
|
|
||||||
case KEY_F12:
|
case KEY_F12:
|
||||||
if(value)
|
if(value)
|
||||||
UserConfigParams::m_display_fps = !UserConfigParams::m_display_fps;
|
UserConfigParams::m_display_fps =
|
||||||
|
!UserConfigParams::m_display_fps;
|
||||||
break;
|
break;
|
||||||
#ifndef WIN32
|
|
||||||
// For now disable F9 toggling fullscreen, since windows requires
|
|
||||||
// to reload all textures, display lists etc. Fullscreen can
|
|
||||||
// be toggled from the main menu (options->display).
|
|
||||||
case KEY_F9:
|
|
||||||
// TODO; toggle fullscreen
|
|
||||||
//irrDriver->toggleFullscreen(false); // 0: do not reset textures
|
|
||||||
// Fall through to put the game into pause mode.
|
|
||||||
#endif
|
|
||||||
case KEY_F10:
|
case KEY_F10:
|
||||||
if(world) history->Save();
|
if(world) history->Save();
|
||||||
break;
|
break;
|
||||||
@ -227,17 +236,20 @@ void InputManager::handleStaticAction(int key, int value)
|
|||||||
/**
|
/**
|
||||||
* Handles input when an input sensing mode (when configuring input)
|
* Handles input when an input sensing mode (when configuring input)
|
||||||
*/
|
*/
|
||||||
void InputManager::inputSensing(Input::InputType type, int deviceID, int button,
|
void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||||
Input::AxisDirection axisDirection, int value)
|
int button, Input::AxisDirection axisDirection,
|
||||||
|
int value)
|
||||||
{
|
{
|
||||||
#if INPUT_MODE_DEBUG
|
#if INPUT_MODE_DEBUG
|
||||||
std::cout << "INPUT SENSING... ";
|
std::cout << "INPUT SENSING... ";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// don't store if we're trying to do something like bindings keyboard keys on a gamepad
|
// don't store if we're trying to do something like bindings keyboard
|
||||||
|
// keys on a gamepad
|
||||||
if (m_mode == INPUT_SENSE_KEYBOARD && type != Input::IT_KEYBOARD)
|
if (m_mode == INPUT_SENSE_KEYBOARD && type != Input::IT_KEYBOARD)
|
||||||
return;
|
return;
|
||||||
if (m_mode == INPUT_SENSE_GAMEPAD && type != Input::IT_STICKMOTION && type != Input::IT_STICKBUTTON)
|
if (m_mode == INPUT_SENSE_GAMEPAD && type != Input::IT_STICKMOTION &&
|
||||||
|
type != Input::IT_STICKBUTTON)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if INPUT_MODE_DEBUG
|
#if INPUT_MODE_DEBUG
|
||||||
@ -282,7 +294,8 @@ void InputManager::inputSensing(Input::InputType type, int deviceID, int button,
|
|||||||
case Input::IT_STICKMOTION:
|
case Input::IT_STICKMOTION:
|
||||||
{
|
{
|
||||||
std::cout << "%% storing new axis binding, value=" << value <<
|
std::cout << "%% storing new axis binding, value=" << value <<
|
||||||
" deviceID=" << deviceID << " button=" << button << " axisDirection=" <<
|
" deviceID=" << deviceID << " button=" << button <<
|
||||||
|
" axisDirection=" <<
|
||||||
(axisDirection == Input::AD_NEGATIVE ? "-" : "+") << "\n";
|
(axisDirection == Input::AD_NEGATIVE ? "-" : "+") << "\n";
|
||||||
// We have to save the direction in which the axis was moved.
|
// We have to save the direction in which the axis was moved.
|
||||||
// This is done by storing it as a sign (and since button can
|
// This is done by storing it as a sign (and since button can
|
||||||
@ -343,8 +356,10 @@ void InputManager::inputSensing(Input::InputType type, int deviceID, int button,
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int InputManager::getPlayerKeyboardID() const
|
int InputManager::getPlayerKeyboardID() const
|
||||||
{
|
{
|
||||||
// In no-assign mode, just return the GUI player ID (devices not assigned yet)
|
// In no-assign mode, just return the GUI player ID (devices not
|
||||||
if (m_device_manager->getAssignMode() == NO_ASSIGN) return PLAYER_ID_GAME_MASTER;
|
// assigned yet)
|
||||||
|
if (m_device_manager->getAssignMode() == NO_ASSIGN)
|
||||||
|
return PLAYER_ID_GAME_MASTER;
|
||||||
|
|
||||||
// Otherwise, after devices are assigned, we can check in more depth
|
// Otherwise, after devices are assigned, we can check in more depth
|
||||||
// Return the first keyboard that is actually being used
|
// Return the first keyboard that is actually being used
|
||||||
@ -373,7 +388,8 @@ int InputManager::getPlayerKeyboardID() const
|
|||||||
* Note: It is the obligation of the called menu to switch of the sense mode.
|
* Note: It is the obligation of the called menu to switch of the sense mode.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void InputManager::dispatchInput(Input::InputType type, int deviceID, int button,
|
void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||||
|
int button,
|
||||||
Input::AxisDirection axisDirection, int value)
|
Input::AxisDirection axisDirection, int value)
|
||||||
{
|
{
|
||||||
// Act different in input sensing mode.
|
// Act different in input sensing mode.
|
||||||
@ -386,21 +402,28 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int button
|
|||||||
|
|
||||||
StateManager::ActivePlayer* player = NULL;
|
StateManager::ActivePlayer* player = NULL;
|
||||||
PlayerAction action;
|
PlayerAction action;
|
||||||
bool action_found = m_device_manager->translateInput( type, deviceID, button, axisDirection, value,
|
bool action_found = m_device_manager->translateInput(type, deviceID,
|
||||||
m_mode, &player, &action);
|
button, axisDirection,
|
||||||
|
value, m_mode,
|
||||||
|
&player, &action);
|
||||||
|
|
||||||
// if didn't find a _menu_ action, try finding a corresponding game action as fallback
|
// if didn't find a _menu_ action, try finding a corresponding game action
|
||||||
// (the GUI can handle them too)
|
// as fallback (the GUI can handle them too)
|
||||||
if (!action_found && m_mode == MENU)
|
if (!action_found && m_mode == MENU)
|
||||||
{
|
{
|
||||||
action_found = m_device_manager->translateInput(type, deviceID, button, axisDirection, value,
|
action_found = m_device_manager->translateInput(type, deviceID,
|
||||||
INGAME, &player, &action);
|
button, axisDirection,
|
||||||
|
value, INGAME, &player,
|
||||||
|
&action);
|
||||||
}
|
}
|
||||||
|
|
||||||
// in menus, some keyboard keys are standard (before each player selected his device)
|
// in menus, some keyboard keys are standard (before each player selected
|
||||||
// So if a key could not be mapped to any known binding, fall back to check the defaults.
|
// his device). So if a key could not be mapped to any known binding,
|
||||||
if (!action_found && StateManager::get()->getGameState() != GUIEngine::GAME && type == Input::IT_KEYBOARD &&
|
// fall back to check the defaults.
|
||||||
m_mode == MENU && m_device_manager->getAssignMode() == NO_ASSIGN)
|
if (!action_found &&
|
||||||
|
StateManager::get()->getGameState() != GUIEngine::GAME &&
|
||||||
|
type == Input::IT_KEYBOARD &&
|
||||||
|
m_mode == MENU && m_device_manager->getAssignMode() == NO_ASSIGN)
|
||||||
{
|
{
|
||||||
action = PA_BEFORE_FIRST;
|
action = PA_BEFORE_FIRST;
|
||||||
|
|
||||||
@ -431,7 +454,8 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int button
|
|||||||
if (m_device_manager->getAssignMode() == DETECT_NEW)
|
if (m_device_manager->getAssignMode() == DETECT_NEW)
|
||||||
{
|
{
|
||||||
// Player is unjoining
|
// Player is unjoining
|
||||||
if ((player != NULL) && (action == PA_RESCUE || action == PA_MENU_CANCEL))
|
if ((player != NULL) && (action == PA_RESCUE ||
|
||||||
|
action == PA_MENU_CANCEL ) )
|
||||||
{
|
{
|
||||||
// returns true if the event was handled
|
// returns true if the event was handled
|
||||||
if (KartSelectionScreen::getInstance()->playerQuit( player ))
|
if (KartSelectionScreen::getInstance()->playerQuit( player ))
|
||||||
@ -457,25 +481,30 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int button
|
|||||||
InputDevice *device = NULL;
|
InputDevice *device = NULL;
|
||||||
if (type == Input::IT_KEYBOARD)
|
if (type == Input::IT_KEYBOARD)
|
||||||
{
|
{
|
||||||
//std::cout << "==== New Player Joining with Key " << button << " ====" << std::endl;
|
//std::cout << "==== New Player Joining with Key " <<
|
||||||
|
// button << " ====" << std::endl;
|
||||||
device = m_device_manager->getKeyboardFromBtnID(button);
|
device = m_device_manager->getKeyboardFromBtnID(button);
|
||||||
}
|
}
|
||||||
else if (type == Input::IT_STICKBUTTON || type == Input::IT_STICKMOTION)
|
else if (type == Input::IT_STICKBUTTON ||
|
||||||
|
type == Input::IT_STICKMOTION )
|
||||||
{
|
{
|
||||||
device = m_device_manager->getGamePadFromIrrID(deviceID);
|
device = m_device_manager->getGamePadFromIrrID(deviceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device != NULL)
|
if (device != NULL)
|
||||||
{
|
{
|
||||||
KartSelectionScreen::getInstance()->playerJoin( device, false );
|
KartSelectionScreen::getInstance()->playerJoin(device,
|
||||||
|
false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return; // we're done here, ignore devices that aren't associated with players
|
return; // we're done here, ignore devices that aren't
|
||||||
|
// associated with players
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... when in-game
|
// ... when in-game
|
||||||
if (StateManager::get()->getGameState() == GUIEngine::GAME && !GUIEngine::ModalDialog::isADialogActive())
|
if (StateManager::get()->getGameState() == GUIEngine::GAME &&
|
||||||
|
!GUIEngine::ModalDialog::isADialogActive() )
|
||||||
{
|
{
|
||||||
// Find the corresponding PlayerKart from our ActivePlayer instance
|
// Find the corresponding PlayerKart from our ActivePlayer instance
|
||||||
Kart* pk;
|
Kart* pk;
|
||||||
@ -490,7 +519,8 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int button
|
|||||||
|
|
||||||
if (pk == NULL)
|
if (pk == NULL)
|
||||||
{
|
{
|
||||||
std::cerr << "Error, trying to process action for an unknown player\n";
|
std::cerr <<
|
||||||
|
"Error, trying to process action for an unknown player\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,29 +531,31 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int button
|
|||||||
{
|
{
|
||||||
|
|
||||||
// reset timer when released
|
// reset timer when released
|
||||||
if (abs(value) == 0 && (/*type == Input::IT_KEYBOARD ||*/ type == Input::IT_STICKBUTTON))
|
if (abs(value) == 0 && type == Input::IT_STICKBUTTON)
|
||||||
{
|
{
|
||||||
//if(type == Input::IT_STICKBUTTON) std::cout << "resetting because type == Input::IT_STICKBUTTON\n";
|
|
||||||
//else std::cout << "resetting for another reason\n";
|
|
||||||
|
|
||||||
m_timer_in_use = false;
|
m_timer_in_use = false;
|
||||||
m_timer = 0;
|
m_timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When in master-only mode, we can safely assume that players are set up, contrarly to
|
// When in master-only mode, we can safely assume that players
|
||||||
// early menus where we accept every input because players are not set-up yet
|
// 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)
|
||||||
{
|
{
|
||||||
if (type == Input::IT_STICKMOTION || type == Input::IT_STICKBUTTON)
|
if (type == Input::IT_STICKMOTION ||
|
||||||
|
type == Input::IT_STICKBUTTON)
|
||||||
{
|
{
|
||||||
GamePadDevice* gp = getDeviceList()->getGamePadFromIrrID(deviceID);
|
GamePadDevice* gp =
|
||||||
|
getDeviceList()->getGamePadFromIrrID(deviceID);
|
||||||
|
|
||||||
if (gp != NULL &&
|
if (gp != NULL &&
|
||||||
abs(value)>gp->m_deadzone)
|
abs(value)>gp->m_deadzone)
|
||||||
{
|
{
|
||||||
//I18N: message shown when an input device is used but is not associated to any player
|
//I18N: message shown when an input device is used but
|
||||||
GUIEngine::showMessage(_("Ignoring '%s', you needed to join earlier to play!",
|
// is not associated to any player
|
||||||
irr::core::stringw(gp->m_name.c_str()).c_str()));
|
GUIEngine::showMessage(
|
||||||
|
_("Ignoring '%s', you needed to join earlier to play!",
|
||||||
|
irr::core::stringw(gp->m_name.c_str()).c_str()) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -538,27 +570,36 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int button
|
|||||||
m_timer = 0.25;
|
m_timer = 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
// player may be NULL in early menus, before player setup has been performed
|
// player may be NULL in early menus, before player setup has
|
||||||
|
// been performed
|
||||||
int playerID = (player == NULL ? 0 : player->getID());
|
int playerID = (player == NULL ? 0 : player->getID());
|
||||||
|
|
||||||
// If only the master player can act, and this player is not the master, ignore his input
|
// If only the master player can act, and this player is not
|
||||||
if (m_device_manager->getAssignMode() == ASSIGN && m_master_player_only &&
|
// the master, ignore his input
|
||||||
|
if (m_device_manager->getAssignMode() == ASSIGN &&
|
||||||
|
m_master_player_only &&
|
||||||
playerID != PLAYER_ID_GAME_MASTER)
|
playerID != PLAYER_ID_GAME_MASTER)
|
||||||
{
|
{
|
||||||
//I18N: message shown when a player that isn't game master tries to modify options that
|
//I18N: message shown when a player that isn't game master
|
||||||
//I18N: only the game master is allowed to
|
//I18N: tries to modify options that only the game master
|
||||||
GUIEngine::showMessage(_("Only the Game Master may act at this point!"));
|
//I18N: is allowed to
|
||||||
|
GUIEngine::showMessage(
|
||||||
|
_("Only the Game Master may act at this point!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all is good, pass the translated input event on to the event handler
|
// all is good, pass the translated input event on to the
|
||||||
GUIEngine::EventHandler::get()->processGUIAction(action, deviceID, abs(value), type, playerID);
|
// event handler
|
||||||
|
GUIEngine::EventHandler::get()
|
||||||
|
->processGUIAction(action, deviceID, abs(value), type,
|
||||||
|
playerID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == Input::IT_KEYBOARD)
|
else if (type == Input::IT_KEYBOARD)
|
||||||
{
|
{
|
||||||
// keyboard press not handled by device manager / bindings. Check static bindings...
|
// keyboard press not handled by device manager / bindings.
|
||||||
|
// Check static bindings...
|
||||||
handleStaticAction( button, value );
|
handleStaticAction( button, value );
|
||||||
}
|
}
|
||||||
} // input
|
} // input
|
||||||
@ -568,14 +609,16 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID, int button
|
|||||||
void InputManager::setMasterPlayerOnly(bool enabled)
|
void InputManager::setMasterPlayerOnly(bool enabled)
|
||||||
{
|
{
|
||||||
#if INPUT_MODE_DEBUG
|
#if INPUT_MODE_DEBUG
|
||||||
std::cout << "====== InputManager::setMasterPlayerOnly(" << enabled << ") ======\n";
|
std::cout <<
|
||||||
|
"====== InputManager::setMasterPlayerOnly(" << enabled << ") ======\n";
|
||||||
#endif
|
#endif
|
||||||
m_master_player_only = enabled;
|
m_master_player_only = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Returns whether only the master player should be allowed to perform changes in menus */
|
/** Returns whether only the master player should be allowed to perform changes
|
||||||
|
* in menus */
|
||||||
bool InputManager::masterPlayerOnly() const
|
bool InputManager::masterPlayerOnly() const
|
||||||
{
|
{
|
||||||
return m_device_manager->getAssignMode() == ASSIGN && m_master_player_only;
|
return m_device_manager->getAssignMode() == ASSIGN && m_master_player_only;
|
||||||
@ -598,8 +641,10 @@ EventPropagation InputManager::input(const SEvent& event)
|
|||||||
{
|
{
|
||||||
if (event.EventType == EET_JOYSTICK_INPUT_EVENT)
|
if (event.EventType == EET_JOYSTICK_INPUT_EVENT)
|
||||||
{
|
{
|
||||||
// Axes - FIXME, instead of checking all of them, ask the bindings which ones to poll
|
// Axes - FIXME, instead of checking all of them, ask the bindings
|
||||||
for (int axis_id=0; axis_id<SEvent::SJoystickEvent::NUMBER_OF_AXES ; axis_id++)
|
// which ones to poll
|
||||||
|
for (int axis_id=0; axis_id<SEvent::SJoystickEvent::NUMBER_OF_AXES ;
|
||||||
|
axis_id++)
|
||||||
{
|
{
|
||||||
int value = event.JoystickEvent.Axis[axis_id];
|
int value = event.JoystickEvent.Axis[axis_id];
|
||||||
|
|
||||||
@ -609,27 +654,32 @@ EventPropagation InputManager::input(const SEvent& event)
|
|||||||
event.JoystickEvent.Joystick, axis_id, value);
|
event.JoystickEvent.Joystick, axis_id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, axis_id,
|
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||||
Input::AD_NEUTRAL, value);
|
axis_id, Input::AD_NEUTRAL, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.JoystickEvent.POV == 65535)
|
if (event.JoystickEvent.POV == 65535)
|
||||||
{
|
{
|
||||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, Input::HAT_H_ID, Input::AD_NEUTRAL,
|
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||||
0);
|
Input::HAT_H_ID, Input::AD_NEUTRAL, 0);
|
||||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, Input::HAT_V_ID, Input::AD_NEUTRAL,
|
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||||
0);
|
Input::HAT_V_ID, Input::AD_NEUTRAL, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// *0.017453925f is to convert degrees to radians
|
// *0.017453925f is to convert degrees to radians
|
||||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, Input::HAT_H_ID, Input::AD_NEUTRAL,
|
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||||
(int)(cos(event.JoystickEvent.POV*0.017453925f/100.0f)*Input::MAX_VALUE));
|
Input::HAT_H_ID, Input::AD_NEUTRAL,
|
||||||
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick, Input::HAT_V_ID, Input::AD_NEUTRAL,
|
(int)(cos(event.JoystickEvent.POV*0.017453925f/100.0f)
|
||||||
(int)(sin(event.JoystickEvent.POV*0.017453925f/100.0f)*Input::MAX_VALUE));
|
*Input::MAX_VALUE));
|
||||||
|
dispatchInput(Input::IT_STICKMOTION, event.JoystickEvent.Joystick,
|
||||||
|
Input::HAT_V_ID, Input::AD_NEUTRAL,
|
||||||
|
(int)(sin(event.JoystickEvent.POV*0.017453925f/100.0f)
|
||||||
|
*Input::MAX_VALUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
GamePadDevice* gp = getDeviceList()->getGamePadFromIrrID(event.JoystickEvent.Joystick);
|
GamePadDevice* gp =
|
||||||
|
getDeviceList()->getGamePadFromIrrID(event.JoystickEvent.Joystick);
|
||||||
|
|
||||||
if (gp == NULL)
|
if (gp == NULL)
|
||||||
{
|
{
|
||||||
@ -642,14 +692,17 @@ EventPropagation InputManager::input(const SEvent& event)
|
|||||||
const bool isButtonPressed = event.JoystickEvent.IsButtonPressed(i);
|
const bool isButtonPressed = event.JoystickEvent.IsButtonPressed(i);
|
||||||
|
|
||||||
// Only report button events when the state of the button changes
|
// Only report button events when the state of the button changes
|
||||||
if ((!gp->isButtonPressed(i) && isButtonPressed) || (gp->isButtonPressed(i) && !isButtonPressed))
|
if ((!gp->isButtonPressed(i) && isButtonPressed) ||
|
||||||
|
(gp->isButtonPressed(i) && !isButtonPressed) )
|
||||||
{
|
{
|
||||||
if (UserConfigParams::m_gamepad_debug)
|
if (UserConfigParams::m_gamepad_debug)
|
||||||
{
|
{
|
||||||
printf("button %i, status=%i\n", i, isButtonPressed);
|
printf("button %i, status=%i\n", i, isButtonPressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchInput(Input::IT_STICKBUTTON, event.JoystickEvent.Joystick, i, Input::AD_POSITIVE,
|
dispatchInput(Input::IT_STICKBUTTON,
|
||||||
|
event.JoystickEvent.Joystick, i,
|
||||||
|
Input::AD_POSITIVE,
|
||||||
isButtonPressed ? Input::MAX_VALUE : 0);
|
isButtonPressed ? Input::MAX_VALUE : 0);
|
||||||
}
|
}
|
||||||
gp->setButtonPressed(i, isButtonPressed);
|
gp->setButtonPressed(i, isButtonPressed);
|
||||||
@ -676,9 +729,10 @@ EventPropagation InputManager::input(const SEvent& event)
|
|||||||
StateManager::get()->escapePressed();
|
StateManager::get()->escapePressed();
|
||||||
return EVENT_BLOCK;
|
return EVENT_BLOCK;
|
||||||
}
|
}
|
||||||
// 'backspace' in a text control must never be mapped, since user can be in a text
|
// 'backspace' in a text control must never be mapped, since user
|
||||||
// area trying to erase text (and if it's mapped to rescue that would dismiss the
|
// can be in a text area trying to erase text (and if it's mapped
|
||||||
// dialog instead of erasing a single letter). Same for spacebar. Same for letters.
|
// to rescue that would dismiss the dialog instead of erasing a
|
||||||
|
// single letter). Same for spacebar. Same for letters.
|
||||||
if (GUIEngine::isWithinATextBox())
|
if (GUIEngine::isWithinATextBox())
|
||||||
{
|
{
|
||||||
if (key == KEY_BACK || key == KEY_SPACE || key == KEY_SHIFT)
|
if (key == KEY_BACK || key == KEY_SPACE || key == KEY_SHIFT)
|
||||||
@ -696,7 +750,8 @@ EventPropagation InputManager::input(const SEvent& event)
|
|||||||
dispatchInput(Input::IT_KEYBOARD, event.KeyInput.Char, key,
|
dispatchInput(Input::IT_KEYBOARD, event.KeyInput.Char, key,
|
||||||
Input::AD_POSITIVE, Input::MAX_VALUE);
|
Input::AD_POSITIVE, Input::MAX_VALUE);
|
||||||
|
|
||||||
// if this action took us into a text box, don't let event continue (FIXME not the cleanest solution)
|
// if this action took us into a text box, don't let event continue
|
||||||
|
// (FIXME not the cleanest solution)
|
||||||
if (!wasInTextBox && GUIEngine::isWithinATextBox())
|
if (!wasInTextBox && GUIEngine::isWithinATextBox())
|
||||||
{
|
{
|
||||||
return EVENT_BLOCK;
|
return EVENT_BLOCK;
|
||||||
@ -705,9 +760,10 @@ EventPropagation InputManager::input(const SEvent& event)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 'backspace' in a text control must never be mapped, since user can be in a text
|
// 'backspace' in a text control must never be mapped, since user
|
||||||
// area trying to erase text (and if it's mapped to rescue that would dismiss the
|
// can be in a text area trying to erase text (and if it's mapped
|
||||||
// dialog instead of erasing a single letter). Same for spacebar. Same for letters.
|
// to rescue that would dismiss the dialog instead of erasing a
|
||||||
|
// single letter). Same for spacebar. Same for letters.
|
||||||
if (GUIEngine::isWithinATextBox())
|
if (GUIEngine::isWithinATextBox())
|
||||||
{
|
{
|
||||||
if (key == KEY_BACK || key == KEY_SPACE || key == KEY_SHIFT)
|
if (key == KEY_BACK || key == KEY_SPACE || key == KEY_SHIFT)
|
||||||
@ -745,16 +801,21 @@ EventPropagation InputManager::input(const SEvent& event)
|
|||||||
EMIE_RMOUSE_LEFT_UP Right mouse button was left up.
|
EMIE_RMOUSE_LEFT_UP Right mouse button was left up.
|
||||||
EMIE_MMOUSE_LEFT_UP Middle mouse button was left up.
|
EMIE_MMOUSE_LEFT_UP Middle mouse button was left up.
|
||||||
EMIE_MOUSE_MOVED The mouse cursor changed its position.
|
EMIE_MOUSE_MOVED The mouse cursor changed its position.
|
||||||
EMIE_MOUSE_WHEEL The mouse wheel was moved. Use Wheel value in event data to find out in what direction and how fast.
|
EMIE_MOUSE_WHEEL The mouse wheel was moved. Use Wheel value in
|
||||||
|
event data to find out in what direction and
|
||||||
|
how fast.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// block events in all modes but initial menus (except in text boxes to allow typing,
|
// block events in all modes but initial menus (except in text boxes to
|
||||||
// and except in modal dialogs in-game)
|
// allow typing, and except in modal dialogs in-game)
|
||||||
// FIXME: 1) that's awful logic 2) that's not what the code below does, events are never blocked in menus
|
// FIXME: 1) that's awful logic 2) that's not what the code below does,
|
||||||
if (getDeviceList()->getAssignMode() != NO_ASSIGN && !GUIEngine::isWithinATextBox() &&
|
// events are never blocked in menus
|
||||||
(!GUIEngine::ModalDialog::isADialogActive() && StateManager::get()->getGameState() == GUIEngine::GAME))
|
if (getDeviceList()->getAssignMode() != NO_ASSIGN &&
|
||||||
|
!GUIEngine::isWithinATextBox() &&
|
||||||
|
(!GUIEngine::ModalDialog::isADialogActive() &&
|
||||||
|
StateManager::get()->getGameState() == GUIEngine::GAME))
|
||||||
{
|
{
|
||||||
return EVENT_BLOCK;
|
return EVENT_BLOCK;
|
||||||
}
|
}
|
||||||
@ -837,9 +898,9 @@ void InputManager::setMode(InputDriverMode new_mode)
|
|||||||
m_sensed_input_high_gamepad.clear();
|
m_sensed_input_high_gamepad.clear();
|
||||||
m_sensed_input_high_kbd.clear();
|
m_sensed_input_high_kbd.clear();
|
||||||
|
|
||||||
// The order is deliberate just in case someone starts to make
|
// The order is deliberate just in case someone starts
|
||||||
// STK multithreaded: m_sensed_input must not be 0 when
|
// to make STK multithreaded: m_sensed_input must not be
|
||||||
// mode == INPUT_SENSE_PREFER_{AXIS,BUTTON}.
|
// 0 when mode == INPUT_SENSE_PREFER_{AXIS,BUTTON}.
|
||||||
m_mode = MENU;
|
m_mode = MENU;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -886,8 +947,8 @@ void InputManager::setMode(InputDriverMode new_mode)
|
|||||||
// We must be in menu mode now in order to switch.
|
// We must be in menu mode now in order to switch.
|
||||||
assert (m_mode == MENU);
|
assert (m_mode == MENU);
|
||||||
|
|
||||||
// Reset the helper values for the relative mouse movement supresses to
|
// Reset the helper values for the relative mouse movement
|
||||||
// the notification of them as an input.
|
// supresses to the notification of them as an input.
|
||||||
m_mouse_val_x = m_mouse_val_y = 0;
|
m_mouse_val_x = m_mouse_val_y = 0;
|
||||||
m_mode = new_mode;
|
m_mode = new_mode;
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include "network/network_manager.hpp"
|
#include "network/network_manager.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
|
|
||||||
|
#define SWAT_ANGLE 22.0f
|
||||||
|
|
||||||
Attachment::Attachment(Kart* kart)
|
Attachment::Attachment(Kart* kart)
|
||||||
{
|
{
|
||||||
m_type = ATTACH_NOTHING;
|
m_type = ATTACH_NOTHING;
|
||||||
@ -40,8 +42,8 @@ Attachment::Attachment(Kart* kart)
|
|||||||
|
|
||||||
// If we attach a NULL mesh, we get a NULL scene node back. So we
|
// If we attach a NULL mesh, we get a NULL scene node back. So we
|
||||||
// have to attach some kind of mesh, but make it invisible.
|
// have to attach some kind of mesh, but make it invisible.
|
||||||
m_node = irr_driver->addAnimatedMesh(
|
m_node = irr_driver->addAnimatedMesh(
|
||||||
attachment_manager->getMesh(ATTACH_BOMB));
|
attachment_manager->getMesh(Attachment::ATTACH_BOMB));
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::string debug_name = kart->getIdent()+" (attachment)";
|
std::string debug_name = kart->getIdent()+" (attachment)";
|
||||||
m_node->setName(debug_name.c_str());
|
m_node->setName(debug_name.c_str());
|
||||||
@ -58,11 +60,10 @@ Attachment::~Attachment()
|
|||||||
} // ~Attachment
|
} // ~Attachment
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void Attachment::set(attachmentType type, float time, Kart *current_kart)
|
void Attachment::set(AttachmentType type, float time, Kart *current_kart)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
|
||||||
m_node->setMesh(attachment_manager->getMesh(type));
|
m_node->setMesh(attachment_manager->getMesh(type));
|
||||||
|
|
||||||
if (!UserConfigParams::m_graphical_effects)
|
if (!UserConfigParams::m_graphical_effects)
|
||||||
@ -71,9 +72,18 @@ void Attachment::set(attachmentType type, float time, Kart *current_kart)
|
|||||||
m_node->setCurrentFrame(0);
|
m_node->setCurrentFrame(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_type = type;
|
m_type = type;
|
||||||
m_time_left = time;
|
m_time_left = time;
|
||||||
m_previous_owner = current_kart;
|
m_previous_owner = current_kart;
|
||||||
|
m_node->setRotation(core::vector3df(0, 0, 0));
|
||||||
|
m_count = m_type==ATTACH_SWATTER
|
||||||
|
? m_kart->getKartProperties()->getSwatterCount()
|
||||||
|
: 1;
|
||||||
|
m_animation_timer = 0.0f;
|
||||||
|
m_animation_phase = SWATTER_AIMING;
|
||||||
|
m_rot_per_sec = core::vector3df(0,0,0);
|
||||||
|
m_animation_target = NULL;
|
||||||
|
|
||||||
// A parachute can be attached as result of the usage of an item. In this
|
// A parachute can be attached as result of the usage of an item. In this
|
||||||
// case we have to save the current kart speed so that it can be detached
|
// case we have to save the current kart speed so that it can be detached
|
||||||
// by slowing down.
|
// by slowing down.
|
||||||
@ -98,6 +108,7 @@ void Attachment::set(attachmentType type, float time, Kart *current_kart)
|
|||||||
void Attachment::clear()
|
void Attachment::clear()
|
||||||
{
|
{
|
||||||
m_type=ATTACH_NOTHING;
|
m_type=ATTACH_NOTHING;
|
||||||
|
|
||||||
m_time_left=0.0;
|
m_time_left=0.0;
|
||||||
m_node->setVisible(false);
|
m_node->setVisible(false);
|
||||||
|
|
||||||
@ -108,6 +119,12 @@ void Attachment::clear()
|
|||||||
} // clear
|
} // clear
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
/** Randomly selects the new attachment. For a server process, the
|
||||||
|
* attachment can be passed into this function.
|
||||||
|
* \param item The item that was collected.
|
||||||
|
* \param new_attachment Optional: only used on the clients, it
|
||||||
|
* specifies the new attachment to use
|
||||||
|
*/
|
||||||
void Attachment::hitBanana(Item *item, int new_attachment)
|
void Attachment::hitBanana(Item *item, int new_attachment)
|
||||||
{
|
{
|
||||||
float leftover_time = 0.0f;
|
float leftover_time = 0.0f;
|
||||||
@ -228,6 +245,11 @@ void Attachment::update(float dt)
|
|||||||
case ATTACH_NOTHING: // Nothing to do, but complete all cases for switch
|
case ATTACH_NOTHING: // Nothing to do, but complete all cases for switch
|
||||||
case ATTACH_MAX:
|
case ATTACH_MAX:
|
||||||
break;
|
break;
|
||||||
|
case ATTACH_SWATTER:
|
||||||
|
updateSwatter(dt);
|
||||||
|
// If the swatter is used up, trigger cleaning up
|
||||||
|
if(m_count==0) m_time_left = -1.0f;
|
||||||
|
break;
|
||||||
case ATTACH_BOMB:
|
case ATTACH_BOMB:
|
||||||
if(m_time_left <= (m_node->getEndFrame() - m_node->getStartFrame() - 1))
|
if(m_time_left <= (m_node->getEndFrame() - m_node->getStartFrame() - 1))
|
||||||
{
|
{
|
||||||
@ -249,4 +271,183 @@ void Attachment::update(float dt)
|
|||||||
if ( m_time_left <= 0.0f)
|
if ( m_time_left <= 0.0f)
|
||||||
clear();
|
clear();
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Updates an armed swatter: it checks for any karts that are close enough
|
||||||
|
* and not invulnerable, it swats the kart.
|
||||||
|
* \param dt Time step size.
|
||||||
|
*/
|
||||||
|
void Attachment::updateSwatter(float dt)
|
||||||
|
{
|
||||||
|
core::vector3df r = m_node->getRotation();
|
||||||
|
r += m_rot_per_sec * dt;
|
||||||
|
switch(m_animation_phase)
|
||||||
|
{
|
||||||
|
case SWATTER_AIMING:
|
||||||
|
aimSwatter();
|
||||||
|
break;
|
||||||
|
case SWATTER_TO_KART:
|
||||||
|
if(fabsf(r.Z)>=90)
|
||||||
|
{
|
||||||
|
checkForHitKart(r.Z>0);
|
||||||
|
m_rot_per_sec *= -1.0f;
|
||||||
|
m_animation_phase = SWATTER_BACK_FROM_KART;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWATTER_BACK_FROM_KART:
|
||||||
|
if (r.Z>0)
|
||||||
|
{
|
||||||
|
r = core::vector3df(0,0,0);
|
||||||
|
m_rot_per_sec = r;
|
||||||
|
m_animation_phase = SWATTER_AIMING;
|
||||||
|
m_animation_target = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWATTER_ITEM_1: // swatter going to the left
|
||||||
|
if(r.Z>SWAT_ANGLE)
|
||||||
|
{
|
||||||
|
m_animation_phase = SWATTER_ITEM_2;
|
||||||
|
m_rot_per_sec *= -1.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWATTER_ITEM_2: // swatter going all the way to the right
|
||||||
|
if(r.Z<-SWAT_ANGLE)
|
||||||
|
{
|
||||||
|
m_animation_phase = SWATTER_ITEM_3;
|
||||||
|
m_rot_per_sec *= -1.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWATTER_ITEM_3: // swatter going back to rest position.
|
||||||
|
if(r.Z>0)
|
||||||
|
{
|
||||||
|
r = core::vector3df(0,0,0);
|
||||||
|
m_rot_per_sec = r;
|
||||||
|
m_animation_phase = SWATTER_AIMING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} // switch m_animation_phase
|
||||||
|
|
||||||
|
m_node->setRotation(r);
|
||||||
|
} // updateSwatter
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Returns true if the point xyz is to the left of the kart.
|
||||||
|
* \param xyz Point to determine the direction
|
||||||
|
*/
|
||||||
|
bool Attachment::isLeftSideOfKart(const Vec3 &xyz)
|
||||||
|
{
|
||||||
|
Vec3 forw_vec = m_kart->getTrans().getBasis().getColumn(2);
|
||||||
|
const Vec3& k1 = m_kart->getXYZ();
|
||||||
|
const Vec3 k2 = k1+forw_vec;
|
||||||
|
return xyz.sideOfLine2D(k1, k2)>0;
|
||||||
|
} // isLeftSideOfKart
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** This function is called when the swatter reaches the hit angle (i.e. it
|
||||||
|
* is furthest down). Check all karts if any one is hit, i.e. is at the right
|
||||||
|
* side and at the right angle and distance.
|
||||||
|
* \param isWattingLeft True if the swatter is aiming to the left side
|
||||||
|
* of the kart.
|
||||||
|
*/
|
||||||
|
void Attachment::checkForHitKart(bool isSwattingLeft)
|
||||||
|
{
|
||||||
|
// Square of the minimum distance
|
||||||
|
const KartProperties *kp = m_kart->getKartProperties();
|
||||||
|
float min_dist2 = kp->getSwatterDistance2();
|
||||||
|
Kart *hit_kart = NULL;
|
||||||
|
Vec3 forw_vec = m_kart->getTrans().getBasis().getColumn(2);
|
||||||
|
const World *world = World::getWorld();
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<world->getNumKarts(); i++)
|
||||||
|
{
|
||||||
|
Kart *kart = world->getKart(i);
|
||||||
|
if(kart->isEliminated() || kart==m_kart || kart->isSquashed())
|
||||||
|
continue;
|
||||||
|
float f = (kart->getXYZ()-m_kart->getXYZ()).length2();
|
||||||
|
|
||||||
|
// Distance is too great, ignore this kart.
|
||||||
|
if(f>min_dist2) continue;
|
||||||
|
|
||||||
|
// Check if the kart is at the right side.
|
||||||
|
const bool left = isLeftSideOfKart(kart->getXYZ());
|
||||||
|
if(left!=isSwattingLeft)
|
||||||
|
{
|
||||||
|
//printf("%s wrong side: %d %d\n",
|
||||||
|
// kart->getIdent().c_str(), left, isSwattingLeft);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 kart_vec = m_kart->getXYZ()-kart->getXYZ();
|
||||||
|
// cos alpha = a*b/||a||/||b||
|
||||||
|
// Since forw_vec is a unit vector, we only have to divide by
|
||||||
|
// the length of the vector to the kart.
|
||||||
|
float cos_angle = kart_vec.dot(forw_vec)/kart_vec.length();
|
||||||
|
float angle = acosf(cos_angle)*180/M_PI;
|
||||||
|
if(angle<45 || angle>135)
|
||||||
|
{
|
||||||
|
//printf("%s angle %f\n", kart->getIdent().c_str(), angle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kart->setSquash(kp->getSquashDuration(),
|
||||||
|
kp->getSquashSlowdown());
|
||||||
|
// It is assumed that only one kart is within reach of the swatter,
|
||||||
|
// so we can stop testing karts here.
|
||||||
|
return;
|
||||||
|
} // for i < num_karts
|
||||||
|
|
||||||
|
} // angleToKart
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Checks for any kart that is not already squashed that is close enough.
|
||||||
|
* If a kart is found, it changes the state of the swatter to be
|
||||||
|
* SWATTER_TARGET and starts the animation.
|
||||||
|
*/
|
||||||
|
void Attachment::aimSwatter()
|
||||||
|
{
|
||||||
|
const World *world = World::getWorld();
|
||||||
|
Kart *min_kart = NULL;
|
||||||
|
// Square of the minimum distance
|
||||||
|
float min_dist2 = m_kart->getKartProperties()->getSwatterDistance2();
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<world->getNumKarts(); i++)
|
||||||
|
{
|
||||||
|
Kart *kart = world->getKart(i);
|
||||||
|
if(kart->isEliminated() || kart==m_kart || kart->isSquashed())
|
||||||
|
continue;
|
||||||
|
float f = (kart->getXYZ()-m_kart->getXYZ()).length2();
|
||||||
|
if(f<min_dist2)
|
||||||
|
{
|
||||||
|
min_dist2 = f;
|
||||||
|
min_kart = kart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No kart close enough, nothing to do.
|
||||||
|
if(!min_kart) return;
|
||||||
|
|
||||||
|
m_count --;
|
||||||
|
m_animation_phase = SWATTER_TO_KART;
|
||||||
|
m_animation_target = min_kart;
|
||||||
|
const KartProperties *kp = m_kart->getKartProperties();
|
||||||
|
m_animation_timer = kp->getSwatterAnimationTime();
|
||||||
|
const bool left = isLeftSideOfKart(min_kart->getXYZ());
|
||||||
|
m_rot_per_sec = core::vector3df(0, 0,
|
||||||
|
left ?90.0f:-90.0f) / m_animation_timer;
|
||||||
|
|
||||||
|
} // aimSwatter
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Starts a (smaller) and faster swatting movement to be played
|
||||||
|
* when the kart is hit by an item.
|
||||||
|
*/
|
||||||
|
void Attachment::swatItem()
|
||||||
|
{
|
||||||
|
assert(m_type==ATTACH_SWATTER);
|
||||||
|
assert(m_animation_target==NULL);
|
||||||
|
|
||||||
|
m_animation_phase = SWATTER_ITEM_1;
|
||||||
|
m_animation_timer =
|
||||||
|
m_kart->getKartProperties()->getSwatterItemAnimationTime();
|
||||||
|
m_count--;
|
||||||
|
m_rot_per_sec = core::vector3df(0, 0, SWAT_ANGLE) / m_animation_timer;
|
||||||
|
} // swatItem
|
||||||
|
@ -27,72 +27,115 @@
|
|||||||
class Kart;
|
class Kart;
|
||||||
class Item;
|
class Item;
|
||||||
|
|
||||||
// Some loop in attachment.cpp depend on ATTACH_FIRST and ATTACH_MAX.
|
|
||||||
// So if new elements are added, make sure to add them in between those values.
|
|
||||||
// Also, please note that Attachment::Attachment relies on ATTACH_FIRST being 0.
|
|
||||||
enum attachmentType
|
|
||||||
{
|
|
||||||
ATTACH_FIRST = 0,
|
|
||||||
ATTACH_PARACHUTE = 0,
|
|
||||||
ATTACH_BOMB,
|
|
||||||
ATTACH_ANVIL,
|
|
||||||
ATTACH_TINYTUX,
|
|
||||||
ATTACH_MAX,
|
|
||||||
ATTACH_NOTHING
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup items
|
* \ingroup items
|
||||||
*/
|
*/
|
||||||
class Attachment: public NoCopy
|
class Attachment: public NoCopy
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
// Some loop in attachment.cpp depend on ATTACH_FIRST and ATTACH_MAX.
|
||||||
|
// So if new elements are added, make sure to add them in between those values.
|
||||||
|
// Also, please note that Attachment::Attachment relies on ATTACH_FIRST being 0.
|
||||||
|
enum AttachmentType
|
||||||
|
{
|
||||||
|
ATTACH_FIRST = 0,
|
||||||
|
ATTACH_PARACHUTE = 0,
|
||||||
|
ATTACH_BOMB,
|
||||||
|
ATTACH_ANVIL,
|
||||||
|
ATTACH_SWATTER,
|
||||||
|
ATTACH_TINYTUX,
|
||||||
|
ATTACH_MAX,
|
||||||
|
ATTACH_NOTHING
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
attachmentType m_type; //!< attachment type
|
/** Attachment type. */
|
||||||
Kart *m_kart; //!< kart the attachment is attached to
|
AttachmentType m_type;
|
||||||
float m_time_left; //!< time left till attachment expires
|
|
||||||
float m_initial_speed; //!< for parachutes only
|
/** Kart the attachment is attached to. */
|
||||||
|
Kart *m_kart;
|
||||||
|
|
||||||
|
/** How often an attachment can be used (e.g. swatter). */
|
||||||
|
int m_count;
|
||||||
|
|
||||||
|
/** Time left till attachment expires. */
|
||||||
|
float m_time_left;
|
||||||
|
|
||||||
|
/** For parachutes only. */
|
||||||
|
float m_initial_speed;
|
||||||
|
|
||||||
/** Scene node of the attachment, which will be attached to the kart's
|
/** Scene node of the attachment, which will be attached to the kart's
|
||||||
* scene node. */
|
* scene node. */
|
||||||
scene::IAnimatedMeshSceneNode
|
scene::IAnimatedMeshSceneNode
|
||||||
*m_node;
|
*m_node;
|
||||||
Kart *m_previous_owner; //!< used by bombs so that it's not passed
|
|
||||||
//!< back to previous owner
|
/** Used by bombs so that it's not passed back to previous owner. */
|
||||||
|
Kart *m_previous_owner;
|
||||||
|
|
||||||
|
/** State of a swatter animation. The swatter is either aiming (looking
|
||||||
|
* for a kart and/or swatting an incoming item), moving towards or back
|
||||||
|
* from a kart, or swatting left and right to hit an item - which has
|
||||||
|
* three phases: going left to an angle a (phae 1), then going to -a
|
||||||
|
* (phase 2), then going back to 0. */
|
||||||
|
enum {SWATTER_AIMING, SWATTER_TO_KART,
|
||||||
|
SWATTER_BACK_FROM_KART,
|
||||||
|
SWATTER_ITEM_1, SWATTER_ITEM_2, SWATTER_ITEM_3,
|
||||||
|
SWATTER_BACK_FROM_ITEM} m_animation_phase;
|
||||||
|
|
||||||
|
/** Timer for swatter animation. */
|
||||||
|
float m_animation_timer;
|
||||||
|
|
||||||
|
/** The kart the swatter is aiming at. */
|
||||||
|
Kart *m_animation_target;
|
||||||
|
|
||||||
|
/** Rotation per second so that the swatter will hit the kart. */
|
||||||
|
core::vector3df m_rot_per_sec;
|
||||||
|
|
||||||
RandomGenerator m_random;
|
RandomGenerator m_random;
|
||||||
|
|
||||||
|
void aimSwatter();
|
||||||
|
bool isLeftSideOfKart(const Vec3 &xyz);
|
||||||
|
void checkForHitKart(bool isSwattingToLeft);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Attachment(Kart* _kart);
|
Attachment(Kart* kart);
|
||||||
~Attachment();
|
~Attachment();
|
||||||
void set (attachmentType _type, float time, Kart *previous_kart=NULL);
|
void clear ();
|
||||||
void set (attachmentType _type) { set(_type, m_time_left); }
|
|
||||||
void clear ();
|
|
||||||
attachmentType getType () const { return m_type; }
|
|
||||||
float getTimeLeft () const { return m_time_left; }
|
|
||||||
void setTimeLeft (float t){ m_time_left = t; }
|
|
||||||
Kart* getPreviousOwner () const { return m_previous_owner; }
|
|
||||||
|
|
||||||
float weightAdjust () const {
|
|
||||||
return m_type==ATTACH_ANVIL
|
|
||||||
?stk_config->m_anvil_weight:0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float airResistanceAdjust () const {
|
|
||||||
return m_type==ATTACH_PARACHUTE
|
|
||||||
?stk_config->m_parachute_friction:0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float speedAdjust () const {
|
|
||||||
return m_type==ATTACH_ANVIL
|
|
||||||
?stk_config->m_anvil_speed_factor:1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Randomly selects the new attachment. For a server process, the
|
|
||||||
* attachment can be passed into this function.
|
|
||||||
* \param item The item that was collected.
|
|
||||||
* \param new_attachment Optional: only used on the clients, it
|
|
||||||
* specifies the new attachment to use
|
|
||||||
*/
|
|
||||||
void hitBanana(Item *item, int new_attachment=-1);
|
void hitBanana(Item *item, int new_attachment=-1);
|
||||||
void update (float dt);
|
void update (float dt);
|
||||||
|
void updateSwatter(float dt);
|
||||||
void moveBombFromTo(Kart *from, Kart *to);
|
void moveBombFromTo(Kart *from, Kart *to);
|
||||||
};
|
void swatItem();
|
||||||
|
|
||||||
|
void set (AttachmentType type, float time, Kart *previous_kart=NULL);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Sets the type of the attachment, but keeps the old time left value. */
|
||||||
|
void set (AttachmentType type) { set(type, m_time_left); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the type of this attachment. */
|
||||||
|
AttachmentType getType() const { return m_type; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns how much time is left before this attachment is removed. */
|
||||||
|
float getTimeLeft() const { return m_time_left; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Sets how long this attachment will remain attached. */
|
||||||
|
void setTimeLeft(float t){ m_time_left = t; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the previous owner of this attachment, used in bombs that
|
||||||
|
* are being passed between karts. */
|
||||||
|
Kart* getPreviousOwner() const { return m_previous_owner; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns additional weight for the kart. */
|
||||||
|
float weightAdjust() const {
|
||||||
|
return m_type==ATTACH_ANVIL ? stk_config->m_anvil_weight : 0.0f; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns if the swatter is currently aiming, i.e. can be used to
|
||||||
|
* swat an incoming projectile. */
|
||||||
|
bool isSwatterReady() const {
|
||||||
|
assert(m_type==ATTACH_SWATTER);
|
||||||
|
return m_animation_phase == SWATTER_AIMING;
|
||||||
|
} // isSwatterReady
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
}; // Attachment
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
AttachmentManager *attachment_manager = 0;
|
AttachmentManager *attachment_manager = 0;
|
||||||
|
|
||||||
struct initAttachmentType {attachmentType attachment; const char *file; const char *icon_file;};
|
struct initAttachmentType {Attachment::AttachmentType attachment;
|
||||||
|
const char *file;
|
||||||
|
const char *icon_file;};
|
||||||
|
|
||||||
/* Some explanations to the attachments:
|
/* Some explanations to the attachments:
|
||||||
Parachute: This will increase the air friction, reducing the maximum speed.
|
Parachute: This will increase the air friction, reducing the maximum speed.
|
||||||
@ -46,17 +48,18 @@ struct initAttachmentType {attachmentType attachment; const char *file; const c
|
|||||||
|
|
||||||
initAttachmentType iat[]=
|
initAttachmentType iat[]=
|
||||||
{
|
{
|
||||||
{ATTACH_PARACHUTE, "parachute.b3d", "parachute-attach-icon.png"},
|
{Attachment::ATTACH_PARACHUTE, "parachute.b3d", "parachute-attach-icon.png"},
|
||||||
{ATTACH_BOMB, "bomb.b3d", "bomb-attach-icon.png" },
|
{Attachment::ATTACH_BOMB, "bomb.b3d", "bomb-attach-icon.png" },
|
||||||
{ATTACH_ANVIL, "anchor.b3d", "anchor-attach-icon.png" },
|
{Attachment::ATTACH_ANVIL, "anchor.b3d", "anchor-attach-icon.png" },
|
||||||
{ATTACH_TINYTUX, "reset-button.b3d","reset-attach-icon.png" },
|
{Attachment::ATTACH_SWATTER, "swatter.b3d", "swatter-icon.png" },
|
||||||
{ATTACH_MAX, "", "" },
|
{Attachment::ATTACH_TINYTUX, "reset-button.b3d","reset-attach-icon.png" },
|
||||||
|
{Attachment::ATTACH_MAX, "", "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
AttachmentManager::~AttachmentManager()
|
AttachmentManager::~AttachmentManager()
|
||||||
{
|
{
|
||||||
for(int i=0; iat[i].attachment!=ATTACH_MAX; i++)
|
for(int i=0; iat[i].attachment!=Attachment::ATTACH_MAX; i++)
|
||||||
{
|
{
|
||||||
scene::IMesh *mesh = m_attachments[iat[i].attachment];
|
scene::IMesh *mesh = m_attachments[iat[i].attachment];
|
||||||
mesh->drop();
|
mesh->drop();
|
||||||
@ -73,7 +76,7 @@ AttachmentManager::~AttachmentManager()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void AttachmentManager::removeTextures()
|
void AttachmentManager::removeTextures()
|
||||||
{
|
{
|
||||||
for(int i=0; iat[i].attachment!=ATTACH_MAX; i++)
|
for(int i=0; iat[i].attachment!=Attachment::ATTACH_MAX; i++)
|
||||||
{
|
{
|
||||||
// FIXME: free attachment textures
|
// FIXME: free attachment textures
|
||||||
} // for
|
} // for
|
||||||
@ -82,7 +85,7 @@ void AttachmentManager::removeTextures()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void AttachmentManager::loadModels()
|
void AttachmentManager::loadModels()
|
||||||
{
|
{
|
||||||
for(int i=0; iat[i].attachment!=ATTACH_MAX; i++)
|
for(int i=0; iat[i].attachment!=Attachment::ATTACH_MAX; i++)
|
||||||
{
|
{
|
||||||
std::string full_path = file_manager->getModelFile(iat[i].file);
|
std::string full_path = file_manager->getModelFile(iat[i].file);
|
||||||
m_attachments[iat[i].attachment]=irr_driver->getAnimatedMesh(full_path);
|
m_attachments[iat[i].attachment]=irr_driver->getAnimatedMesh(full_path);
|
||||||
|
@ -33,20 +33,23 @@ namespace irr
|
|||||||
class AttachmentManager: public NoCopy
|
class AttachmentManager: public NoCopy
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
scene::IAnimatedMesh *m_attachments[ATTACH_MAX];
|
scene::IAnimatedMesh *m_attachments[Attachment::ATTACH_MAX];
|
||||||
Material *m_all_icons [ATTACH_MAX];
|
Material *m_all_icons [Attachment::ATTACH_MAX];
|
||||||
public:
|
public:
|
||||||
AttachmentManager() {};
|
AttachmentManager() {};
|
||||||
~AttachmentManager();
|
~AttachmentManager();
|
||||||
void removeTextures ();
|
void removeTextures ();
|
||||||
void loadModels ();
|
void loadModels ();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the mest for a certain attachment.
|
/** Returns the mest for a certain attachment.
|
||||||
* \param type Type of the attachment needed. */
|
* \param type Type of the attachment needed. */
|
||||||
scene::IAnimatedMesh *getMesh(attachmentType type) const {return m_attachments[type]; }
|
scene::IAnimatedMesh *getMesh(Attachment::AttachmentType type) const
|
||||||
|
{return m_attachments[type]; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the icon to display in the race gui if a kart
|
/** Returns the icon to display in the race gui if a kart
|
||||||
* has an attachment. */
|
* has an attachment. */
|
||||||
const Material*
|
const Material* getIcon (int type) const {return m_all_icons [type]; }
|
||||||
getIcon (int type) const {return m_all_icons [type];}
|
// ------------------------------------------------------------------------
|
||||||
};
|
};
|
||||||
|
|
||||||
extern AttachmentManager *attachment_manager;
|
extern AttachmentManager *attachment_manager;
|
||||||
|
@ -142,6 +142,10 @@ void Powerup::set(PowerupManager::PowerupType type, int n)
|
|||||||
|
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
|
// No sound effect when arming the glove
|
||||||
|
case PowerupManager::POWERUP_SWATTER:
|
||||||
|
break;
|
||||||
|
|
||||||
case PowerupManager::POWERUP_ZIPPER:
|
case PowerupManager::POWERUP_ZIPPER:
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
@ -193,6 +197,7 @@ void Powerup::use()
|
|||||||
{
|
{
|
||||||
// Play custom kart sound when collectible is used
|
// Play custom kart sound when collectible is used
|
||||||
if (m_type != PowerupManager::POWERUP_NOTHING &&
|
if (m_type != PowerupManager::POWERUP_NOTHING &&
|
||||||
|
m_type != PowerupManager::POWERUP_SWATTER &&
|
||||||
m_type != PowerupManager::POWERUP_ZIPPER)
|
m_type != PowerupManager::POWERUP_ZIPPER)
|
||||||
m_owner->playCustomSFX(SFXManager::CUSTOM_SHOOT);
|
m_owner->playCustomSFX(SFXManager::CUSTOM_SHOOT);
|
||||||
|
|
||||||
@ -248,6 +253,10 @@ void Powerup::use()
|
|||||||
projectile_manager->newProjectile(m_owner, m_type);
|
projectile_manager->newProjectile(m_owner, m_type);
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
|
case PowerupManager::POWERUP_SWATTER:
|
||||||
|
m_owner->getAttachment()->set(Attachment::ATTACH_SWATTER,
|
||||||
|
m_owner->getKartProperties()->getSwatterDuration());
|
||||||
|
break;
|
||||||
case PowerupManager::POWERUP_BUBBLEGUM:
|
case PowerupManager::POWERUP_BUBBLEGUM:
|
||||||
{
|
{
|
||||||
Vec3 hit_point;
|
Vec3 hit_point;
|
||||||
@ -302,7 +311,8 @@ void Powerup::use()
|
|||||||
if(kart == m_owner) continue;
|
if(kart == m_owner) continue;
|
||||||
if(kart->getPosition() == 1)
|
if(kart->getPosition() == 1)
|
||||||
{
|
{
|
||||||
kart->attach(ATTACH_ANVIL, stk_config->m_anvil_time);
|
kart->attach(Attachment::ATTACH_ANVIL,
|
||||||
|
stk_config->m_anvil_time);
|
||||||
kart->updatedWeight();
|
kart->updatedWeight();
|
||||||
kart->adjustSpeed(stk_config->m_anvil_speed_factor*0.5f);
|
kart->adjustSpeed(stk_config->m_anvil_speed_factor*0.5f);
|
||||||
|
|
||||||
@ -338,7 +348,8 @@ void Powerup::use()
|
|||||||
if(kart->isEliminated() || kart== m_owner) continue;
|
if(kart->isEliminated() || kart== m_owner) continue;
|
||||||
if(m_owner->getPosition() > kart->getPosition())
|
if(m_owner->getPosition() > kart->getPosition())
|
||||||
{
|
{
|
||||||
kart->attach(ATTACH_PARACHUTE, stk_config->m_parachute_time_other);
|
kart->attach(Attachment::ATTACH_PARACHUTE,
|
||||||
|
stk_config->m_parachute_time_other);
|
||||||
|
|
||||||
if(kart->getController()->isPlayerController())
|
if(kart->getController()->isPlayerController())
|
||||||
player_kart = kart;
|
player_kart = kart;
|
||||||
|
@ -93,7 +93,7 @@ PowerupManager::PowerupType
|
|||||||
static std::string powerup_names[] = {
|
static std::string powerup_names[] = {
|
||||||
"", /* Nothing */
|
"", /* Nothing */
|
||||||
"bubblegum", "cake", "bowling", "zipper", "plunger", "switch",
|
"bubblegum", "cake", "bowling", "zipper", "plunger", "switch",
|
||||||
"parachute", "anchor"
|
"swatter", "parachute", "anchor"
|
||||||
};
|
};
|
||||||
|
|
||||||
for(unsigned int i=POWERUP_FIRST; i<=POWERUP_LAST; i++)
|
for(unsigned int i=POWERUP_FIRST; i<=POWERUP_LAST; i++)
|
||||||
|
@ -79,7 +79,7 @@ public:
|
|||||||
POWERUP_BUBBLEGUM = POWERUP_FIRST,
|
POWERUP_BUBBLEGUM = POWERUP_FIRST,
|
||||||
POWERUP_CAKE,
|
POWERUP_CAKE,
|
||||||
POWERUP_BOWLING, POWERUP_ZIPPER, POWERUP_PLUNGER,
|
POWERUP_BOWLING, POWERUP_ZIPPER, POWERUP_PLUNGER,
|
||||||
POWERUP_SWITCH,
|
POWERUP_SWITCH, POWERUP_SWATTER,
|
||||||
POWERUP_PARACHUTE,
|
POWERUP_PARACHUTE,
|
||||||
POWERUP_ANVIL, //powerup.cpp assumes these two come last
|
POWERUP_ANVIL, //powerup.cpp assumes these two come last
|
||||||
POWERUP_LAST=POWERUP_ANVIL,
|
POWERUP_LAST=POWERUP_ANVIL,
|
||||||
|
@ -205,7 +205,8 @@ void DefaultAIController::update(float dt)
|
|||||||
// Special behaviour if we have a bomb attach: try to hit the kart ahead
|
// Special behaviour if we have a bomb attach: try to hit the kart ahead
|
||||||
// of us.
|
// of us.
|
||||||
bool commands_set = false;
|
bool commands_set = false;
|
||||||
if(m_handle_bomb && m_kart->getAttachment()->getType()==ATTACH_BOMB &&
|
if(m_handle_bomb &&
|
||||||
|
m_kart->getAttachment()->getType()==Attachment::ATTACH_BOMB &&
|
||||||
m_kart_ahead )
|
m_kart_ahead )
|
||||||
{
|
{
|
||||||
// Use nitro if the kart is far ahead, or faster than this kart
|
// Use nitro if the kart is far ahead, or faster than this kart
|
||||||
@ -559,6 +560,23 @@ void DefaultAIController::handleItems(const float dt)
|
|||||||
}
|
}
|
||||||
break; // POWERUP_ANVIL
|
break; // POWERUP_ANVIL
|
||||||
|
|
||||||
|
case PowerupManager::POWERUP_SWATTER:
|
||||||
|
{
|
||||||
|
// Squared distance for which the swatter works
|
||||||
|
float d2 = m_kart->getKartProperties()->getSwatterDistance2();
|
||||||
|
// Fire if the closest kart ahead or to the back is not already
|
||||||
|
// squashed and close enough.
|
||||||
|
// FIXME: this can be improved on, since more than one kart might
|
||||||
|
// be hit, and a kart ahead might not be at an angle at
|
||||||
|
// which the glove can be used.
|
||||||
|
if( ( m_kart_ahead && !m_kart_ahead->isSquashed() &&
|
||||||
|
(m_kart_ahead->getXYZ()-m_kart->getXYZ()).length2()<d2 &&
|
||||||
|
m_kart_ahead->getSpeed() < m_kart->getSpeed() ) ||
|
||||||
|
( m_kart_behind && !m_kart_behind->isSquashed() &&
|
||||||
|
(m_kart_behind->getXYZ()-m_kart->getXYZ()).length2()<d2) )
|
||||||
|
m_controls->m_fire = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
printf("Invalid or unhandled powerup '%d' in default AI.\n",
|
printf("Invalid or unhandled powerup '%d' in default AI.\n",
|
||||||
m_kart->getPowerup()->getType());
|
m_kart->getPowerup()->getType());
|
||||||
@ -728,8 +746,8 @@ void DefaultAIController::handleNitroAndZipper()
|
|||||||
// If a parachute or anvil is attached, the nitro doesn't give much
|
// If a parachute or anvil is attached, the nitro doesn't give much
|
||||||
// benefit. Better wait till later.
|
// benefit. Better wait till later.
|
||||||
const bool has_slowdown_attachment =
|
const bool has_slowdown_attachment =
|
||||||
m_kart->getAttachment()->getType()==ATTACH_PARACHUTE ||
|
m_kart->getAttachment()->getType()==Attachment::ATTACH_PARACHUTE ||
|
||||||
m_kart->getAttachment()->getType()==ATTACH_ANVIL;
|
m_kart->getAttachment()->getType()==Attachment::ATTACH_ANVIL;
|
||||||
if(has_slowdown_attachment) return;
|
if(has_slowdown_attachment) return;
|
||||||
|
|
||||||
// If the kart is very slow (e.g. after rescue), use nitro
|
// If the kart is very slow (e.g. after rescue), use nitro
|
||||||
|
@ -148,7 +148,8 @@ void NewAIController::update(float dt)
|
|||||||
// Special behaviour if we have a bomb attach: try to hit the kart ahead
|
// Special behaviour if we have a bomb attach: try to hit the kart ahead
|
||||||
// of us.
|
// of us.
|
||||||
bool commands_set = false;
|
bool commands_set = false;
|
||||||
if(m_handle_bomb && m_kart->getAttachment()->getType()==ATTACH_BOMB &&
|
if(m_handle_bomb &&
|
||||||
|
m_kart->getAttachment()->getType()==Attachment::ATTACH_BOMB &&
|
||||||
m_kart_ahead )
|
m_kart_ahead )
|
||||||
{
|
{
|
||||||
// Use nitro if the kart is far ahead, or faster than this kart
|
// Use nitro if the kart is far ahead, or faster than this kart
|
||||||
@ -442,6 +443,7 @@ void NewAIController::handleItems( const float DELTA, const int STEPS )
|
|||||||
m_controls->m_fire = m_time_since_last_shot > 3.0f &&
|
m_controls->m_fire = m_time_since_last_shot > 3.0f &&
|
||||||
m_kart->getPosition()>1;
|
m_kart->getPosition()>1;
|
||||||
}
|
}
|
||||||
|
case PowerupManager::POWERUP_SWATTER: // fallthrough
|
||||||
default:
|
default:
|
||||||
m_controls->m_fire = true;
|
m_controls->m_fire = true;
|
||||||
}
|
}
|
||||||
@ -600,8 +602,8 @@ void NewAIController::handleNitroAndZipper()
|
|||||||
// If a parachute or anvil is attached, the nitro doesn't give much
|
// If a parachute or anvil is attached, the nitro doesn't give much
|
||||||
// benefit. Better wait till later.
|
// benefit. Better wait till later.
|
||||||
const bool has_slowdown_attachment =
|
const bool has_slowdown_attachment =
|
||||||
m_kart->getAttachment()->getType()==ATTACH_PARACHUTE ||
|
m_kart->getAttachment()->getType()==Attachment::ATTACH_PARACHUTE ||
|
||||||
m_kart->getAttachment()->getType()==ATTACH_ANVIL;
|
m_kart->getAttachment()->getType()==Attachment::ATTACH_ANVIL;
|
||||||
if(has_slowdown_attachment) return;
|
if(has_slowdown_attachment) return;
|
||||||
|
|
||||||
// If the kart is very slow (e.g. after rescue), use nitro
|
// If the kart is very slow (e.g. after rescue), use nitro
|
||||||
|
@ -336,7 +336,7 @@ void PlayerController::update(float dt)
|
|||||||
m_controls->m_rescue=false;
|
m_controls->m_rescue=false;
|
||||||
}
|
}
|
||||||
if (m_kart->playingEmergencyAnimation() &&
|
if (m_kart->playingEmergencyAnimation() &&
|
||||||
m_kart->getAttachment()->getType() != ATTACH_TINYTUX)
|
m_kart->getAttachment()->getType() != Attachment::ATTACH_TINYTUX)
|
||||||
{
|
{
|
||||||
m_bzzt_sound->play();
|
m_bzzt_sound->play();
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ void EmergencyAnimation::forceRescue(bool is_auto_rescue)
|
|||||||
m_up_velocity = m_kart->getKartProperties()->getRescueHeight() / m_timer;
|
m_up_velocity = m_kart->getKartProperties()->getRescueHeight() / m_timer;
|
||||||
m_xyz = m_kart->getXYZ();
|
m_xyz = m_kart->getXYZ();
|
||||||
|
|
||||||
m_kart->attach(ATTACH_TINYTUX, m_timer);
|
m_kart->attach(Attachment::ATTACH_TINYTUX, m_timer);
|
||||||
|
|
||||||
m_curr_rotation.setPitch(m_kart->getPitch());
|
m_curr_rotation.setPitch(m_kart->getPitch());
|
||||||
m_curr_rotation.setRoll(m_kart->getRoll() );
|
m_curr_rotation.setRoll(m_kart->getRoll() );
|
||||||
@ -137,6 +137,13 @@ void EmergencyAnimation::handleExplosion(const Vec3 &pos, bool direct_hit)
|
|||||||
if(playingEmergencyAnimation()) return;
|
if(playingEmergencyAnimation()) return;
|
||||||
if(m_kart->isInvulnerable())
|
if(m_kart->isInvulnerable())
|
||||||
return;
|
return;
|
||||||
|
Attachment *a=m_kart->getAttachment();
|
||||||
|
if(a->getType()==Attachment::ATTACH_SWATTER &&
|
||||||
|
a->isSwatterReady())
|
||||||
|
{
|
||||||
|
a->swatItem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_xyz = m_kart->getXYZ();
|
m_xyz = m_kart->getXYZ();
|
||||||
// Ignore explosion that are too far away.
|
// Ignore explosion that are too far away.
|
||||||
|
@ -97,6 +97,7 @@ Kart::Kart (const std::string& ident, Track* track, int position, bool is_first_
|
|||||||
m_wheel_toggle = 1;
|
m_wheel_toggle = 1;
|
||||||
m_finish_time = 0.0f;
|
m_finish_time = 0.0f;
|
||||||
m_invulnerable_time = 0.0f;
|
m_invulnerable_time = 0.0f;
|
||||||
|
m_squash_time = 0.0f;
|
||||||
m_shadow_enabled = false;
|
m_shadow_enabled = false;
|
||||||
m_shadow = NULL;
|
m_shadow = NULL;
|
||||||
m_terrain_particles = NULL;
|
m_terrain_particles = NULL;
|
||||||
@ -482,10 +483,11 @@ void Kart::reset()
|
|||||||
m_camera->setInitialTransform();
|
m_camera->setInitialTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop any animations currently being played.
|
// Reset squashing and animations
|
||||||
m_kart_model->setAnimation(KartModel::AF_DEFAULT);
|
m_kart_model->resetWheels();
|
||||||
|
|
||||||
// If the controller was replaced (e.g. replaced by end controller),
|
// If the controller was replaced (e.g. replaced by end controller),
|
||||||
// restore the original controller.
|
// restore the original controller.
|
||||||
if(m_saved_controller)
|
if(m_saved_controller)
|
||||||
{
|
{
|
||||||
m_controller = m_saved_controller;
|
m_controller = m_saved_controller;
|
||||||
@ -501,6 +503,8 @@ void Kart::reset()
|
|||||||
m_finished_race = false;
|
m_finished_race = false;
|
||||||
m_finish_time = 0.0f;
|
m_finish_time = 0.0f;
|
||||||
m_invulnerable_time = 0.0f;
|
m_invulnerable_time = 0.0f;
|
||||||
|
m_squash_time = 0.0f;
|
||||||
|
m_kart_model->scaleKart(Vec3(1.0f, 1.0f, 1.0f));
|
||||||
m_collected_energy = 0;
|
m_collected_energy = 0;
|
||||||
m_has_started = false;
|
m_has_started = false;
|
||||||
m_wheel_rotation = 0;
|
m_wheel_rotation = 0;
|
||||||
@ -742,6 +746,18 @@ void Kart::update(float dt)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_squash_time>0)
|
||||||
|
{
|
||||||
|
m_squash_time-=dt;
|
||||||
|
// If squasing time ends, reset the model
|
||||||
|
if(m_squash_time<=0)
|
||||||
|
{
|
||||||
|
m_kart_model->scaleKart(Vec3(1.0f, 1.0f, 1.0f));
|
||||||
|
MaxSpeed::setSlowdown(MaxSpeed::MS_DECREASE_SQUASH,
|
||||||
|
/*slowdown*/1.0f, /*fade in*/0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update the position and other data taken from the physics
|
// Update the position and other data taken from the physics
|
||||||
Moveable::update(dt);
|
Moveable::update(dt);
|
||||||
|
|
||||||
@ -937,6 +953,19 @@ void Kart::update(float dt)
|
|||||||
}
|
}
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Squashes this kart: it will scale the kart in up direction, and causes
|
||||||
|
* a slowdown while this kart is squashed.
|
||||||
|
* \param time How long the kart will be squashed.
|
||||||
|
* \param slowdown Reduction of max speed.
|
||||||
|
*/
|
||||||
|
void Kart::setSquash(float time, float slowdown)
|
||||||
|
{
|
||||||
|
m_kart_model->scaleKart(Vec3(1.0f, 0.5f, 1.0f));
|
||||||
|
MaxSpeed::setSlowdown(MaxSpeed::MS_DECREASE_SQUASH, slowdown, 0.1f);
|
||||||
|
m_squash_time = time;
|
||||||
|
} // setSquash
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Plays any terrain specific sound effect.
|
/** Plays any terrain specific sound effect.
|
||||||
*/
|
*/
|
||||||
@ -1399,7 +1428,8 @@ void Kart::updatePhysics(float dt)
|
|||||||
float engine_power = getActualWheelForce() + handleNitro(dt)
|
float engine_power = getActualWheelForce() + handleNitro(dt)
|
||||||
+ m_slipstream->getSlipstreamPower();
|
+ m_slipstream->getSlipstreamPower();
|
||||||
|
|
||||||
if(m_attachment->getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
|
if(m_attachment->getType()==Attachment::ATTACH_PARACHUTE)
|
||||||
|
engine_power*=0.2f;
|
||||||
|
|
||||||
if (m_flying)
|
if (m_flying)
|
||||||
{
|
{
|
||||||
|
@ -120,6 +120,10 @@ private:
|
|||||||
/** Time a kart is invulnerable. */
|
/** Time a kart is invulnerable. */
|
||||||
float m_invulnerable_time;
|
float m_invulnerable_time;
|
||||||
|
|
||||||
|
/** How long a kart is being squashed. If this is >0
|
||||||
|
* the kart is squashed. */
|
||||||
|
float m_squash_time;
|
||||||
|
|
||||||
// Bullet physics parameters
|
// Bullet physics parameters
|
||||||
// -------------------------
|
// -------------------------
|
||||||
btRaycastVehicle::btVehicleTuning
|
btRaycastVehicle::btVehicleTuning
|
||||||
@ -225,10 +229,12 @@ public:
|
|||||||
void adjustSpeed (float f);
|
void adjustSpeed (float f);
|
||||||
void capSpeed (float max_speed);
|
void capSpeed (float max_speed);
|
||||||
void updatedWeight ();
|
void updatedWeight ();
|
||||||
virtual void collectedItem (Item *item, int random_attachment);
|
void collectedItem (Item *item, int random_attachment);
|
||||||
virtual void reset ();
|
void reset ();
|
||||||
virtual void handleZipper (const Material *m=NULL, bool play_sound=false);
|
void handleZipper (const Material *m=NULL, bool play_sound=false);
|
||||||
virtual void crashed (Kart *k, const Material *m=NULL);
|
void setSquash (float time, float slowdown);
|
||||||
|
|
||||||
|
void crashed (Kart *k, const Material *m=NULL);
|
||||||
|
|
||||||
virtual void update (float dt);
|
virtual void update (float dt);
|
||||||
virtual void finishedRace (float time);
|
virtual void finishedRace (float time);
|
||||||
@ -247,8 +253,8 @@ public:
|
|||||||
void setKartProperties(const KartProperties *kp) { m_kart_properties=kp; }
|
void setKartProperties(const KartProperties *kp) { m_kart_properties=kp; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets the attachment and time it stays attached. */
|
/** Sets the attachment and time it stays attached. */
|
||||||
void attach(attachmentType attachment_, float time)
|
void attach(Attachment::AttachmentType attachment, float time)
|
||||||
{ m_attachment->set(attachment_, time); }
|
{ m_attachment->set(attachment, time); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets a new powerup. */
|
/** Sets a new powerup. */
|
||||||
void setPowerup (PowerupManager::PowerupType t, int n)
|
void setPowerup (PowerupManager::PowerupType t, int n)
|
||||||
@ -420,7 +426,11 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets the energy the kart has collected. */
|
/** Sets the energy the kart has collected. */
|
||||||
void setEnergy(float val) { m_collected_energy = val; }
|
void setEnergy(float val) { m_collected_energy = val; }
|
||||||
};
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns if the kart is currently being squashed. */
|
||||||
|
bool isSquashed() const { return m_squash_time >0; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
}; // Kart
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -376,6 +376,18 @@ void KartModel::setDefaultPhysicsPosition(const Vec3 ¢er_shift,
|
|||||||
|
|
||||||
} // setDefaultPhysicsPosition
|
} // setDefaultPhysicsPosition
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Resets the kart model. It removes any scaling (squashing) and stops
|
||||||
|
* animation from being played.
|
||||||
|
*/
|
||||||
|
void KartModel::reset()
|
||||||
|
{
|
||||||
|
m_animated_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
// Stop any animations currently being played.
|
||||||
|
setAnimation(KartModel::AF_DEFAULT);
|
||||||
|
|
||||||
|
} // reset
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Enables- or disables the end animation.
|
/** Enables- or disables the end animation.
|
||||||
* \param type The type of animation to play.
|
* \param type The type of animation to play.
|
||||||
@ -529,3 +541,10 @@ void KartModel::resetWheels()
|
|||||||
const float suspension[4]={0,0,0,0};
|
const float suspension[4]={0,0,0,0};
|
||||||
update(0, 0.0f, suspension);
|
update(0, 0.0f, suspension);
|
||||||
} // reset
|
} // reset
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Scales the kart model by a certain amount. */
|
||||||
|
void KartModel::scaleKart(const Vec3 &s)
|
||||||
|
{
|
||||||
|
m_animated_node->setScale(s.toIrrVector());
|
||||||
|
} // squashKart
|
@ -141,6 +141,7 @@ public:
|
|||||||
KartModel(bool is_master);
|
KartModel(bool is_master);
|
||||||
~KartModel();
|
~KartModel();
|
||||||
KartModel* makeCopy();
|
KartModel* makeCopy();
|
||||||
|
void reset();
|
||||||
void loadInfo(const XMLNode &node);
|
void loadInfo(const XMLNode &node);
|
||||||
bool loadModels(const KartProperties &kart_properties);
|
bool loadModels(const KartProperties &kart_properties);
|
||||||
scene::ISceneNode*
|
scene::ISceneNode*
|
||||||
@ -180,6 +181,7 @@ public:
|
|||||||
void update(float rotation, float steer, const float suspension[4]);
|
void update(float rotation, float steer, const float suspension[4]);
|
||||||
void resetWheels();
|
void resetWheels();
|
||||||
void setDefaultPhysicsPosition(const Vec3 ¢er_shift, float wheel_radius);
|
void setDefaultPhysicsPosition(const Vec3 ¢er_shift, float wheel_radius);
|
||||||
|
void scaleKart(const Vec3 &s);
|
||||||
|
|
||||||
/** Enables- or disables the end animation. */
|
/** Enables- or disables the end animation. */
|
||||||
void setAnimation(AnimationFrameType type);
|
void setAnimation(AnimationFrameType type);
|
||||||
|
@ -88,9 +88,14 @@ KartProperties::KartProperties(const std::string &filename)
|
|||||||
m_camera_distance = m_camera_forward_up_angle =
|
m_camera_distance = m_camera_forward_up_angle =
|
||||||
m_camera_backward_up_angle = m_explosion_invulnerability_time =
|
m_camera_backward_up_angle = m_explosion_invulnerability_time =
|
||||||
m_rescue_time = m_rescue_height = m_explosion_time =
|
m_rescue_time = m_rescue_height = m_explosion_time =
|
||||||
m_explosion_radius = m_ai_steering_variation = UNDEFINED;
|
m_explosion_radius = m_ai_steering_variation =
|
||||||
|
m_swatter_distance2 = m_swatter_duration = m_swatter_animation_time =
|
||||||
|
m_swatter_item_animation_time = m_squash_slowdown =
|
||||||
|
m_squash_duration = UNDEFINED;
|
||||||
|
|
||||||
m_gravity_center_shift = Vec3(UNDEFINED);
|
m_gravity_center_shift = Vec3(UNDEFINED);
|
||||||
m_has_skidmarks = true;
|
m_has_skidmarks = true;
|
||||||
|
m_swatter_count = -1;
|
||||||
m_version = 0;
|
m_version = 0;
|
||||||
m_color = video::SColor(255, 0, 0, 0);
|
m_color = video::SColor(255, 0, 0, 0);
|
||||||
m_shape = 32; // close enough to a circle.
|
m_shape = 32; // close enough to a circle.
|
||||||
@ -435,6 +440,23 @@ void KartProperties::getAllData(const XMLNode * root)
|
|||||||
zipper_node->get("max-speed-increase", &m_zipper_max_speed_increase);
|
zipper_node->get("max-speed-increase", &m_zipper_max_speed_increase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(const XMLNode *swatter_node= root->getNode("swatter"))
|
||||||
|
{
|
||||||
|
swatter_node->get("duration", &m_swatter_duration );
|
||||||
|
swatter_node->get("count", &m_swatter_count );
|
||||||
|
swatter_node->get("animation-time", &m_swatter_animation_time);
|
||||||
|
swatter_node->get("item-animation-time",
|
||||||
|
&m_swatter_item_animation_time);
|
||||||
|
swatter_node->get("squash-duration", &m_squash_duration );
|
||||||
|
swatter_node->get("squash-slowdown", &m_squash_slowdown );
|
||||||
|
if(swatter_node->get("distance", &m_swatter_distance2) )
|
||||||
|
{
|
||||||
|
// Avoid squaring if distance is not defined, so that
|
||||||
|
// distance2 remains UNDEFINED (which is a negative value)
|
||||||
|
m_swatter_distance2 *= m_swatter_distance2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(const XMLNode *camera_node= root->getNode("camera"))
|
if(const XMLNode *camera_node= root->getNode("camera"))
|
||||||
{
|
{
|
||||||
camera_node->get("distance", &m_camera_distance);
|
camera_node->get("distance", &m_camera_distance);
|
||||||
@ -594,6 +616,14 @@ void KartProperties::checkAllSet(const std::string &filename)
|
|||||||
CHECK_NEG(m_nitro_max_speed_increase, "nitro max-speed-increase" );
|
CHECK_NEG(m_nitro_max_speed_increase, "nitro max-speed-increase" );
|
||||||
CHECK_NEG(m_nitro_duration, "nitro duration" );
|
CHECK_NEG(m_nitro_duration, "nitro duration" );
|
||||||
CHECK_NEG(m_nitro_fade_out_time, "nitro fade-out-time" );
|
CHECK_NEG(m_nitro_fade_out_time, "nitro fade-out-time" );
|
||||||
|
CHECK_NEG(m_swatter_distance2, "swatter distance" );
|
||||||
|
CHECK_NEG(m_swatter_animation_time, "swatter animation-time" );
|
||||||
|
CHECK_NEG(m_swatter_item_animation_time,"swatter item-animation-time" );
|
||||||
|
CHECK_NEG(m_swatter_duration, "swatter duration" );
|
||||||
|
CHECK_NEG(m_swatter_count, "swatter count" );
|
||||||
|
CHECK_NEG(m_squash_duration, "swatter squash-duration" );
|
||||||
|
CHECK_NEG(m_squash_slowdown, "swatter squash-slowdown" );
|
||||||
|
|
||||||
CHECK_NEG(m_rescue_height, "rescue height" );
|
CHECK_NEG(m_rescue_height, "rescue height" );
|
||||||
CHECK_NEG(m_rescue_time, "rescue time" );
|
CHECK_NEG(m_rescue_time, "rescue time" );
|
||||||
CHECK_NEG(m_rescue_vert_offset, "rescue vert-offset" );
|
CHECK_NEG(m_rescue_vert_offset, "rescue vert-offset" );
|
||||||
|
@ -193,6 +193,21 @@ private:
|
|||||||
/** Duration during which the increased maximum speed
|
/** Duration during which the increased maximum speed
|
||||||
* due to nitro fades out. */
|
* due to nitro fades out. */
|
||||||
float m_nitro_fade_out_time;
|
float m_nitro_fade_out_time;
|
||||||
|
/** Square of the maximum distance a swatter can operate. */
|
||||||
|
float m_swatter_distance2;
|
||||||
|
/** How often the swatter can be fired. */
|
||||||
|
int m_swatter_count;
|
||||||
|
/** How long the swatter lasts. */
|
||||||
|
float m_swatter_duration;
|
||||||
|
/** How long a kart will remain squashed. */
|
||||||
|
float m_squash_duration;
|
||||||
|
/** The slowdown to apply while a kart is squashed. The new maxspeed
|
||||||
|
* is max_speed*m_squash_slowdown. */
|
||||||
|
float m_squash_slowdown;
|
||||||
|
/** Animation time for the swatter. */
|
||||||
|
float m_swatter_animation_time;
|
||||||
|
/** How long the item swatting animation will last. */
|
||||||
|
float m_swatter_item_animation_time;
|
||||||
|
|
||||||
/** Engine sound effect. */
|
/** Engine sound effect. */
|
||||||
std::string m_engine_sfx_type;
|
std::string m_engine_sfx_type;
|
||||||
@ -295,7 +310,9 @@ public:
|
|||||||
~KartProperties ();
|
~KartProperties ();
|
||||||
void getAllData (const XMLNode * root);
|
void getAllData (const XMLNode * root);
|
||||||
void checkAllSet(const std::string &filename);
|
void checkAllSet(const std::string &filename);
|
||||||
|
float getStartupBoost() const;
|
||||||
|
|
||||||
|
/** Returns the maximum steering angle (depending on speed). */
|
||||||
float getMaxSteerAngle (float speed) const;
|
float getMaxSteerAngle (float speed) const;
|
||||||
|
|
||||||
/** Returns the material for the kart icons. */
|
/** Returns the material for the kart icons. */
|
||||||
@ -492,24 +509,27 @@ public:
|
|||||||
/** Return the fade out time once a rubber band is removed. */
|
/** Return the fade out time once a rubber band is removed. */
|
||||||
float getRubberBandFadeOutTime () const {return m_rubber_band_fade_out_time;}
|
float getRubberBandFadeOutTime () const {return m_rubber_band_fade_out_time;}
|
||||||
|
|
||||||
|
|
||||||
/** Returns duration of a plunger in your face. */
|
/** Returns duration of a plunger in your face. */
|
||||||
float getPlungerInFaceTime () const
|
float getPlungerInFaceTime () const
|
||||||
{return m_plunger_in_face_duration[race_manager->getDifficulty()];}
|
{return m_plunger_in_face_duration[race_manager->getDifficulty()];}
|
||||||
|
|
||||||
/** Returns the time a zipper is active. */
|
/** Returns the time a zipper is active. */
|
||||||
float getZipperTime () const {return m_zipper_time; }
|
float getZipperTime () const {return m_zipper_time; }
|
||||||
|
|
||||||
/** Returns the time a zipper is active. */
|
/** Returns the time a zipper is active. */
|
||||||
float getZipperFadeOutTime () const {return m_zipper_fade_out_time; }
|
float getZipperFadeOutTime () const {return m_zipper_fade_out_time; }
|
||||||
|
|
||||||
/** Returns the additional force added applied to the kart. */
|
/** Returns the additional force added applied to the kart. */
|
||||||
float getZipperForce () const { return m_zipper_force; }
|
float getZipperForce () const { return m_zipper_force; }
|
||||||
|
|
||||||
/** Returns the initial zipper speed gain. */
|
/** Returns the initial zipper speed gain. */
|
||||||
float getZipperSpeedGain () const { return m_zipper_speed_gain; }
|
float getZipperSpeedGain () const { return m_zipper_speed_gain; }
|
||||||
|
|
||||||
/** Returns the increase of the maximum speed of the kart
|
/** Returns the increase of the maximum speed of the kart
|
||||||
* if a zipper is active. */
|
* if a zipper is active. */
|
||||||
float getZipperMaxSpeedIncrease () const
|
float getZipperMaxSpeedIncrease () const
|
||||||
{ return m_zipper_max_speed_increase;}
|
{ return m_zipper_max_speed_increase;}
|
||||||
|
|
||||||
|
|
||||||
/** Returns additional rotation of 3d model when skidding. */
|
/** Returns additional rotation of 3d model when skidding. */
|
||||||
float getSkidVisual () const {return m_skid_visual; }
|
float getSkidVisual () const {return m_skid_visual; }
|
||||||
|
|
||||||
@ -585,8 +605,30 @@ public:
|
|||||||
|
|
||||||
/** Returns the full path where the files for this kart are stored. */
|
/** Returns the full path where the files for this kart are stored. */
|
||||||
const std::string& getKartDir () const {return m_root; }
|
const std::string& getKartDir () const {return m_root; }
|
||||||
float getStartupBoost() const;
|
|
||||||
};
|
/** Returns the square of the maximum distance at which a swatter
|
||||||
|
* can hit karts. */
|
||||||
|
float getSwatterDistance2() const { return m_swatter_distance2; }
|
||||||
|
|
||||||
|
/** Returns how often a swatter can be used. */
|
||||||
|
int getSwatterCount() const { return m_swatter_count; }
|
||||||
|
|
||||||
|
/** Returns how long a swatter will stay attached/ready to be used. */
|
||||||
|
float getSwatterDuration() const { return m_swatter_duration; }
|
||||||
|
|
||||||
|
/** Returns how long a kart remains squashed. */
|
||||||
|
float getSquashDuration() const {return m_squash_duration; }
|
||||||
|
|
||||||
|
/** Returns the slowdown of a kart that is squashed. */
|
||||||
|
float getSquashSlowdown() const {return m_squash_slowdown; }
|
||||||
|
|
||||||
|
/** Returns how long it takes for the swatter to hit a target. */
|
||||||
|
float getSwatterAnimationTime() const { return m_swatter_animation_time; }
|
||||||
|
|
||||||
|
/** Returns how long it takes for the swatter to swat at an item. */
|
||||||
|
float getSwatterItemAnimationTime() const
|
||||||
|
{return m_swatter_item_animation_time; }
|
||||||
|
}; // KartProperties
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
enum {MS_DECREASE_MIN,
|
enum {MS_DECREASE_MIN,
|
||||||
MS_DECREASE_TERRAIN = MS_DECREASE_MIN,
|
MS_DECREASE_TERRAIN = MS_DECREASE_MIN,
|
||||||
MS_DECREASE_AI,
|
MS_DECREASE_AI,
|
||||||
|
MS_DECREASE_SQUASH,
|
||||||
MS_DECREASE_MAX};
|
MS_DECREASE_MAX};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -974,6 +974,12 @@ int main(int argc, char *argv[] )
|
|||||||
UserConfigParams::m_internet_status = NetworkHttp::IPERM_ALLOWED;
|
UserConfigParams::m_internet_status = NetworkHttp::IPERM_ALLOWED;
|
||||||
GUIEngine::ModalDialog::dismiss();
|
GUIEngine::ModalDialog::dismiss();
|
||||||
network_http = new NetworkHttp();
|
network_http = new NetworkHttp();
|
||||||
|
// Note that the network thread must be started after
|
||||||
|
// the assignment to network_http (since the thread
|
||||||
|
// might use network_http, otherwise a race condition
|
||||||
|
// can be introduced resulting in a crash).
|
||||||
|
network_http->startNetworkThread();
|
||||||
|
|
||||||
} // onConfirm
|
} // onConfirm
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
virtual void onCancel()
|
virtual void onCancel()
|
||||||
@ -982,6 +988,7 @@ int main(int argc, char *argv[] )
|
|||||||
UserConfigParams::m_internet_status = NetworkHttp::IPERM_NOT_ALLOWED;
|
UserConfigParams::m_internet_status = NetworkHttp::IPERM_NOT_ALLOWED;
|
||||||
GUIEngine::ModalDialog::dismiss();
|
GUIEngine::ModalDialog::dismiss();
|
||||||
network_http = new NetworkHttp();
|
network_http = new NetworkHttp();
|
||||||
|
network_http->startNetworkThread();
|
||||||
} // onCancel
|
} // onCancel
|
||||||
}; // ConfirmServer
|
}; // ConfirmServer
|
||||||
|
|
||||||
|
@ -180,10 +180,10 @@ void Physics::KartKartCollision(Kart *kartA, Kart *kartB)
|
|||||||
Attachment *attachmentA=kartA->getAttachment();
|
Attachment *attachmentA=kartA->getAttachment();
|
||||||
Attachment *attachmentB=kartB->getAttachment();
|
Attachment *attachmentB=kartB->getAttachment();
|
||||||
|
|
||||||
if(attachmentA->getType()==ATTACH_BOMB)
|
if(attachmentA->getType()==Attachment::ATTACH_BOMB)
|
||||||
{
|
{
|
||||||
// If both karts have a bomb, explode them immediately:
|
// If both karts have a bomb, explode them immediately:
|
||||||
if(attachmentB->getType()==ATTACH_BOMB)
|
if(attachmentB->getType()==Attachment::ATTACH_BOMB)
|
||||||
{
|
{
|
||||||
attachmentA->setTimeLeft(0.0f);
|
attachmentA->setTimeLeft(0.0f);
|
||||||
attachmentB->setTimeLeft(0.0f);
|
attachmentB->setTimeLeft(0.0f);
|
||||||
@ -198,7 +198,7 @@ void Physics::KartKartCollision(Kart *kartA, Kart *kartB)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(attachmentB->getType()==ATTACH_BOMB &&
|
else if(attachmentB->getType()==Attachment::ATTACH_BOMB &&
|
||||||
attachmentB->getPreviousOwner()!=kartA)
|
attachmentB->getPreviousOwner()!=kartA)
|
||||||
{
|
{
|
||||||
attachmentB->moveBombFromTo(kartB, kartA);
|
attachmentB->moveBombFromTo(kartB, kartA);
|
||||||
|
@ -556,7 +556,7 @@ void RaceGUI::drawGlobalPlayerIcons(const KartIconDisplayInfo* info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//attachment
|
//attachment
|
||||||
if (kart->getAttachment()->getType() != ATTACH_NOTHING)
|
if (kart->getAttachment()->getType() != Attachment::ATTACH_NOTHING)
|
||||||
{
|
{
|
||||||
video::ITexture *icon_attachment =
|
video::ITexture *icon_attachment =
|
||||||
attachment_manager->getIcon(kart->getAttachment()->getType())
|
attachment_manager->getIcon(kart->getAttachment()->getType())
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||||
bool invisible, bool ai_ignore)
|
bool invisible, bool ai_ignore)
|
||||||
{
|
{
|
||||||
if(sideOfLine2D(p0, p2, p1)>0 ||
|
if(p1.sideOfLine2D(p0, p2)>0 ||
|
||||||
sideOfLine2D(p0, p2, p3)<0)
|
p3.sideOfLine2D(p0, p2)<0)
|
||||||
{
|
{
|
||||||
printf("Warning: quad has wrong orientation: p0=%f %f %f p1=%f %f %f\n",
|
printf("Warning: quad has wrong orientation: p0=%f %f %f p1=%f %f %f\n",
|
||||||
p0.getX(), p0.getY(), p0.getZ(),p1.getX(), p1.getY(), p1.getZ());
|
p0.getX(), p0.getY(), p0.getZ(),p1.getX(), p1.getY(), p1.getZ());
|
||||||
@ -85,16 +85,6 @@ void Quad::getVertices(video::S3DVertex *v, const video::SColor &color) const
|
|||||||
v[3].Color = color;
|
v[3].Color = color;
|
||||||
} // setVertices
|
} // setVertices
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
/** Returns wether a point is to the left or to the right of a line.
|
|
||||||
* While all arguments are 3d, only the x and y coordinates are actually used.
|
|
||||||
*/
|
|
||||||
float Quad::sideOfLine2D(const Vec3& l1, const Vec3& l2, const Vec3& p) const
|
|
||||||
{
|
|
||||||
return (l2.getX()-l1.getX())*(p.getZ()-l1.getZ()) -
|
|
||||||
(l2.getZ()-l1.getZ())*(p.getX()-l1.getX());
|
|
||||||
} // sideOfLine
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
bool Quad::pointInQuad(const Vec3& p) const
|
bool Quad::pointInQuad(const Vec3& p) const
|
||||||
{
|
{
|
||||||
@ -113,12 +103,12 @@ bool Quad::pointInQuad(const Vec3& p) const
|
|||||||
// If a point is exactly on the line of two quads (e.g. between points
|
// If a point is exactly on the line of two quads (e.g. between points
|
||||||
// 0,1 on one quad, and 3,2 of the previous quad), assign this point
|
// 0,1 on one quad, and 3,2 of the previous quad), assign this point
|
||||||
// to be on the 'later' quad, i.e. on the line between points 0 and 1.
|
// to be on the 'later' quad, i.e. on the line between points 0 and 1.
|
||||||
if(sideOfLine2D(m_p[0], m_p[2], p)<0) {
|
if(p.sideOfLine2D(m_p[0], m_p[2])<0) {
|
||||||
return sideOfLine2D(m_p[0], m_p[1], p) >= 0.0 &&
|
return p.sideOfLine2D(m_p[0], m_p[1]) >= 0.0 &&
|
||||||
sideOfLine2D(m_p[1], m_p[2], p) >= 0.0;
|
p.sideOfLine2D(m_p[1], m_p[2]) >= 0.0;
|
||||||
} else {
|
} else {
|
||||||
return sideOfLine2D(m_p[2], m_p[3], p) > 0.0 &&
|
return p.sideOfLine2D(m_p[2], m_p[3]) > 0.0 &&
|
||||||
sideOfLine2D(m_p[3], m_p[0], p) >= 0.0;
|
p.sideOfLine2D(m_p[3], m_p[0]) >= 0.0;
|
||||||
}
|
}
|
||||||
} // pointInQuad
|
} // pointInQuad
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ private:
|
|||||||
/** Set if this quad should not be used by the AI. */
|
/** Set if this quad should not be used by the AI. */
|
||||||
bool m_ai_ignore;
|
bool m_ai_ignore;
|
||||||
|
|
||||||
float sideOfLine2D(const Vec3& l1, const Vec3& l2, const Vec3& p) const;
|
|
||||||
public:
|
public:
|
||||||
Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||||
bool invis=false, bool ai_ignore=false);
|
bool invis=false, bool ai_ignore=false);
|
||||||
|
@ -123,6 +123,19 @@ public:
|
|||||||
void min(const Vec3& a) {if(a.getX()<m_floats[0]) m_floats[0]=a.getX();
|
void min(const Vec3& a) {if(a.getX()<m_floats[0]) m_floats[0]=a.getX();
|
||||||
if(a.getY()<m_floats[1]) m_floats[1]=a.getY();
|
if(a.getY()<m_floats[1]) m_floats[1]=a.getY();
|
||||||
if(a.getZ()<m_floats[2]) m_floats[2]=a.getZ();}
|
if(a.getZ()<m_floats[2]) m_floats[2]=a.getZ();}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Determines which side of a line this point is. This is using
|
||||||
|
* a 2d projection (into the X-Z plane).
|
||||||
|
* \param start The start point of the line.
|
||||||
|
* \param end The end point of the line.
|
||||||
|
* \return >0 Point is to the left side; <0 if it's on the right.
|
||||||
|
*/
|
||||||
|
float sideOfLine2D(const Vec3& start, const Vec3& end) const
|
||||||
|
{
|
||||||
|
return (end.getX()-start.getX())*(m_floats[2]-start.getZ()) -
|
||||||
|
(end.getZ()-start.getZ())*(m_floats[0]-start.getX());
|
||||||
|
|
||||||
|
} // sideOfLine2D
|
||||||
}; // Vec3
|
}; // Vec3
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user