Apply new formatting for NiceBullet

This commit is contained in:
Shtoyan 2023-04-09 01:35:25 +04:00
parent 33ce2f5ef5
commit 2f3385583c

View File

@ -12,6 +12,7 @@
// E-mail: dkanus@gmail.com
//======================================================================================================================
class NiceBullet extends Actor;
// Link to interaction with the server
var NiceReplicationInfo niceRI;
// Controller of our instigator
@ -20,7 +21,6 @@ var NicePlayerController nicePlayer;
var NicePlayerController localPlayer;
// Link to our mutator
var NicePack niceMutator;
//======================================================================================================================
// Battle bullet characteristic
var float charOrigDamage;
@ -180,22 +180,29 @@ var string ambientSoundRef;
//======================================================================================================================
// Functions
static function PreloadAssets() {
if(default.ambientSound == none && default.ambientSoundRef != "")
if (default.ambientSound == none && default.ambientSoundRef != "") {
default.ambientSound = sound(DynamicLoadObject(default.ambientSoundRef, class'Sound', true));
if(default.staticMesh == none && default.staticMeshRef != "")
}
if (default.staticMesh == none && default.staticMeshRef != "") {
UpdateDefaultStaticMesh(StaticMesh(DynamicLoadObject(default.staticMeshRef, class'StaticMesh', true)));
if(default.mesh == none && default.meshRef != "")
}
if (default.mesh == none && default.meshRef != "") {
UpdateDefaultMesh(Mesh(DynamicLoadObject(default.meshRef, class'Mesh', true)));
if(default.regularImpact.noise == none && default.regularImpact.noiseRef != "")
}
if (default.regularImpact.noise == none && default.regularImpact.noiseRef != "") {
default.regularImpact.noise =
sound(DynamicLoadObject(default.regularImpact.noiseRef, class'Sound', true));
if(default.explosionImpact.noise == none && default.explosionImpact.noiseRef != "")
}
if (default.explosionImpact.noise == none && default.explosionImpact.noiseRef != "") {
default.explosionImpact.noise =
sound(DynamicLoadObject(default.explosionImpact.noiseRef, class'Sound', true));
if(default.disintegrationImpact.noise == none && default.disintegrationImpact.noiseRef != "")
}
if (default.disintegrationImpact.noise == none && default.disintegrationImpact.noiseRef != "") {
default.disintegrationImpact.noise =
sound(DynamicLoadObject(default.disintegrationImpact.noiseRef, class'Sound', true));
}
}
static function bool UnloadAssets() {
default.AmbientSound = none;
UpdateDefaultStaticMesh(none);
@ -205,20 +212,26 @@ static function bool UnloadAssets(){
default.disintegrationImpact.noise = none;
return true;
}
function PostBeginPlay() {
super.PostBeginPlay();
bounceHeadMod = 1.0;
}
function UpdateTrails() {
local Actor trailBase;
// Do nothing on dedicated server
if(Level.NetMode == NM_DedicatedServer)
if (Level.NetMode == NM_DedicatedServer) {
return;
}
// Spawn necessary trails first
if(trailClass != none && bulletTrail == none)
if (trailClass != none && bulletTrail == none) {
bulletTrail = Spawn(trailClass, self);
if(trailXClass != none && bulletXTrail == none)
}
if (trailXClass != none && bulletXTrail == none) {
bulletXTrail = Spawn(trailXClass, self);
}
// Handle positioning differently for stuck and regular projectiles
if (bStuck && base != none) {
if (bUseBone) {
@ -235,25 +248,30 @@ function UpdateTrails(){
bulletXTrail.SetRelativeRotation(relativeRotation);
}
}
}
else
} else {
trailBase = self;
}
// Update lifetime and base (latter is for non-bone attachments only)
if (bulletTrail != none) {
if(trailBase != none)
if (trailBase != none) {
bulletTrail.SetBase(trailBase);
}
bulletTrail.lifespan = lifeSpan;
}
if (bulletXTrail != none) {
if(trailBase != none)
if (trailBase != none) {
bulletXTrail.SetBase(trailBase);
}
bulletXTrail.lifespan = lifeSpan;
}
}
function ResetPathBuilding() {
finishedSegmentPart = -1.0;
shiftPoint = location;
}
// Resets default values for this bullet.
// Must be called before each new use of a bullet.
function Renew() {
@ -266,98 +284,136 @@ function Renew(){
ResetIgnoreList();
ResetPathBuilding();
}
simulated function Tick(float delta) {
super.Tick(delta);
if(localPlayer == none)
if (localPlayer == none) {
localPlayer = NicePlayerController(Level.GetLocalPlayerController());
}
if (charFuseTime > 0) {
charFuseTime -= delta;
if (charFuseTime < 0) {
if (charExplodeOnFuse && !charIsDud) {
GenerateImpactEffects(explosionImpact, location, movementDirection);
if(bStuck)
if (bStuck) {
class'NiceBulletAdapter'.static.Explode(self, niceRI, location, base);
else
} else {
class'NiceBulletAdapter'.static.Explode(self, niceRI, location);
}
if(!charExplodeOnFuse)
}
if (!charExplodeOnFuse) {
GenerateImpactEffects(disintegrationImpact, location, movementDirection);
}
KillBullet();
}
}
if (bInitFinished && !bInitFinishDetected) {
bInitFinishDetected = true;
UpdateTrails();
}
if(bInitFinished && !bBulletDead && !bStuck)
if (bInitFinished && !bBulletDead && !bStuck) {
DoProcessMovement(delta);
}
if (bInitFinished && bStuck) {
if(base == none || (KFMonster(base) != none && KFMonster(base).health <= 0))
if (base == none || (KFMonster(base) != none && KFMonster(base).health <= 0)) {
nicePlayer.ExplodeStuckBullet(stuckID);
}
}
}
// Extracts pawn actor from it's auxiliary collision
// @param other Actor we collided with
// @return Pawn we're interested in
function Actor GetMainActor(Actor other) {
if(other == none)
if (other == none) {
return none;
}
// Try owner
if( KFPawn(other) == none && KFMonster(other) == none
&& (KFPawn(other.owner) != none || KFMonster(other.owner) != none) )
if (
KFPawn(other) == none &&
KFMonster(other) == none &&
(KFPawn(other.owner) != none || KFMonster(other.owner) != none)
) {
other = other.owner;
}
// Try base
if( KFPawn(other) == none && KFMonster(other) == none
&& (KFPawn(other.base) != none || KFMonster(other.base) != none) )
if (
KFPawn(other) == none &&
KFMonster(other) == none &&
(KFPawn(other.base) != none || KFMonster(other.base) != none)
) {
other = other.base;
}
return other;
}
// Returns 'true' if passed actor is either world geometry, 'Level' itself or nothing ('none')
// Neither of these related to pawn damage dealing
function bool IsLevelActor(Actor other) {
if(other == none)
if (other == none) {
return true;
}
return (other.bWorldGeometry || other == Level);
}
// Adds given actor and every colliding object connected to it to ignore list
// Removes their collision in case ignore is active (see 'bIgnoreIsActive')
function TotalIgnore(Actor other) {
// These mark what objects, associated with 'other' we also need to ignore
local KFPawn pawnOther;
local KFMonster zedOther;
if(other == none)
if (other == none) {
return;
}
// Try to find main actor as KFPawn
pawnOther = KFPawn(other);
if(pawnOther == none)
if (pawnOther == none) {
pawnOther = KFPawn(other.base);
if(pawnOther == none)
}
if (pawnOther == none) {
pawnOther = KFPawn(other.owner);
}
// Try to find main actor as KFMonster
zedOther = KFMonster(other);
if(zedOther == none)
if (zedOther == none) {
zedOther = KFMonster(other.base);
if(zedOther == none)
}
if (zedOther == none) {
zedOther = KFMonster(other.owner);
}
// Ignore everything that's associated with this actor and can have collision
IgnoreActor(other);
IgnoreActor(other.base);
IgnoreActor(other.owner);
if(pawnOther != none)
if (pawnOther != none) {
IgnoreActor(pawnOther.AuxCollisionCylinder);
if(zedOther != none)
}
if (zedOther != none) {
IgnoreActor(zedOther.MyExtCollision);
}
}
// Adds a given actor to ignore list and removes it's collision in case ignore is active (see 'bIgnoreIsActive')
function IgnoreActor(Actor other) {
local int i;
local IgnoreEntry newIgnoredEntry;
// Check if that's a non-level actor and not already on the list
if(IsLevelActor(other))
if (IsLevelActor(other)) {
return;
for(i = 0;i < ignoredActors.Length;i ++)
if(ignoredActors[i].ignored == other)
}
for (i = 0; i < ignoredActors.Length; i ++) {
if (ignoredActors[i].ignored == other) {
return;
}
}
// Add actor to the ignore list & disable collision if needed
if (other != none) {
// Make entry
@ -365,47 +421,63 @@ function IgnoreActor(Actor other){
newIgnoredEntry.bExtDisabled = !other.bCollideActors;
// Add and activate it
ignoredActors[ignoredActors.Length] = newIgnoredEntry;
if(bIgnoreIsActive)
if (bIgnoreIsActive) {
other.SetCollision(false);
}
}
}
// Restores ignored state of the actors and zeroes our ignored arrays
function ResetIgnoreList() {
SetIgnoreActive(false);
ignoredActors.Length = 0;
}
// Activates/deactivates ignore for actors on the ignore list.
// Ignore deactivation doesn't restore collision if actor was set to not collide prior most recent ignore activation.
// Activating ignore when it's already active does nothing; same with deactivation.
// Ignore deactivation is supposed to be used in the same function call in which activation took place before.
function SetIgnoreActive(bool bActive) {
local int i;
// Do nothing if we're already in a correct state
if(bActive == bIgnoreIsActive)
if (bActive == bIgnoreIsActive) {
return;
}
// Change ignore state & disable collision for ignored actors
bIgnoreIsActive = bActive;
for(i = 0;i < ignoredActors.Length;i ++)
for (i = 0; i < ignoredActors.Length; i ++) {
if (ignoredActors[i].ignored != none) {
// Mark actors that were set to not collide before activation
if(bActive && !ignoredActors[i].ignored.bCollideActors)
if (bActive && !ignoredActors[i].ignored.bCollideActors) {
ignoredActors[i].bExtDisabled = true;
}
// Change collision for actors that weren't externally modified
if(!ignoredActors[i].bExtDisabled)
if (!ignoredActors[i].bExtDisabled) {
ignoredActors[i].ignored.SetCollision(!bActive);
}
// After we deactivated our rules - forget about external modifications
if(!bActive)
if (!bActive) {
ignoredActors[i].bExtDisabled = false;
}
}
}
}
function SetHumanPawnCollision(bool bEnable) {
local int i;
if(niceMutator == none)
if (niceMutator == none) {
niceMutator = class'NicePack'.static.Myself(Level);
for(i = 0;i < niceMutator.recordedHumanPawns.Length;i ++)
if(niceMutator.recordedHumanPawns[i] != none)
}
for (i = 0; i < niceMutator.recordedHumanPawns.Length; i ++) {
if (niceMutator.recordedHumanPawns[i] != none) {
niceMutator.recordedHumanPawns[i].bBlockHitPointTraces = bEnable;
}
}
}
function float CheckHeadshot(KFMonster kfZed, Vector hitLocation, Vector hitDirection) {
local float hsMod;
local float precision;
@ -413,6 +485,7 @@ function float CheckHeadshot(KFMonster kfZed, Vector hitLocation, Vector hitDire
local NiceMonster niceZed;
local KFPlayerReplicationInfo KFPRI;
local class<NiceVeterancyTypes> niceVet;
niceZed = NiceMonster(kfZed);
hitDirection = Normal(hitDirection);
bIsShotgunBullet = ClassIsChildOf(charDamageType, class'NiceDamageTypeVetEnforcer');
@ -420,27 +493,36 @@ function float CheckHeadshot(KFMonster kfZed, Vector hitLocation, Vector hitDire
hsMod = bounceHeadMod; // NICETODO: Add bounce and perk and damage type head-shot zones bonuses
hsMod *= charDamageType.default.headSizeModifier;
hsMod *= bounceHeadMod;
if(nicePlayer != none)
if (nicePlayer != none) {
KFPRI = KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo);
if(KFPRI != none)
}
if (KFPRI != none) {
niceVet = class<NiceVeterancyTypes>(KFPRI.ClientVeteranSkill);
if(niceVet != none)
}
if (niceVet != none) {
hsMod *= niceVet.static.GetHeadshotCheckMultiplier(KFPRI, charDamageType);
}
precision = niceZed.IsHeadshotClient(hitLocation, hitDirection, niceZed.clientHeadshotScale * hsMod);
if(precision <= 0.0 && bIsShotgunBullet && nicePlayer != none && class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillSupportGraze')){
if (
precision <= 0.0 &&
bIsShotgunBullet &&
nicePlayer != none &&
class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillSupportGraze')
) {
bGrazing = true;
hsMod *= class'NiceSkillSupportGraze'.default.hsBonusZoneMult;
precision = niceZed.IsHeadshotClient(hitLocation, hitDirection, niceZed.clientHeadshotScale * hsMod);
}
return precision;
}
else{
if(kfZed.IsHeadShot(hitLocation, hitDirection, 1.0))
} else {
if (kfZed.IsHeadShot(hitLocation, hitDirection, 1.0)) {
return 1.0;
else
} else {
return 0.0;
}
}
}
// Makes bullet trace a directed line segment given by start and end points.
// All traced actors and geometry are then properly affected by corresponding 'HandleHitPawn', 'HandleHitZed' and
// 'HandleHitWall' functions.
@ -457,6 +539,7 @@ function DoTraceLine(Vector lineStart, Vector lineEnd){
local array<int> hitPoints;
local KFMonster tracedZed;
local KFPawn tracedPawn;
lineDirection = (lineEnd - lineStart);
lineDirection = (lineDirection) / VSize(lineDirection);
// Do not trace for disabled bullets and prevent infinite loops
@ -464,64 +547,79 @@ function DoTraceLine(Vector lineStart, Vector lineEnd){
iterationCount++;
// Trace next object
if (!bGhost || localPlayer == none || localPlayer.tracesThisTick <= localPlayer.tracesPerTickLimit) {
if(Instigator != none)
if (Instigator != none) {
tracedActor = Instigator.Trace(hitLocation, hitNormal, lineEnd, lineStart, true);
else
} else {
tracedActor = none;
localPlayer.tracesThisTick ++;
}
else
localPlayer.tracesThisTick++;
} else {
tracedActor = none;
if(charAffectedByScream && !charIsDud && localPlayer != none && localPlayer.localCollisionManager != none && localPlayer.localCollisionManager.IsCollidingWithAnything(lineStart, lineEnd))
}
if (
charAffectedByScream &&
!charIsDud &&
localPlayer != none &&
localPlayer.localCollisionManager != none &&
localPlayer.localCollisionManager.IsCollidingWithAnything(lineStart, lineEnd)
) {
HandleScream(lineStart, lineDirection);
}
if (tracedActor != none && IsLevelActor(tracedActor)) {
HandleHitWall(tracedActor, hitLocation, hitNormal);
break;
}
else{
} else {
TotalIgnore(tracedActor);
tracedActor = GetMainActor(tracedActor);
}
// If tracing between current trace points haven't found anything and tracing step is less than segment's length
// -- shift tracing bounds
if(tracedActor == none)
if (tracedActor == none) {
return;
}
// First, try to handle pawn like a zed; if fails, - try to handle it like 'KFPawn'
tracedZed = KFMonster(tracedActor);
tracedPawn = KFPawn(tracedActor);
if(tracedPawn != none && NiceHumanPawn(instigator) != none &&
(NiceHumanPawn(instigator).ffScale <= 0 && NiceMedicProjectile(self) == none) )
if (
tracedPawn != none &&
NiceHumanPawn(instigator) != none &&
(NiceHumanPawn(instigator).ffScale <= 0 && NiceMedicProjectile(self) == none)
) {
continue;
}
if (tracedZed != none) {
if (tracedZed.Health > 0) {
headshotLevel = CheckHeadshot(tracedZed, hitLocation, lineDirection);
HandleHitZed(tracedZed, hitLocation, lineDirection, headshotLevel);
}
}
else if(tracedPawn != none && tracedPawn.Health > 0){
if(tracedPawn.Health > 0)
} else if (tracedPawn != none && tracedPawn.Health > 0) {
if (tracedPawn.Health > 0) {
HandleHitPawn(tracedPawn, hitLocation, lineDirection, hitPoints);
}
else
} else {
HandleHitWall(tracedActor, hitLocation, hitNormal);
}
}
}
// Replaces current path segment with the next one.
// Doesn't check whether or not we've finished with the current segment.
function BuildNextPathSegment() {
// Only set start point to our location when we build path segment for the first time
// After that we can't even assume that bullet is exactly in the 'pathSegmentE' point
if(finishedSegmentPart < 0.0)
if (finishedSegmentPart < 0.0) {
pathSegmentS = Location;
else
} else {
pathSegmentS = pathSegmentE;
}
movementDirection += (movementAcceleration * trajUpdFreq) / movementSpeed;
pathSegmentE = pathSegmentS + movementDirection * movementSpeed * trajUpdFreq;
finishedSegmentPart = 0.0;
shiftPoint = pathSegmentS;
}
// Updates 'shiftPoint' to the next bullet position in current segment.
// Does nothing if current segment is finished or no segment was built at all.
// @param delta Amount of time bullet has to move through the segment.
@ -531,9 +629,11 @@ function float ShiftInSegment(float delta){
local float remainingTime;
// Part of segment we can pass in a given time
local float segmentPartWeCanPass;
// Exit if there's no segment in progress
if(finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0)
if (finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0) {
return delta;
}
// [movementSpeed * delta] / [movementSpeed * trajUpdFreq] = [delta / trajUpdFreq]
segmentPartWeCanPass = delta / trajUpdFreq;
// If we can move through the rest of the segment - move to end point and mark it finished
@ -541,19 +641,20 @@ function float ShiftInSegment(float delta){
remainingTime = delta - (1.0 - finishedSegmentPart) * trajUpdFreq;
finishedSegmentPart = 1.1;
shiftPoint = pathSegmentE;
}
} else {
// Otherwise compute new 'shiftPoint' normally
else{
remainingTime = 0.0;
finishedSegmentPart += (delta / trajUpdFreq);
shiftPoint = pathSegmentS + movementDirection * movementSpeed * trajUpdFreq * finishedSegmentPart;
}
return remainingTime;
}
// Moves bullet according to settings and decides when and how much tracing should it do.
// @param delta Amount of time passed after previous bullet movement
function DoProcessMovement(float delta) {
local Vector tempVect;
SetIgnoreActive(true);
//SetHumanPawnCollision(true);
// Simple linear movement
@ -567,12 +668,12 @@ function DoProcessMovement(float delta){
// If in future complex movement would be re-enabled, - we want to set first point of the path to
// the location of bullet at a time and not use outdated information.
finishedSegmentPart = -1.0;
}
} else {
// Non-linear movement support
else{
while(delta > 0.0) {
if(finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0)
if (finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0) {
BuildNextPathSegment();
}
// Remember current 'shiftPoint'. That's where we stopped tracing last time and where we must resume.
tempVect = shiftPoint;
// Update 'shiftPoint' (bullet position)
@ -585,11 +686,13 @@ function DoProcessMovement(float delta){
Move(shiftPoint - location);
}
SetRotation(Rotator(movementDirection));
if(charMinExplosionDist > 0)
if (charMinExplosionDist > 0) {
charMinExplosionDist -= VSize(tempVect);
}
SetIgnoreActive(false);
// SetHumanPawnCollision(false);
}
function Stick(Actor target, Vector hitLocation) {
local NiceMonster targetZed;
local name boneStick;
@ -597,8 +700,10 @@ function Stick(Actor target, Vector hitLocation){
local float t;
local Vector boneStrickOrig;
local ExplosionData expData;
if(bGhost)
if (bGhost) {
return;
}
expData.explosionDamageType = charExplosionDamageType;
expData.explosionDamage = charExplosionDamage;
expData.explosionRadius = charExplosionRadius;
@ -609,22 +714,36 @@ function Stick(Actor target, Vector hitLocation){
expData.affectedByScream = charAffectedByScream;
expData.sourceWeapon = sourceWeapon;
targetZed = NiceMonster(target);
if (targetZed == none) {
expData.bulletClass = class;
expData.instigator = instigator;
niceRI.ServerStickProjectile(KFHumanPawn(instigator), target, 'None', hitLocation - target.location,
Rotator(movementDirection), expData);
class'NiceProjectileSpawner'.static.StickProjectile(KFHumanPawn(instigator), target, 'None',
hitLocation - target.location, Rotator(movementDirection), expData);
}
else{
niceRI.ServerStickProjectile(
KFHumanPawn(instigator),
target,
'None',
hitLocation - target.location,
Rotator(movementDirection),
expData
);
class'NiceProjectileSpawner'.static.StickProjectile(
KFHumanPawn(instigator),
target,
'None',
hitLocation - target.location,
Rotator(movementDirection),
expData
);
} else {
expData.bulletClass = class;
expData.instigator = instigator;
boneStick = targetZed.GetClosestBone(hitLocation, movementDirection, distToBone);
if(CheckHeadshot(targetZed, hitLocation, movementDirection) > 0.0)
if (CheckHeadshot(targetZed, hitLocation, movementDirection) > 0.0) {
boneStick = targetZed.HeadBone;
if(boneStick == targetZed.HeadBone)
}
if (boneStick == targetZed.HeadBone) {
expData.stuckToHead = true;
}
boneStrickOrig = targetZed.GetBoneCoords(boneStick).origin;
t = movementDirection.x * (boneStrickOrig.x - hitLocation.x) +
movementDirection.y * (boneStrickOrig.y - hitLocation.y) +
@ -632,37 +751,56 @@ function Stick(Actor target, Vector hitLocation){
t /= VSizeSquared(movementDirection);
t *= 0.5;
hitLocation = hitLocation + t * movementDirection;
niceRI.ServerStickProjectile(KFHumanPawn(instigator), targetZed, boneStick,
hitLocation - boneStrickOrig, Rotator(movementDirection), expData);
class'NiceProjectileSpawner'.static.StickProjectile(KFHumanPawn(instigator), targetZed, boneStick,
hitLocation - boneStrickOrig, Rotator(movementDirection), expData);
niceRI.ServerStickProjectile(
KFHumanPawn(instigator),
targetZed,
boneStick,
hitLocation - boneStrickOrig,
Rotator(movementDirection),
expData
);
class'NiceProjectileSpawner'.static.StickProjectile(
KFHumanPawn(instigator),
targetZed,
boneStick,
hitLocation - boneStrickOrig,
Rotator(movementDirection),
expData
);
}
KillBullet();
}
function DoExplode(Vector explLocation, Vector impactNormal) {
if(charIsDud)
if (charIsDud) {
return;
if(bStuck)
}
if (bStuck) {
class'NiceBulletAdapter'.static.Explode(self, niceRI, explLocation, base);
else
} else {
class'NiceBulletAdapter'.static.Explode(self, niceRI, explLocation);
}
GenerateImpactEffects(explosionImpact, explLocation, impactNormal, true, true);
if(bShakeViewOnExplosion)
if (bShakeViewOnExplosion) {
ShakeView(explLocation);
}
KillBullet();
}
function HandleHitWall(Actor wall, Vector hitLocation, Vector hitNormal) {
local bool bBulletTooWeak;
if (charExplodeOnWallHit && !charIsDud && charMinExplosionDist <= 0.0) {
DoExplode(hitLocation, hitNormal);
return;
}
else{
} else {
class'NiceBulletAdapter'.static.HitWall(self, niceRI, wall, hitLocation, hitNormal);
GenerateImpactEffects(regularImpact, hitLocation, hitNormal, true, true);
if(charIsSticky)
if (charIsSticky) {
Stick(wall, hitLocation);
}
}
if (bShouldBounce && !bDisableComplexMovement) {
movementDirection = (movementDirection - 2.0 * hitNormal * (movementDirection dot hitNormal));
bBulletTooWeak = !class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, none, false, false);
@ -670,97 +808,133 @@ function HandleHitWall(Actor wall, Vector hitLocation, Vector hitNormal){
ResetPathBuilding();
ResetIgnoreList();
bounceHeadMod *= 2;
}
else if(movementFallTime > 0.0){
} else if (movementFallTime > 0.0) {
charIsDud = true;
lifeSpan = movementFallTime;
movementFallTime = 0.0;
movementDirection = vect(0, 0, 0);
ResetPathBuilding();
ResetIgnoreList();
}
else
} else {
bBulletTooWeak = true;
if(bBulletTooWeak)
}
if (bBulletTooWeak) {
KillBullet();
}
}
function HandleHitPawn(KFPawn hitPawn, Vector hitLocation, Vector hitDirection, array<int> hitPoints) {
if (charExplodeOnPawnHit && !charIsDud && charMinExplosionDist <= 0.0) {
DoExplode(hitLocation, hitDirection);
GenerateImpactEffects(explosionImpact, hitLocation, hitDirection);
return;
}
else{
} else {
class'NiceBulletAdapter'.static.HitPawn(self, niceRI, hitPawn, hitLocation, hitDirection, hitPoints);
if(bGenRegEffectOnPawn)
if (bGenRegEffectOnPawn) {
GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false);
}
}
if (!class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, none, false, false)) {
charPenetrationCount += 1;
KillBullet();
}
}
function HandleHitZed(KFMonster targetZed, Vector hitLocation, Vector hitDirection, float headshotLevel) {
local bool bHitZedCalled;
if (class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillDemoDirectApproach')) {
class'NiceBulletAdapter'.static.HitZed(self, niceRI, targetZed, hitLocation, hitDirection, headshotLevel);
if(bGenRegEffectOnPawn)
if (bGenRegEffectOnPawn) {
GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false);
}
bHitZedCalled = true;
}
if (charExplodeOnPawnHit && !charIsDud && charMinExplosionDist <= 0.0) {
class'NiceBulletAdapter'.static.Explode(self, niceRI, hitLocation, targetZed);
GenerateImpactEffects(explosionImpact, hitLocation, hitDirection);
if(bShakeViewOnExplosion)
if (bShakeViewOnExplosion) {
ShakeView(hitLocation);
}
KillBullet();
return;
}
else{
} else {
if (!bHitZedCalled) {
class'NiceBulletAdapter'.static.HitZed(self, niceRI, targetZed, hitLocation, hitDirection, headshotLevel);
if(bGenRegEffectOnPawn)
class'NiceBulletAdapter'.static.HitZed(
self,
niceRI,
targetZed,
hitLocation,
hitDirection,
headshotLevel
);
if (bGenRegEffectOnPawn) {
GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false);
}
}
bHitZedCalled = true;
if (!bGhost && !bAlreadyHitZed) {
bAlreadyHitZed = true;
if(nicePlayer != none && niceRI != none)
if (nicePlayer != none && niceRI != none) {
niceRI.ServerJunkieExtension(nicePlayer, headshotLevel > 0.0);
}
if(charIsSticky)
}
if (charIsSticky) {
Stick(targetZed, hitLocation);
}
if(!class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, targetZed, (headshotLevel > 0.0), (headshotLevel > charDamageType.default.prReqPrecise))){
}
if (!class'NiceBulletAdapter'.static.ZedPenetration(
charDamage,
self,
targetZed,
(headshotLevel > 0.0),
(headshotLevel > charDamageType.default.prReqPrecise)
)
) {
charPenetrationCount += 1;
KillBullet();
}
}
function HandleScream(Vector disintegrationLocation, Vector entryDirection) {
if(!charIsDud)
if (!charIsDud) {
GenerateImpactEffects(disintegrationImpact, disintegrationLocation, entryDirection);
}
class'NiceBulletAdapter'.static.HandleScream(self, niceRI, disintegrationLocation, entryDirection);
}
function GenerateImpactEffects(ImpactEffect effect, Vector hitLocation, Vector hitNormal,
optional bool bWallImpact, optional bool bGenerateDecal){
function GenerateImpactEffects(
ImpactEffect effect,
Vector hitLocation,
Vector hitNormal,
optional bool bWallImpact,
optional bool bGenerateDecal
) {
local float actualCullDistance;
local float actualImpactShift;
local bool generatedEffect;
// No need to play visuals on a server, for a dead bullets or in case there's no local player at all
if(Level.NetMode == NM_DedicatedServer || bBulletDead || localPlayer == none)
if (Level.NetMode == NM_DedicatedServer || bBulletDead || localPlayer == none) {
return;
if(!localPlayer.CanSpawnEffect(bGhost) && !effect.bImportanEffect)
}
if (!localPlayer.CanSpawnEffect(bGhost) && !effect.bImportanEffect) {
return;
}
// -- Classic effect
if(effect.bPlayROEffect && !bBulletDead)
if (effect.bPlayROEffect && !bBulletDead) {
Spawn(class'ROBulletHitEffect',,, hitLocation, rotator(-hitNormal));
}
// -- Generate decal
if (bGenerateDecal && effect.decalClass != none) {
// Find appropriate cull distance for this decal
actualCullDistance = effect.decalClass.default.cullDistance;
// Double cull distance if local player is an instigator
if(instigator != none && localPlayer == instigator.Controller)
if (instigator != none && localPlayer == instigator.Controller) {
actualCullDistance *= 2; // NICETODO: magic number
}
// Spawn decal
if (!localPlayer.BeyondViewDistance(hitLocation, actualCullDistance)) {
Spawn(effect.decalClass, self,, hitLocation, rotator(- hitNormal));
@ -769,10 +943,11 @@ function GenerateImpactEffects(ImpactEffect effect, Vector hitLocation, Vector h
}
// -- Generate custom effect
if (effect.emitterClass != none && EffectIsRelevant(hitLocation, false)) {
if(bWallImpact)
if (bWallImpact) {
actualImpactShift = effect.emitterShiftWall;
else
} else {
actualImpactShift = effect.emitterShiftPawn;
}
Spawn(effect.emitterClass,,, hitLocation - movementDirection * actualImpactShift, rotator(movementDirection));
generatedEffect = true;
}
@ -783,28 +958,43 @@ function GenerateImpactEffects(ImpactEffect effect, Vector hitLocation, Vector h
Spawn(class'NiceSoundCls',,, hitLocation);
generatedEffect = true;
}
if(generatedEffect)
if (generatedEffect) {
localPlayer.AddEffect();
}
}
function ShakeView(Vector hitLocation) {
local float distance, scale;
if(nicePlayer == none || shakeRadiusMult < 0.0)
if (nicePlayer == none || shakeRadiusMult < 0.0) {
return;
}
distance = VSize(hitLocation - nicePlayer.ViewTarget.Location);
if (distance < charExplosionRadius * shakeRadiusMult) {
if(distance < charExplosionRadius)
if (distance < charExplosionRadius) {
scale = 1.0;
else
} else {
scale = (charExplosionRadius * ShakeRadiusMult - distance) / (charExplosionRadius);
nicePlayer.ShakeView(shakeRotMag*scale, shakeRotRate, shakeRotTime, shakeOffsetMag * scale, shakeOffsetRate, shakeOffsetTime);
}
nicePlayer.ShakeView(
shakeRotMag * scale,
shakeRotRate,
shakeRotTime,
shakeOffsetMag * scale,
shakeOffsetRate,
shakeOffsetTime
);
}
}
function KillBullet() {
local int i;
if (bulletTrail != none) {
for (i = 0; i < bulletTrail.Emitters.Length; i ++) {
if(bulletTrail.Emitters[i] == none)
if (bulletTrail.Emitters[i] == none) {
continue;
}
bulletTrail.Emitters[i].ParticlesPerSecond = 0;
bulletTrail.Emitters[i].InitialParticlesPerSecond = 0;
bulletTrail.Emitters[i].RespawnDeadParticles = false;
@ -812,6 +1002,7 @@ function KillBullet(){
bulletTrail.SetBase(none);
bulletTrail.AutoDestroy = true;
}
if (bulletXTrail != none) {
bulletXTrail.mRegen = false;
bulletXTrail.LifeSpan = LifeSpan;
@ -821,12 +1012,12 @@ function KillBullet(){
SoundVolume = 0;
LifeSpan = FMin(LifeSpan, 0.1);
}
event Destroyed() {
KillBullet();
}
defaultproperties
{
defaultproperties {
insideBouncesLeft=2
trajUpdFreq=0.100000
maxTraceCycles=128