//============================================================================== // NicePack / NiceMeleeFire //============================================================================== // Adjustment of vanilla melee fire class to NicePack. //============================================================================== // 'Nice pack' source // Do whatever the fuck you want with it // Author: dkanus // E-mail: dkanus@gmail.com //============================================================================== class NiceMeleeFire extends NiceFire; var float weaponRange; var float damageDelay; // How far to rot view? var vector impactShakeRotMag; // How fast to rot view? var vector impactShakeRotRate; // How much time to rot the instigator's view? var float impactShakeRotTime; // Max view offset vertically? var vector impactShakeOffsetMag; // How fast to offset view vertically? var vector impactShakeOffsetRate; // How much time to offset view? var float impactShakeOffsetTime; // Sound for this melee strike hitting a pawn (fleshy hits). var array meleeHitSounds; var float meleeHitVolume; var array fireAnims; // The class to spawn for the hit effect for // this melee weapon hitting the world (not pawns). var class hitEffectClass; var array meleeHitSoundRefs; // The angle to do sweeping strikes in front of the player. // If zero, - do no strikes. var float wideDamageMinHitAngle; static function PreloadAssets(LevelInfo level, optional KFFire spawned){ local int i; local NiceMeleeFire niceFire; super.PreloadAssets(level, spawned); for(i = 0; i < default.meleeHitSoundRefs.length;i ++){ if(default.meleeHitSoundRefs[i] == "") continue; if( default.meleeHitSounds.length >= i + 1 && default.meleeHitSounds[i] != none) continue; default.meleeHitSounds[i] = Sound( DynamicLoadObject( default.meleeHitSoundRefs[i], class'Sound', true)); } niceFire = NiceMeleeFire(spawned); if(niceFire != none) for(i = 0; i < default.meleeHitSoundRefs.length;i ++) niceFire.meleeHitSounds[i] = default.meleeHitSounds[i]; } static function bool UnloadAssets(){ local int i; super.UnloadAssets(); for(i = 0; i < default.meleeHitSoundRefs.length;i ++) default.meleeHitSounds[i] = none; return true; } simulated function DoBurst(optional bool bSkipFirstShot){} function DoFireEffect(){} function float MaxRange(){ local bool hasWindCutterSkill; traceRange = weaponRange; if(instigator == none) return traceRange; hasWindCutterSkill = class'NiceVeterancyTypes'.static. HasSkill( NicePlayerController(instigator.controller), class'NiceSkillZerkWindCutter'); if(hasWindCutterSkill) traceRange *= class'NiceSkillZerkWindCutter'.default.rangeBonus; return traceRange; } simulated function bool AllowFire(){ local KFPawn kfPwn; // Check pawn actions kfPwn = KFPawn(instigator); if(kfPwn == none || kfPwn.SecondaryItem != none || kfPwn.bThrowingNade) return false; return true; } function name GetCorrectAnim(bool bLoop, bool bAimed){ local int AnimToPlay; if(fireAnims.length > 0){ AnimToPlay = rand(fireAnims.length); fireAnim = fireAnims[AnimToPlay]; } return FireAnim; } simulated function NiceMonster DealTargetMeleeDamage ( NiceReplicationInfo niceRI, class niceDmgType ){ local float headSizeModifier; local float headshotLevel; local NiceMonster niceZed; local Vector hitLocation, hitNormal; local KFPlayerReplicationInfo KFPRI; local class niceVet; if(niceRI == none || instigator == none) return none; KFPRI = KFPlayerReplicationInfo(instigator.PlayerReplicationInfo); if(KFPRI == none) return none; niceVet = class(KFPRI.ClientVeteranSkill); if(niceVet == none) return none; if(niceDmgType != none) headSizeModifier = niceDmgType.default.headSizeModifier; headSizeModifier = 1.0; headSizeModifier *= niceVet.static.GetHeadshotCheckMultiplier(KFPRI, niceDmgType); headshotLevel = TraceZed(niceZed, hitLocation, hitNormal, headSizeModifier); if(niceZed != none) HitZed(niceZed, headshotLevel, niceRI, niceDmgType); else HitWall(niceRI, niceDmgType); return niceZed; } function HitZed(NiceMonster niceZed, float headshotLevel, NiceReplicationInfo niceRI, class niceDmgType){ local Vector hitLocation, hitNormal; local NiceMeleeWeapon niceWeap; ImpactShakeView(); niceWeap = NiceMeleeWeapon(weapon); if(niceWeap != none && niceWeap.BloodyMaterial != none) niceWeap.Skins[niceWeap.BloodSkinSwitchArray] = niceWeap.BloodyMaterial; niceRI.ServerDealMeleeDamage( niceZed, damageMax, instigator, hitLocation, -hitNormal, niceDmgType, true, headshotLevel); } function HitWall( NiceReplicationInfo niceRI, class niceDmgType){ local Actor wall; local Vector hitLocation, hitNormal; local Rotator rotation; TraceWall(wall, hitLocation, hitNormal); if(wall != none){ niceRI.ServerDealMeleeDamage( wall, damageMax, instigator, hitLocation, -hitNormal, niceDmgType, false); rotation = Rotator ( HitLocation - instigator.location - instigator.EyePosition() ); instigator.spawn(hitEffectClass,,, hitLocation, rotation); } } simulated function DealArcMeleeDamage ( NiceMonster niceZed, NiceReplicationInfo niceRI, class niceDmgType ){ local NiceMonster otherZed; local float actualMinAngle, tempRadians; local bool hasCleave; if(weapon == none) return; hasCleave = class'NiceVeterancyTypes'.static. HasSkill( NicePlayerController(instigator.controller), class'NiceSkillZerkCleave'); actualMinAngle = wideDamageMinHitAngle; if(hasCleave){ tempRadians = acos(actualMinAngle); tempRadians += class'NiceSkillZerkCleave'.default.bonusDegrees; tempRadians = FMin(tempRadians, Pi); actualMinAngle = cos(tempRadians); } foreach weapon.VisibleCollidingActors( class'NiceMonster', otherZed, weaponRange * 2, instigator.location + instigator.EyePosition()){ if(niceZed != none && otherZed == niceZed) continue; if(otherZed == instigator || otherZed.Health <= 0) continue; TryHitZedArc(actualMinAngle, otherZed, niceRI, niceDmgType); } } function TryHitZedArc(float minAngle, NiceMonster niceZed, NiceReplicationInfo niceRI, class niceDmgType){ local vector hitLocation, hitNormal; local vector dir, lookDir; local float diffAngle, victimDist; victimDist = VSize(instigator.location - niceZed.location); if(victimDist + niceZed.CollisionRadius > weaponRange * 1.1) return; lookDir = Normal(Vector(instigator.GetViewRotation())); dir = Normal(niceZed.location - instigator.location); diffAngle = lookDir dot dir; if(diffAngle <= minAngle) return; hitLocation = niceZed.location + niceZed.CollisionHeight * vect(0,0,0.7); niceRI.ServerDealMeleeDamage( niceZed, damageMax * 0.5, instigator, hitLocation, hitNormal, niceDmgType, false, 0.0); if(meleeHitSounds.Length > 0) niceZed.PlaySound( meleeHitSounds[Rand(meleeHitSounds.length)], SLOT_None, meleeHitVolume,,,, false); } simulated function Timer(){ local NiceMonster niceZed; local NiceReplicationInfo niceRI; local class niceDmgType; niceRI = GetNiceRI(); niceDmgType = class(damageType); if(niceRI == none || instigator == none || niceDmgType == none) return; niceZed = DealTargetMeleeDamage(niceRI, niceDmgType); DealArcMeleeDamage(niceZed, niceRI, niceDmgType); } simulated function MDFEffectsClient(float newAmmoPerFire, float rec){ local float fireSpeedMod; fireSpeedMod = GetFireSpeed(); super.MDFEffectsClient(newAmmoPerFire, rec); SetTimer(damageDelay / fireSpeedMod, false); } function PlayFiring_animation(){ if(weapon == none) return; if(weapon.Mesh == none) return; if(fireCount <= 0){ weapon.PlayAnim(GetCorrectAnim(false, false), fireAnimRate, 0.0); return; } if(weapon.HasAnim(FireLoopAnim)) weapon.PlayAnim(GetCorrectAnim(true, false), fireLoopAnimRate, 0.0); else weapon.PlayAnim(GetCorrectAnim(false, false), fireAnimRate, 0.0); } function PlayFiring(){ local float randPitch; local bool shouldPlayStereo; if(weapon == none) return; if(weapon.instigator == none) return; PlayFiring_animation(); if(bRandomPitchFireSound){ randPitch = FRand() * RandomPitchAdjustAmt; if(FRand() < 0.5) randPitch *= -1.0; } shouldPlayStereo = weapon.instigator.IsLocallyControlled() && weapon.instigator.IsFirstPerson() && StereoFireSound != none; if(shouldPlayStereo){ weapon.PlayOwnedSound( StereoFireSound, SLOT_Interact, TransientSoundVolume * 0.85,, TransientSoundRadius, 1.0 + randPitch, false); } else{ weapon.PlayOwnedSound( FireSound, SLOT_Interact, TransientSoundVolume,, TransientSoundRadius, 1.0 + randPitch, false); } ClientPlayForceFeedback(fireForce); if(!currentContext.bIsBursting) fireCount ++; } function ImpactShakeView(){ local NicePlayerController nicePlayer; if(instigator == none) return; nicePlayer = NicePlayerController(instigator.controller); if(nicePlayer == none) return; nicePlayer.WeaponShakeView( impactShakeRotMag, impactShakeRotRate, impactShakeRotTime, impactShakeOffsetMag, impactShakeOffsetRate, impactShakeOffsetTime); } simulated function HandleRecoil(float Rec){} defaultproperties { weaponRange=70.000000 damageDelay=0.300000 ImpactShakeRotMag=(X=50.000000,Y=50.000000,Z=50.000000) ImpactShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000) ImpactShakeRotTime=2.000000 ImpactShakeOffsetMag=(X=10.000000,Y=10.000000,Z=10.000000) ImpactShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000) ImpactShakeOffsetTime=2.000000 MeleeHitVolume=1.000000 HitEffectClass=Class'KFMod.KFMeleeHitEffect' WideDamageMinHitAngle=1.000000 bFiringDoesntAffectMovement=True FireEndAnim= FireForce="ShockRifleFire" aimerror=100.000000 }