/* 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: Patrick Boenzli co-programmer: ... */ #include "fps_player.h" #include "interactive_model.h" #include "state.h" #include "src/lib/util/loading/factory.h" #include "md2/md2Model.h" #include "weapons/weapon_manager.h" #include "weapons/test_gun.h" #include "weapons/turret.h" #include "weapons/cannon.h" #include "weapons/fps_sniper_rifle.h" #include "weapons/aiming_system.h" #include "aabb.h" #include "bsp_entity.h" #include "key_mapper.h" #include "debug.h" #include "shared_network_data.h" ObjectListDefinition(FPSPlayer); CREATE_FACTORY(FPSPlayer); #include "script_class.h" CREATE_SCRIPTABLE_CLASS(FPSPlayer, addMethod("setAbsCoor", Executor3(&PNode::setAbsCoor)) ->addMethod("getAbsCoorX", Executor0ret(&PNode::getAbsCoorX)) ->addMethod("getAbsCoorY", Executor0ret(&PNode::getAbsCoorY)) ->addMethod("getAbsCoorZ", Executor0ret(&PNode::getAbsCoorZ)) ); /** * destructs the FPSPlayer, deletes alocated memory */ FPSPlayer::~FPSPlayer () { this->setPlayer(NULL); if( this->aimingSystem) delete this->aimingSystem; } /** * creates a new FPSPlayer from Xml Data * @param root the xml element containing FPSPlayer data * */ FPSPlayer::FPSPlayer(const TiXmlElement* root) { this->init(); if (root != NULL) this->loadParams(root); } /** * initializes a FPSPlayer */ void FPSPlayer::init() { this->registerObject(this, FPSPlayer::_objectList); this->bLeft = false; this->bRight = false; this->bForward = false; this->bBackward = false; this->bJump = false; this->bPosBut = false; this->bFire = false; this->xMouse = 0.0f; this->yMouse = 0.0f; this->setHealthMax(100); this->setHealth(80); this->fallVelocity = 0.0f; this->jumpForce = 0.0f; this->cameraNode.setParent(this); this->attitude = this->getAbsDir().getAttitude(); this->heading = this->getAbsDir().getHeading(); //add events to the eventlist registerEvent(KeyMapper::PEV_FORWARD); registerEvent(KeyMapper::PEV_BACKWARD); registerEvent(KeyMapper::PEV_LEFT); registerEvent(KeyMapper::PEV_RIGHT); registerEvent(KeyMapper::PEV_FIRE1); registerEvent(KeyMapper::PEV_JUMP); registerEvent(EV_MOUSE_MOTION); this->aimingSystem = NULL; // weapon manager for the fps dynamic_cast(this->getWeaponManager().getFixedTarget())->setVisibility( false); if( State::isOnline()) { Weapon* wpRight = new FPSSniperRifle(0); wpRight->setName("testGun Right"); this->addWeapon(wpRight,1, 0); wpRight->addChild(this->aimingSystem); this->toList( OM_PLAYERS ); } this->aimingSystem = new AimingSystem(this); this->getWeaponManager().changeWeaponConfig(1); this->getWeaponManager().setSlotCount(2); this->getWeaponManager().setSlotDirection(0, Quaternion(M_PI_4*-0.55f, Vector(0,0,1))); this->getWeaponManager().setSlotCapability(0, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL); this->getWeaponManager().setSlotDirection(1, Quaternion(M_PI_4*.5, Vector(1,0,0))); this->getWeaponManager().setSlotPosition(0, Vector(1.5, -0.7, 1.1)); this->getWeaponManager().setSlotPosition(1, Vector(5.0, 0.0, 0.0)); this->getWeaponManager().setParentNode(&this->cameraNode); this->cameraNode.addNodeFlags(PNODE_PROHIBIT_CHILD_DELETE); this->getWeaponManager().getFixedTarget()->setParent(&this->cameraNode); this->getWeaponManager().getFixedTarget()->setRelCoor(1000,0,0); // network registration registerVar( new SynchronizeableBool( &bLeft, &bLeft, "bLeft", PERMISSION_OWNER ) ); registerVar( new SynchronizeableBool( &bRight, &bRight, "bRight", PERMISSION_OWNER ) ); registerVar( new SynchronizeableBool( &bForward, &bForward, "bForward", PERMISSION_OWNER ) ); registerVar( new SynchronizeableBool( &bBackward, &bBackward, "bBackward", PERMISSION_OWNER ) ); registerVar( new SynchronizeableBool( &bJump, &bJump, "bJump", PERMISSION_OWNER ) ); registerVar( new SynchronizeableFloat( &heading, &heading, "heading", PERMISSION_OWNER ) ); registerVar( new SynchronizeableFloat( &attitude, &attitude, "attitude", PERMISSION_OWNER ) ); //subscribe to collision reaction this->subscribeReaction(CoRe::CREngine::CR_PHYSICS_FULL_WALK, BspEntity::staticClassID()); this->initWeapon = false; this->damageTicker = 0.0f; } /** * loads the Settings of a FPSPlayer from an XML-element. * @param root the XML-element to load the Spaceship's properties from */ void FPSPlayer::loadParams(const TiXmlElement* root) { Playable::loadParams(root); } void FPSPlayer::setPlayDirection(const Quaternion& quat, float speed) { this->attitude = this->getAbsDir().getAttitude(); this->heading = this->getAbsDir().getHeading(); } void FPSPlayer::reset() { this->bLeft = false; this->bRight = false; this->bForward = false; this->bBackward = false; this->xMouse = 0.0f; this->yMouse = 0.0f; this->setHealth(80); } void FPSPlayer::enter() { dynamic_cast(this->getWeaponManager().getFixedTarget())->setVisibility( true ); State::getCameraNode()->setParentSoft(&this->cameraNode); State::getCameraTargetNode()->setParentSoft(&this->cameraNode); this->getWeaponManager().getFixedTarget()->setParent(State::getCameraTargetNode()); this->getWeaponManager().getFixedTarget()->setRelCoor(0,0,0); if ( !State::isOnline() ) { this->respawn(); } } void FPSPlayer::leave() { dynamic_cast(this->getWeaponManager().getFixedTarget())->setVisibility( false); this->detachCamera(); } /** * the function called for each passing timeSnap * @param time The timespan passed since last update */ void FPSPlayer::tick (float time) { if ( !this->initWeapon ) { this->initWeapon = true; this->cameraNode.setParentMode(PNODE_ROTATE_AND_MOVE); this->getWeaponManager().getParentNode()->setParentMode(PNODE_ROTATE_AND_MOVE); this->getWeaponManager().getFixedTarget()->setParent(&this->cameraNode); this->getWeaponManager().getFixedTarget()->setParentMode(PNODE_ROTATE_AND_MOVE); if( this->aimingSystem != NULL) { this->aimingSystem->toList(OM_GROUP_01); this->aimingSystem->setParent(&this->cameraNode); // this->aimingSystem->setParentMode(PNODE_ROTATE_AND_MOVE); this->aimingSystem->setRelDir(Quaternion(M_PI_4*-0.58f, Vector(0,0,1))); this->aimingSystem->setRelCoor(0, -1, -1); } AABB* box = this->getModelAABB(); if( box != NULL) { float f = 1.0; this->cameraNode.setRelCoor(0, box->halfLength[1] * f, 0); // this->cameraNode.setRelCoor(10, box->halfLength[1] * f, 0); float v = 0.1f; this->getWeaponManager().setSlotPosition(0, Vector(-8.0, box->halfLength[1] * v, 1.1)); this->getWeaponManager().setSlotPosition(1, Vector(5.0, box->halfLength[1] * v, 0.0)); } } this->getWeaponManager().tick(time); if( this->bFire) { this->getWeaponManager().fire(); } //dealing damage if ( State::isOnline() && (SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/)) { this->damageTicker -= time; if ( this->damageTicker <= 0.0f && this->beFire() ) { this->damageTicker = 0.25; WorldEntity * victim = aimingSystem->getNearestTarget(); if ( victim ) { PRINTF(0)("FIRE: hit %s\n", victim->getClassCName()); victim->hit( 20, this ); } else { PRINTF(0)("FIRE: nothing hit\n"); } } } if( ( xMouse != 0 || yMouse != 0 ) && (this->getOwner() == SharedNetworkData::getInstance()->getHostID() || !State::isOnline() ) ) { xMouse *= time ; yMouse *= time ; heading -= xMouse/5.; attitude-= yMouse/5.; if ( attitude > 1.95 ) attitude = 1.95; else if ( attitude < -1.07 ) attitude = -1.07; xMouse = yMouse = 0; } this->setAbsDir(Quaternion(heading, Vector(0,1,0))); this->cameraNode.setRelDir(Quaternion( attitude, Vector( 0, 0, 1 ) )); Vector velocity; if ( this->bForward ) { velocity += this->getAbsDirX(); } if ( this->bBackward ) { velocity -= this->getAbsDirX(); } if ( this->bRight ) { velocity += this->getAbsDirZ(); } if ( this->bLeft ) { velocity -= this->getAbsDirZ(); } velocity *= 100; if( this->bJump) { printf("position:( %f, %f, %f ) \n", this->getAbsCoorX(), this->getAbsCoorY(), this->getAbsCoorZ()); } if( this->getModel( 0) != NULL && this->getModel(0)->isA(InteractiveModel::staticClassID())) { if( this->bJump) { if( this->jumpForce < 1.0f) { this->jumpForce = 300.0f; if( ((InteractiveModel*)this->getModel(0))->getAnimation() != JUMP) ((InteractiveModel*)this->getModel(0))->setAnimation(JUMP); } } else if(velocity.len() != 0.0f) { if( ((InteractiveModel*)this->getModel(0))->getAnimation() != RUN) ((InteractiveModel*)this->getModel(0))->setAnimation(RUN); } else { if( ((InteractiveModel*)this->getModel(0))->getAnimation() != STAND) ((InteractiveModel*)this->getModel(0))->setAnimation(STAND); } } velocity.y += this->jumpForce; if( this->jumpForce > 1.0f) this->jumpForce *= 0.9f; // physical falling of the player if( !this->isOnGround()) { this->fallVelocity += 300.0f * time; velocity -= Vector(0.0, 1.0, 0.0) * this->fallVelocity; // PRINTF(0)("vel %f\n", this->fallVelocity); } else { this->fallVelocity = 0.0f; } this->shiftCoor( velocity*time ); if( likely(this->getModel(0) != NULL) && this->getModel(0)->isA(InteractiveModel::staticClassID())) { ((InteractiveModel*)this->getModel(0))->tick(time); } this->setOnGround(false); if( this->aimingSystem != NULL) this->aimingSystem->flushList(); } /** * draws the MD2Creature after transforming it. */ void FPSPlayer::draw () const { // only draw if this entity is not the player since the player nevers sees himself if( this->getCurrentPlayer() == NULL) WorldEntity::draw(); } /** * process */ void FPSPlayer::process(const Event &event) { Playable::process(event); if( event.type == KeyMapper::PEV_LEFT) this->bLeft = event.bPressed; else if( event.type == KeyMapper::PEV_RIGHT) this->bRight = event.bPressed; else if( event.type == KeyMapper::PEV_FORWARD) this->bForward = event.bPressed; //this->shiftCoor(0,.1,0); else if( event.type == KeyMapper::PEV_BACKWARD) this->bBackward = event.bPressed; //this->shiftCoor(0,-.1,0); else if( event.type == EV_MOUSE_MOTION) { this->xMouse += event.xRel; this->yMouse += event.yRel; } else if( event.type == KeyMapper::PEV_JUMP) { this->bJump = event.bPressed; } else if( event.type == KeyMapper::PEV_FIRE1) { this->bFire = event.bPressed; } } void FPSPlayer::respawn( ) { if( State::isOnline()) toList( OM_PLAYERS ); this->damageTicker = 0.0f; Playable::respawn(); } void FPSPlayer::destroy( WorldEntity* killer ) { Playable::destroy( killer ); toList( OM_DEAD ); }