/* * orxonox - the future of 3D-vertical-scrollers * * Copyright (C) 2004 orx * * This program 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, or (at your option) * any later version. * * ### File Specific: * main-programmer: Reto Luechinger */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY #include "adm_turret.h" #include "weapons/weapon_manager.h" #include "weapons/weapon.h" #include "lib/util/loading/factory.h" #include "world_entities/projectiles/projectile.h" #include "loading/load_param.h" #include "debug.h" #include "loading/load_param_xml.h" ObjectListDefinition(AdmTurret); CREATE_FACTORY(AdmTurret); /** * Standard constructor */ AdmTurret::AdmTurret () { this->init(); } /** * destructs the turret, deletes allocated memory */ AdmTurret::~AdmTurret () { // will be deleted } /** * Constructor with XML Element */ AdmTurret::AdmTurret (const TiXmlElement* root) { this->init(); if (root != NULL) { this->loadParams(root); } } /** * XML Loader */ void AdmTurret::loadParams(const TiXmlElement* root) { if (root != NULL) { WorldEntity::loadParams(root); LoadParam(root, "target", this, AdmTurret, setTarget) .describe("The filename of the World Entity, that is to be shot at") .defaultValues(""); LoadParamXML(root, "Cannons", this, AdmTurret, addCannons) .describe("add cannons to ADM"); LoadParamXML(root, "Sensor", this, AdmTurret, addSensor) .describe("add sensor to ADM"); } //HACK this is really ugly because if you move the AdmTurret its cannons wont follow if ( this->cannons ) this->cannons->setParent( NullParent::getNullParent() ); } /** * Sets Target onto the World Entity with filename "target", given as String */ void AdmTurret::setTarget(const std::string& target) { WorldEntity* targetEntity = WorldEntity::objectList().getObject(target); if (targetEntity != NULL) { this->myTarget = targetEntity; } else { PRINTF(1)("ERROR ADMTURRET : Target %s does not exist\n", target.c_str()); } } void AdmTurret::init() { this->registerObject(this, AdmTurret::_objectList); //this->removeNodeFlags( 7 ); } void AdmTurret::tick(float dt) { WorldEntity::tick(dt); //rotate sensor 2PI/sec this->sensor->setAbsDir( this->sensor->getAbsDir() * Quaternion( PI*2*dt, Vector( 0, 1, 0 ) ) ); Vector playerPos = this->myTarget->getAbsCoor(); this->moveTowards( playerPos - ( this->cannons->getAbsCoor() ), dt); } void AdmTurret::draw() const { WorldEntity::draw(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glLineWidth(2.0); Vector mp = this->cannons->getAbsCoor(); Vector op = this->cannons->getAbsDir().apply( Vector(-1, 0, 0) ); op *= 100; op += mp; glColor3f(1.0, 0.0, 0.0 ); glBegin(GL_LINE_STRIP); glVertex3f(mp.x, mp.y, mp.z); glVertex3f(op.x, op.y, op.z); glEnd(); op = this->myTarget->getAbsCoor() - ( this->cannons->getAbsCoor() ); op += mp; glColor3f(0.0, 1.0, 0.0 ); glBegin(GL_LINE_STRIP); glVertex3f(mp.x, mp.y, mp.z); glVertex3f(op.x, op.y, op.z); glEnd(); glPopAttrib(); glPopMatrix(); } void AdmTurret::collidesWith(WorldEntity* entity, const Vector& location) { } void AdmTurret::activate() { } void AdmTurret::deactivate() { } bool AdmTurret::isVisible(const WorldEntity myTarget) { return true; } float AdmTurret::aim(const WorldEntity Target) { return 0; } void AdmTurret::fire() { // Projectile* pj = this->getProjectile(); // if (pj == NULL) return; //pj->setOwner(this->getOwner()); //pj->setParent(PNode::getNullParent()); //pj->setVelocity(this->getAbsDir().apply(Vector( , , )) ); //pj->setAbsCoor(this->getEmissionPoint()); //pj->setAbsDir(this->getAbsDir()); //pj->activate(); } void AdmTurret::addCannons( const TiXmlElement * root ) { this->cannons = new WorldEntity(); this->cannons->setParent(this); this->cannons->loadParams( root ); //this->cannons->addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT); //this->cannons->addNodeFlags(PNODE_PROHIBIT_CHILD_DELETE); this->cannons->toList( getOMListNumber() ); } void AdmTurret::addSensor( const TiXmlElement * root ) { this->sensor = new WorldEntity(); this->sensor->setParent(this); this->sensor->loadParams( root ); //this->sensor->addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT); //this->sensor->addNodeFlags(PNODE_PROHIBIT_CHILD_DELETE); this->sensor->toList( getOMListNumber() ); } void AdmTurret::moveTowards( Vector targetDir, float dt ) { #if 0 static Quaternion mrot = this->getAbsDir(); Quaternion ry( dt, Vector(0, 1, 0) ); mrot *= ry; this->setAbsDir(mrot); static Quaternion rot = this->cannons->getAbsDir(); Quaternion rx( dt, Vector( 0, 0, 1 ) ); rot *= rx; this->cannons->setAbsDir(rot*mrot); return; #endif Quaternion cur = this->getAbsDir(); Quaternion ry( dt, cur.inverse().apply( Vector( 0, 1, 0 ) ) ); Quaternion tmp1 = cur * ry; Quaternion tmp2 = cur * ry.inverse(); bool usetmp1 = false; Quaternion r1; if ( tmp1.apply( Vector(1, 0, 0) ).dot(targetDir) < tmp2.apply( Vector(1, 0, 0)).dot(targetDir) ) { usetmp1 = true; cur = tmp1; r1 = ry; } else { cur = tmp2; r1 = ry.inverse(); } this->setAbsDir( cur ); Quaternion cur2 = this->cannons->getAbsDir(); Quaternion rx( dt, cur.inverse().apply( Vector( 0, 0, 1 ) ) ); Quaternion rr( dt, cur2.inverse().apply( Vector( 0, 1, 0 ) ) ); if ( !usetmp1 ) rr = rr.inverse(); tmp1 = cur2 * rx; tmp2 = cur2 * rx.inverse(); Quaternion dec; Quaternion r2; if ( tmp1.apply( Vector(-1, 0, 0) ).dot(targetDir) > tmp2.apply( Vector(-1, 0, 0) ).dot(targetDir) ) { r2 = rx; dec = tmp1; } else { r2 = rx.inverse(); dec = tmp2; } float dp = dec.apply( Vector(-1, 0, 0) ).dot(Vector(0, 1, 0)); if ( dp > -0.9 && dp < 0.9 ) { cur2 = dec; } this->cannons->setAbsDir( cur2 ); }