#using scripts\codescripts\struct; #using scripts\shared\callbacks_shared; #using scripts\shared\clientfield_shared; #using scripts\shared\util_shared; #using scripts\shared\system_shared; #namespace flashgrenades; function init_shared() { level.sound_flash_start = ""; level.sound_flash_loop = ""; level.sound_flash_stop = ""; callback::on_connect( &monitorFlash ); } function flashRumbleLoop( duration ) { self endon("stop_monitoring_flash"); self endon("flash_rumble_loop"); self notify("flash_rumble_loop"); goalTime = getTime() + duration * 1000; while ( getTime() < goalTime ) { self PlayRumbleOnEntity( "damage_heavy" ); {wait(.05);}; } } function monitorFlash_Internal(amount_distance, amount_angle, attacker, direct_on_player) { hurtattacker = false; hurtvictim = true; /* if ( amount_angle < 0.5 ) { amount_angle = 0.5; } else if ( amount_angle > 0.8 ) { amount_angle = 1; } */ //duration = amount_distance * amount_angle * 6; // TFLAME - 2/7/15 - The angle input is making it unreadable and inconsistent how enemies are being affected based on hitmarker. Removing for now. duration = amount_distance * 3.5; min_duration = 2.5; // TFLAME - 2/10/15 - The old calculation here is hard to read and very inconsistent. Lets have a min/max and be done with it. max_self_duration = 2.5; if ( duration < min_duration ) { duration = min_duration; } if ( isdefined( attacker ) && (attacker == self) ) // TFLAME - 8/1/12 - Don't want tacticals to be too frustrating to use, reducing amount they affect player using them { duration = duration/3; } if ( duration < 0.25 ) { return; } rumbleduration = undefined; if ( duration > 2 ) { rumbleduration = 0.75; } else { rumbleduration = 0.25; } assert(isdefined(self.team)); if (level.teamBased && isdefined(attacker) && isdefined(attacker.team) && attacker.team == self.team && attacker != self) { friendlyfire = [[ level.figure_out_friendly_fire]]( self ); if ( friendlyfire == 0 ) // no FF { return; } else if ( friendlyfire == 1 ) // FF { } else if ( friendlyfire == 2) // reflect { duration = duration * .5; rumbleduration = rumbleduration * .5; hurtvictim = false; hurtattacker = true; } else if ( friendlyfire == 3 ) // share { duration = duration * .5; rumbleduration = rumbleduration * .5; hurtattacker = true; } } if ( self hasPerk ("specialty_flashprotection") ) { // do a little bit, not a complete negation duration *= 0.1; rumbleduration *= 0.1; } if (hurtvictim) { // No flashbang effect if in vehicle if ( self util::mayApplyScreenEffect() || (!direct_on_player && (self IsRemoteControlling()) ) ) { if( isDefined(attacker) && self != attacker &&isPlayer(attacker) ) { attacker AddWeaponStat( GetWeapon( "flash_grenade" ), "hits", 1 ); attacker AddWeaponStat( GetWeapon( "flash_grenade" ), "used", 1 ); } self thread applyFlash(duration, rumbleduration, attacker); } } if (hurtattacker) { // No flashbang effect if in vehicle if ( attacker util::mayApplyScreenEffect() ) attacker thread applyFlash(duration, rumbleduration, attacker); } } function monitorFlash() { self endon("disconnect"); self endon ("killFlashMonitor"); self.flashEndTime = 0; while(1) { self waittill( "flashbang", amount_distance, amount_angle, attacker ); if ( !isalive( self ) ) { continue; } self monitorFlash_Internal(amount_distance, amount_angle, attacker, true); } } function monitorRCBombFlash() { self endon("death"); self.flashEndTime = 0; while(1) { self waittill( "flashbang", amount_distance, amount_angle, attacker ); driver = self getseatoccupant(0); if ( !isdefined(driver) || !isalive( driver ) ) { continue; } driver monitorFlash_Internal(amount_distance, amount_angle, attacker, false); } } function applyFlash(duration, rumbleduration, attacker) { // wait for the highest flash duration this frame, // and apply it in the following frame if (!isdefined(self.flashDuration) || duration > self.flashDuration) { self.flashDuration = duration; } if (!isdefined(self.flashRumbleDuration) || rumbleduration > self.flashRumbleDuration) { self.flashRumbleDuration = rumbleduration; } self thread playFlashSound( duration ); wait .05; if (isdefined(self.flashDuration)) { if ( self hasPerk ("specialty_flashprotection") == false ) { self shellshock( "flashbang", self.flashDuration, false ); } self.flashEndTime = getTime() + (self.flashDuration * 1000); self.lastFlashedBy = attacker; } if (isdefined(self.flashRumbleDuration)) { self thread flashRumbleLoop( self.flashRumbleDuration ); //TODO: Non-hacky rumble. } self.flashDuration = undefined; self.flashRumbleDuration = undefined; } function playFlashSound( duration ) { self endon( "death" ); self endon( "disconnect" ); flashSound = spawn ("script_origin",(0,0,1)); flashSound.origin = self.origin; flashSound linkTo( self ); flashSound thread deleteEntOnOwnerDeath( self ); flashSound playsound( level.sound_flash_start ); flashSound playLoopSound ( level.sound_flash_loop ); if ( duration > 0.5 ) wait( duration - 0.5 ); flashSound playsound( level.sound_flash_start ); flashSound StopLoopSound( .5); wait(0.5); flashSound notify ( "delete" ); flashSound delete(); } function deleteEntOnOwnerDeath( owner ) { self endon( "delete" ); owner waittill( "death" ); self delete(); } /*util::isFlashbanged() { return isdefined( self.flashEndTime ) && gettime() < self.flashEndTime; } */