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

276 lines
7.7 KiB
Ucode

class StinkyClot extends ZombieClot;
var() name CompleteAnim;
var() name GrabBone;
var float NextStuckTestTime;
var transient vector OldLocation;
var transient int StuckCounter;
// Teleporting
const TELEPORT_NONE = 0;
const TELEPORT_FADEOUT = 1;
const TELEPORT_FADEIN = 2;
var byte TeleportPhase, ClientTeleportPhase;
var transient vector TeleportLocation;
var transient float AlphaFader;
var string TeleportSoundRef;
var sound TeleportSound;
var transient Actor LastMoveTarget[2];
replication
{
reliable if (Role == ROLE_Authority)
TeleportPhase;
}
simulated function PostBeginPlay()
{
super.PostBeginPlay();
if ( TeleportSound == none ) {
TeleportSound = sound(DynamicLoadObject(TeleportSoundRef, class'Sound', true));
default.TeleportSound = TeleportSound;
}
}
simulated function PostNetBeginPlay()
{
super.PostNetBeginPlay();
SetSkin();
}
simulated event PostNetReceive()
{
super.PostNetReceive();
if (ClientTeleportPhase != TeleportPhase) {
ClientTeleportPhase = TeleportPhase;
if (TeleportPhase == TELEPORT_FADEIN) {
AlphaFader = 1;
PlaySound(TeleportSound, SLOT_Interact, 4.0);
}
else {
AlphaFader = 255;
}
}
SetSkin();
}
simulated function Tick(float dt)
{
super.Tick(dt);
if ( Controller != none && Controller.MoveTarget != none && Controller.MoveTarget != self
&& Controller.IsInState('Moving') )
{
if ( LastMoveTarget[0] != Controller.MoveTarget && LastMoveTarget[1] != Controller.MoveTarget ) {
LastMoveTarget[1] = LastMoveTarget[0];
LastMoveTarget[0] = Controller.MoveTarget;
OldLocation = Location;
StuckCounter = 0;
NextStuckTestTime = Level.TimeSeconds + 1;
}
else if ( Level.TimeSeconds > NextStuckTestTime ) {
NextStuckTestTime = Level.TimeSeconds + 1;
OldLocation.Z = Location.Z; // ignore Z difference, because zed may be constantly jumping
if ( VSizeSquared(Location - OldLocation) < 10000 ) {
StuckCounter += 3; // 10 seconds to move away from the current location
}
else {
OldLocation = Location;
StuckCounter += 1; // 30s to reach the target
}
if ( StuckCounter >= 30 ) {
// if can't reach the target - simply teleport to it
TeleportLocation = Controller.MoveTarget.Location;
TeleportLocation.Z += CollisionHeight;
StartTeleport();
}
}
}
if ( TeleportPhase != TELEPORT_NONE ) {
switch ( TeleportPhase ) {
case TELEPORT_FADEOUT:
AlphaFader = FMax(AlphaFader - dt * 512, 0);
if (Level.NetMode != NM_Client && AlphaFader == 0) {
DoTeleport();
}
break;
case TELEPORT_FADEIN:
AlphaFader = FMin(AlphaFader + dt * 256, 255);
if (Level.NetMode != NM_Client && AlphaFader == 255) {
TeleportPhase = TELEPORT_NONE;
if (Level.NetMode != NM_DedicatedServer)
SetSkin();
}
break;
}
if (Level.NetMode != NM_DedicatedServer && ColorModifier(Skins[0]) != none) {
ColorModifier(Skins[0]).Color.A = AlphaFader;
}
}
}
simulated function SetSkin()
{
if ( bBlockActors && TeleportPhase == TELEPORT_NONE) {
Skins[0] = default.Skins[0];
if ( bCrispified )
ZombieCrispUp();
}
else {
Skins[0] = ColorModifier'ScrnTex.Zeds.StinkyColor';
ColorModifier(Skins[0]).Color.A = AlphaFader;
ColorModifier(Skins[0]).AlphaBlend = TeleportPhase != TELEPORT_NONE;
}
}
function StartTeleport()
{
TeleportPhase = TELEPORT_FADEOUT;
AlphaFader = 255;
if ( Level.NetMode != NM_DedicatedServer ) {
SetSkin();
}
StuckCounter = 0;
NextStuckTestTime = Level.TimeSeconds + 5;
}
function DoTeleport()
{
TeleportPhase = TELEPORT_FADEIN;
AlphaFader = 0;
if ( Level.NetMode != NM_DedicatedServer ) {
SetSkin();
}
Velocity = vect(0,0,0);
Acceleration = vect(0,0,0);
if (SetLocation(TeleportLocation))
{
PlaySound(TeleportSound, SLOT_Interact, 4.0);
Controller.StopWaiting();
}
}
function TakeDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class<DamageType> damageType, optional int HitIndex )
{
if ( bBlockActors )
super.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType, HitIndex);
// stinky clot does not take damage
}
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
{
local int i;
local TheGuardian gnome;
for( i=0; i<Attached.length; i++ ) {
gnome = TheGuardian(Attached[i]);
if ( gnome != none )
gnome.PawnBaseDied();
}
super.Died(Killer,damageType,HitLocation);
}
function bool FlipOver()
{
return false;
}
function RemoveHead()
{
KilledBy(LastDamagedBy);
}
// removed references to KFMonsterController
event Bump(actor Other)
{
if ( KFDoorMover(Other) != none )
BlowUpDoor(KFDoorMover(Other));
else
super(Monster).Bump(Other);
}
function BlowUpDoor(KFDoorMover door)
{
local int i;
local KFUseTrigger key;
if ( door == none || !door.bClosed )
return;
key = door.MyTrigger;
if ( key != none ) {
for ( i=0; i<key.DoorOwners.Length; ++i ) {
if ( !key.DoorOwners[i].bDoorIsDead )
key.DoorOwners[i].GoBang(self, Location, vector(Rotation), none);
}
}
else
door.GoBang(self, Location, vector(Rotation), none);
}
function KickActor()
{
// no KFMonsterController to perform a kick
}
simulated function SetBurningBehavior()
{
}
simulated function UnSetBurningBehavior()
{
}
simulated function float GetOriginalGroundSpeed()
{
return GroundSpeed;
}
defaultproperties
{
CompleteAnim="ClotPunt"
GrabBone="CHR_RArmPalm"
TeleportSoundRef="ScrnZedPack_S.Shiver.ShiverWarpGroup"
EventClasses(0)="ScrnBalanceSrv.StinkyClot"
MoanVoice=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Talk'
MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_HitPlayer'
JumpSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Jump'
bUseExtendedCollision=False
DetachedArmClass=Class'KFChar.SeveredArmClot'
DetachedLegClass=Class'KFChar.SeveredLegClot'
DetachedHeadClass=Class'KFChar.SeveredHeadClot'
HeadHealth=1000.000000
HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Pain'
DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Death'
ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
GroundSpeed=55.000000
JumpZ=480.000000
HealthMax=1000.000000
Health=1000
MenuName="Stinky Clot"
ControllerClass=Class'ScrnBalanceSrv.StinkyController'
bAlwaysRelevant=True
AmbientSound=Sound'KF_BaseClot.Clot_Idle1Loop'
Mesh=SkeletalMesh'KF_Freaks_Trip.CLOT_Freak'
DrawScale=0.500000
Skins(0)=Combiner'KF_Specimens_Trip_T.clot_cmb'
CollisionRadius=13.000000
CollisionHeight=22.000000
bBlockActors=False
}