Various slipstreaming refinements (#3202)

* New getRecentPreviousXYZ function

* New getRecentPreviousXYZ function

* New getRecentPreviousXYZ function

* General slipstreaming refinements

* Increase the minimum time to get the slipstream bonus

The obsolete parameter is not yet removed as several other files would have to be changed to not trigger an error.

* Slipstreaming characteristics update

* Changed slipstreaming characteristics

* Update slipstreaming characteristics

* Update slipstreaming characteristics

* Update slipstreaming characteristics

* Update slipstreaming characteristics

* Update slipstreaming characteristics

* Remove slipstreaming power engine bonus per kart type

Power engine bonus is already balanced by the different weights : a heavier kart needs more engine power to achieve/maintain the same speed.

* Remove an unused function

* Various slipstreaming refinements

* Pull the XYZ history size from config

* Pull the XYZ history size from config

* Remove unnecessary logs

* Fix a frenchism with fix
This commit is contained in:
Alayan-stk-2 2018-04-18 03:09:49 +02:00 committed by auriamg
parent acdba401a9
commit be8ae4dca6
12 changed files with 342 additions and 165 deletions

View File

@ -313,26 +313,26 @@
<!-- Slipstream
base-speed: the speed for which length and width are valid.
They are upscaled when faster and downscaled when slower.
They are upscaled when faster and downscaled when slower.
length: How far behind a kart slipstream works
(note : this helps OTHER karts)
(note : this helps OTHER karts)
width: how wide slipstream works furthest away from the kart.
inner-factor: The proportion of the slipstreaming area with
twice faster slipstream "credits" collection.
collect-time: How many seconds of sstream give maximum benefit
use-time: How long the benefit will last (obsolete, unused).
twice faster slipstream "credits" collection.
min-collect-time: How many seconds of sstream are needed to get a bonus
it can be accumulated faster if in the inner quad)
max-collect-time: How many seconds of sstream bonus can be accumulated at most
add-power: Additional power due to sstreaming.
min-speed: Minimum speed necessary for slipstream to take effect.
max-speed-increase: How much the speed of the kart might exceed
its normal maximum speed.
duration: How long the higher speed lasts after slipstream stopped
working (it works for at least collect-time more if the kart
don't go behind another kart to get further sstreaming time)
duration-factor: A multiplicator to how long the higher speed lasts
1 means it last as long the total time collected
fade-out-time: How long the slip stream speed increase will
gradually be reduced. -->
<slipstream base-speed="20" length="8" width="4" inner-factor="0.5"
collect-time="2" use-time="5" add-power="200" min-speed="8"
max-speed-increase="5" duration="1" fade-out-time="2" />
min-collect-time="3" max-collect-time="8" add-power="300" min-speed="8"
max-speed-increase="5" duration-factor="1" fade-out-time="2" />
</characteristic>
<!-- The different difficulties (like easy, medium, hard) -->
@ -366,8 +366,8 @@
invulnerability-time="7" />
<nitro engine-force="350" max-speed-increase="4.5" duration="1.5"
fade-out-time="2.5" />
<slipstream length="*0.9" collect-time="*0.9" add-power="*1.1"
duration="*1.2" fade-out-time="*1.1" />
<slipstream length="*0.9" collect-time="*0.9"
duration-factor="*1" fade-out-time="*1" />
</characteristic>
<characteristic name="medium">
<engine power="*0.63" max-speed="*1" brake-factor="*0.73"
@ -379,7 +379,7 @@
<explosion time="1.8" radius="5"
invulnerability-time="6" />
<nitro engine-force="425" consumption="1.4" duration="1" />
<slipstream add-power="*0.9" duration="*0.9" fade-out-time="*0.9" />
<slipstream duration-factor="*0.8" fade-out-time="*1" />
</characteristic>
<characteristic name="heavy">
<engine power="*1" max-speed="*1" brake-factor="*0.66"
@ -394,8 +394,8 @@
invulnerability-time="6" />
<nitro engine-force="600" consumption="2" max-speed-increase="8"
duration="0.7" fade-out-time="1.3" />
<slipstream length="*1.1" collect-time="*1.1" add-power="*0.8"
duration="*0.7" fade-out-time="*0.7" />
<slipstream length="*1.1" collect-time="*1.1"
duration-factor="*0.6" fade-out-time="*1" />
</characteristic>
</kart-types>

View File

@ -46,16 +46,16 @@ SlipStream::SlipStream(AbstractKart* kart)
m_kart = kart;
m_moving = NULL;
m_moving_fast = NULL;
m_moving_bonus = NULL;
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
m_moving = new MovingTexture(0.0f, 0.0f);
m_moving_fast = new MovingTexture(0.0f, 0.0f);
Material* material =
material_manager->getMaterialSPM("slipstream.png", "");
SP::SPMesh* mesh = createMesh(material);
SP::SPMesh* mesh = createMesh(material, false);
m_node = irr_driver->addMesh(mesh, "slipstream");
mesh->drop();
std::string debug_name = m_kart->getIdent()+" (slip-stream)";
@ -67,8 +67,10 @@ SlipStream::SlipStream(AbstractKart* kart)
assert(spmn);
m_moving->setSPTM(spmn->getTextureMatrix(0).data());
m_moving_fast = new MovingTexture(0.0f, 0.0f);
material = material_manager->getMaterialSPM("slipstream2.png", "");
mesh = createMesh(material);
mesh = createMesh(material, false);
m_node_fast = irr_driver->addMesh(mesh, "slipstream2");
mesh->drop();
debug_name = m_kart->getIdent()+" (slip-stream2)";
@ -79,10 +81,29 @@ SlipStream::SlipStream(AbstractKart* kart)
spmn = dynamic_cast<SP::SPMeshNode*>(m_node_fast);
assert(spmn);
m_moving_fast->setSPTM(spmn->getTextureMatrix(0).data());
m_moving_bonus = new MovingTexture(0.0f, 0.0f);
material = material_manager->getMaterialSPM("slipstream_bonus.png", "");
mesh = createMesh(material, true);
m_bonus_node = irr_driver->addMesh(mesh, "slipstream-bonus");
mesh->drop();
debug_name = m_kart->getIdent()+" (slip-stream-bonus)";
m_bonus_node->setName(debug_name.c_str());
m_bonus_node->setPosition(core::vector3df(0, 0 * 0.25f + 2.5f,
m_kart->getKartLength()));
m_bonus_node->setVisible(true);
spmn = dynamic_cast<SP::SPMeshNode*>(m_bonus_node);
assert(spmn);
m_moving_bonus->setSPTM(spmn->getTextureMatrix(0).data());
}
#endif
m_slipstream_time = 0.0f;
m_bonus_time = 0.0f;
m_bonus_active = false;
m_current_target_id = -1;//should not match a real possible kart ID
m_previous_target_id = -1;
//The kart starts at 0 speed anyway
float length = 0.0f;
@ -101,6 +122,8 @@ SlipStream::SlipStream(AbstractKart* kart)
m_slipstream_quad = new Quad(p[0], p[1], p[2], p[3]);
//The position will be corrected in the update anyway
m_slipstream_inner_quad = new Quad(p[0], p[1], p[2], p[3]);
//The position will be corrected in the update anyway
m_slipstream_outer_quad = new Quad(p[0], p[1], p[2], p[3]);
#ifndef SERVER_ONLY
if (UserConfigParams::m_slipstream_debug)
{
@ -155,6 +178,10 @@ SlipStream::~SlipStream()
{
irr_driver->removeNode(m_node_fast);
}
if (m_bonus_node)
{
irr_driver->removeNode(m_bonus_node);
}
if (m_debug_dc)
{
m_debug_dc->removeFromSP();
@ -165,11 +192,13 @@ SlipStream::~SlipStream()
}
delete m_slipstream_quad;
delete m_slipstream_inner_quad;
delete m_slipstream_outer_quad;
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
delete m_moving;
delete m_moving_fast;
delete m_moving_bonus;
}
#endif
@ -181,6 +210,7 @@ void SlipStream::reset()
{
m_slipstream_mode = SS_NONE;
m_slipstream_time = 0;
m_bonus_time = 0;
// Reset a potential max speed increase
m_kart->increaseMaxSpeed(MaxSpeed::MS_INCREASE_SLIPSTREAM, 0, 0, 0, 0);
@ -193,13 +223,19 @@ void SlipStream::reset()
* texture coordniates.
* \param material The material to use.
*/
SP::SPMesh* SlipStream::createMesh(Material* material)
SP::SPMesh* SlipStream::createMesh(Material* material, bool bonus_mesh)
{
SP::SPMesh* spm = NULL;
#ifndef SERVER_ONLY
// All radius, starting with the one closest to the kart (and
// widest) to the one furthest away. A 0 indicates the end of the list
float radius[] = {1.5f, 1.0f, 0.5f, 0.0f};
std::vector<float> radius = {1.5f, 1.0f, 0.5f, 0.0f};
if (bonus_mesh)
{
radius = {0.9f,0.6f,0.3f,0.0f};
}
// The distance of each of the circle from the kart. The number of
// entries in this array must be the same as the number of non-zero
@ -217,7 +253,12 @@ SP::SPMesh* SlipStream::createMesh(Material* material)
// (radius1-radius0)/(distance1-distance0) = (radius2-radius1)/(distnace2-distance0)
// This way the line connecting the upper "+" is a straight line,
// and so the 3d cone shape will not be disturbed.
float distance[] = {2.0f, 6.0f, 10.0f };
std::vector<float> distance = {2.0f, 6.0f, 10.0f };
if (bonus_mesh)
{
distance = {0.4f, 0.8f, 1.2f };
}
// The alpha values for the rings, no 'end of list' entry required.
int alphas[] = {0, 255, 0};
@ -230,7 +271,10 @@ SP::SPMesh* SlipStream::createMesh(Material* material)
assert(num_circles > 0);
// Length is distance of last circle to distance of first circle:
m_length = distance[num_circles-1] - distance[0];
float length = distance[num_circles-1] - distance[0];
if (!bonus_mesh)
m_length = length;
// The number of points for each circle. Since part of the slip stream
// might be under the ground (esp. first and last segment), specify
@ -241,12 +285,24 @@ SP::SPMesh* SlipStream::createMesh(Material* material)
const float f = 2*M_PI/float(num_segments);
SP::SPMeshBuffer* buffer = new SP::SPMeshBuffer();
static_cast<SP::SPPerObjectUniform*>(buffer)->addAssignerFunction
("custom_alpha", [this](SP::SPUniformAssigner* ua)->void
{
// In sp shader it's assigned reverse by 1.0 - custom_alpha
ua->setValue(1.0f - m_slipstream_time);
});
if(!bonus_mesh)
{
static_cast<SP::SPPerObjectUniform*>(buffer)->addAssignerFunction
("custom_alpha", [this](SP::SPUniformAssigner* ua)->void
{
// In sp shader it's assigned reverse by 1.0 - custom_alpha
ua->setValue(1.0f - m_slipstream_time);
});
}
else
{
static_cast<SP::SPPerObjectUniform*>(buffer)->addAssignerFunction
("custom_alpha", [this](SP::SPUniformAssigner* ua)->void
{
// In sp shader it's assigned reverse by 1.0 - custom_alpha
ua->setValue(1.0f - m_bonus_time);
});
}
std::vector<uint16_t> indices;
std::vector<video::S3DVertexSkinnedMesh> vertices;
@ -265,7 +321,7 @@ SP::SPMesh* SlipStream::createMesh(Material* material)
// Enable texture matrix and dummy normal for visualization
v.m_normal = 0x1FF << 10 | 1 << 30;
v.m_color = video::SColor(alphas[j], 255, 255, 255);
v.m_all_uvs[0] = MiniGLM::toFloat16(curr_distance/m_length);
v.m_all_uvs[0] = MiniGLM::toFloat16(curr_distance/length);
v.m_all_uvs[1] = MiniGLM::toFloat16(
(float)(i-first_segment)/(last_segment-first_segment)
+ (j%2)*(.5f/num_segments));
@ -299,13 +355,8 @@ SP::SPMesh* SlipStream::createMesh(Material* material)
return spm;
} // createMesh
//-----------------------------------------------------------------------------
/** Sets the animation intensity (or speed).
* \param f Intensity: 0 = no slip stream,
* 1 = collecting
* 2 = bonus can be used
*/
void SlipStream::setIntensity(float f, const AbstractKart *kart)
//----------------------------------------------------------------------------- */
void SlipStream::updateSlipstreamingTextures(float f, const AbstractKart *kart)
{
if (!kart || !m_node || !m_node_fast)
{
@ -320,7 +371,7 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
return;
}
float ktf = m_kart->getKartProperties()->getSlipstreamCollectTime();
float ktf = m_kart->getKartProperties()->getSlipstreamMinCollectTime();
const float above_terrain = 0.2f;
core::vector3df my_pos = m_kart->getNode()->getPosition();
@ -343,7 +394,9 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
m_node_fast->setVisible(f>=ktf);
//specify the texture speed movement
if (f > 8.0f) f = 8.0f;
float max_f = m_kart->getKartProperties()->getSlipstreamMaxCollectTime();
if (f > max_f) f = max_f;
f = f/2;
m_moving->setSpeed(f, 0);
@ -353,7 +406,32 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
// For debugging: make the slip stream effect visible all the time
m_node->setVisible(true);
m_moving->setSpeed(1.0f, 0.0f);
} // setIntensity
} // updateSlipstreamingTextures
//----------------------------------------------------------------------------- */
void SlipStream::updateBonusTexture()
{
if (!m_bonus_node)
{
return;
}
const float above_terrain = 0.2f;
core::vector3df my_pos = m_kart->getNode()->getPosition();
my_pos.Y += above_terrain;
core::vector3df previous_pos = m_kart->getRecentPreviousXYZ().toIrrVector();
core::vector3df diff = my_pos - previous_pos;
core::vector3df rotation = diff.getHorizontalAngle();
m_bonus_node->setPosition(my_pos);
m_bonus_node->setRotation(rotation);
m_bonus_node->setVisible(m_bonus_time > 0.0f && m_kart->getSpeed() > 2.0f);
float bonus_speed = 1.0f + std::max(m_bonus_time/1.5f,0.0f);
m_moving_bonus->setSpeed(bonus_speed, 0);
} //updateBonusTexture
//-----------------------------------------------------------------------------
/** Returns true if enough slipstream credits have been accumulated
@ -362,28 +440,9 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
bool SlipStream::isSlipstreamReady() const
{
return m_slipstream_time>
m_kart->getKartProperties()->getSlipstreamCollectTime();
m_kart->getKartProperties()->getSlipstreamMinCollectTime();
} // isSlipstreamReady
//-----------------------------------------------------------------------------
/** Returns the additional force being applied to the kart because of
* slipstreaming.
*/
void SlipStream::updateSlipstreamPower()
{
// See if we are currently using accumulated slipstream credits:
// -------------------------------------------------------------
if(m_slipstream_mode==SS_USE)
{
const KartProperties *kp = m_kart->getKartProperties();
m_kart->increaseMaxSpeed(MaxSpeed::MS_INCREASE_SLIPSTREAM,
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamAddPower(),
kp->getSlipstreamDuration(),
kp->getSlipstreamFadeOutTime());
}
} // upateSlipstreamPower
//-----------------------------------------------------------------------------
/** Sets the color of the debug mesh (which shows the area in which slipstream
* can be accumulated).
@ -493,6 +552,12 @@ void SlipStream::updateQuad()
//Update the slipstreaming quad
m_slipstream_quad->setQuad(p[0], p[1], p[2], p[3]);
p[1]=Vec3((-ew*0.5f+offx)*1.1f, 0, -kl*0.5f-(length+offz)*1.1f);
p[2]=Vec3((ew*0.5f+offx)*1.1f, 0, -kl*0.5f-(length+offz)*1.1f);
//Update the slipstreaming outer quad
m_slipstream_outer_quad->setQuad(p[0], p[1], p[2], p[3]);
#ifndef SERVER_ONLY
//recalculate quad position for debug drawing
if (UserConfigParams::m_slipstream_debug)
@ -518,10 +583,8 @@ void SlipStream::updateQuad()
offx = (kl*0.5f+length)*noffset.x();
offz = (kl*0.5f+length)*noffset.z();
p[0]=Vec3(-kw*0.5f, 0, kl*0.5f );
p[1]=Vec3(-ew*0.5f+offx, 0, -kl*0.5f-length+offz);
p[2]=Vec3( ew*0.5f+offx, 0, -kl*0.5f-length+offz);
p[3]=Vec3( kw*0.5f, 0, kl*0.5f );
//Update the slipstreaming inner quad
m_slipstream_inner_quad->setQuad(p[0], p[1], p[2], p[3]);
@ -570,16 +633,12 @@ void SlipStream::update(float dt)
{
m_moving->update(dt);
m_moving_fast->update(dt);
m_moving_bonus->update(dt);
}
#endif
if(m_slipstream_mode==SS_USE)
{
m_slipstream_time -= dt;//This makes slipstream_time decrease twice faster
if(m_slipstream_time<0) m_slipstream_mode=SS_NONE;
}
updateSlipstreamPower();
m_bonus_time -= dt;
if (m_bonus_time <= 0) m_bonus_active = false;
// If this kart is too slow for slipstreaming taking effect, do nothing
// Use a margin because what really matters is the target's speed
@ -593,7 +652,11 @@ void SlipStream::update(float dt)
if(m_kart->getSpeed() < kp->getSlipstreamMinSpeed() - 2.0f)
{
#ifndef SERVER_ONLY
if (CVS->isGLSL()) setIntensity(0, NULL);
if (CVS->isGLSL())
{
updateSlipstreamingTextures(0,NULL);
updateBonusTexture();
}
#endif
m_slipstream_mode = SS_NONE;
if(UserConfigParams::m_slipstream_debug)
@ -611,7 +674,9 @@ void SlipStream::update(float dt)
unsigned int num_karts = world->getNumKarts();
bool is_sstreaming = false;
bool is_inner_sstreaming = false;
bool is_outer_sstreaming = false;
m_target_kart = NULL;
std::vector<float> target_value;
// Note that this loop can not be simply replaced with a shorter loop
// using only the karts with a better position - since a kart might
@ -619,13 +684,19 @@ void SlipStream::update(float dt)
for(unsigned int i=0; i<num_karts; i++)
{
m_target_kart= world->getKart(i);
target_value.push_back(0);
// Don't test for slipstream with itself, a kart that is being
// rescued or exploding, a ghost kart or an eliminated kart
if(m_target_kart==m_kart ||
m_target_kart->getKartAnimation() ||
m_target_kart->isGhostKart() ||
m_target_kart->isEliminated() ) continue;
m_target_kart->isEliminated() )
{
if (m_previous_target_id >= 0 && (int) i==m_previous_target_id)
m_previous_target_id = -1;
continue;
}
const KartProperties *kp_target = m_target_kart->getKartProperties();
@ -649,7 +720,8 @@ void SlipStream::update(float dt)
m_target_kart->getSlipstream()
->setDebugColor(video::SColor(255, 0, 0, 0), true);
}
if (m_previous_target_id >= 0 && (int) i==m_previous_target_id)
m_previous_target_id = -1;
continue;
}
#endif
@ -659,13 +731,15 @@ void SlipStream::update(float dt)
// (additional target_kart_length because that kart's center
// is not the center of rotation of the slipstreaming quad)
Vec3 delta = m_kart->getXYZ() - m_target_kart->getXYZ();
float l = kp_target->getSlipstreamLength();
float l = kp_target->getSlipstreamLength()*1.1;//Outer quad margin
float speed_factor = m_target_kart->getSpeed()
/kp_target->getSlipstreamBaseSpeed();
l = l*speed_factor + m_target_kart->getKartLength()
+ 0.5f*m_kart->getKartLength();
if(delta.length2() > l*l)
{
if (m_previous_target_id >= 0 && (int) i==m_previous_target_id)
m_previous_target_id = -1;
continue;
}
// Real test 1: if in inner slipstream quad of other kart
@ -674,7 +748,8 @@ void SlipStream::update(float dt)
{
is_inner_sstreaming = true;
is_sstreaming = true;
break;
target_value[i] = 2000.0f - delta.length2();
continue;
}
if(UserConfigParams::m_slipstream_debug &&
m_kart->getController()->isLocalPlayerController())
@ -686,14 +761,74 @@ void SlipStream::update(float dt)
->pointInside(lc))
{
is_sstreaming = true;
break;
target_value[i] = 1000.0f - delta.length2();
continue;
}
else if (m_previous_target_id >= 0 && (int) i==m_previous_target_id)
{
m_previous_target_id = -1;
}
if(UserConfigParams::m_slipstream_debug &&
m_kart->getController()->isLocalPlayerController())
m_target_kart->getSlipstream()
->setDebugColor(video::SColor(255, 0, 0, 255),false);
// Real test3: if in outer slipstream quad of other kart
if(m_target_kart->getSlipstream()->m_slipstream_outer_quad
->pointInside(lc))
{
is_outer_sstreaming = true;
continue;
}
} // for i < num_karts
int best_target=-1;
float best_target_value=0.0f;
//Select the best target
for(unsigned int i=0; i<num_karts; i++)
{
if (target_value[i] > best_target_value)
{
best_target_value = target_value[i];
best_target=i;
}
} // for i < num_karts
if (best_target >= 0)
{
m_target_kart = world->getKart(best_target);
}
//When changing slipstream target (including no good target)
if (best_target!=m_current_target_id)
{
m_previous_target_id = m_current_target_id;
m_current_target_id = best_target;
}
if(isSlipstreamReady() && (m_current_target_id < 0
|| (m_previous_target_id >= 0
&& target_value[m_previous_target_id] == 0.0f)))
{
// The first time slipstream is ready after collecting, and
// you are leaving the slipstream area, the bonus is activated
float additional_time = m_slipstream_time*kp->getSlipstreamDurationFactor();
if (m_bonus_time <= 0.0f)
m_bonus_time = additional_time;
else
m_bonus_time += additional_time;
m_slipstream_time = 0.0f;
m_bonus_active = true;
m_kart->instantSpeedIncrease(MaxSpeed::MS_INCREASE_SLIPSTREAM,
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamAddPower(),
m_bonus_time,
kp->getSlipstreamFadeOutTime());
}
if(!is_sstreaming)
{
if(UserConfigParams::m_slipstream_debug &&
@ -706,28 +841,18 @@ void SlipStream::update(float dt)
->setDebugColor(video::SColor(255, 0, 255, 0),true);
}
if(isSlipstreamReady())
{
// The first time slipstream is ready after collecting
// and you are leaving the slipstream area, you get an
// instant speed_increase
if(m_slipstream_mode==SS_COLLECT)
{
m_slipstream_mode = SS_USE;
m_kart->instantSpeedIncrease(MaxSpeed::MS_INCREASE_SLIPSTREAM,
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamAddPower(),
kp->getSlipstreamDuration(),
kp->getSlipstreamFadeOutTime());
return;
}
}
m_slipstream_time -=dt;
//Reduces the easiness of reusing most of the accumulated time with another kart
if(is_outer_sstreaming)
m_slipstream_time -=dt;
else
m_slipstream_time -=3*dt;
if(m_slipstream_time<0) m_slipstream_mode = SS_NONE;
#ifndef SERVER_ONLY
if (CVS->isGLSL()) setIntensity(0, NULL);
if (CVS->isGLSL())
{
updateSlipstreamingTextures(0,NULL);
updateBonusTexture();
}
#endif
return;
} // if !is_sstreaming
@ -751,14 +876,18 @@ void SlipStream::update(float dt)
m_slipstream_time = m_slipstream_mode==SS_NONE ? dt : m_slipstream_time+dt;
}
//Cap the possible credits. Keep this similar to the animation speed cap.
if (m_slipstream_time > 8.0f)
m_slipstream_time = 8.0f;
//Cap the possible credits
if (m_slipstream_time > m_kart->getKartProperties()->getSlipstreamMaxCollectTime())
m_slipstream_time = m_kart->getKartProperties()->getSlipstreamMaxCollectTime();
if(isSlipstreamReady())
m_kart->setSlipstreamEffect(9.0f);
#ifndef SERVER_ONLY
if (CVS->isGLSL()) setIntensity(m_slipstream_time, m_target_kart);
if (CVS->isGLSL())
{
updateSlipstreamingTextures(m_slipstream_time, m_target_kart);
updateBonusTexture();
}
#endif
m_slipstream_mode = SS_COLLECT;
} // update

View File

@ -58,12 +58,19 @@ private:
MovingTexture *m_moving_fast;
/** The moving texture for the fast node */
MovingTexture *m_moving_bonus;
/** The scene node. */
scene::ISceneNode *m_node;
/** The fast scene node. */
scene::ISceneNode *m_node_fast;
/** The node used when the bonus is active. */
scene::ISceneNode *m_bonus_node;
/** For debugging: a simple quad to display where slipstream works. */
std::shared_ptr<SP::SPDynamicDrawCall> m_debug_dc;
@ -71,15 +78,27 @@ private:
std::shared_ptr<SP::SPDynamicDrawCall> m_debug_dc2;
/** The length of the slipstream cylinder. This is used to scale
* the actual scene node correctly. */
float m_length;
* the actual scene node correctly. Shared between node and node_fast */
float m_length;
/** The time a kart was in slipstream. */
float m_slipstream_time;
/** The remaining active time bonus */
float m_bonus_time;
/** This bool is used to know the first time we're going out of the slipstreaming area */
bool m_bonus_active;
/** Used to trigger automatically the slipstreaming bonus */
int m_current_target_id;
int m_previous_target_id;
/** Slipstream mode: either nothing happening, or the kart is collecting
* 'slipstream credits', or the kart is using accumulated credits. */
enum {SS_NONE, SS_COLLECT, SS_USE} m_slipstream_mode;
* 'slipstream credits'. Credits can be accumulated while the bonus is used */
enum {SS_NONE, SS_COLLECT} m_slipstream_mode;
/** This is slipstream area if the kart is at 0,0,0 without rotation. */
Quad *m_slipstream_quad;
@ -87,20 +106,24 @@ private:
/** This is the inner slipstream area if the kart is at 0,0,0 without rotation. */
Quad *m_slipstream_inner_quad;
/** This is the outer slipstream area if the kart is at 0,0,0 without rotation.
No slipstream time is accumulated there, but it's lost slower*/
Quad *m_slipstream_outer_quad;
/** The kart from which this kart gets slipstream. Used by the AI to
** overtake the right kart. */
AbstractKart* m_target_kart;
SP::SPMesh* createMesh(Material* material);
SP::SPMesh* createMesh(Material* material, bool bonus_mesh);
void setDebugColor(const video::SColor &color, bool inner);
void updateQuad();
void updateSlipstreamingTextures(float f, const AbstractKart* kart);
void updateBonusTexture();
public:
SlipStream (AbstractKart* kart);
virtual ~SlipStream ();
void reset();
virtual void update(float dt);
void setIntensity(float f, const AbstractKart* kart);
void updateSlipstreamPower();
bool isSlipstreamReady() const;
// ------------------------------------------------------------------------
@ -112,6 +135,6 @@ public:
const AbstractKart* getSlipstreamTarget() const {return m_target_kart;}
// ------------------------------------------------------------------------
/** Returns if slipstream is being used. */
bool inUse() const {return m_slipstream_mode==SS_USE; }
bool inUse() const {return m_bonus_time>0.0f; }
}; // SlipStream
#endif

View File

@ -213,7 +213,7 @@ AbstractCharacteristic::ValueType AbstractCharacteristic::getType(
return TYPE_FLOAT;
case NITRO_MAX:
return TYPE_FLOAT;
case SLIPSTREAM_DURATION:
case SLIPSTREAM_DURATION_FACTOR:
return TYPE_FLOAT;
case SLIPSTREAM_BASE_SPEED:
return TYPE_FLOAT;
@ -223,9 +223,9 @@ AbstractCharacteristic::ValueType AbstractCharacteristic::getType(
return TYPE_FLOAT;
case SLIPSTREAM_INNER_FACTOR:
return TYPE_FLOAT;
case SLIPSTREAM_COLLECT_TIME:
case SLIPSTREAM_MIN_COLLECT_TIME:
return TYPE_FLOAT;
case SLIPSTREAM_USE_TIME:
case SLIPSTREAM_MAX_COLLECT_TIME:
return TYPE_FLOAT;
case SLIPSTREAM_ADD_POWER:
return TYPE_FLOAT;
@ -449,8 +449,8 @@ std::string AbstractCharacteristic::getName(CharacteristicType type)
return "NITRO_FADE_OUT_TIME";
case NITRO_MAX:
return "NITRO_MAX";
case SLIPSTREAM_DURATION:
return "SLIPSTREAM_DURATION";
case SLIPSTREAM_DURATION_FACTOR:
return "SLIPSTREAM_DURATION_FACTOR";
case SLIPSTREAM_BASE_SPEED:
return "SLIPSTREAM_BASE_SPEED";
case SLIPSTREAM_LENGTH:
@ -459,10 +459,10 @@ std::string AbstractCharacteristic::getName(CharacteristicType type)
return "SLIPSTREAM_WIDTH";
case SLIPSTREAM_INNER_FACTOR:
return "SLIPSTREAM_INNER_FACTOR";
case SLIPSTREAM_COLLECT_TIME:
return "SLIPSTREAM_COLLECT_TIME";
case SLIPSTREAM_USE_TIME:
return "SLIPSTREAM_USE_TIME";
case SLIPSTREAM_MIN_COLLECT_TIME:
return "SLIPSTREAM_MIN_COLLECT_TIME";
case SLIPSTREAM_MAX_COLLECT_TIME:
return "SLIPSTREAM_MAX_COLLECT_TIME";
case SLIPSTREAM_ADD_POWER:
return "SLIPSTREAM_ADD_POWER";
case SLIPSTREAM_MIN_SPEED:
@ -1468,16 +1468,16 @@ float AbstractCharacteristic::getNitroMax() const
} // getNitroMax
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamDuration() const
float AbstractCharacteristic::getSlipstreamDurationFactor() const
{
float result;
bool is_set = false;
process(SLIPSTREAM_DURATION, &result, &is_set);
process(SLIPSTREAM_DURATION_FACTOR, &result, &is_set);
if (!is_set)
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
getName(SLIPSTREAM_DURATION).c_str());
getName(SLIPSTREAM_DURATION_FACTOR).c_str());
return result;
} // getSlipstreamDuration
} // getSlipstreamDurationFactor
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamBaseSpeed() const
@ -1528,28 +1528,28 @@ float AbstractCharacteristic::getSlipstreamInnerFactor() const
} // getSlipstreamInnerFactor
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamCollectTime() const
float AbstractCharacteristic::getSlipstreamMinCollectTime() const
{
float result;
bool is_set = false;
process(SLIPSTREAM_COLLECT_TIME, &result, &is_set);
process(SLIPSTREAM_MIN_COLLECT_TIME, &result, &is_set);
if (!is_set)
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
getName(SLIPSTREAM_COLLECT_TIME).c_str());
getName(SLIPSTREAM_MIN_COLLECT_TIME).c_str());
return result;
} // getSlipstreamCollectTime
} // getSlipstreamMinCollectTime
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamUseTime() const
float AbstractCharacteristic::getSlipstreamMaxCollectTime() const
{
float result;
bool is_set = false;
process(SLIPSTREAM_USE_TIME, &result, &is_set);
process(SLIPSTREAM_MAX_COLLECT_TIME, &result, &is_set);
if (!is_set)
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
getName(SLIPSTREAM_USE_TIME).c_str());
getName(SLIPSTREAM_MAX_COLLECT_TIME).c_str());
return result;
} // getSlipstreamUseTime
} // getSlipstreamMaxCollecTime
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamAddPower() const

View File

@ -193,13 +193,13 @@ public:
NITRO_MAX,
// Slipstream
SLIPSTREAM_DURATION,
SLIPSTREAM_DURATION_FACTOR,
SLIPSTREAM_BASE_SPEED,
SLIPSTREAM_LENGTH,
SLIPSTREAM_WIDTH,
SLIPSTREAM_INNER_FACTOR,
SLIPSTREAM_COLLECT_TIME,
SLIPSTREAM_USE_TIME,
SLIPSTREAM_MIN_COLLECT_TIME,
SLIPSTREAM_MAX_COLLECT_TIME,
SLIPSTREAM_ADD_POWER,
SLIPSTREAM_MIN_SPEED,
SLIPSTREAM_MAX_SPEED_INCREASE,
@ -361,13 +361,13 @@ public:
float getNitroFadeOutTime() const;
float getNitroMax() const;
float getSlipstreamDuration() const;
float getSlipstreamDurationFactor() const;
float getSlipstreamBaseSpeed() const;
float getSlipstreamLength() const;
float getSlipstreamWidth() const;
float getSlipstreamInnerFactor() const;
float getSlipstreamCollectTime() const;
float getSlipstreamUseTime() const;
float getSlipstreamMinCollectTime() const;
float getSlipstreamMaxCollectTime() const;
float getSlipstreamAddPower() const;
float getSlipstreamMinSpeed() const;
float getSlipstreamMaxSpeedIncrease() const;

View File

@ -476,9 +476,12 @@ public:
* defined even if the kart is flying. */
virtual const Vec3& getNormal() const = 0;
// ------------------------------------------------------------------------
/** Returns the position 0,25s before */
/** Returns the position 0.25s before */
virtual const Vec3& getPreviousXYZ() const = 0;
// ------------------------------------------------------------------------
/** Returns the most recent different previous position */
virtual const Vec3& getRecentPreviousXYZ() const = 0;
// ------------------------------------------------------------------------
/** Returns the height of the terrain. we're currently above */
virtual float getHoT() const = 0;
// ------------------------------------------------------------------------

View File

@ -147,9 +147,12 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_boosted_ai = false;
m_type = RaceManager::KT_AI;
for (int i=0;i<30;i++)
m_xyz_history_size = stk_config->time2Ticks(XYZ_HISTORY_TIME);
Vec3 initial_position = getXYZ();
for (int i=0;i<m_xyz_history_size;i++)
{
m_previous_xyz[i] = getXYZ();
m_previous_xyz.push_back(initial_position);
}
m_time_previous_counter = 0.0f;
@ -376,7 +379,7 @@ void Kart::reset()
m_has_caught_nolok_bubblegum = false;
m_is_jumping = false;
for (int i=0;i<30;i++)
for (int i=0;i<m_xyz_history_size;i++)
{
m_previous_xyz[i] = getXYZ();
}
@ -1228,7 +1231,7 @@ void Kart::eliminate()
m_stars_effect->reset();
m_stars_effect->update(1);
}
if (m_attachment)
{
m_attachment->clear();
@ -1306,14 +1309,14 @@ void Kart::update(float dt)
}
m_time_previous_counter += dt;
while (m_time_previous_counter > (1.0f/120.0f))
while (m_time_previous_counter > stk_config->ticks2Time(1))
{
m_previous_xyz[0] = getXYZ();
for (int i=29;i>0;i--)
for (int i=m_xyz_history_size-1;i>0;i--)
{
m_previous_xyz[i] = m_previous_xyz[i-1];
}
m_time_previous_counter -= (1.0f/120.0f);
m_time_previous_counter -= stk_config->ticks2Time(1);
}
// Update the position and other data taken from the physics (or
@ -3092,12 +3095,20 @@ const Vec3& Kart::getNormal() const
} // getNormal
// ------------------------------------------------------------------------
/** Returns the position 0,25s before */
/** Returns the position 0.25s before */
const Vec3& Kart::getPreviousXYZ() const
{
return m_previous_xyz[29];
return m_previous_xyz[m_xyz_history_size-1];
} // getPreviousXYZ
// ------------------------------------------------------------------------
/** Returns a more recent different previous position */
const Vec3& Kart::getRecentPreviousXYZ() const
{
//Not the most recent, because the angle variations would be too
//irregular on some tracks whose roads are not smooth enough
return m_previous_xyz[m_xyz_history_size/5];
} // getRecentPreviousXYZ
// ------------------------------------------------------------------------
void Kart::playSound(SFXBuffer* buffer)

View File

@ -74,8 +74,15 @@ protected:
* new lap is triggered. */
Vec3 m_xyz_front;
/** The coordinates of the 30 previous positions */
Vec3 m_previous_xyz[30];
/* Determines the time covered by the history size, in seconds */
const float XYZ_HISTORY_TIME = 0.25f;
/* Determines the number of previous XYZ positions of the kart to remember
Initialized in the constructor and unchanged from then on */
int m_xyz_history_size;
/** The coordinates of the XYZ_HISTORY_SIZE previous positions */
std::vector<Vec3> m_previous_xyz;
float m_time_previous_counter;
@ -479,9 +486,13 @@ public:
* defined even if the kart is flying. */
virtual const Vec3& getNormal() const;
// ------------------------------------------------------------------------
/** Returns the position 0,25s before */
/** Returns the position 0.25s before */
virtual const Vec3& getPreviousXYZ() const;
// ------------------------------------------------------------------------
/** Returns a more recent different previous position */
virtual const Vec3& getRecentPreviousXYZ() const;
// ------------------------------------------------------------------------
/** For debugging only: check if a kart is flying. */
bool isFlying() const { return m_flying; }

View File

@ -1037,10 +1037,10 @@ float KartProperties::getNitroMax() const
} // getNitroMax
// ----------------------------------------------------------------------------
float KartProperties::getSlipstreamDuration() const
float KartProperties::getSlipstreamDurationFactor() const
{
return m_cached_characteristic->getSlipstreamDuration();
} // getSlipstreamDuration
return m_cached_characteristic->getSlipstreamDurationFactor();
} // getSlipstreamDurationFactor
// ----------------------------------------------------------------------------
float KartProperties::getSlipstreamBaseSpeed() const
@ -1067,16 +1067,16 @@ float KartProperties::getSlipstreamInnerFactor() const
} // getSlipstreamInnerFactor
// ----------------------------------------------------------------------------
float KartProperties::getSlipstreamCollectTime() const
float KartProperties::getSlipstreamMinCollectTime() const
{
return m_cached_characteristic->getSlipstreamCollectTime();
} // getSlipstreamCollectTime
return m_cached_characteristic->getSlipstreamMinCollectTime();
} // getSlipstreamMinCollectTime
// ----------------------------------------------------------------------------
float KartProperties::getSlipstreamUseTime() const
float KartProperties::getSlipstreamMaxCollectTime() const
{
return m_cached_characteristic->getSlipstreamUseTime();
} // getSlipstreamUseTime
return m_cached_characteristic->getSlipstreamMaxCollectTime();
} // getSlipstreamMaxCollectTime
// ----------------------------------------------------------------------------
float KartProperties::getSlipstreamAddPower() const

View File

@ -481,13 +481,13 @@ public:
float getNitroFadeOutTime() const;
float getNitroMax() const;
float getSlipstreamDuration() const;
float getSlipstreamDurationFactor() const;
float getSlipstreamBaseSpeed() const;
float getSlipstreamLength() const;
float getSlipstreamWidth() const;
float getSlipstreamInnerFactor() const;
float getSlipstreamCollectTime() const;
float getSlipstreamUseTime() const;
float getSlipstreamMinCollectTime() const;
float getSlipstreamMaxCollectTime() const;
float getSlipstreamAddPower() const;
float getSlipstreamMinSpeed() const;
float getSlipstreamMaxSpeedIncrease() const;

View File

@ -561,8 +561,8 @@ void XmlCharacteristic::load(const XMLNode *node)
if (const XMLNode *sub_node = node->getNode("slipstream"))
{
sub_node->get("duration",
&m_values[SLIPSTREAM_DURATION]);
sub_node->get("duration-factor",
&m_values[SLIPSTREAM_DURATION_FACTOR]);
sub_node->get("base-speed",
&m_values[SLIPSTREAM_BASE_SPEED]);
sub_node->get("length",
@ -571,10 +571,10 @@ void XmlCharacteristic::load(const XMLNode *node)
&m_values[SLIPSTREAM_WIDTH]);
sub_node->get("inner-factor",
&m_values[SLIPSTREAM_INNER_FACTOR]);
sub_node->get("collect-time",
&m_values[SLIPSTREAM_COLLECT_TIME]);
sub_node->get("use-time",
&m_values[SLIPSTREAM_USE_TIME]);
sub_node->get("min-collect-time",
&m_values[SLIPSTREAM_MIN_COLLECT_TIME]);
sub_node->get("max-collect-time",
&m_values[SLIPSTREAM_MAX_COLLECT_TIME]);
sub_node->get("add-power",
&m_values[SLIPSTREAM_ADD_POWER]);
sub_node->get("min-speed",

View File

@ -48,7 +48,7 @@ Startup: time(std::vector<float>/floatVector), boost(std::vector<float>/floatVec
Rescue: duration, vertOffset, height
Explosion: duration, radius, invulnerabilityTime
Nitro: duration, engineForce, consumption, smallContainer, bigContainer, maxSpeedIncrease, fadeOutTime, max
Slipstream: duration, baseSpeed, length, width, innerFactor, collectTime, useTime, addPower, minSpeed, maxSpeedIncrease, fadeOutTime
Slipstream: durationFactor, baseSpeed, length, width, innerFactor, minCollectTime, maxCollectTime, addPower, minSpeed, maxSpeedIncrease, fadeOutTime
Skid: increase, decrease, max, timeTillMax, visual, visualTime, revertVisualTime, minSpeed, timeTillBonus(std::vector<float>/floatVector), bonusSpeed(std::vector<float>/floatVector), bonusTime(std::vector<float>/floatVector), bonusForce(std::vector<float>/floatVector), physicalJumpTime, graphicalJumpTime, postSkidRotateFactor, reduceTurnMin, reduceTurnMax, enabled(bool)"""
""" A GroupMember is an attribute of a group.