//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include TargetLife::TargetLife(ScorchedContext &context, unsigned int playerId) : context_(context), sphereGeom_(true), targetInfo_(CollisionIdTarget), life_(100.0f), maxLife_(1.0f), size_(2.0f, 2.0f, 2.0f), rotation_(0.0f), driveOverToDestroy_(false), targetGeom_(0) { targetInfo_.data = (void *) playerId; } TargetLife::~TargetLife() { if (targetGeom_) context_.actionController->getPhysics().destroyGeom(targetGeom_); targetGeom_ = 0; } void TargetLife::newGame() { setLife(maxLife_); } void TargetLife::setLife(float life) { life_ = life; if (life_ >= maxLife_) life_ = maxLife_; if (life_ <= 0) { life_ = 0; rotation_ = 0.0f; dGeomDisable(targetGeom_); } else { setSize(size_); dGeomEnable(targetGeom_); } } void TargetLife::setSize(Vector &size) { size_ = size; if (sphereGeom_) { double radius = MAX(size_[0], size_[1]) / 2.0f; dGeomSphereSetRadius(targetGeom_, radius); } else { dGeomBoxSetLengths(targetGeom_, size_[0], size_[1], size_[2]); } setPosition(target_->getTargetPosition()); } Vector TargetLife::getGeomRelativePosition(Vector &position) { dVector3 p; p[0] = position[0]; p[1] = position[1]; p[2] = position[2]; p[3] = 0; dVector3 result; const dReal *R = dGeomGetRotation(targetGeom_); dMULTIPLY1_331(result,R, p); Vector vResult((float)result[0], (float)result[1], (float)result[2]); return vResult; } void TargetLife::setRotation(float rotation) { rotation_ = rotation; dQuaternion q; dQFromAxisAndAngle(q, 0.0, 0.0, 1.0, double(rotation_) / 180.0 * 3.14); dGeomSetQuaternion(targetGeom_, q); } void TargetLife::setPosition(Vector &pos) { // Set the position so the geom sits on the top of the ground dGeomSetPosition(targetGeom_, pos[0], pos[1], pos[2] + size_[2] / 2.0f); } void TargetLife::setBoundingSphere(bool sphereGeom) { if (targetGeom_) context_.actionController->getPhysics().destroyGeom(targetGeom_); targetGeom_ = 0; sphereGeom_ = sphereGeom; dSpaceID spaceId = context_.actionController->getPhysics().getTargetSpace(); if (target_->getPlayerId() >= TankAIAdder::MIN_TANK_ID && target_->getPlayerId() <= TankAIAdder::MAX_TANK_ID) { spaceId = context_.actionController->getPhysics().getTankSpace(); } // The tank collision object if (sphereGeom_) { double radius = MAX(size_[0], size_[1]) / 2.0f; targetGeom_ = dCreateSphere(spaceId, radius); } else { targetGeom_ = dCreateBox(spaceId, size_[0], size_[1], size_[2]); } dGeomSetData(targetGeom_, &targetInfo_); dGeomDisable(targetGeom_); } bool TargetLife::writeMessage(NetBuffer &buffer) { buffer.addToBuffer(maxLife_); buffer.addToBuffer(life_); buffer.addToBuffer(size_); buffer.addToBuffer(rotation_); return true; } bool TargetLife::readMessage(NetBufferReader &reader) { float l; if (!reader.getFromBuffer(maxLife_)) return false; if (!reader.getFromBuffer(l)) return false; setLife(l); if (!reader.getFromBuffer(size_)) return false; if (!reader.getFromBuffer(rotation_)) return false; return true; }