Script:Files:script/vehicles/strogg drop.script

From Mod Wiki
#define STROGG_DROP_ACCELERATION            -1066
#define STROGG_DROP_SPEED_INITIAL            -200
#define STROGG_DROP_SOUND_TIME                4

object strogg_drop {
    void            preinit();
    void            init();
    void            destroy();
    void            syncFields();

    void            Idle();

    void            OnItemChanged();
    void            OnTargetPosChanged();
    void            OnSetDeploymentParms( float deploymentItemIndex, float playerIndex, vector target, float rotation );
    void            vSetDeploymentParms( float deploymentItemIndex, float playerIndex, vector target, float rotation ) {
        OnSetDeploymentParms( deploymentItemIndex, playerIndex, target, rotation );
    }

    boolean            ContinueDrop();

    void            ClearRequest();

    void            SetupItem();
    void            SetupTrajectory();

    entity            item;
    vector            itemTargetPos;
    float            itemRotation;

    float            deployPlayerIndex;
    float            launchTime;

    vector            startPos;

    boolean            alwaysDrop;
    boolean            cancelled;

    entity            vGetItem() {
        return item;
    }    
}

void strogg_drop::preinit() {
    deployPlayerIndex = -1;
    launchTime = -1;
    cancelled = false;
}

void strogg_drop::init() {
    setState( "Idle" );
}

void strogg_drop::destroy() {
    ClearRequest();
}

void strogg_drop::syncFields() {
    syncBroadcast( "item" );
    syncBroadcast( "itemTargetPos" );
    syncBroadcast( "itemRotation" );
    syncBroadcast( "launchTime" );
    syncCallback( "item", "OnItemChanged" );
    syncCallback( "itemTargetPos", "OnTargetPosChanged" );
}


#define STROGG_DROP_PARABOLE_TIME 5

void strogg_drop::Idle() {
    float height;
    float flightTime;
    float endTime;
    float soundTime;
    vector currentPos;

    // FeaRog: wait for the server to synchronise the launch info through to avoid weirdness
    while( launchTime < 0 ) {
        sys.waitFrame();
    }

    playEffect( "fx_trail", "", 1 );

    //
    // Part 1 parabolic reentry
    //
    flightTime = sys.getTime() - launchTime;
    while ( flightTime < STROGG_DROP_PARABOLE_TIME ) {
        sys.waitFrame();
        flightTime = sys.getTime() - launchTime;

        if ( STROGG_DROP_PARABOLE_TIME < flightTime ) {
            break;
        }

        currentPos_x    = startPos_x;
        currentPos_y    = startPos_y + (STROGG_DROP_PARABOLE_TIME - flightTime) * 1000;
        currentPos_z    = startPos_z + sys.sqrt( (STROGG_DROP_PARABOLE_TIME - flightTime) * 1000 ) * 100;
        setOrigin( currentPos );
        item.setOrigin( currentPos );
    }
    playEffect( "fx_booster", "", false );
    startSound( "snd_landfall", SND_VEHICLE_IDLE );
    startSound( "snd_landfall_far", SND_VEHICLE );

    soundTime = sys.getTime();

    // Solve the quadratic equation for 0 (assuming height 0 is good enough an estimate for the ground height)
    {
        float roots = sys.solveRoots( STROGG_DROP_ACCELERATION / 2.0, STROGG_DROP_SPEED_INITIAL, startPos_z );
        float time_zero;
        if ( roots > 0 ) {
            time_zero = sys.getRoot( 0 );
        }

        soundTime += time_zero - STROGG_DROP_SOUND_TIME;
    }

    //
    // Part 2 just a linear fall
    //
    while ( true ) {
        sys.waitFrame();

        if( !ContinueDrop() ) {
            // player switched teams before we've deployed
            stopEffect( "fx_trail" );
            stopEffect( "fx_booster" );

            if ( !sys.isClient() ) {
                player p = sys.getClient( deployPlayerIndex );
                objManager.PlaySoundForPlayer( getKey( "snd_cancel_deploy" ), p );
            }

            ClearRequest();

            if( !sys.isClient() ) {
                item.remove();
                remove();
            }

            return;
        }

        flightTime = sys.getTime() - launchTime - STROGG_DROP_PARABOLE_TIME;

        height = startPos_z + ( ( STROGG_DROP_SPEED_INITIAL + ( STROGG_DROP_ACCELERATION * ( flightTime ) / 2 ) ) * flightTime );

        if ( height < itemTargetPos_z ) {
            setOrigin( itemTargetPos );
            item.setOrigin( itemTargetPos );

            break;
        }

        if ( sys.getTime() > soundTime ) {
//			sys.print( "playsound: current(" + sys.getTime() + ")\n" );
            soundTime += 10000;/// so it only plays it once
        }

        currentPos        = startPos;
        currentPos_z    = height;

        setOrigin( currentPos );
        item.setOrigin( currentPos );
    }

    stopEffect( "fx_trail" );
    stopEffect( "fx_booster" );
    playEffect( "fx_hitground", "", false );
    startSound( "snd_impact", SND_VEHICLE_IDLE );

    ClearRequest();

    if ( item != $null_entity ) {
        sys.waitFrame();
        item.setOrigin( getWorldOrigin() );
        item.setAngles( getAngles() );
        item.vOnDeploy();
    }

    sys.wait( 5.f );

    if ( !sys.isClient() ) {
        remove();
    }
}

void strogg_drop::OnItemChanged() {
    SetupItem();
}

void strogg_drop::OnTargetPosChanged() {
    SetupTrajectory();
}

void strogg_drop::ClearRequest() {
    if ( sys.isClient() ) {
        return;
    }

    if ( deployPlayerIndex != -1 ) {
        sys.clearDeployRequest( deployPlayerIndex );
        deployPlayerIndex = -1;
    }
}

void strogg_drop::OnSetDeploymentParms( float deploymentItemIndex, float playerIndex, vector target, float rotation ) {
    deployPlayerIndex    = playerIndex;
    itemTargetPos        = target;
    itemRotation        = rotation;

    player p = sys.getClient( playerIndex );
    item = sys.spawnType( deploymentItemIndex );
    item.vSetDeployableOwner( p );

    deployable_base deployable = item;
    if ( deployable != $null_entity ) {
        p.SetTargetingItem( item );
    }

    string statName = item.getKey( "stat_name" );
    if ( statName != "" ) {
        sys.increaseStatInt( sys.allocStatInt( statName + "_deployed" ), deployPlayerIndex, 1 );
    }

    launchTime            = sys.getTime();

    SetupTrajectory();

    vector currentPos;
    currentPos_x    = startPos_x;
    currentPos_y    = startPos_y + STROGG_DROP_PARABOLE_TIME * 1000;
    currentPos_z    = startPos_z + sys.sqrt( STROGG_DROP_PARABOLE_TIME * 1000 ) * 100;
    setOrigin( currentPos );
    item.setOrigin( currentPos );

    SetupItem();
}

void strogg_drop::SetupItem() {
    if ( item == $null_entity ) {
        return;
    }

    alwaysDrop = item.getIntKey( "always_drop" );
    item.setOrigin( getWorldOrigin() );
    item.setAngles( getAngles() );
    item.setGameTeam( getGameTeam() );
    item.vSetManualDeploy();
}

void strogg_drop::SetupTrajectory() {
    vector worldMaxs    = sys.getWorldMaxs();

    startPos            = itemTargetPos;
    startPos_z            = worldMaxs_z;

    vector angles;
    angles_y            = itemRotation;

    setAngles( angles );
}

boolean strogg_drop::ContinueDrop() {
    // special cases
    if ( deployPlayerIndex == -1 || alwaysDrop ) {
        return true;
    }

    player p = sys.getClient( deployPlayerIndex );
    if( getEntityAllegiance( p ) != TA_FRIEND ) {
        return false;
    }

    if( sys.getTerritoryForPoint( itemTargetPos, getGameTeam(), 1.f, 0.f ) == $null_entity ) {
        return false;
    }

    return !cancelled;
}

void strogg_drop::vCancelDeployForPlayer( float playerIndex ) {
    if ( deployPlayerIndex == playerIndex ) {
        cancelled = true;
    }
}