NicePack/sources/Zeds/Mean/MeanZombieStalker.uc
2022-01-23 17:03:23 +04:00

276 lines
8.7 KiB
Ucode

class MeanZombieStalker extends NiceZombieStalker;
#exec OBJ LOAD FILE=MeanZedSkins.utx
simulated function Tick(float DeltaTime)
{
Super(NiceMonster).Tick(DeltaTime);
if(Role == ROLE_Authority && bShotAnim && !bWaitForAnim){
if( LookTarget!=none ) {
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
}
}
if(Level.NetMode == NM_DedicatedServer)
return; // Servers aren't interested 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;
if(LocalKFHumanPawn != none && LocalKFHumanPawn.Health > 0 && LocalKFHumanPawn.ShowStalkers() &&
VSizeSquared(Location - LocalKFHumanPawn.Location) < LocalKFHumanPawn.GetStalkerViewDistanceMulti() * 640000.0) // 640000 = 800 Units
bSpotted = True;
else
bSpotted = false;
if(!bSpotted && !bCloaked && Skins[0] != Combiner'MeanZedSkins.stalker_cmb')
UncloakStalker();
else if (Level.TimeSeconds - LastUncloakTime > 1.2){
// if we're uberbrite, turn down the light
if( bSpotted && Skins[0] != Finalblend'KFX.StalkerGlow' ){
bUnlit = false;
CloakStalker();
}
else if(Skins[0] != Shader'MeanZedSkins.stalker_invisible')
CloakStalker();
}
}
}
simulated function CloakStalker()
{
// No cloaking if zapped
if( bZapped )
{
return;
}
if ( bSpotted )
{
if( Level.NetMode == NM_DedicatedServer )
return;
Skins[0] = Finalblend'KFX.StalkerGlow';
Skins[1] = Finalblend'KFX.StalkerGlow';
bUnlit = true;
return;
}
if ( !bDecapitated ) // No head, no cloak, honey. updated : Being charred means no cloak either :D Not.
{
Visibility = 1;
bCloaked = true;
if( Level.NetMode == NM_DedicatedServer )
Return;
Skins[0] = Shader'MeanZedSkins.stalker_invisible';
Skins[1] = Shader'MeanZedSkins.stalker_invisible';
// 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
// added Controller check here
if (Level.NetMode!=NM_Client && !KFGameType(Level.Game).bDidStalkerInvisibleMessage && FRand()<0.25 && Controller != none && 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] != Combiner'MeanZedSkins.stalker_cmb' )
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
if (PlayerShadow != none)
PlayerShadow.bShadowActive = true;
bAcceptsProjectors = true;
SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
}
}
}
simulated function SetZappedBehavior()
{
super(NiceMonster).SetZappedBehavior();
bUnlit = false;
// Handle setting the zed to uncloaked so the zapped overlay works properly
if( Level.Netmode != NM_DedicatedServer )
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
if (PlayerShadow != none)
PlayerShadow.bShadowActive = true;
bAcceptsProjectors = true;
SetOverlayMaterial(Material'KFZED_FX_T.Energy.ZED_overlay_Hit_Shdr', 999, true);
}
}
function RangedAttack(Actor A) {
if ( bShotAnim || Physics == PHYS_Swimming)
return;
else if ( CanAttack(A) ) {
bShotAnim = true;
SetAnimAction('ClawAndMove');
//PlaySound(sound'Claw2s', SLOT_none); KFTODO: Replace this
return;
}
}
// Copied from the Gorefast code
// Overridden to handle playing upper body only attacks when moving
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 the Gorefast code, updated with the stalker attacks
// Handle playing the anim action on the upper body only if we're attacking and moving
simulated function int AttackAndMoveDoAnimAction( name AnimName ) {
local int meleeAnimIndex;
if( AnimName == 'ClawAndMove' ) {
meleeAnimIndex = Rand(3);
AnimName = meleeAnims[meleeAnimIndex];
}
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 );
}
function bool MeleeDamageTarget(int hitdamage, vector pushdir)
{
local bool result;
local float effectStrenght;
local NiceHumanPawn targetPawn;
result = super(NiceMonster).MeleeDamageTarget(hitdamage, pushdir);
// if true means we checked ctlr and ctrl.target != none
if (result)
targetPawn = NiceHumanPawn(Controller.Target);
if (result && targetPawn != none)
{
if (targetPawn.ShieldStrength > 100)
return result;
else if (targetPawn.ShieldStrength <= 0)
effectStrenght = 1.0;
else
effectStrenght = (100 - targetPawn.ShieldStrength) * 0.01;
MakeBleed(targetPawn, effectStrenght);
}
return result;
}
final private function MakeBleed(NiceHumanPawn poorpawn, coerce int effectStrenght)
{
local Inventory I;
local MeanBleedInventory bleedinv;
local bool bFoundPoison;
if (poorpawn.Inventory != none)
{
for (I = poorpawn.Inventory; I != none; I = I.Inventory)
{
if (MeanBleedInventory(I) != none)
{
bleedinv = MeanBleedInventory(I);
bFoundPoison = true;
bleedinv.stalker = self;
bleedinv.bleedLevel = effectStrenght;
// reset bleed count
bleedinv.maxBleedCount = bleedinv.default.maxBleedCount;
}
}
}
if (!bFoundPoison)
{
I = Controller.Spawn(class<Inventory>(DynamicLoadObject(string(class'MeanBleedInventory'), class'Class')));
bleedinv = MeanBleedInventory(I);
bleedinv.stalker = self;
bleedinv.bleedLevel = effectStrenght;
bleedinv.GiveTo(poorpawn);
}
}
function RemoveHead()
{
Super(NiceMonster).RemoveHead();
if (!bCrispified)
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
}
}
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
{
Super(NiceMonster).PlayDying(DamageType,HitLoc);
if(bUnlit)
bUnlit=!bUnlit;
LocalKFHumanPawn = none;
if (!bCrispified)
{
Skins[1] = FinalBlend'MeanZedSkins.stalker_fb';
Skins[0] = Combiner'MeanZedSkins.stalker_cmb';
}
}
static simulated function PreCacheMaterials(LevelInfo myLevel)
{//should be derived and used.
myLevel.AddPrecacheMaterial(Combiner'MeanZedSkins.stalker_cmb');
myLevel.AddPrecacheMaterial(Combiner'MeanZedSkins.stalker_env_cmb');
myLevel.AddPrecacheMaterial(Texture'MeanZedSkins.stalker_diff');
myLevel.AddPrecacheMaterial(Texture'MeanZedSkins.stalker_spec');
myLevel.AddPrecacheMaterial(Material'MeanZedSkins.stalker_invisible');
myLevel.AddPrecacheMaterial(Combiner'MeanZedSkins.StalkerCloakOpacity_cmb');
myLevel.AddPrecacheMaterial(Material'MeanZedSkins.StalkerCloakEnv_rot');
myLevel.AddPrecacheMaterial(Material'MeanZedSkins.stalker_opacity_osc');
myLevel.AddPrecacheMaterial(Material'KFCharacters.StalkerSkin');
}
defaultproperties
{
MeleeDamage=6
MenuName="Mean Stalker"
Skins(0)=Shader'MeanZedSkins.stalker_invisible'
Skins(1)=Shader'MeanZedSkins.stalker_invisible'
}