Support for grouping check structures. E.g. it is now possible to

have more than one lap line, which will always be in synch (i.e.
if one is triggered, all will be set to inactive).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@6161 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-09-28 23:29:21 +00:00
parent 3d66c17292
commit 4b4bddf35e
3 changed files with 99 additions and 51 deletions

View File

@ -29,6 +29,7 @@
CheckManager::CheckManager(const XMLNode &node, Track *track)
{
bool lap_line_found = false;
for(unsigned int i=0; i<node.getNumNodes(); i++)
{
const XMLNode *check_node = node.getNode(i);
@ -37,9 +38,13 @@ CheckManager::CheckManager(const XMLNode &node, Track *track)
{
CheckLine *cl = new CheckLine(this, *check_node, i);
m_all_checks.push_back(cl);
if(cl->getType()==CheckStructure::CT_NEW_LAP)
// Only record the first lap line to be used to compute
// start coordinates with. The track exporter always exports
// the one based on the quads first.
if(cl->getType()==CheckStructure::CT_NEW_LAP && !lap_line_found)
{
track->setStartCoordinates(cl->getLine2D());
lap_line_found = true;
}
} // checkline
else if(type=="check-sphere")

View File

@ -42,13 +42,16 @@ CheckStructure::CheckStructure(CheckManager *check_manager,
{
printf("Unknown check structure '%s' - ignored.\n", kind.c_str());
}
m_activate_check_index = -1;
node.get("other-id", &m_activate_check_index);
if( (m_check_type==CT_TOGGLE || m_check_type==CT_ACTIVATE) &&
m_activate_check_index==-1)
{
printf("Unknown other-id in checkline.\n");
}
m_check_structures_to_change_state.clear();
node.get("other-ids", &m_check_structures_to_change_state);
// Backwards compatibility to tracks exported with older versions of
// the track exporter
if(m_check_structures_to_change_state.size()==0)
node.get("other-id", &m_check_structures_to_change_state);
m_same_group.clear();
node.get("same-group", &m_same_group);
m_active_at_reset=true;
node.get("active", &m_active_at_reset);
} // CheckStructure
@ -103,45 +106,76 @@ void CheckStructure::trigger(unsigned int kart_index)
{
switch(m_check_type)
{
case CT_NEW_LAP : World::getWorld()->newLap(kart_index);
m_is_active[kart_index] = false;
if(UserConfigParams::m_check_debug)
{
printf("CHECK: %s new lap %d triggered, now deactivated.\n",
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
m_index);
}
break;
case CT_ACTIVATE: {
CheckStructure *cs=
m_check_manager->getCheckStructure(m_activate_check_index);
cs->m_is_active[kart_index] = true;
if(UserConfigParams::m_check_debug)
{
printf("CHECK: %s %d triggered, activating %d.\n",
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
m_index, m_activate_check_index);
}
break;
}
case CT_TOGGLE: {
CheckStructure *cs=
m_check_manager->getCheckStructure(m_activate_check_index);
cs->m_is_active[kart_index] = !cs->m_is_active[kart_index];
if(UserConfigParams::m_check_debug)
{
// At least on gcc 4.3.2 we can't simply print
// cs->m_is_active[kart_index] ("cannot pass objects of
// non-POD type struct std::_Bit_reference through ...;
// call will abort at runtime"). So we use this somewhat
// unusual but portable construct.
printf("CHECK: %s %d triggered, setting %d to %d.\n",
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
m_index, m_activate_check_index,
cs->m_is_active[kart_index]==true);
}
break;
}
case CT_NEW_LAP :
World::getWorld()->newLap(kart_index);
m_is_active[kart_index] = false;
if(UserConfigParams::m_check_debug)
{
printf("CHECK: %s new lap %d triggered, now deactivated.\n",
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
m_index);
}
// Set all checkstructures of the same group to the same state.
// This is to avoid e.g. only deactivating one of many new lap
// counters, which could enable the user to cheat by crossing
// all different lap counting lines.
for(unsigned int i=0; i<m_same_group.size(); i++)
{
CheckStructure *cs =
m_check_manager->getCheckStructure(m_same_group[i]);
cs->m_is_active[kart_index] = false;
printf("CHECK: also deactivating index %d\n", m_same_group[i]);
}
break;
case CT_ACTIVATE:
{
for(unsigned int i=0; i<m_check_structures_to_change_state.size();
i++)
{
int check_index = m_check_structures_to_change_state[i];
CheckStructure *cs=
m_check_manager->getCheckStructure(check_index);
// We don't have to activate all members of the group of
// cs, since this check line's m_check_structure_to_change
// will include the full groups.
cs->m_is_active[kart_index] = true;
if(UserConfigParams::m_check_debug)
{
printf("CHECK: %s %d triggered, activating %d.\n",
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
m_index, check_index);
}
} // for i<m_check_structures_to_change_state.size()
break;
}
case CT_TOGGLE:
{
for(unsigned int i=0; i<m_check_structures_to_change_state.size();
i++)
{
int check_index = m_check_structures_to_change_state[i];
CheckStructure *cs=
m_check_manager->getCheckStructure(check_index);
// We don't have to toggle all members of the group of
// cs, since this check line's m_check_structure_to_change
// will include the full groups. This esp. avoids toggling
// cs more than once!
cs->m_is_active[kart_index] = !cs->m_is_active[kart_index];
if(UserConfigParams::m_check_debug)
{
// At least on gcc 4.3.2 we can't simply print
// cs->m_is_active[kart_index] ("cannot pass objects of
// non-POD type struct std::_Bit_reference through ...;
// call will abort at runtime"). So we use this somewhat
// unusual but portable construct.
printf("CHECK: %s %d triggered, setting %d to %d.\n",
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
m_index, check_index,
cs->m_is_active[kart_index]==true);
}
} // for i < m_check_structures_to_change_state
break;
}
default: break;
} // switch m_check_type
} // trigger

View File

@ -1,7 +1,7 @@
// $Id: check_structure.hpp 1681 2008-04-09 13:52:48Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2010 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -53,7 +53,7 @@ public:
/** Different types of check structures:
* ACTIVATE: Activates another check structure (independent of
* the state that check structure is in)
* TOGGLE: Switches (or inverts) the state of another check structure.
* TOGGLE: Switches (inverts) the state of another check structure.
* NEW_LAP: On crossing a new lap is counted.
* AMBIENT_SPHERE: Modifies the ambient color.
* A combination of an activate and new_lap line are used to
@ -86,8 +86,17 @@ private:
bool m_active_at_reset;
/** If this is a CT_ACTIVATE or CT_SWITCH type, this will contain
* the index of the corresponding check structure that is triggered. */
int m_activate_check_index;
* the indices of the corresponding check structures that get their
* state changed (activated or switched). */
std::vector<int> m_check_structures_to_change_state;
/** A list of check lines that should be activated/switched when this
* lines is activated/switched. I.e. can be used if more than one lap
* counting line is used to make sure they are all in synch, otherwise
* players could cross first one then the other lap counting line
* as huge shortcuts. */
std::vector<int> m_same_group;
public:
CheckStructure(CheckManager *check_manager, const XMLNode &node,
unsigned int index);