diff --git a/src/tracks/check_manager.cpp b/src/tracks/check_manager.cpp index a76ca5009..6b8760e8a 100644 --- a/src/tracks/check_manager.cpp +++ b/src/tracks/check_manager.cpp @@ -29,6 +29,7 @@ CheckManager::CheckManager(const XMLNode &node, Track *track) { + bool lap_line_found = false; for(unsigned int i=0; igetType()==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") diff --git a/src/tracks/check_structure.cpp b/src/tracks/check_structure.cpp index 3a4b9e4aa..cdab31b86 100644 --- a/src/tracks/check_structure.cpp +++ b/src/tracks/check_structure.cpp @@ -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; igetCheckStructure(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; igetCheckStructure(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 igetCheckStructure(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 diff --git a/src/tracks/check_structure.hpp b/src/tracks/check_structure.hpp index cb69d3d58..31bceea38 100644 --- a/src/tracks/check_structure.hpp +++ b/src/tracks/check_structure.hpp @@ -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 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 m_same_group; + public: CheckStructure(CheckManager *check_manager, const XMLNode &node, unsigned int index);