Script:Files:script/weapons/lightningpistol.script

From Mod Wiki
Revision as of 18:08, 2 November 2007 by Wizz (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
/***********************************************************************

weapon_lightningpistol.script

***********************************************************************/

object weapon_lightningpistol : weapon_base {
    void        preinit();
    void        init();
    void        destroy();

    void        Idle();
    void        Fire();
    void        Raise();
    void        Lower();
    void        Cleanup();
    void        UpdateLightningEffect( vector hitPos, vector hitDir, float traceFraction, vector traceNormal );
    void        DoLightning( boolean doDamage );
    void        Overheat();
    void        Reload() { Overheat(); }

    void        LoadScopeGUI();
    void        FreeScopeGUI();

    void        OnIronSightsEnabled() { hide(); }
    void        OnIronSightsDisabled() { show(); }

    void        OnBecomeViewWeapon();    
    void        OnFinishViewWeapon();

    float        range;
    object        effect;
    object        effectImpact;

    float        worldMuzzle;
    entity        worldModel;

    float        localMuzzle;
    float        scopeGUIHandle;

    handle        statNumFired;

    float        lightningDamage;

    boolean        dryfireAttack;
}

void weapon_lightningpistol::preinit() {
    range = getFloatKeyWithDefault( "range", 2048 );

    string statName = getKey( "stat_name" );
    if ( statName != "" ) {
        statNumFired = sys.allocStatInt( statName + "_shots_fired" );
    }

    lightningDamage = GetDamage( getKey( "dmg_lightning" ) );
}

void weapon_lightningpistol::init() {
    worldModel    = getWorldModel( 0 );
    worldMuzzle = worldModel.getJointHandle( "muzzle" );

    localMuzzle    = getJointHandle( "muzzle" );

    weaponState( "Raise", 0 );
}

void weapon_lightningpistol::destroy() {
    stopSound( SND_WEAPON_FIRE2 );
    killEffect( "fx_muzzle_flash" );

    FreeScopeGUI();

    if ( effect != $null_entity ) {
        effect.remove();
    }
    if ( effectImpact != $null_entity ) {
        effectImpact.remove();
    }

    if ( ShouldRunGuis() ) {
        KillUpdateHeat();
    }
}

void weapon_lightningpistol::Cleanup() {
    FreeScopeGUI();
    DisableIronSights();
    stopSound( SND_WEAPON_FIRE2 );
}

void weapon_lightningpistol::Idle() {
    myPlayer.disableSprint( 0.f );

    weaponReady();

    if ( ironSightsEnabled ) {
        playCycle( ANIMCHANNEL_ALL, "idle_zoom" );
    } else {
        playCycle( ANIMCHANNEL_ALL, "idle" );
    }

    while ( true ) {
        if ( WEAPON_LOWERWEAPON ) {
            weaponState( "Lower", 4 );
        }

        CheckIronSights();

        // dryfire sound
        if ( myPlayer.getButton( PK_ATTACK ) ) {
            if ( !dryfireAttack && !ammoAvailable( 0 ) ) {
                if ( myPlayer == sys.getLocalViewPlayer() ) {
                    startSound( "snd_dryfire", SND_WEAPON_DRYFIRE );
                    dryfireAttack = true;
                }
            }
        } else {
            dryfireAttack = false;
        }

        if ( ( sys.getTime() >= reFire ) ) {
            if ( WEAPON_ATTACK ) {
                if ( ammoAvailable( 0 ) > 0 ) {
                    weaponState( "Fire", 0 );
                }
            }
        }

        if ( myPlayer.AI_SPRINT ) {
            weaponState( "Sprint", 4 );
        }

        sys.waitFrame();
    }
}

void weapon_lightningpistol::Fire() {
    myPlayer.disableSprint( 1.f );

    PlayFireSound();
    startSound( "snd_fire_loop", SND_WEAPON_FIRE2 );

    // start firing - create the lightning effect
    effect = spawnClientEffect( "fx_lightning" );
    if ( effect != $null_entity ) {
        effect.setEffectLooping( 1 );
    }

    float nextAnimation = 0;

    while ( ammoAvailable( 0 ) > 0 && WEAPON_ATTACK ) {
        if ( sys.getTime() > nextAnimation ) {
            if ( !sys.isClient() ) {
                if ( myPlayer != $null_entity ) {
                    sys.increaseStatInt( statNumFired, myPlayer.getEntityNumber(), 1 );
                }
            }
            PlayFireEffect();
            playAnim( ANIMCHANNEL_ALL, "fire" );
            nextAnimation = sys.getTime() + fireRate;
            AmmoCheckClip( 0 );
            DoLightning( true );
        } else {
            DoLightning( false );
        }

        if ( IsOverheated() ) {
            if ( effect != $null_entity ) {
                effect.remove();
            }
            if ( effectImpact != $null_entity ) {
                effectImpact.remove();
            }

            stopSound( SND_WEAPON_FIRE2 );

            weaponState( "Overheat", 4 );
        }

        CheckIronSights();

        if ( WEAPON_LOWERWEAPON ) {
            break;
        }

        sys.waitFrame();
    }

    if ( !ammoAvailable( 0 ) ) {
        if ( !dryfireAttack ) {
            if ( myPlayer == sys.getLocalViewPlayer() ) {
                startSound( "snd_dryfire", SND_WEAPON_DRYFIRE );
                dryfireAttack = true;
            }
        }
        weaponHolstered();
//		nextWeapon();
    }

    if ( effect != $null_entity ) {
        effect.remove();
    }
    if ( effectImpact != $null_entity ) {
        effectImpact.remove();
    }

    stopSound( SND_WEAPON_FIRE2 );

    weaponState( "Idle", 0 );
}

void weapon_lightningpistol::UpdateLightningEffect( vector hitPos, vector hitDir, float traceFraction, vector traceNormal ) {
    vector muzzlePos;

    if ( !sys.doClientSideStuff() ) {
        return;
    }

    if ( sys.getLocalViewPlayer() != myPlayer || pm_thirdperson.getBoolValue() ) {
        muzzlePos = worldModel.getJointPos( worldMuzzle );
        if ( effect != $null_entity ) {
            effect.unbind();
            effect.setOrigin( muzzlePos );
        }
    } else {
        if ( effect != $null_entity ) {
            effect.unbind();
            effect.setOrigin( '0 0 0' );
            effect.bindToJoint( self, "muzzle", 0 );
        }
        muzzlePos = getJointPos( localMuzzle );
    }

    vector dir = hitPos - muzzlePos;
    vector angles;

    float len = sys.vecLengthSquared( dir );
    dir = sys.vecNormalize( dir );
    float dp = dir * hitDir;
    if ( len < 1500 || dp < 0.f ) {
        dir = hitDir;
    } else
    if ( len < 2000 ) {
        float blend = (len - 1500) / 500;
        dir = dir * blend + hitDir * (1-blend);
    }

    // the beam
    if ( effect != $null_entity ) {
        effect.setEffectEndOrigin( hitPos );

        angles = sys.vecToAngles( dir );
        effect.setAngles( angles );
    }

    // impact effect
    if ( traceFraction < 1.0f ) {
        if ( effectImpact == $null_entity ) {
            effectImpact = spawnClientEffect( "fx_lightning_hit" );
            if ( effectImpact != $null_entity ) {
                effectImpact.setEffectLooping( 1 );
            }
        }
    } else {
        if ( effectImpact != $null_entity ) {
            effectImpact.remove();
        }
    }

    if ( effectImpact != $null_entity ) {
        effectImpact.setOrigin( hitPos );

        if ( traceFraction < 1.0f ) {
            dir = traceNormal;
        } else {
            dir = -dir;
        }

        angles = sys.vecToAngles( dir );
        effectImpact.setAngles( angles );
    }
}

void weapon_lightningpistol::DoLightning( boolean doDamage ) {
    fired();

    float mask = MASK_PROJECTILE | MASK_SHOT_BOUNDINGBOX;
    if ( sys.isClient() ) {
        mask = mask | CONTENTS_WATER;
    }
    melee( mask, range, true, true );

    vector traceEnd = getMeleeEndPos();
    vector startPos = myPlayer.getViewOrigin();
    vector dir = traceEnd - startPos;
    dir = sys.vecNormalize( dir );

    float traceFraction = getMeleeFraction();
    vector traceNormal = getMeleeNormal();

    entity collisionEnt = getMeleeEntity();
    string collisionSurface = getMeleeSurfaceType();

    if ( doDamage ) {
        if ( collisionEnt != $null_entity ) {
            // TODO: This could possibly be done with meleeAttack instead
            object traceObject = saveMeleeTrace();
            collisionEnt.applyDamage( self, myPlayer, dir, lightningDamage, 1.f - getMeleeFraction(), traceObject );
            sys.freeTrace( traceObject );

            spawnClientCrawlEffect( "fx_crawl", collisionEnt, 0.5 );
        }

        UseAmmo_Stroyent( 0 );
    }

    AddHeat();

    UpdateLightningEffect( traceEnd, dir, traceFraction, traceNormal );
}

void weapon_lightningpistol::Overheat() {
    boolean wasEnabled = false;
    float lastZoomState;

    wasEnabled = ironSightsEnabled;
    if ( wasEnabled ) {
        show();
        DisableIronSights();
        waitUntil( !ironSightsThreadActive );
    }

    weaponReloading();
    stopSound( SND_WEAPON_FIRE2 );

    if ( effect != $null_entity ) {
        effect.remove();
    }
    if ( effectImpact != $null_entity ) {
        effectImpact.remove();
        effectImpact = $null_entity;
    }

    StartCooling();

    playAnim( ANIMCHANNEL_ALL, "overheat" );
    waitUntil( animDone( ANIMCHANNEL_ALL, 4 ) );

    FinishCooling();

    /*if ( wasEnabled ) {
		EnableIronSights();
		waitUntil( !ironSightsThreadActive );
	}*/

    weaponState( "Idle", 4 );
}

void weapon_lightningpistol::Raise() {
    if ( ShouldRunGuis() ) {
        CreateUpdateHeat();
    }
    Base_Raise();    
}

void weapon_lightningpistol::Lower() {
    stopSound( SND_WEAPON_FIRE2 );

    if ( ShouldRunGuis() ) {
        KillUpdateHeat();
    }
    Base_Lower();    
}

void weapon_lightningpistol::LoadScopeGUI() {
    FreeScopeGUI();

    scopeGUIHandle = sys.allocHudModule( getKey( "gui_sniper_scope" ), getFloatKeyWithDefault( "hud_sort", 0 ), false );
}

void weapon_lightningpistol::FreeScopeGUI() {
    if ( scopeGUIHandle != -1 ) {
        sys.freeHudModule( scopeGUIHandle );
        scopeGUIHandle = -1;
    }
}

void weapon_lightningpistol::OnBecomeViewWeapon() {
    if ( localIronSightsEffectsActive ) {
        AddLocalIronSightsEffects();
    }
    if ( ShouldRunGuis() ) {
        CreateUpdateHeat();
    }
    UpdateCrosshair();
}

void weapon_lightningpistol::OnFinishViewWeapon() {
    KillUpdateHeat();
    sys.setGUIFloat( GUI_GLOBALS_HANDLE, "gameHud.weaponReloadTime", 0 );
    sys.setGUIFloat( GUI_GLOBALS_HANDLE, "weapons.cooling", 0.f );
    RemoveLocalIronSightsEffects();
}