rott/kf_sources/FoundryObj/Classes/PipeBombPlaceable.uc
2026-07-14 20:27:09 +07:00

288 lines
7.9 KiB
Ucode

class PipeBombPlaceable extends PipeBombProjectile
placeable;
var(PipeBombProjectile) int TeamIndex; // team which "placed" pipebomb. Use to avoid unnecessary friendly fire
var(PipeBombProjectile) int EnemyCountdown; // Countdown to explosion after enemy detected
var(PipeBombProjectile) bool bTriggerOnEnemy; // team which "placed" pipebomb. Use to avoid unnecessary friendly fire
var(PipeBombProjectile) bool bImmuneToDamage; // team which "placed" pipebomb. Use to avoid unnecessary friendly fire
var(PipeBombProjectile) float MyDamage;
var(PipeBombProjectile) float MyDamageRadius;
var(PipeBombProjectile) float MyMomentumTransfer;
static function PreloadAssets()
{
}
static function bool UnloadAssets()
{
return true;
}
simulated function PostBeginPlay()
{
if ( Level.NetMode != NM_DedicatedServer)
{
BombLight = Spawn(class'PipebombLight',self);
BombLight.SetBase(self);
}
// removed initial velocity
Countdown = EnemyCountdown;
Damage = MyDamage;
DamageRadius = MyDamageRadius;
MomentumTransfer = MyMomentumTransfer;
PlacedTeam = TeamIndex;
SetTimer(1.0, True); // this projectile is supposed to be placed in a map, so arm it immediately
}
function Timer()
{
local Pawn CheckPawn;
local float ThreatLevel;
if( !bHidden && !bTriggered )
{
if( ArmingCountDown >= 0 )
{
ArmingCountDown -= 0.1;
if( ArmingCountDown <= 0 )
{
SetTimer(1.0,True);
}
}
else
{
// Check for enemies
if( !bEnemyDetected )
{
bAlwaysRelevant=false;
PlaySound(BeepSound,,0.5,,50.0);
if ( bTriggerOnEnemy ) {
foreach VisibleCollidingActors( class 'Pawn', CheckPawn, DetectionRadius, Location )
{
if( CheckPawn == Instigator || KFGameType(Level.Game).FriendlyFireScale > 0 &&
CheckPawn.PlayerReplicationInfo != none &&
CheckPawn.PlayerReplicationInfo.Team.TeamIndex == PlacedTeam )
{
// Make the thing beep if someone on our team is within the detection radius
// This gives them a chance to get out of the way
ThreatLevel += 0.001;
}
else
{
if( (CheckPawn != Instigator) && (CheckPawn.Role == ROLE_Authority) &&
((CheckPawn.PlayerReplicationInfo != none && CheckPawn.PlayerReplicationInfo.Team.TeamIndex != PlacedTeam) ||
CheckPawn.GetTeamNum() != PlacedTeam))
{
if( KFMonster(CheckPawn) != none )
{
ThreatLevel += KFMonster(CheckPawn).MotionDetectorThreat;
if( ThreatLevel >= ThreatThreshhold )
{
bEnemyDetected=true;
SetTimer(0.15,True);
}
}
else
{
bEnemyDetected=true;
SetTimer(0.15,True);
}
}
}
}
if( ThreatLevel >= ThreatThreshhold )
{
bEnemyDetected=true;
SetTimer(0.15,True);
}
else if( ThreatLevel > 0 )
{
SetTimer(0.5,True);
}
else
{
SetTimer(1.0,True);
}
}
else {
SetTimer(1.0,True);
}
}
// Play some fast beeps and blow up
else
{
bAlwaysRelevant=true;
Countdown--;
if( CountDown > 0 )
{
PlaySound(BeepSound,SLOT_Misc,2.0,,150.0);
}
else
{
Explode(Location, vector(Rotation));
}
}
}
}
else
{
Destroy();
}
}
simulated function Explode(vector HitLocation, vector HitNormal)
{
super.Explode(HitLocation, HitNormal);
TriggerEvent(Event, self, Instigator);
}
function Trigger( actor Other, pawn EventInstigator )
{
if ( !bHidden && !bTriggered ) {
Instigator = EventInstigator;
Explode(Location, vector(Rotation));
}
}
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
{
if ( bImmuneToDamage )
return;
Instigator = InstigatedBy;
super.TakeDamage(Damage, InstigatedBy, Hitlocation, Momentum, damageType, HitIndex);
}
simulated function HurtRadius( float DamageAmount, float DamageRadius, class<DamageType> DamageType, float Momentum, vector HitLocation )
{
local actor Victims;
local float damageScale, dist;
local vector dir;
local int NumKilled;
local KFMonster KFMonsterVictim;
local Pawn P;
local KFPawn KFP;
local array<Pawn> CheckedPawns;
local int i;
local bool bAlreadyChecked;
if ( bHurtEntry )
return;
bHurtEntry = true;
foreach CollidingActors (class 'Actor', Victims, DamageRadius, HitLocation)
{
// don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag
if( (Victims != self) && (Hurtwall != Victims) && (Victims.Role == ROLE_Authority) && !Victims.IsA('FluidSurfaceInfo')
&& ExtendedZCollision(Victims)==None )
{
if( (Instigator==None || Instigator.Health<=0) && KFPawn(Victims)!=None )
Continue;
dir = Victims.Location - HitLocation;
dist = FMax(1,VSize(dir));
dir = dir/dist;
damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius);
if ( Instigator == None || Instigator.Controller == None )
{
Victims.SetDelayedDamageInstigatorController( InstigatorController );
}
P = Pawn(Victims);
if( P != none )
{
for (i = 0; i < CheckedPawns.Length; i++)
{
if (CheckedPawns[i] == P)
{
bAlreadyChecked = true;
break;
}
}
if( bAlreadyChecked )
{
bAlreadyChecked = false;
P = none;
continue;
}
KFMonsterVictim = KFMonster(Victims);
if( KFMonsterVictim != none && KFMonsterVictim.Health <= 0 )
{
KFMonsterVictim = none;
}
KFP = KFPawn(Victims);
if( KFMonsterVictim != none )
{
damageScale *= KFMonsterVictim.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity));
}
else if( KFP != none )
{
// don't hurt the same team
if ( KFP.PlayerReplicationInfo != none && KFP.PlayerReplicationInfo.Team != none
&& KFP.PlayerReplicationInfo.Team.TeamIndex == PlacedTeam )
damageScale = 0;
else {
damageScale *= KFP.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity));
// Reduce damage to poeple so I can make the damage radius a bit bigger for killing zeds
damageScale *= 0.5;
}
}
CheckedPawns[CheckedPawns.Length] = P;
if ( damageScale <= 0)
{
P = none;
continue;
}
else
{
//Victims = P;
P = none;
}
}
Victims.TakeDamage(damageScale * DamageAmount,Instigator,Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius)
* dir,(damageScale * Momentum * dir),DamageType);
if( Role == ROLE_Authority && KFMonsterVictim != none && KFMonsterVictim.Health <= 0 )
{
NumKilled++;
}
if (Vehicle(Victims) != None && Vehicle(Victims).Health > 0)
{
Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, InstigatorController, DamageType, Momentum, HitLocation);
}
}
}
bHurtEntry = false;
}
defaultproperties
{
TeamIndex=255
EnemyCountdown=5
bTriggerOnEnemy=True
MyDamage=1500.000000
ArmingCountDown=0.000000
ExplodeSounds(0)=SoundGroup'Inf_Weapons.antitankmine.antitankmine_explode01'
ExplodeSounds(1)=SoundGroup'Inf_Weapons.antitankmine.antitankmine_explode02'
ExplodeSounds(2)=SoundGroup'Inf_Weapons.antitankmine.antitankmine_explode03'
StaticMesh=StaticMesh'KF_pickups2_Trip.Supers.Pipebomb_Pickup'
}