First commit
This commit is contained in:
commit
5b48414900
263 changed files with 24830 additions and 0 deletions
33
sources/Zeds/Mean/MeanHuskFireProjectile.uc
Normal file
33
sources/Zeds/Mean/MeanHuskFireProjectile.uc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
class MeanHuskFireProjectile extends NiceHuskFireProjectile;
|
||||
simulated singular function Touch(Actor Other){
|
||||
local vector HitLocation, HitNormal;
|
||||
//Don't touch bulletwhip attachment. Taken from HuskFireProjectile
|
||||
if ( Other == none || KFBulletWhipAttachment(Other) != none )
return;
|
||||
if ( Other.bProjTarget || Other.bBlockActors ) {
LastTouched = Other;
if ( Velocity == vect(0,0,0) || Other.IsA('Mover') ) {
ProcessTouch(Other,Location);
LastTouched = none;
return;
}
|
||||
if ( Other.TraceThisActor(HitLocation, HitNormal, Location, Location - 2*Velocity, GetCollisionExtent()) )
HitLocation = Location;
|
||||
ProcessTouch(Other, HitLocation);
LastTouched = none;
if ( (Role < ROLE_Authority) && (Other.Role == ROLE_Authority) && (Pawn(Other) != none) )
ClientSideTouch(Other, HitLocation);
|
||||
}
|
||||
}
|
||||
// Don't hit Zed extra collision cylinders
|
||||
simulated function ProcessTouch(Actor Other, Vector HitLocation) {
|
||||
// Don't let it hit this player, or blow up on another player
|
||||
if (Other == none || Other == Instigator || Other.Base == Instigator)
return;
|
||||
// Don't collide with bullet whip attachments
|
||||
if (KFBulletWhipAttachment(Other) != none) {
return;
|
||||
}
|
||||
// Use the instigator's location if it exists. This fixes issues with
|
||||
// the original location of the projectile being really far away from
|
||||
// the real Origloc due to it taking a couple of milliseconds to
|
||||
// replicate the location to the client and the first replicated location has
|
||||
// already moved quite a bit.
|
||||
if (Instigator != none) {
OrigLoc = Instigator.Location;
|
||||
}
|
||||
if (!bDud && ((VSizeSquared(Location - OrigLoc) < ArmDistSquared) || OrigLoc == vect(0,0,0))) {
if( Role == ROLE_Authority ) {
AmbientSound=none;
PlaySound(Sound'ProjectileSounds.PTRD_deflect04',,2.0);
Other.TakeDamage( ImpactDamage, Instigator, HitLocation, Normal(Velocity), ImpactDamageType );
}
|
||||
bDud = true;
Velocity = vect(0,0,0);
LifeSpan=1.0;
SetPhysics(PHYS_Falling);
|
||||
}
|
||||
if (!bDud) {
Explode(HitLocation,Normal(HitLocation-Other.Location));
|
||||
}
|
||||
}
|
||||
defaultproperties
|
||||
{
additionalDamagePart=0.250000
|
||||
}
|
||||
18
sources/Zeds/Mean/MeanPoisonInventory.uc
Normal file
18
sources/Zeds/Mean/MeanPoisonInventory.uc
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
class MeanPoisonInventory extends Inventory;
|
||||
var float poisonStartTime, maxSpeedPenaltyTime, poisonSpeedDown;
|
||||
simulated function Tick(float DeltaTime) {
|
||||
if(Level.TimeSeconds - poisonStartTime > maxSpeedPenaltyTime)
Destroy();
|
||||
}
|
||||
simulated function float GetMovementModifierFor(Pawn InPawn){
|
||||
local float actualSpeedDown;
|
||||
local class<NiceVeterancyTypes> niceVet;
|
||||
|
||||
niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(InPawn.PlayerReplicationInfo);
|
||||
if(niceVet != none){
actualSpeedDown = 1.0 - (1.0 - poisonSpeedDown) * niceVet.static.SlowingModifier(KFPlayerReplicationInfo(InPawn.PlayerReplicationInfo));
actualSpeedDown = FMax(0.0, FMin(1.0, actualSpeedDown));
return actualSpeedDown;
|
||||
}
|
||||
// If something went wrong - ignore slowdown altogether
|
||||
return 1.0;
|
||||
}
|
||||
defaultproperties
|
||||
{
maxSpeedPenaltyTime=5.000000
poisonSpeedDown=0.600000
|
||||
}
|
||||
52
sources/Zeds/Mean/MeanZombieBloat.uc
Normal file
52
sources/Zeds/Mean/MeanZombieBloat.uc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
class MeanZombieBloat extends NiceZombieBloat;
|
||||
#exec OBJ LOAD FILE=MeanZedSkins.utx
|
||||
/**
|
||||
* bAmIBarfing true if the bloat is in the barf animation
|
||||
*/
|
||||
var bool bAmIBarfing;
|
||||
/**
|
||||
* bileCoolDownTimer timer that counts to when the bloat will spawn another set of pile pellets
|
||||
* bileCoolDownMax max time in between pellet spawns
|
||||
*/
|
||||
var float bileCoolDownTimer,bileCoolDownMax;
|
||||
/**
|
||||
* Spawn extra sets of bile pellets here once the bile cool down timer
|
||||
* has reached the max limit
|
||||
*/
|
||||
simulated function Tick(float DeltaTime) {
|
||||
Super.Tick(DeltaTime);
|
||||
if(!bDecapitated && bAmIBarfing) {
bileCoolDownTimer+= DeltaTime;
if(bileCoolDownTimer >= bileCoolDownMax) {
SpawnTwoShots();
bileCoolDownTimer= 0.0;
}
|
||||
}
|
||||
}
|
||||
function Touch(Actor Other) {
|
||||
super.Touch(Other);
|
||||
if (Other.IsA('ShotgunBullet')) {
ShotgunBullet(Other).Damage = 0;
|
||||
}
|
||||
}
|
||||
function RangedAttack(Actor A) {
|
||||
local int LastFireTime;
|
||||
if ( bShotAnim )
return;
|
||||
if ( Physics == PHYS_Swimming ) {
SetAnimAction('Claw');
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
|
||||
}
|
||||
else if ( VSize(A.Location - Location) < MeleeRange + CollisionRadius + A.CollisionRadius ) {
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
SetAnimAction('Claw');
//PlaySound(sound'Claw2s', SLOT_Interact); KFTODO: Replace this
Controller.bPreparingMove = true;
Acceleration = vect(0,0,0);
|
||||
}
|
||||
else if ( (KFDoorMover(A) != none || VSize(A.Location-Location) <= 250) && !bDecapitated ) {
bShotAnim = true;
SetAnimAction('ZombieBarfMoving');
RunAttackTimeout = GetAnimDuration('ZombieBarf', 1.0);
bMovingPukeAttack=true;
|
||||
// Randomly send out a message about Bloat Vomit burning(3% chance)
if ( FRand() < 0.03 && KFHumanPawn(A) != none && PlayerController(KFHumanPawn(A).Controller) != none ) {
PlayerController(KFHumanPawn(A).Controller).Speech('AUTO', 7, "");
}
|
||||
}
|
||||
}
|
||||
//ZombieBarf animation triggers this
|
||||
function SpawnTwoShots() {
|
||||
super.SpawnTwoShots();
|
||||
bAmIBarfing= true;
|
||||
}
|
||||
simulated function AnimEnd(int Channel) {
|
||||
local name Sequence;
|
||||
local float Frame, Rate;
|
||||
|
||||
GetAnimParams( ExpectingChannel, Sequence, Frame, Rate );
|
||||
super.AnimEnd(Channel);
|
||||
if(Sequence == 'ZombieBarf')
bAmIBarfing= false;
|
||||
}
|
||||
defaultproperties
|
||||
{
bileCoolDownMax=0.750000
HeadHealth=125.000000
MenuName="Mean Bloat"
Skins(0)=Combiner'MeanZedSkins.bloat_cmb'
|
||||
}
|
||||
14
sources/Zeds/Mean/MeanZombieClot.uc
Normal file
14
sources/Zeds/Mean/MeanZombieClot.uc
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
class MeanZombieClot extends NiceZombieClot;
|
||||
#exec OBJ LOAD FILE=MeanZedSkins.utx
|
||||
function int ModBodyDamage(out int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class<NiceWeaponDamageType> damageType, float headshotLevel, KFPlayerReplicationInfo KFPRI, optional float lockonTime){
|
||||
local bool bDecreaseDamage;
|
||||
// Decrease damage if needed
|
||||
bDecreaseDamage = false;
|
||||
if(damageType != none)
bDecreaseDamage = (headshotLevel <= 0.0) && damageType.default.bCheckForHeadShots;
|
||||
if(damageType != none && damageType.default.heatPart > 0)
bDecreaseDamage = false;
|
||||
if(bDecreaseDamage && HeadHealth > 0)
Damage *= 0.5;
|
||||
return super.ModBodyDamage(Damage, instigatedBy, hitlocation, momentum, damageType, headshotLevel, KFPRI, lockonTime);
|
||||
}
|
||||
defaultproperties
|
||||
{
MenuName="Mean Clot"
Skins(0)=Combiner'MeanZedSkins.clot_cmb'
|
||||
}
|
||||
32
sources/Zeds/Mean/MeanZombieCrawler.uc
Normal file
32
sources/Zeds/Mean/MeanZombieCrawler.uc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
class MeanZombieCrawler extends NiceZombieCrawler;
|
||||
#exec OBJ LOAD FILE=MeanZedSkins.utx
|
||||
simulated function PostBeginPlay() {
|
||||
super.PostBeginPlay();
|
||||
PounceSpeed = Rand(221)+330;
|
||||
MeleeRange = Rand(41)+50;
|
||||
}
|
||||
/**
|
||||
* Copied from ZombieCrawler.Bump() but changed damage type
|
||||
* to be the new poison damage type
|
||||
*/
|
||||
event Bump(actor Other) {
|
||||
if(bPouncing && KFHumanPawn(Other) != none)
Poison(KFHumanPawn(Other));
|
||||
super.Bump(Other);
|
||||
}
|
||||
function bool MeleeDamageTarget(int hitdamage, vector pushdir) {
|
||||
local bool result;
|
||||
result= super.MeleeDamageTarget(hitdamage, pushdir);
|
||||
if(result && KFHumanPawn(Controller.Target) != none)
Poison(KFHumanPawn(Controller.Target));
|
||||
return result;
|
||||
}
|
||||
function Poison(KFHumanPawn poisonedPawn){
|
||||
local Inventory I;
|
||||
local bool bFoundPoison;
|
||||
if(poisonedPawn.Inventory != none){
for(I = poisonedPawn.Inventory; I != none; I = I.Inventory)
if(I != none && MeanPoisonInventory(I) != none){
bFoundPoison = true;
MeanPoisonInventory(I).poisonStartTime = Level.TimeSeconds;
}
|
||||
}
|
||||
if(!bFoundPoison){
I = Controller.Spawn(class<Inventory>(DynamicLoadObject("NicePack.MeanPoisonInventory", Class'Class')));
MeanPoisonInventory(I).poisonStartTime = Level.TimeSeconds;
I.GiveTo(poisonedPawn);
|
||||
}
|
||||
}
|
||||
defaultproperties
|
||||
{
GroundSpeed=190.000000
WaterSpeed=175.000000
MenuName="Mean Crawler"
Skins(0)=Combiner'MeanZedSkins.crawler_cmb'
|
||||
}
|
||||
42
sources/Zeds/Mean/MeanZombieFleshPound.uc
Normal file
42
sources/Zeds/Mean/MeanZombieFleshPound.uc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
class MeanZombieFleshPound extends NiceZombieFleshPound;
|
||||
#exec OBJ LOAD FILE=MeanZedSkins.utx
|
||||
state RageCharging
|
||||
{
|
||||
Ignores StartChargingFP;
|
||||
function bool CanGetOutOfWay()
|
||||
{
return false;
|
||||
}
|
||||
// Don't override speed in this state
|
||||
function bool CanSpeedAdjust()
|
||||
{
return false;
|
||||
}
|
||||
function BeginState()
|
||||
{
bChargingPlayer = true;
if( Level.NetMode!=NM_DedicatedServer )
ClientChargingAnims();
|
||||
RageEndTime = (Level.TimeSeconds + 15) + (FRand() * 18);
NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
function EndState()
|
||||
{
bChargingPlayer = false;
bFrustrated = false;
if(Controller != none)
NiceZombieFleshPoundController(Controller).RageFrustrationTimer = 0;
if( Health>0 && !bZapped )
{
SetGroundSpeed(GetOriginalGroundSpeed());
}
|
||||
if( Level.NetMode!=NM_DedicatedServer )
ClientChargingAnims();
|
||||
NetUpdateTime = Level.TimeSeconds - 1;
|
||||
}
|
||||
function Tick( float Delta )
|
||||
{
if( !bShotAnim )
{
SetGroundSpeed(OriginalGroundSpeed * 2.3);//2.0;
}
|
||||
// Keep the flesh pound moving toward its target when attacking
if( Role == ROLE_Authority && bShotAnim)
{
if( LookTarget!=none )
{
Acceleration = AccelRate * Normal(LookTarget.Location - Location);
}
}
|
||||
global.Tick(Delta);
|
||||
}
|
||||
function Bump( Actor Other )
|
||||
{
local float RageBumpDamage;
local KFMonster KFMonst;
|
||||
KFMonst = KFMonster(Other);
|
||||
// Hurt/Kill enemies that we run into while raging
if( !bShotAnim && KFMonst!=none && NiceZombieFleshPound(Other)==none && Pawn(Other).Health>0 )
{
// Random chance of doing obliteration damage
if( FRand() < 0.4 )
{
RageBumpDamage = 501;
}
else
{
RageBumpDamage = 450;
}
|
||||
RageBumpDamage *= KFMonst.PoundRageBumpDamScale;
|
||||
Other.TakeDamage(RageBumpDamage, self, Other.Location, Velocity * Other.Mass, class'NiceDamTypePoundCrushed');
}
else Global.Bump(Other);
|
||||
}
|
||||
// If fleshie hits his target on a charge, then he should settle down for abit.
|
||||
function bool MeleeDamageTarget(int hitdamage, vector pushdir)
|
||||
{
local bool RetVal,bWasEnemy;
|
||||
bWasEnemy = (Controller.Target==Controller.Enemy);
RetVal = Super(NiceMonster).MeleeDamageTarget(hitdamage*1.75, pushdir*3);
// Only stop if you've successfully killed your target
if(Pawn(Controller.Target) == none)
return RetVal;
if( KFPawn(Controller.Target) != none && Pawn(Controller.Target).Health <= 0 && RetVal && bWasEnemy ){
GoToState('');
}
return RetVal;
|
||||
}
|
||||
}
|
||||
defaultproperties
|
||||
{
MenuName="Mean FleshPound"
Skins(0)=Combiner'MeanZedSkins.fleshpound_cmb'
|
||||
}
|
||||
24
sources/Zeds/Mean/MeanZombieGorefast.uc
Normal file
24
sources/Zeds/Mean/MeanZombieGorefast.uc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
class MeanZombieGorefast extends NiceZombieGorefast;
|
||||
#exec OBJ LOAD FILE=MeanZedSkins.utx
|
||||
var float minRageDist;
|
||||
function bool IsStunPossible(){
|
||||
return false;
|
||||
}
|
||||
function RangedAttack(Actor A) {
|
||||
Super(NiceMonster).RangedAttack(A);
|
||||
if(!bShotAnim && !bDecapitated && VSize(A.Location-Location) <= minRageDist)
GoToState('RunningState');
|
||||
}
|
||||
state RunningState {
|
||||
function RangedAttack(Actor A){
if(bShotAnim || Physics == PHYS_Swimming)
return;
else if(CanAttack(A)){
bShotAnim = true;
|
||||
//Always do the charging melee attack
SetAnimAction('ClawAndMove');
RunAttackTimeout = GetAnimDuration('GoreAttack1', 1.0);
return;
}
|
||||
}
|
||||
Begin:
|
||||
GoTo('CheckCharge');
|
||||
CheckCharge:
|
||||
if(Controller != none && Controller.Target != none && VSize(Controller.Target.Location - Location) < minRageDist){
Sleep(0.5 + FRand() * 0.5);
GoTo('CheckCharge');
|
||||
}
|
||||
else
GoToState('');
|
||||
}
|
||||
defaultproperties
|
||||
{
minRageDist=1400.000000
MenuName="Mean Gorefast"
Skins(0)=Combiner'MeanZedSkins.gorefast_cmb'
|
||||
}
|
||||
41
sources/Zeds/Mean/MeanZombieHusk.uc
Normal file
41
sources/Zeds/Mean/MeanZombieHusk.uc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
class MeanZombieHusk extends NiceZombieHusk;
|
||||
#exec OBJ LOAD FILE=NicePackT.utx
|
||||
var int consecutiveShots, totalShots, maxNormalShots;
|
||||
function DoStun(optional Pawn instigatedBy, optional Vector hitLocation, optional Vector momentum, optional class<NiceWeaponDamageType> damageType, optional float headshotLevel, optional KFPlayerReplicationInfo KFPRI){
|
||||
super.DoStun(instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI);
|
||||
totalShots = maxNormalShots;
|
||||
}
|
||||
function SpawnTwoShots() {
|
||||
local vector X,Y,Z, FireStart;
|
||||
local rotator FireRotation;
|
||||
local KFMonsterController KFMonstControl;
|
||||
if(Controller != none && KFDoorMover(Controller.Target) != none){
Controller.Target.TakeDamage(22, Self, Location, vect(0,0,0), Class'DamTypeVomit');
return;
|
||||
}
|
||||
GetAxes(Rotation,X,Y,Z);
|
||||
FireStart = GetBoneCoords('Barrel').Origin;
|
||||
if (!SavedFireProperties.bInitialized){
SavedFireProperties.AmmoClass = Class'SkaarjAmmo';
SavedFireProperties.ProjectileClass = HuskFireProjClass;
SavedFireProperties.WarnTargetPct = 1;
SavedFireProperties.MaxRange = 65535;
SavedFireProperties.bTossed = False;
SavedFireProperties.bTrySplash = true;
SavedFireProperties.bLeadTarget = True;
SavedFireProperties.bInstantHit = False;
SavedFireProperties.bInitialized = True;
|
||||
}
|
||||
// Turn off extra collision before spawning vomit, otherwise spawn fails
|
||||
ToggleAuxCollision(false);
|
||||
if(Controller != none)
FireRotation = Controller.AdjustAim(SavedFireProperties, FireStart, 600);
|
||||
foreach DynamicActors(class'KFMonsterController', KFMonstControl){
if(KFMonstControl != controller){
if(PointDistToLine(KFMonstControl.Pawn.Location, vector(FireRotation), FireStart) < 75){
KFMonstControl.GetOutOfTheWayOfShot(vector(FireRotation),FireStart);
}
}
|
||||
}
|
||||
Spawn(HuskFireProjClass, Self,, FireStart, FireRotation);
|
||||
// Turn extra collision back on
|
||||
ToggleAuxCollision(true);
|
||||
}
|
||||
function RangedAttack(Actor A) {
|
||||
local int LastFireTime;
|
||||
if ( bShotAnim )
return;
|
||||
if ( Physics == PHYS_Swimming ) {
SetAnimAction('Claw');
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
|
||||
}
|
||||
else if ( VSize(A.Location - Location) < MeleeRange + CollisionRadius + A.CollisionRadius ) {
bShotAnim = true;
LastFireTime = Level.TimeSeconds;
SetAnimAction('Claw');
//PlaySound(sound'Claw2s', SLOT_Interact); KFTODO: Replace this
Controller.bPreparingMove = true;
Acceleration = vect(0,0,0);
|
||||
}
|
||||
else if((KFDoorMover(A) != none ||
(!Region.Zone.bDistanceFog && VSize(A.Location-Location) <= 65535) ||
(Region.Zone.bDistanceFog && VSizeSquared(A.Location-Location) < (Square(Region.Zone.DistanceFogEnd) * 0.8))) // Make him come out of the fog a bit
&& !bDecapitated ) {
bShotAnim = true;
|
||||
SetAnimAction('ShootBurns');
Controller.bPreparingMove = true;
Acceleration = vect(0,0,0);
|
||||
//Increment the number of consecutive shtos taken and apply the cool down if needed
totalShots ++;
consecutiveShots ++;
if(consecutiveShots < 3 && totalShots > maxNormalShots)
NextFireProjectileTime = Level.TimeSeconds;
else{
NextFireProjectileTime = Level.TimeSeconds + ProjectileFireInterval + (FRand() * 2.0);
consecutiveShots = 0;
}
|
||||
}
|
||||
}
|
||||
defaultproperties
|
||||
{
maxNormalShots=3
HuskFireProjClass=Class'NicePack.MeanHuskFireProjectile'
remainingStuns=1
MenuName="Mean Husk"
ControllerClass=Class'NicePack.MeanZombieHuskController'
Skins(0)=Texture'NicePackT.MonsterMeanHusk.burns_tatters'
Skins(1)=Shader'NicePackT.MonsterMeanHusk.burns_shdr'
|
||||
}
|
||||
67
sources/Zeds/Mean/MeanZombieHuskController.uc
Normal file
67
sources/Zeds/Mean/MeanZombieHuskController.uc
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
class MeanZombieHuskController extends NiceZombieHuskController;
|
||||
var float aimAtFeetZDelta;
|
||||
function bool DefendMelee(float Dist) {
|
||||
return (Dist < 1000);
|
||||
}
|
||||
function rotator AdjustAim(FireProperties FiredAmmunition, vector projStart, int aimerror) {
|
||||
local rotator FireRotation, TargetLook;
|
||||
local float FireDist, TargetDist, ProjSpeed;
|
||||
local actor HitActor;
|
||||
local vector FireSpot, FireDir, TargetVel, HitLocation, HitNormal;
|
||||
local int realYaw;
|
||||
local bool bDefendCloseRange, bClean, bLeadTargetNow;
|
||||
local bool bWantsToAimAtFeet;
|
||||
if ( FiredAmmunition.ProjectileClass != none )
projspeed = FiredAmmunition.ProjectileClass.default.speed;
|
||||
// make sure bot has a valid target
|
||||
if ( Target == none ) {
Target = Enemy;
if ( Target == none )
return Rotation;
|
||||
}
|
||||
FireSpot = Target.Location;
|
||||
TargetDist = VSize(Target.Location - Pawn.Location);
|
||||
// perfect aim at stationary objects
|
||||
if ( Pawn(Target) == none ) {
if ( !FiredAmmunition.bTossed )
return rotator(Target.Location - projstart);
else {
FireDir = AdjustToss(projspeed,ProjStart,Target.Location,true);
SetRotation(Rotator(FireDir));
return Rotation;
}
|
||||
}
|
||||
bLeadTargetNow = FiredAmmunition.bLeadTarget && bLeadTarget;
|
||||
bDefendCloseRange = ( (Target == Enemy) && DefendMelee(TargetDist) );
|
||||
aimerror = AdjustAimError(aimerror,TargetDist,bDefendCloseRange,FiredAmmunition.bInstantHit, bLeadTargetNow);
|
||||
// lead target with non instant hit projectiles
|
||||
if ( bLeadTargetNow ) {
TargetVel = Target.Velocity;
// hack guess at projecting falling velocity of target
if ( Target.Physics == PHYS_Falling) {
if ( Target.PhysicsVolume.Gravity.Z <= Target.PhysicsVolume.Default.Gravity.Z ) {
TargetVel.Z = FMin(TargetVel.Z + FMax(-400, Target.PhysicsVolume.Gravity.Z * FMin(1,TargetDist/projSpeed)),0);
} else {
TargetVel.Z = FMin(0, TargetVel.Z);
}
}
// more or less lead target (with some random variation)
FireSpot += FMin(1, 0.7 + 0.6 * FRand()) * TargetVel * TargetDist/projSpeed;
FireSpot.Z = FMin(Target.Location.Z, FireSpot.Z);
/**
* If the target is within 1000uu, offset the Z coordinate of the
* FireSpot vector with aimAtFeetZDelta. Otherwise, the husk will
* aim at behind the target, not at his feet.
*/
if (aimAtFeetZDelta != 0.0 && Target.Physics == PHYS_Falling && bDefendCloseRange) {
FireSpot.Z= Pawn.Location.Z + aimAtFeetZDelta;
}
|
||||
if ( (Target.Physics != PHYS_Falling) && (FRand() < 0.55) && (VSize(FireSpot - ProjStart) > 1000) ) {
// don't always lead far away targets, especially if they are moving sideways with respect to the bot
TargetLook = Target.Rotation;
if ( Target.Physics == PHYS_Walking )
TargetLook.Pitch = 0;
bClean = ( ((Vector(TargetLook) Dot Normal(Target.Velocity)) >= 0.71) && FastTrace(FireSpot, ProjStart) );
}
else // make sure that bot isn't leading into a wall
bClean = FastTrace(FireSpot, ProjStart);
if ( !bClean) {
// reduce amount of leading
if ( FRand() < 0.3 )
FireSpot = Target.Location;
else
FireSpot = 0.5 * (FireSpot + Target.Location);
}
|
||||
}
|
||||
bClean = false; //so will fail first check unless shooting at feet
|
||||
// Randomly determine if we should try and splash damage with the fire projectile
|
||||
if( FiredAmmunition.bTrySplash ) {
if( Skill < 2.0 ) {
if(FRand() > 0.85) {
bWantsToAimAtFeet = true;
}
}
else if( Skill < 3.0 ) {
if(FRand() > 0.5) {
bWantsToAimAtFeet = true;
}
}
else if( Skill >= 3.0 ) {
if(FRand() > 0.25) {
bWantsToAimAtFeet = true;
}
}
|
||||
}
|
||||
if ( FiredAmmunition.bTrySplash && (Pawn(Target) != none) && (((Target.Physics == PHYS_Falling)
&& (Pawn.Location.Z + 80 >= Target.Location.Z)) || ((Pawn.Location.Z + 19 >= Target.Location.Z)
&& (bDefendCloseRange || bWantsToAimAtFeet))) ) {
HitActor = Trace(HitLocation, HitNormal, FireSpot - vect(0,0,1) * (Target.CollisionHeight + 10), FireSpot, false);
|
||||
bClean = (HitActor == none);
//So if we're too close, and not jumping, bClean is false
//same distance but jumping, bClean is true
if ( !bClean ) {
FireSpot = HitLocation + vect(0,0,3);
bClean = FastTrace(FireSpot, ProjStart);
}
else
bClean = ( (Target.Physics == PHYS_Falling) && FastTrace(FireSpot, ProjStart) );
/**
* Update the aimAtFeetZDelta variable with the appropriate offset
* once the Husk decides to aim at the target's feet. Update the
* default property so all Super Husks can access it
*/
if (bClean && TargetDist > 625.0) {
aimAtFeetZDelta= FireSpot.Z - Pawn.Location.Z;
}
|
||||
}
|
||||
if ( !bClean ) {
//try middle
FireSpot.Z = Target.Location.Z;
bClean = FastTrace(FireSpot, ProjStart);
|
||||
}
|
||||
if ( FiredAmmunition.bTossed && !bClean && bEnemyInfoValid ) {
FireSpot = LastSeenPos;
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none ) {
bCanFire = false;
FireSpot += 2 * Target.CollisionHeight * HitNormal;
}
bClean = true;
|
||||
}
|
||||
if( !bClean ) {
// try head
FireSpot.Z = Target.Location.Z + 0.9 * Target.CollisionHeight;
bClean = FastTrace(FireSpot, ProjStart);
|
||||
}
|
||||
if ( !bClean && (Target == Enemy) && bEnemyInfoValid ) {
FireSpot = LastSeenPos;
if ( Pawn.Location.Z >= LastSeenPos.Z )
FireSpot.Z -= 0.4 * Enemy.CollisionHeight;
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none ) {
FireSpot = LastSeenPos + 2 * Enemy.CollisionHeight * HitNormal;
if ( Monster(Pawn).SplashDamage() && (Skill >= 4) ) {
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none )
FireSpot += 2 * Enemy.CollisionHeight * HitNormal;
}
bCanFire = false;
}
|
||||
}
|
||||
// adjust for toss distance
|
||||
if ( FiredAmmunition.bTossed ) {
FireDir = AdjustToss(projspeed,ProjStart,FireSpot,true);
|
||||
}
|
||||
else {
FireDir = FireSpot - ProjStart;
|
||||
}
|
||||
FireRotation = Rotator(FireDir);
|
||||
realYaw = FireRotation.Yaw;
|
||||
InstantWarnTarget(Target,FiredAmmunition,vector(FireRotation));
|
||||
FireRotation.Yaw = SetFireYaw(FireRotation.Yaw + aimerror);
|
||||
FireDir = vector(FireRotation);
|
||||
// avoid shooting into wall
|
||||
FireDist = FMin(VSize(FireSpot-ProjStart), 400);
|
||||
FireSpot = ProjStart + FireDist * FireDir;
|
||||
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
|
||||
if ( HitActor != none ) {
if ( HitNormal.Z < 0.7 ) {
FireRotation.Yaw = SetFireYaw(realYaw - aimerror);
FireDir = vector(FireRotation);
FireSpot = ProjStart + FireDist * FireDir;
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
}
if ( HitActor != none ) {
FireSpot += HitNormal * 2 * Target.CollisionHeight;
if ( Skill >= 4 ) {
HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
if ( HitActor != none )
FireSpot += Target.CollisionHeight * HitNormal;
}
FireDir = Normal(FireSpot - ProjStart);
FireRotation = rotator(FireDir);
}
|
||||
}
|
||||
//Make it so the Husk always shoots the ground it the target is close
|
||||
SetRotation(FireRotation);
|
||||
return FireRotation;
|
||||
}
|
||||
defaultproperties
|
||||
{
|
||||
}
|
||||
31
sources/Zeds/Mean/MeanZombieScrake.uc
Normal file
31
sources/Zeds/Mean/MeanZombieScrake.uc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
class MeanZombieScrake extends NiceZombieScrake;
|
||||
#exec OBJ LOAD FILE=MeanZedSkins.utx
|
||||
function RangedAttack(Actor A){
|
||||
Super.RangedAttack(A);
|
||||
if(!bShotAnim){
if(bConfusedState)
return;
if(float(Health) / HealthMax < 0.75 || lastStunTime >= 0.0){
MovementAnims[0] = 'ChargeF';
GoToState('RunningState');
}
|
||||
}
|
||||
}
|
||||
simulated event SetAnimAction(name NewAction){
|
||||
if(Role < Role_AUTHORITY && NewAction == 'ChargeF')
PlayAnim('ChargeF', GetOriginalGroundSpeed() * 3.5);
|
||||
else
super.SetAnimAction(NewAction);
|
||||
}
|
||||
simulated function Unstun(){
|
||||
bCharging = true;
|
||||
MovementAnims[0] = 'ChargeF';
|
||||
super.Unstun();
|
||||
}
|
||||
function TakeDamageClient(int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<NiceWeaponDamageType> damageType, float headshotLevel, float lockonTime){
|
||||
Super.TakeDamageClient(Damage, instigatedBy, hitLocation, momentum, damageType, headshotLevel, lockonTime);
|
||||
if(bIsStunned && Health > 0 && (headshotLevel <= 0.0) && Level.TimeSeconds > LastStunTime + 0.1)
Unstun();
|
||||
}
|
||||
function TakeFireDamage(int Damage, Pawn Instigator){
|
||||
Super.TakeFireDamage(Damage, Instigator);
|
||||
if(bIsStunned && Health > 0 && Damage > 150 && Level.TimeSeconds > LastStunTime + 0.1)
Unstun();
|
||||
}
|
||||
function bool CheckMiniFlinch(int flinchScore, Pawn instigatedBy, Vector hitLocation, Vector momentum, class<NiceWeaponDamageType> damageType, float headshotLevel, KFPlayerReplicationInfo KFPRI){
|
||||
if((ClassIsChildOf(damageType, class 'DamTypeMelee') || ClassIsChildOf(damageType, class 'NiceDamageTypeVetBerserker'))
&& !KFPRI.ClientVeteranSkill.Static.CanMeleeStun() && (headshotLevel <= 0.0) && flinchScore < 250)
return false;
|
||||
return super.CheckMiniFlinch(flinchScore, instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI);
|
||||
}
|
||||
defaultproperties
|
||||
{
MenuName="Mean Scrake"
Skins(0)=Shader'MeanZedSkins.scrake_FB'
Skins(1)=TexPanner'MeanZedSkins.scrake_saw_panner'
|
||||
}
|
||||
5
sources/Zeds/Mean/MeanZombieSiren.uc
Normal file
5
sources/Zeds/Mean/MeanZombieSiren.uc
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class MeanZombieSiren extends NiceZombieSiren;
|
||||
#exec OBJ LOAD FILE=MeanZedSkins.utx
|
||||
defaultproperties
|
||||
{
ScreamRadius=800
ScreamForce=-250000
MenuName="Mean Siren"
Skins(0)=FinalBlend'MeanZedSkins.siren_hair_fb'
Skins(1)=Combiner'MeanZedSkins.siren_cmb'
|
||||
}
|
||||
128
sources/Zeds/Mean/MeanZombieStalker.uc
Normal file
128
sources/Zeds/Mean/MeanZombieStalker.uc
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
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
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] != 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);
|
||||
targetPawn = NiceHumanPawn(Controller.Target);
|
||||
if(result && targetPawn != none && (targetPawn.hmgShieldLevel <= 0 ||
!class'NiceVeterancyTypes'.static.HasSkill(NicePlayerController(targetPawn.Controller),
class'NiceSkillEnforcerFullCounter')) ){
if(targetPawn.ShieldStrength > 100)
return result;
else if(targetPawn.ShieldStrength < 0)
effectStrenght = 1.0;
else
effectStrenght = (100 - targetPawn.ShieldStrength) * 0.01;
class'MeanReplicationInfo'.static
.findSZri(targetPawn.PlayerReplicationInfo)
.setBleeding(Self, effectStrenght);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
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'
|
||||
}
|
||||
4
sources/Zeds/Mean/NiceDamTypeStalkerBleed.uc
Normal file
4
sources/Zeds/Mean/NiceDamTypeStalkerBleed.uc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
class NiceDamTypeStalkerBleed extends NiceZedSlashingDamageType;
|
||||
defaultproperties
|
||||
{
bArmorStops=False
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue