/*
 * server/SectorSpecial.cc:
 *
 * Copyright (C) 2000 John Watson, jwatson@tempusmud.com
 * 
 * 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
 * of the License, or (at your option) any later version.
 * 
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 */

#include "SectorSpecial.h"
#include "../util/Persist.h"
#include "Sound.h"
#include "Sector.h"

#include <iostream>

SectorSpecial::SectorSpecial( istream & is ) {
        
        sound = new Sound();
        sound->die = true;

        sect = 0;
        
        cur_travel = 0;
        iterations = 0;
        wait_tick  = 0;
        
        flags  = Persist::readShort( is );
        travel = Persist::readShort( is );
        damage = Persist::readShort( is );
        sound_type  = Persist::readShort( is );

        speed      = is.get();
        delay      = is.get();
        tag        = is.get();
        iterations = is.get();

        if ( flags & START_EXTENDED ) {
                flags &= ~IS_EXTENDING;
        }
        else
                flags |= IS_EXTENDING;

}

SectorSpecial::SectorSpecial( const SectorSpecial & other ) {
        sound = new Sound();
        sound->die = true;
        
        sect = 0;
        cur_travel = 0;
        iterations = 0;
        wait_tick  = 0;
        
        flags  = other.flags;
        travel = other.travel;
        damage = other.damage;
        sound_type = other.sound_type;

        speed      = other.speed;
        delay      = other.delay;
        tag        = other.tag;
        iterations = other.iterations;
}    

SectorSpecial::~SectorSpecial() {
        delete sound;
}

void SectorSpecial::writeSectorSpecial( ostream & os ) {
        Persist::writeShort( os, flags );
        Persist::writeShort( os, travel );
        Persist::writeShort( os, damage );
        Persist::writeShort( os, sound_type );

        os.put( speed );
        os.put( delay );
        os.put( tag );
        os.put( iterations );

}

void SectorSpecial::performDelay( unsigned int tick ) {
        
        if ( delay > 0 ) {
                wait_tick = tick + delay * 1000;

                if ( sound_type )
                        sound->init( Sound::SND_LIFT_STOP, 200, 0, false );
        }
}

void SectorSpecial::halt() {
        iterations = 0;
        
        if ( sound_type )
                sound->init( Sound::SND_LIFT_STOP, 200, 0, false );
}

void SectorSpecial::getWorldRange( float * zmin, float * zmax ) const {
        
        if ( sect == 0 )
                return;

        if ( isDoor() ) {
                *zmin = sect->getCeilingHeight();
                *zmax = *zmin + cur_travel;
        }
        else {
                *zmax = sect->getFloorHeight();
                *zmin = *zmax - cur_travel;
        }
}

void SectorSpecial::triggerSpecial( int value ) {

        //
        // start moving indefinitely
        //
        if ( value == -1 ) {
                iterations = value;
        } 

        //
        // stop moving immediately
        //

        else if ( value == 0 ) {
                if ( iterations != 0 )
                        halt();
        }

        //
        // return to initial position as soon as natural
        //

        else if ( value == -2 ) {

                if ( flags & SectorSpecial::START_EXTENDED ) {
                        if ( cur_travel == travel ) {
                                if ( iterations )
                                        halt();
                        }
                        else if ( isExtending() )
                                iterations = 1;
                        else
                                iterations = 2;
                }
                else if ( cur_travel == 0 ) {
                        if ( iterations )
                                halt();
                }
                else if ( isExtending() )
                        iterations = 2;
                else
                        iterations = 1;
        }

        //
        // simply schedule some iterations
        //

        else if ( value > 0 && ( iterations <= 0 || iterations > value ) )
                iterations = value;
        
}
