140 lines
7.8 KiB
Ucode
140 lines
7.8 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'
|
|
}
|