Script:Files:script/maps/generic/hackable objective.script

From Mod Wiki
Revision as of 10:15, 5 November 2007 by Wizz (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
object hackable_objective {
    void                    preinit();
    void                    syncFields();
    void                    destroy();

    float                    vGetPliersProgressBarValue( float action );
    boolean                    vCheckActionCode( entity p, float actionCode );

    void                    vMakePrimaryObjective( boolean value );

    void                    vCreateMission();
    void                    vFreeMission();
    void                    vCompleteMission();

    void                    OnUpdateGui( entity p );
    float                    OnActivate( entity p, float distance );
    float                    OnUpdateCrosshairInfo( entity p );

    boolean                    HasHackContext( entity other );

    float                    GetActivateCode( entity p, float distance );

    void                    OnHacked( entity p );
    void                    OnHacked_Base( entity p );

    void                    OnIsPrimaryObjectiveChanged();
    void                    OnHackCountChanged();

    void                    SetObjectiveIndicator();
    void                    ClearObjectiveIndicator();
    void                    UpdateObjectiveProgress();
    float                    CalcObjectiveProgress();
    void                    UpdateObjectiveThread();
    void                    SetObjectiveReminderTime( float time );

    void                    KillFizzleThread();
    void                    CreateFizzleThread( float delay );
    void                    OnFizzled();
    void                    FizzleThread( float delay );

    void                    SetObjectiveIndex( float index );

    boolean                    AllowHack() { return true; }

    void                    vHack( entity p );

    string                    vGetObjectiveString() { return "hackObjective"; }

    team_base                baseTeam;

    boolean                    isPrimaryObjective;

    boolean                    vIsPrimaryObjective() { return isPrimaryObjective; }

    void                    vOnContextDefend( entity p );
    void                    vOnContextHack( entity p );

    float                    hackCount;
    float                    maxHackCount;

    float                    objectiveIndex;

    float                    objectiveGUI;

    handle                    progressMessage;
    float                    nextProgressMessageTime;

    float                    infoToolTip;
    float                    useMeToolTip1;
    float                    useMeToolTip2;

    handle                    objectName;

    task                    missionTask;

    float                    fizzleTime;
    float                    fizzleEndTime;
    boolean                    fizzleThreadActive;

    float                    hackProficiency;

    entity                    hacker;
    float                    lastHackTime;
    boolean                    forceMessage;

    float                    nextObjectiveReminderTime;

    flashpoint_obj            flashpoint;
}

void hackable_objective::preinit() {
    setGameTeam( sys.getTeam( getKey( "team" ) ) );

    hackProficiency    = GetProficiency( getKey( "prof_hack" ) );

    baseTeam        = getGameTeam();
    objectiveIndex    = getFloatKeyWithDefault( "objective_index", -1 );

    fizzleTime        = getFloatKeyWithDefault( "fizzle_time", 60.f );

    progressMessage = sys.localizeString( getKeyWithDefault( "progress_message", "maps/generic/obj_hacking" ) ); //"is hacking the objective!" );

    maxHackCount    = getFloatKeyWithDefault( "hack_count", 100.f );
    objectName        = sys.localizeString( getKeyWithDefault( "object_name", "maps/generic/obj_hackable" ) );

    forceMessage    = false;

    infoToolTip        = GetToolTip( getKey( "tt_intro_info" ) );
    useMeToolTip1    = GetToolTip( getKey( "tt_intro_use_me_1" ) );
    useMeToolTip2    = GetToolTip( getKey( "tt_intro_use_me_2" ) );

    objectiveGUI = -1;
    if ( getIntKey( "use_objective_gui" ) ) {
        objectiveGUI = getGUI( "0" );
    }
}

void hackable_objective::syncFields() {
    sync( "hackCount" );
    syncCallback( "hackCount", "OnHackCountChanged" );
}

void hackable_objective::destroy() {
    vFreeMission();

    if ( flashpoint != $null ) {
        delete flashpoint;
    }

    if ( isPrimaryObjective ) {
        ClearObjectiveIndicator();
    }
}

void hackable_objective::OnIsPrimaryObjectiveChanged() {
    ClearObjectiveIndicator();

    if ( isPrimaryObjective ) {
        SetObjectiveIndicator();
    }
}

void hackable_objective::SetObjectiveReminderTime( float time ) {
    if ( time > nextObjectiveReminderTime ) {
        nextObjectiveReminderTime = time;
    }
}

void hackable_objective::UpdateObjectiveThread() {
    waitUntil( objManager.gameState == GS_GAMEON );

    objManager.PlaySound( getKey( "snd_intro_strogg" ), stroggTeam );
    objManager.PlaySound( getKey( "snd_intro_gdf" ), gdfTeam );

    SetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );

    while ( true ) {
        UpdateObjectiveProgress();

        if ( !sys.isClient() ) {
            if ( sys.getTime() >= nextObjectiveReminderTime ) {
                objManager.PlaySound( getKey( "snd_reminder_strogg" ), stroggTeam );
                objManager.PlaySound( getKey( "snd_reminder_gdf" ), gdfTeam );

                SetObjectiveReminderTime( sys.getTime() + OBJECTIVEMESSAGE_WAIT_TIME );
            }
        }

        sys.waitFrame();
    }
}

void hackable_objective::SetObjectiveIndicator() {
    UpdateObjectiveProgress();

    thread UpdateObjectiveThread();

    if ( sys.getLocalPlayer() != $null_entity ) {
        sys.setGUIFloat( GUI_GLOBALS_HANDLE, "hackObjective.active", 1.f );
    }
}


void hackable_objective::ClearObjectiveIndicator() {
    sys.killThread( "UpdateObjectiveThread_" + getName() );

    if ( sys.getLocalPlayer() != $null_entity ) {
        sys.setGUIFloat( GUI_GLOBALS_HANDLE, "hackObjective.active", 0.f );
    }
}

void hackable_objective::UpdateObjectiveProgress() {
    if ( sys.getLocalPlayer() != $null_entity ) {
        float progress = CalcObjectiveProgress();
        sys.setGUIFloat( GUI_GLOBALS_HANDLE, "hackObjective.progress", progress );        
    }
}

float hackable_objective::CalcObjectiveProgress() {
    return hackCount / maxHackCount;
}


void hackable_objective::vMakePrimaryObjective( boolean value ) {
    isPrimaryObjective = value;

    OnIsPrimaryObjectiveChanged();
}


boolean    hackable_objective::vCheckActionCode( entity p, float actionCode ) {
    if ( objManager.gameState != GS_GAMEON ) {
        return false;
    }

    if ( actionCode == AC_HACK && AllowHack() ) {
        if ( p.getGameTeam() == baseTeam ) {
            return false;
        }
        return getEntityAllegiance( p ) == TA_ENEMY;
    }

    return false;
}

void hackable_objective::OnHacked( entity p ) {
    OnHacked_Base( p );
}

void hackable_objective::OnHacked_Base( entity p ) {
    object newTeam = p.getGameTeam();    

    string statName = newTeam.getName();
    if ( objectiveIndex != -1 ) {
        statName = statName + "_primary";
        objManager.CompleteObjective( objectiveIndex, p );
    } else {
        statName = statName + "_secondary";
    }
    statName = statName + "_objective_hacked";

    if ( p != $null_entity ) {
        sys.increaseStatInt( sys.allocStatInt( statName ), p.getEntityNumber(), 1 );
        sys.increaseStatInt( sys.allocStatInt( newTeam.getName() + "_hack_uses" ), p.getEntityNumber(), 1 );
    }

    objManager.OnHackComplete( self );

    G_PlayObjectiveCompletedRollEnt( self );
    objManager.PlaySound( getKey( "snd_finished_strogg" ), stroggTeam );
    objManager.PlaySound( getKey( "snd_finished_gdf" ), gdfTeam );

    setGameTeam( newTeam );

    KillFizzleThread();
}

void hackable_objective::OnUpdateGui( entity p ) {
    float guiHandle = getGUI( "0" );
    if ( guiHandle == GUI_INVALID ) {
        return;
    }

    if ( self.getEntityAllegiance( p ) != TA_FRIEND ) {
        sys.setGUIFloat( guiHandle, "disabled", 1 );
    } else {
        sys.setGUIFloat( guiHandle, "disabled", 0 );
    }
}

boolean hackable_objective::HasHackContext( entity other ) {
    object otherTeam = other.getGameTeam();
    if ( otherTeam == baseTeam ) {
        return false;
    }

    if ( otherTeam == getGameTeam() ) {
        return false;
    }

    if ( !AllowHack() ) {
        return false;
    }

    return true;
}

float hackable_objective::GetActivateCode( entity p, float distance ) {
    if ( objManager.gameState != GS_GAMEON ) {
        return AK_INWARMUP;
    }

    if ( p.getViewingEntity() != p ) {
        return AK_NONE;
    }

    if ( p.getHealth() <= 0 ) {
        return AK_NONE;
    }

    float allegiance = getEntityAllegiance( p );

    if ( p.getGameTeam() == baseTeam ) {
        return AK_NONE;
    }

    if ( p.getGameTeam() == getGameTeam() ) {
        return AK_NONE;
    }

    if ( distance < DISTANCE_FOR_ACTION ) {
        if ( AllowHack() ) {
            if ( p.hasAbility( "hack" ) ) {
                return AK_HACK;
            }
        }
    }

    return AK_NONE;
}

float hackable_objective::OnUpdateCrosshairInfo( entity p ) {
    if ( sys.getLocalPlayer() == $null_entity ) {
        return 1.f;
    }

    float allegiance = getEntityAllegiance( p );
    vector color = GetAllegianceColor( allegiance );
    float distance = chGetDistance();
    float range = InchesToMetres( distance );
    float health = getHealth();

    chSetNumLines( 0 );
    float index;

    if ( p.isLocalPlayer() && objectiveIndex != -1 ) {
        p.sendToolTip( infoToolTip );
    }

    // see if theres a valid action to perform
    float code = GetActivateCode( p, distance );
    if ( code != AK_NONE && p.vHasActionItem( code ) ) {
        index = chAddLine();
        chSetLineMaterial( index, p.vGetActionIcon( code ) );
        chSetLineType( index, CI_IMAGE );
        chSetLineSize( index, 64, 64 );
        chSetLineColor( index, g_colorWhite, 0.9f );

        if ( p.isLocalPlayer() ) {
            if ( !p.isToolTipPlaying() ) {
                if ( sys.getTime() - p.getCrosshairStartTime() > 1.f ) {
                    if ( p.getCurrentWeapon() != p.vGetActionItem( code ) ) {
                        p.sendToolTip( useMeToolTip1 );
                    } else {
                        p.sendToolTip( useMeToolTip2 );
                    }
                }
            }
        }
    } else if ( code == AK_INWARMUP ) {
        if ( p.isLocalPlayer() && distance < DISTANCE_FOR_ACTION ) {
            team_base team = p.getGameTeam();
            if ( team != $null_entity ) {
                p.sendToolTip( GetToolTip( getKey( "tt_noobjective" ) ) );
            }
        }
    }

    index = chAddLine();
    chSetLineTextIndex( index, objectName );
    chSetLineColor( index, color, 1.f );
    chSetLineType( index, CI_TEXT );
    chSetLineSize( index, 0, 0 );

    return 1.f;
}

float hackable_objective::vGetPliersProgressBarValue( float action ) {
    if ( action == AC_HACK ) {
        return hackCount / maxHackCount;
    }

    return 0.f;
}

void hackable_objective::vHack( entity p ) {
    float time = sys.getTime();
    entity oldHacker = hacker;
    if ( hacker == $null_entity || lastHackTime < time - 2 ) {
        hacker = p;
        if ( lastHackTime < time - 10 ) {
            oldHacker = $null_entity;
        }
    }

    if ( objectiveIndex != -1 || forceMessage ) {
        if ( p == hacker ) {
            if ( sys.getTime() > nextProgressMessageTime ) {
                objManager.PushCPrintString( p.getUserName() );
                objManager.CPrintEvent( progressMessage, $null );
                nextProgressMessageTime = sys.getTime() + 5.f;
            }

            if ( hacker != oldHacker ) {

                if ( !sys.isClient() ) {
                    objManager.setBotActionStateForEvent( ACTION_STATE_START_HACK, hacker ); //mal: let the bots know someone is hacking the obj!
                }

                objManager.PlaySound( getKey( "snd_hacking_strogg" ), stroggTeam );
                objManager.PlaySound( getKey( "snd_hacking_gdf" ), gdfTeam );

                SetObjectiveReminderTime( sys.getTime() + ( OBJECTIVEMESSAGE_WAIT_TIME * 0.5f ) );
            }
        }
    }

    lastHackTime = time;

    if ( hackCount >= maxHackCount ) {
        hackCount = 0;
    }

    float count = 1;
    team_base team = p.getGameTeam();
    if ( team.HasFastHackBonus( p ) ) {
        count = count * 1.25f;
    }

    hackCount = hackCount + count;
    OnHackCountChanged();

    if ( hackProficiency != -1 ) {
        p.giveProficiency( hackProficiency, ( count / maxHackCount ), missionTask, "hacking objective" );
    }

    if ( !sys.isClient() ) {
        if ( hackCount >= maxHackCount ) {
            OnHacked( p );
        } else {
            if ( fizzleTime > 0.f ) {
                CreateFizzleThread( fizzleTime );
            }
        }
    }
}

float hackable_objective::OnActivate( entity p, float distance ) {
    if ( distance > 128.f ) {
        return 0.0f;
    }

    if ( p.getViewingEntity() != p ) {
        return 0.0f;
    }

    if ( vCheckActionCode( p, AC_HACK ) ) {
        if ( p.isDisguised() ) {
            p.disguise( $null_entity );
        }

        team_base team = p.getGameTeam();
        team.SelectActionItem( p, AK_HACK );
    }

    return 1.f;
}

void hackable_objective::SetObjectiveIndex( float index ) {
    objectiveIndex = index;
}

void hackable_objective::vCreateMission() {
    vFreeMission();
    missionTask = taskManager.allocEntityTask( GetPlayerTask( getKey( "task_hack" ) ), self );
}

void hackable_objective::vFreeMission() {
    if ( missionTask != $null ) {
        missionTask.free();
        missionTask = $null;
    }
}

void hackable_objective::vCompleteMission() {
    if ( missionTask != $null ) {
        missionTask.complete();
        missionTask.free();
        missionTask = $null;
    }
}

void hackable_objective::KillFizzleThread() {
    fizzleEndTime = 0;
}

void hackable_objective::CreateFizzleThread( float delay ) {
    fizzleEndTime = sys.getTime() + delay;
    if ( !fizzleThreadActive ) {
        thread FizzleThread( delay );
    }
}

void hackable_objective::OnFizzled() {
    hackCount = 0;
    OnHackCountChanged();

    if ( !sys.isClient() ) {
        objManager.setBotActionStateForEvent( ACTION_STATE_HACK_FIZZLED, self ); //mal: let the bots know the hack has fizzled
    }
}

void hackable_objective::FizzleThread( float delay ) {
    fizzleThreadActive = true;
    while ( sys.getTime() < fizzleEndTime ) {
        sys.wait( fizzleEndTime - sys.getTime() );
    }
    fizzleThreadActive = false;
    if ( fizzleEndTime != 0 ) {
        OnFizzled();
    }
}

void hackable_objective::vOnContextDefend( entity p ) {
    player local = sys.getLocalViewPlayer();
    if ( local == $null_entity || p == $null_entity ) {
        return;
    }

    if ( flashpoint != $null ) {
        delete flashpoint;
    }

    flashpoint = new flashpoint_obj;
    flashpoint.SetOwner( self );
    flashpoint.SetMaterial( getKey( "mtr_icon_flash_defend" ) );
}

void hackable_objective::vOnContextHack( entity p ) {
    player local = sys.getLocalViewPlayer();
    if ( local == $null_entity || p == $null_entity ) {
        return;
    }

    if ( flashpoint != $null ) {
        delete flashpoint;
    }

    flashpoint = new flashpoint_obj;
    flashpoint.SetOwner( self );
    flashpoint.SetMaterial( getKey( "mtr_icon_flash" ) );
}

void hackable_objective::OnHackCountChanged() {
    if ( objectiveGUI != -1 ) {
        if ( sys.doClientSideStuff() ) {
            sys.setGUIFloat( objectiveGUI, "progress", CalcObjectiveProgress() );
        }
    }
}