NicePack/sources/Zeds/Nice/NiceZombieGhost.uc

243 lines
7.6 KiB
Ucode

// Completely invisible Stalker
// (c) PooSH, 2014
// used 'ClawAndMove' code from Scary Ghost's SuperStaler
// Ported to 'NiceMonster' parent class
class NiceZombieGhost extends NiceZombieStalker;
// max distance squared for player to see cloacked Stalkers.
// Beyond that distance Stalkers will appear completely invisible.
var float CloakDistanceSqr;
// Unclock distance squared for Commandos
var float UncloakDistanceSqr;
var const Material CloakMat;
var const Material InvisibleMat;
var const Material UncloakMat, UncloakFBMat;
var const Material GlowFX;
static simulated function PreCacheMaterials(LevelInfo myLevel)
{
myLevel.AddPrecacheMaterial(default.CloakMat);
myLevel.AddPrecacheMaterial(default.InvisibleMat);
myLevel.AddPrecacheMaterial(default.UncloakMat);
myLevel.AddPrecacheMaterial(default.UncloakFBMat);
myLevel.AddPrecacheMaterial(default.GlowFX);
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.stalker_env_cmb');
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.stalker_diff');
myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.stalker_spec');
myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.StalkerCloakOpacity_cmb');
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.StalkerCloakEnv_rot');
myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.stalker_opacity_osc');
myLevel.AddPrecacheMaterial(Material'KFCharacters.StalkerSkin');
}
simulated function PostNetBeginPlay()
{
super.PostNetBeginPlay();
if ( LocalKFHumanPawn != none ) {
CloakDistanceSqr = fmax(CloakDistanceSqr, 3.0 * UncloakDistanceSqr * LocalKFHumanPawn.GetStalkerViewDistanceMulti());
UncloakDistanceSqr *= LocalKFHumanPawn.GetStalkerViewDistanceMulti();
}
}
function RenderOverlays(Canvas Canvas)
{
Canvas.SetDrawColor(0, 92, 255, 255);
super.RenderOverlays(Canvas);
}
// makes Stalker invisible or glowing (for commando)
simulated function CloakStalker()
{
// No cloaking if zapped
if( bZapped )
{
return;
}
if ( bSpotted ) {
if( Level.NetMode == NM_DedicatedServer )
return;
Skins[0] = GlowFX;
Skins[1] = GlowFX;
bUnlit = true;
}
else if ( !bDecapitated && !bCrispified ) // No head, no cloak, honey. updated : Being charred means no cloak either :D
{
Visibility = 1;
bCloaked = true;
if( Level.NetMode == NM_DedicatedServer )
Return;
Skins[0] = InvisibleMat;
Skins[1] = InvisibleMat;
bUnlit = false;
// Invisible - no shadow
if(PlayerShadow != none)
PlayerShadow.bShadowActive = false;
if(RealTimeShadow != none)
RealTimeShadow.Destroy();
// Remove/disallow projectors on invisible people
Projectors.Remove(0, Projectors.Length);
bAcceptsProjectors = false;
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
}
}
simulated function UnCloakStalker()
{
if( bZapped )
{
return;
}
if( !bCrispified )
{
LastUncloakTime = Level.TimeSeconds;
Visibility = default.Visibility;
bCloaked = false;
bUnlit = false;
// 25% chance of our Enemy saying something about us being invisible
if( Level.NetMode!=NM_Client && !KFGameType(Level.Game).bDidStalkerInvisibleMessage && FRand()<0.25 && Controller.Enemy!=none &&
PlayerController(Controller.Enemy.Controller)!=none )
{
PlayerController(Controller.Enemy.Controller).Speech('AUTO', 17, "");
KFGameType(Level.Game).bDidStalkerInvisibleMessage = true;
}
if( Level.NetMode == NM_DedicatedServer )
Return;
if ( Skins[0] != UncloakMat )
{
Skins[1] = FinalBlend'KF_Specimens_Trip_T.stalker_fb';
Skins[0] = UncloakMat;
if (PlayerShadow != none)
PlayerShadow.bShadowActive = true;
bAcceptsProjectors = true;
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
}
}
}
function RemoveHead()
{
Super(NiceMonster).RemoveHead();
if (!bCrispified)
{
Skins[1] = UncloakFBMat;
Skins[0] = UncloakMat;
}
}
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
{
Super(NiceMonster).PlayDying(DamageType,HitLoc);
if(bUnlit)
bUnlit=!bUnlit;
LocalKFHumanPawn = none;
if (!bCrispified)
{
Skins[1] = UncloakFBMat;
Skins[0] = UncloakMat;
}
}
simulated function Tick(float DeltaTime)
{
local float DistanceSqr;
Super(NiceMonster).Tick(DeltaTime);
// Keep the stalker moving toward its target when attacking
if( Role == ROLE_Authority && bShotAnim && !bWaitForAnim && !bZapped ) {
if( LookTarget!=none ) {
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
}
}
if( Level.NetMode==NM_DedicatedServer )
Return; // Servers aren't intrested in this info.
if( bZapped ) {
// Make sure we check if we need to be cloaked as soon as the zap wears off
NextCheckTime = Level.TimeSeconds;
}
else if( Level.TimeSeconds > NextCheckTime && Health > 0 )
{
NextCheckTime = Level.TimeSeconds + 0.5;
bSpotted = false;
if ( LocalKFHumanPawn != none ) {
DistanceSqr = VSizeSquared(Location - LocalKFHumanPawn.Location);
if( LocalKFHumanPawn.Health > 0 && LocalKFHumanPawn.ShowStalkers()
&& DistanceSqr < UncloakDistanceSqr )
{
bSpotted = True;
if ( Skins[0] != GlowFX ) {
Skins[0] = GlowFX;
Skins[1] = GlowFX;
bUnlit = true; }
}
else if ( DistanceSqr < CloakDistanceSqr ) {
if ( bCloaked && Skins[0] != CloakMat ) {
Skins[0] = CloakMat;
Skins[1] = CloakMat;
bUnlit = false;
}
}
else if ( Skins[0] != InvisibleMat ) {
CloakStalker();
}
}
}
}
function RangedAttack(Actor A)
{
if ( !bShotAnim && Physics != PHYS_Swimming && CanAttack(A) ) {
bShotAnim = true;
SetAnimAction('ClawAndMove');
}
}
// copied from ZombieSuperStalker (c) Scary Ghost
simulated event SetAnimAction(name NewAction)
{
if( NewAction=='' )
Return;
ExpectingChannel = AttackAndMoveDoAnimAction(NewAction);
bWaitForAnim= false;
if( Level.NetMode!=NM_Client ) {
AnimAction = NewAction;
bResetAnimAct = True;
ResetAnimActTime = Level.TimeSeconds+0.3;
}
}
// copied from ZombieSuperStalker (c) Scary Ghost
simulated function int AttackAndMoveDoAnimAction( name AnimName )
{
local int meleeAnimIndex;
local float duration;
if( AnimName == 'ClawAndMove' ) {
meleeAnimIndex = Rand(3);
AnimName = meleeAnims[meleeAnimIndex];
duration= GetAnimDuration(AnimName, 1.0);
}
if( AnimName=='StalkerSpinAttack' || AnimName=='StalkerAttack1' || AnimName=='JumpAttack') {
AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
PlayAnim(AnimName,, 0.1, 1);
return 1;
}
return super.DoAnimAction( AnimName );
}
defaultproperties
{
CloakDistanceSqr=62500.000000
UncloakDistanceSqr=360000.000000
CloakMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
InvisibleMat=Shader'KF_Specimens_Trip_T.patriarch_invisible'
UncloakMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
UncloakFBMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
MenuName="Ghost"
Skins(0)=Shader'KF_Specimens_Trip_T.patriarch_invisible'
Skins(1)=Shader'KF_Specimens_Trip_T.patriarch_invisible'
}