1 // 2 // SuperTuxKart - a fun racing game with go-kart 3 // Copyright (C) 2012-2015 Joerg Henrichs 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 3 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 #ifndef HEADER_ABSTRACT_KART_HPP 20 #define HEADER_ABSTRACT_KART_HPP 21 22 #include <memory> 23 24 #include "items/powerup_manager.hpp" 25 #include "karts/moveable.hpp" 26 #include "karts/controller/kart_control.hpp" 27 #include "race/race_manager.hpp" 28 29 namespace irr 30 { 31 namespace scene 32 { 33 class IDummyTransformationSceneNode; 34 } 35 } 36 37 class AbstractKartAnimation; 38 class Attachment; 39 class btKart; 40 class btQuaternion; 41 class Controller; 42 class Item; 43 class ItemState; 44 class KartGFX; 45 class KartModel; 46 class KartProperties; 47 class Material; 48 class Powerup; 49 class RenderInfo; 50 class SFXBuffer; 51 class Skidding; 52 class SlipStream; 53 class Stars; 54 class TerrainInfo; 55 56 57 /** An abstract interface for the actual karts. Some functions are actually 58 * implemented here in order to allow inlining. 59 * \ingroup karts 60 */ 61 class AbstractKart : public Moveable 62 { 63 private: 64 /** Length of the kart, copy of the data from KartModel. */ 65 float m_kart_length; 66 /** Width of the kart, copy of the data from KartModel. */ 67 float m_kart_width; 68 /** Height of the kart, copy of the data from KartModel. */ 69 float m_kart_height; 70 /** Coordinate on up axis */ 71 float m_kart_highest_point; 72 /** The position of all four wheels in the 3d model */ 73 const Vec3* m_wheel_graphics_position; 74 75 /** Index of kart in world. */ 76 unsigned int m_world_kart_id; 77 78 /** Name of the kart with translation. */ 79 core::stringw m_name; 80 81 // ------------------------------------------------------------------------ 82 void loadKartProperties(const std::string& new_ident, 83 HandicapLevel handicap, 84 std::shared_ptr<RenderInfo> ri); 85 protected: 86 btTransform m_starting_transform; 87 88 int m_live_join_util; 89 90 /** The kart properties. */ 91 std::unique_ptr<KartProperties> m_kart_properties; 92 93 /** The handicap level of this kart. */ 94 HandicapLevel m_handicap; 95 96 /** This stores a copy of the kart model. It has to be a copy 97 * since otherwise incosistencies can happen if the same kart 98 * is used more than once. */ 99 std::unique_ptr<KartModel> m_kart_model; 100 101 /** Handles the attachment the kart might have. */ 102 std::unique_ptr<Attachment> m_attachment; 103 104 /** The kart controls (e.g. steering, fire, ...). */ 105 KartControl m_controls; 106 107 /** A kart animation object to handle rescue, explosion etc. */ 108 AbstractKartAnimation *m_kart_animation; 109 110 /** Node between wheels and kart. Allows kart to be scaled independent of wheels, when being squashed.*/ 111 irr::scene::IDummyTransformationSceneNode *m_wheel_box; 112 public: 113 AbstractKart(const std::string& ident, 114 int world_kart_id, 115 int position, const btTransform& init_transform, 116 HandicapLevel handicap, 117 std::shared_ptr<RenderInfo> ri); 118 virtual ~AbstractKart(); 119 // ------------------------------------------------------------------------ 120 /** Returns a name to be displayed for this kart. */ getName() const121 const core::stringw& getName() const { return m_name; } 122 // ------------------------------------------------------------------------ 123 virtual void reset(); 124 virtual void init(RaceManager::KartType type) = 0; 125 // ======================================================================== 126 // Functions related to controlling the kart 127 // ------------------------------------------------------------------------ 128 /** Returns the current steering value for this kart. */ getSteerPercent() const129 virtual float getSteerPercent() const { return m_controls.getSteer(); } 130 // ------------------------------------------------------------------------ 131 /** Returns all controls of this kart. */ getControls()132 KartControl& getControls() { return m_controls; } 133 // ------------------------------------------------------------------------ 134 /** Returns all controls of this kart - const version. */ getControls() const135 const KartControl& getControls() const { return m_controls; } 136 137 // ======================================================================== 138 // Access to the kart properties. 139 // ------------------------------------------------------------------------ 140 /** Returns the kart properties of this kart. */ getKartProperties() const141 const KartProperties* getKartProperties() const 142 { return m_kart_properties.get(); } 143 // ======================================================================== 144 /** Change to new kart instancely (used in network live join). */ 145 virtual void changeKart(const std::string& new_ident, 146 HandicapLevel handicap, 147 std::shared_ptr<RenderInfo> ri); 148 // ======================================================================== 149 // Access to the handicap. 150 // ------------------------------------------------------------------------ 151 /** Returns the handicap of this kart. */ getHandicap() const152 const HandicapLevel getHandicap() const { return m_handicap; } 153 // ------------------------------------------------------------------------ 154 /** Sets the handicap. */ setHandicap(const HandicapLevel h)155 void setHandicap(const HandicapLevel h) { m_handicap=h; } 156 157 // ------------------------------------------------------------------------ 158 /** Returns a unique identifier for this kart (name of the directory the 159 * kart was loaded from). */ 160 virtual const std::string& getIdent() const; 161 // ------------------------------------------------------------------------ 162 /** Returns the maximum steering angle for this kart, which depends on the 163 * speed. */ 164 virtual float getMaxSteerAngle () const = 0; 165 // ------------------------------------------------------------------------ 166 /** Returns the (maximum) speed for a given turn radius. 167 * \param radius The radius for which the speed needs to be computed. */ 168 virtual float getSpeedForTurnRadius(float radius) const = 0; 169 // ------------------------------------------------------------------------ 170 /** Returns the time till full steering is reached for this kart. 171 * This can depend on the current steering value, which must be >= 0. 172 */ 173 virtual float getTimeFullSteer(float steer) const = 0; 174 175 // ======================================================================== 176 // Attachment related functions. 177 // ------------------------------------------------------------------------ 178 /** Returns the current attachment. */ getAttachment() const179 const Attachment* getAttachment() const {return m_attachment.get(); } 180 // ------------------------------------------------------------------------ 181 /** Returns the current attachment, non-const version. */ getAttachment()182 Attachment* getAttachment() {return m_attachment.get(); } 183 184 // ======================================================================== 185 // Access to the graphical kart model. 186 // ------------------------------------------------------------------------ 187 /** Returns this kart's kart model. */ getKartModel() const188 KartModel* getKartModel() const { return m_kart_model.get(); } 189 // ------------------------------------------------------------------------ 190 /** Returns the length of the kart. */ getKartLength() const191 float getKartLength() const { return m_kart_length; } 192 // ------------------------------------------------------------------------ 193 /** Returns the height of the kart. */ getKartHeight() const194 float getKartHeight() const { return m_kart_height; } 195 // ------------------------------------------------------------------------ 196 /** Returns the width of the kart. */ getKartWidth() const197 float getKartWidth() const {return m_kart_width; } 198 // ------------------------------------------------------------------------ 199 /** Returns the highest point of the kart (coordinate on up axis) */ getHighestPoint() const200 float getHighestPoint() const { return m_kart_highest_point; } 201 // ------------------------------------------------------------------------ 202 /** Called after the kart comes to rest. It can be used to e.g. compute 203 * differences between graphical and physical chassis. Note that 204 * overwriting this function is possible, but this implementation must 205 * be called. */ 206 virtual void kartIsInRestNow(); 207 208 // ------------------------------------------------------------------------ 209 /** Returns the time at which the kart was at a given distance. 210 * Returns -1.0f if none */ 211 virtual float getTimeForDistance(float distance); 212 // ------------------------------------------------------------------------ 213 /** Returns true if this kart has no wheels. */ 214 bool isWheeless() const; 215 // ------------------------------------------------------------------------ 216 /** Returns the coordinates of the front of the kart. This is used for 217 * determining when the lap line is crossed. */ 218 virtual const Vec3& getFrontXYZ() const = 0; 219 // ------------------------------------------------------------------------ 220 /** Returns the position of a wheel relative to the kart. 221 * \param i Index of the wheel: 0=front right, 1 = front left, 2 = rear 222 * right, 3 = rear left. */ getWheelGraphicsPosition(int i) const223 const Vec3& getWheelGraphicsPosition(int i) const 224 {assert(i>=0 && i<4); return m_wheel_graphics_position[i];} 225 226 // ======================================================================== 227 // Emergency animation related functions. 228 // ------------------------------------------------------------------------ 229 /** Returns a kart animation (if any), or NULL if currently no kart 230 * animation is being shown. */ getKartAnimation()231 AbstractKartAnimation *getKartAnimation() { return m_kart_animation; } 232 // ------------------------------------------------------------------------ getKartAnimation() const233 const AbstractKartAnimation *getKartAnimation() const 234 { return m_kart_animation; } 235 // ------------------------------------------------------------------------ 236 /** Sets a new kart animation. */ 237 virtual void setKartAnimation(AbstractKartAnimation *ka); 238 // ------------------------------------------------------------------------ 239 240 // ------------------------------------------------------------------------ 241 // ------------------------------------------------------------------------ 242 /** Returns the index of this kart in world. */ getWorldKartId() const243 unsigned int getWorldKartId() const { return m_world_kart_id; } 244 // ------------------------------------------------------------------------ 245 /** Saves the old controller in m_saved_controller and stores a new 246 * controller. The save controller is needed in case of a reset. 247 * \param controller The new controller to use (atm it's always an 248 * end controller). */ 249 virtual void setController(Controller *controller) = 0; 250 // ------------------------------------------------------------------------ 251 /** Returns the controller of this kart. */ 252 virtual Controller* getController() = 0; 253 // ------------------------------------------------------------------------ 254 /** Returns the controller of this kart (const version). */ 255 virtual const Controller* getController() const = 0; 256 // ------------------------------------------------------------------------ 257 /** Returns the skidding object for this kart (which can be used to query 258 * skidding related values). */ 259 virtual const Skidding *getSkidding() const = 0; 260 // ------------------------------------------------------------------------ 261 virtual RaceManager::KartType getType() const = 0; 262 // ------------------------------------------------------------------------ 263 /** Returns the skidding object for this kart (which can be used to query 264 * skidding related values), non-const. */ 265 virtual Skidding *getSkidding() = 0; 266 // ------------------------------------------------------------------------ 267 /** Returns true if the kart is eliminated. */ 268 virtual bool isEliminated() const = 0; 269 // ------------------------------------------------------------------------ 270 /** Marks this kart to be eliminated. */ 271 virtual void eliminate() = 0; 272 // ------------------------------------------------------------------------ 273 virtual void finishedRace(float time, bool from_server=false) = 0; 274 // ------------------------------------------------------------------------ 275 /** Returns the finished time for a kart. */ 276 virtual float getFinishTime() const = 0; 277 // ------------------------------------------------------------------------ 278 /** Returns true if the kart has a plunger attached to its face. */ 279 virtual int getBlockedByPlungerTicks() const = 0; 280 // ------------------------------------------------------------------------ 281 /** Sets that the view is blocked by a plunger. The duration depends on 282 * the difficulty, see KartPorperties getPlungerInFaceTime. */ 283 virtual void blockViewWithPlunger() = 0; 284 // ------------------------------------------------------------------------ 285 /** Returns if the kart is currently being squashed. */ 286 virtual bool isSquashed() const = 0; 287 // ------------------------------------------------------------------------ 288 /** Squashes this kart: it will scale the kart in up direction, and causes 289 * a slowdown while this kart is squashed. 290 * Returns true if the squash is successful, false otherwise. 291 * \param time How long the kart will be squashed. 292 * \param slowdown Reduction of max speed. */ 293 virtual bool setSquash(float time, float slowdown) = 0; 294 // ------------------------------------------------------------------------ 295 /** Makes the kart unsquashed again. */ 296 virtual void unsetSquash() = 0; 297 // ------------------------------------------------------------------------ 298 /** Returns the speed of the kart in meters/second. This is not declared 299 * pure abstract, since this function is not needed for certain classes, 300 * like Ghost. */ 301 virtual float getSpeed() const = 0; 302 // ------------------------------------------------------------------------ 303 /** Returns the current maximum speed for this kart, this includes all 304 * bonus and maluses that are currently applied. */ 305 virtual float getCurrentMaxSpeed() const = 0; 306 // ------------------------------------------------------------------------ 307 /** Returns how much increased speed time is left over in the given 308 * category. 309 * \param category Which category to report on. */ 310 virtual int getSpeedIncreaseTicksLeft(unsigned int category) const = 0; 311 312 // ------------------------------------------------------------------------ 313 /** Sets the kart AI boost state. 314 * Not pure abstract, since there is no need to implement this e.g. in Ghost. 315 * \param boosted True if a boost should be applied. */ 316 virtual void setBoostAI(bool boosted) = 0; 317 318 // ------------------------------------------------------------------------ 319 /** Returns the kart AI boost state. 320 * Not pure abstract, since there is no need to implement this e.g. in Ghost. */ 321 virtual bool getBoostAI() const = 0; 322 323 // ------------------------------------------------------------------------ 324 325 /** Sets an increased maximum speed for a category. 326 * \param category The category for which to set the higher maximum speed. 327 * \param add_speed How much speed (in m/s) is added to the maximum speed. 328 * \param engine_force Additional engine force to affect the kart. 329 * \param duration How long the speed increase will last. 330 * \param fade_out_time How long the maximum speed will fade out linearly. 331 */ 332 virtual void increaseMaxSpeed(unsigned int category, float add_speed, 333 float engine_force, int duration, 334 int fade_out_time) = 0; 335 336 // ---------------------------------------------------------------------------- 337 /** This adjusts the top speed using increaseMaxSpeed, but additionally 338 * causes an instant speed boost, which can be smaller than add-max-speed. 339 * (e.g. a zipper can give an instant boost of 5 m/s, but over time would 340 * allow the speed to go up by 10 m/s). 341 * \param category The category for which the speed is increased. 342 * \param add_max_speed Increase of the maximum allowed speed. 343 * \param speed_boost An instant speed increase for this kart. 344 * \param engine_force Additional engine force. 345 * \param duration Duration of the increased speed. 346 * \param fade_out_time How long the maximum speed will fade out linearly. 347 */ 348 virtual void instantSpeedIncrease(unsigned int category, float add_max_speed, 349 float speed_boost, float engine_force, 350 int duration, int fade_out_time) = 0; 351 352 // ------------------------------------------------------------------------ 353 /** Defines a slowdown, which is in fraction of top speed. 354 * \param category The category for which the speed is increased. 355 * \param max_speed_fraction Fraction of top speed to allow only. 356 * \param fade_in_time How long till maximum speed is capped. */ 357 virtual void setSlowdown(unsigned int category, float max_speed_fraction, 358 int fade_in_time) = 0; 359 // ------------------------------------------------------------------------ 360 /** Returns the remaining collected energy. */ 361 virtual float getEnergy() const = 0; 362 // ------------------------------------------------------------------------ 363 /** Called when an item is collected. It will either adjust the collected 364 * energy, or update the attachment or powerup for this kart. 365 * \param item The item that was hit. */ 366 virtual void collectedItem(ItemState *item_state) = 0; 367 // ------------------------------------------------------------------------ 368 /** Returns the current position of this kart in the race. */ 369 virtual int getPosition() const = 0; 370 // ------------------------------------------------------------------------ 371 /** Returns the current position of this kart in the race. */ 372 virtual void setPosition(int p) = 0; 373 // ------------------------------------------------------------------------ 374 /** Returns the initial position of this kart. */ 375 virtual int getInitialPosition() const = 0; 376 // ------------------------------------------------------------------------ 377 /** True if the wheels are touching the ground. */ 378 virtual bool isOnGround() const = 0; 379 // ------------------------------------------------------------------------ 380 /** Returns the slipstream object of this kart. */ 381 virtual const SlipStream* getSlipstream() const = 0; 382 // ------------------------------------------------------------------------ 383 /** Returns the slipstream object of this kart. */ 384 virtual SlipStream* getSlipstream() = 0; 385 // ------------------------------------------------------------------------ 386 /** Activates a slipstream effect, atm that is display some nitro. */ 387 virtual void setSlipstreamEffect(float f) = 0; 388 // ------------------------------------------------------------------------ 389 /** Plays a beep sfx. */ 390 virtual void beep() = 0; 391 // ------------------------------------------------------------------------ 392 /** This function will play a particular character voice for this kart. 393 * It returns whether or not a character voice sample exists for the 394 * particular event. If there is no voice sample, a default can be 395 * played instead. */ 396 virtual bool playCustomSFX(unsigned int type) = 0; 397 // ------------------------------------------------------------------------ 398 /** Show fire to go with a zipper. */ 399 virtual void showZipperFire() = 0; 400 // ------------------------------------------------------------------------ 401 /** Sets zipper time, and apply one time additional speed boost. It can be 402 * used with a specific material, in which case the zipper parmaters are 403 * taken from this material (parameters that are <0 will be using the 404 * kart-specific values from kart-properties. */ 405 virtual void handleZipper(const Material *m=NULL, 406 bool play_sound=false) = 0; 407 // ------------------------------------------------------------------------ 408 /** Returns true if this kart has finished the race. */ 409 virtual bool hasFinishedRace() const = 0; 410 // ------------------------------------------------------------------------ 411 virtual void setEnergy(float val) = 0; 412 // ------------------------------------------------------------------------ 413 /** Return whether nitro is being used despite the nitro button not being 414 * pressed due to minimal use time requirements 415 */ 416 virtual bool isOnMinNitroTime() const = 0; 417 // ------------------------------------------------------------------------ 418 /** Returns the current material the kart is on. */ 419 virtual const Material *getMaterial() const = 0; 420 // ------------------------------------------------------------------------ 421 /** Returns the previous material the kart was one (which might be 422 * the same as getMaterial() ). */ 423 virtual const Material *getLastMaterial() const = 0; 424 // ------------------------------------------------------------------------ 425 /** Returns the current powerup. */ 426 virtual const Powerup *getPowerup() const = 0; 427 // ------------------------------------------------------------------------ 428 /** Returns the current powerup. */ 429 virtual Powerup *getPowerup() = 0; 430 // ------------------------------------------------------------------------ 431 /** Returns the last used powerup type. */ 432 virtual PowerupManager::PowerupType getLastUsedPowerup() = 0; 433 // ------------------------------------------------------------------------ 434 /** Returns the number of powerups. */ 435 virtual int getNumPowerup() const = 0; 436 // ------------------------------------------------------------------------ 437 /** Returns a points to this kart's graphical effects. */ 438 virtual KartGFX* getKartGFX() = 0; 439 // ------------------------------------------------------------------------ 440 virtual void setPowerup (PowerupManager::PowerupType t, int n) = 0; 441 // ------------------------------------------------------------------------ 442 /** Returns the bullet vehicle which represents this kart. */ 443 virtual btKart* getVehicle() const = 0; 444 // ------------------------------------------------------------------------ 445 virtual btQuaternion getVisualRotation() const = 0; 446 // ------------------------------------------------------------------------ 447 /** Returns true if the kart is 'resting', i.e. (nearly) not moving. */ 448 virtual bool isInRest() const = 0; 449 // ------------------------------------------------------------------------ 450 /** Starts the engine sound effect. Called once the track intro phase is 451 * over. */ 452 virtual void startEngineSFX() = 0; 453 // ------------------------------------------------------------------------ 454 /** Multiplies the velocity of the kart by a factor f (both linear 455 * and angular). This is used by anvils, which suddenly slow down the kart 456 * when they are attached. */ 457 virtual void adjustSpeed(float f) = 0; 458 // ------------------------------------------------------------------------ 459 /** This is used on the client side only to set the speed of the kart 460 * from the server information. */ 461 virtual void setSpeed(float s) = 0; 462 // ------------------------------------------------------------------------ 463 /** Returns if the kart is invulnerable. */ 464 virtual bool isInvulnerable() const = 0; 465 // ------------------------------------------------------------------------ 466 virtual void setInvulnerableTicks(int ticks) = 0; 467 // ------------------------------------------------------------------------ 468 /** Returns if the kart is protected by a shield. */ 469 virtual bool isShielded() const = 0; 470 // ------------------------------------------------------------------------ 471 virtual void setShieldTime(float t) = 0; 472 // ------------------------------------------------------------------------ 473 virtual float getShieldTime() const = 0; 474 // ------------------------------------------------------------------------ 475 /** Decreases the kart's shield time. */ 476 virtual void decreaseShieldTime() = 0; 477 // ------------------------------------------------------------------------ 478 479 /** Shows the star effect for a certain time. */ 480 virtual void showStarEffect(float t) = 0; 481 // ------------------------------------------------------------------------ 482 /** Returns the terrain info oject. */ 483 virtual const TerrainInfo *getTerrainInfo() const = 0; 484 // ------------------------------------------------------------------------ 485 /** Called when the kart crashes against another kart. 486 * \param k The kart that was hit. 487 * \param update_attachments If true the attachment of this kart and the 488 * other kart hit will be updated (e.g. bombs will be moved). */ 489 virtual void crashed(AbstractKart *k, bool update_attachments) = 0; 490 // ------------------------------------------------------------------------ 491 virtual void crashed(const Material *m, const Vec3 &normal) = 0; 492 // ------------------------------------------------------------------------ 493 /** Returns the normal of the terrain the kart is over atm. This is 494 * defined even if the kart is flying. */ 495 virtual const Vec3& getNormal() const = 0; 496 // ------------------------------------------------------------------------ 497 /** Returns the position 0.25s before */ 498 virtual const Vec3& getPreviousXYZ() const = 0; 499 // ------------------------------------------------------------------------ 500 /** Returns the most recent different previous position */ 501 virtual const Vec3& getRecentPreviousXYZ() const = 0; 502 // ------------------------------------------------------------------------ 503 /** Returns the time at which the recent previous position occured */ 504 virtual const float getRecentPreviousXYZTime() const = 0; 505 // ------------------------------------------------------------------------ 506 /** Returns the height of the terrain. we're currently above */ 507 virtual float getHoT() const = 0; 508 // ------------------------------------------------------------------------ 509 /** Returns the pitch of the terrain depending on the heading. */ 510 virtual float getTerrainPitch(float heading) const = 0; 511 // ------------------------------------------------------------------------- 512 /** Returns a bullet transform object located at the kart's position 513 and oriented in the direction the kart is going. Can be useful 514 e.g. to calculate the starting point and direction of projectiles. */ 515 virtual btTransform getAlignedTransform(const float customPitch=-1) = 0; 516 // ------------------------------------------------------------------------- 517 /** Set a text that is displayed on top of a kart. 518 */ 519 virtual void setOnScreenText(const core::stringw& text) = 0; 520 // ------------------------------------------------------------------------ 521 /** Returns whether this kart wins or loses. */ 522 virtual bool getRaceResult() const = 0; 523 // ------------------------------------------------------------------------ 524 /** Returns whether this kart is a ghost (replay) kart. */ 525 virtual bool isGhostKart() const = 0; 526 // ------------------------------------------------------------------------ 527 /** Returns whether this kart is jumping. */ 528 virtual bool isJumping() const = 0; 529 // ------------------------------------------------------------------------ 530 virtual void playSound(SFXBuffer* buffer) = 0; 531 // ------------------------------------------------------------------------ 532 virtual bool isVisible() const = 0; 533 // ------------------------------------------------------------------------ 534 virtual void makeKartRest(); 535 // ------------------------------------------------------------------------ 536 virtual void setStartupBoost(float val) = 0; 537 // ------------------------------------------------------------------------ 538 virtual float getStartupBoost() const = 0; 539 // ------------------------------------------------------------------------ 540 virtual float getStartupBoostFromStartTicks(int ticks) const = 0; 541 // ------------------------------------------------------------------------ 542 virtual Stars* getStarsEffect() const = 0; 543 // ------------------------------------------------------------------------ getLiveJoinUntilTicks() const544 int getLiveJoinUntilTicks() const { return m_live_join_util; } 545 // ------------------------------------------------------------------------ setLiveJoinKart(int util_ticks)546 void setLiveJoinKart(int util_ticks) { m_live_join_util = util_ticks; } 547 // ------------------------------------------------------------------------ 548 /** Return the confirmed finish ticks (sent by the server) 549 * indicating that this kart has really finished the race. */ 550 virtual int getNetworkConfirmedFinishTicks() const = 0; 551 }; // AbstractKart 552 553 554 #endif 555 556 /* EOF */ 557