class ZombieBloatOS extends KFMonsterOS; var class VomitJet; var Actor BloatJet; var bool bPlayBileSplash; var float DistBeforePuke; var bool bEnableOldBloatPuke; //Call Puke Emitter via AnimNotify_Script than Effect //Otherwise, compiling will complain about missing meshes //Redo this function to aim puke to player //Also, bEnableOldBloatPuke doesn't work simulated function SpawnPukeEmitter() { local vector X,Y,Z, FireStart; GetAxes(Rotation,X,Y,Z); FireStart = GetBoneCoords('bip01 head').Origin; Spawn(VomitJet,,,FireStart,Rotation); } function BodyPartRemoval(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { super.BodyPartRemoval(Damage, instigatedBy, hitlocation, momentum, damageType); if((Health - Damage)<=0) Gored=3; if(bEnableOldBloatPuke) { if(Gored>=3 && Gored < 5) BileBomb(); } } function bool FlipOver() { return false; } function Died(Controller Killer, class damageType, vector HitLocation) { // Actually become gored when you die to non-bleedout damage if(damagetype != class'DamTypeBleedOut') Gored=3; super.Died(Killer,damageType,HitLocation); } simulated function bool HitCanInterruptAction() { if( bShotAnim ) return false; return true; } function DoorAttack(Actor A) { if ( bShotAnim || Physics == PHYS_Swimming) return; else if ( A!=none ) { bShotAnim = true; if( !bDecapitated ) SetAnimAction('ZombieBarf'); else { SetAnimAction('Claw'); PlaySound(sound'Claw2s', SLOT_None); } } } 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); Controller.bPreparingMove = true; Acceleration = vect(0,0,0); } else if( (KFDoorMover(A)!=none || VSize(A.Location-Location)<=DistBeforePuke) && !bDecapitated ) { bShotAnim=true; SetAnimAction('ZombieBarf'); Controller.bPreparingMove = true; Acceleration = vect(0,0,0); if ( FRand() < 0.03 && KFHumanPawn(A) != none && PlayerController(KFHumanPawn(A).Controller) != none ) PlayerController(KFHumanPawn(A).Controller).Speech('AUTO', 7, ""); } } function SpawnTwoShots() { local vector X,Y,Z, FireStart; local rotator FireRotation; // Credit: https://github.com/InsultingPros/SuperZombieMut/blob/somechanges/Classes/ZombieSuperBloat.uc#L94 // check this from the very start to prevent any log spam / dead bloats dont barf!(headless bloats dont barf either!) if (Controller == none || IsInState('ZombieDyingOS') || bDecapitated ) return; 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 = Location+(vect(30,0,64) >> Rotation)*DrawScale; if ( !SavedFireProperties.bInitialized ) { SavedFireProperties.AmmoClass = class'SkaarjAmmo'; SavedFireProperties.ProjectileClass = class'KFBloatVomitOS'; SavedFireProperties.WarnTargetPct = 1; SavedFireProperties.MaxRange = 500; SavedFireProperties.bTossed = false; SavedFireProperties.bTrySplash = false; SavedFireProperties.bLeadTarget = true; SavedFireProperties.bInstantHit = true; SavedFireProperties.bInitialized = true; } ToggleAuxCollision(false); FireRotation = Controller.AdjustAim(SavedFireProperties,FireStart,600); Spawn(class'KFBloatVomit',,,FireStart,FireRotation); FireStart-=(0.5*CollisionRadius*Y); FireRotation.Yaw -= 1200; Spawn(class'KFBloatVomit',,,FireStart,FireRotation); FireStart+=(CollisionRadius*Y); FireRotation.Yaw += 2400; Spawn(class'KFBloatVomit',,,FireStart,FireRotation); ToggleAuxCollision(true); } simulated function Tick(float deltatime) { local vector BileExplosionLoc; local Actor GibBileExplosion; super.tick(deltatime); if( Level.NetMode!=NM_DedicatedServer && Gored>0 && !bPlayBileSplash ) { BileExplosionLoc = self.Location; BileExplosionLoc.z += (CollisionHeight - (CollisionHeight * 0.5)); GibBileExplosion = Spawn(class 'BileExplosionOS',self,, BileExplosionLoc ); bPlayBileSplash = true; } } function BileBomb() { local bool AttachSucess; if(bEnableOldBloatPuke) { BloatJet = spawn(class'BileJetOS', self,,,); if(Gored < 5) AttachSucess=AttachToBone(BloatJet,'Bip01 Spine'); if(!AttachSucess) BloatJet.SetBase(self); BloatJet.SetRelativeRotation(rot(0,-4096,0)); } else BloatJet = spawn(class'BileJet', self,,Location,Rotator(-PhysicsVolume.Gravity)); } function PlayDyingAnimation(class DamageType, vector HitLoc) { local bool AttachSucess; super.PlayDyingAnimation(DamageType, HitLoc); if( bDecapitated && DamageType == class'DamTypeBleedOut' ) return; if(Role == ROLE_Authority) { BileBomb(); if(BloatJet!=none && bEnableOldBloatPuke) { if(Gored < 5) AttachSucess=AttachToBone(BloatJet,'Bip01 Spine'); if(!AttachSucess) BloatJet.SetBase(self); BloatJet.SetRelativeRotation(rot(0,-4096,0)); } } } State Dying { function tick(float deltaTime) { if (BloatJet != none) { BloatJet.SetLocation(location); BloatJet.SetRotation(GetBoneRotation('Bip01 Spine')); } super.tick(deltaTime); } } function RemoveHead() { bCanDistanceAttackDoors = false; super.RemoveHead(); } simulated function TakeDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType, optional int HitIndex) { if (DamageType == class 'Burned') Damage *= 1.5; if (damageType == class 'DamTypeVomit' || damageType == class 'DamTypeVomitOS') return; else if( damageType == class 'DamTypeBlowerThrower' ) Damage *= 0.25; super.TakeDamage(Damage,instigatedBy,hitlocation,momentum,damageType); } static simulated function PreCacheMaterials(LevelInfo myLevel) { myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.Bloat.BloatSkin'); } defaultproperties { VomitJet=Class'KFOldSchoolZeds.KFVomitJetOS' DistBeforePuke=250.000000 MeleeAnims(0)="BloatChop2" MeleeAnims(1)="BloatChop2" MeleeAnims(2)="BloatChop2" MoanVoice=SoundGroup'KFOldSchoolZeds_Sounds.Bloat.Bloat_Speech' BleedOutDuration=6.000000 bCannibal=True ZapThreshold=0.500000 ZappedDamageMod=1.500000 bHarpoonToBodyStuns=False ZombieFlag=1 MeleeDamage=14 damageForce=70000 bFatAss=True KFRagdollName="BloatRag" JumpSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieJump' PuntAnim="BloatPunt" Intelligence=BRAINS_Stupid bCanDistanceAttackDoors=True bUseExtendedCollision=True ColOffset=(Z=60.000000) ColRadius=27.000000 ColHeight=22.000000 PlayerCountHealthScale=0.250000 OnlineHeadshotOffset=(X=10.000000,Y=-5.000000,Z=69.000000) OnlineHeadshotScale=1.200000 HitSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombiePain' DeathSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombieDeath' AmmunitionClass=Class'KFMod.BZombieAmmo' ScoringValue=17 IdleHeavyAnim="BloatIdle" IdleRifleAnim="BloatIdle" MeleeRange=30.000000 GroundSpeed=75.000000 WaterSpeed=102.000000 HealthMax=525.000000 Health=525 HeadRadius=8.000000 HeadHeight=5.500000 MenuName="Bloat 2.5" MovementAnims(0)="WalkBloat" MovementAnims(1)="WalkBloat" WalkAnims(0)="WalkBloat" WalkAnims(1)="WalkBloat" WalkAnims(2)="WalkBloat" WalkAnims(3)="WalkBloat" IdleCrouchAnim="BloatIdle" IdleWeaponAnim="BloatIdle" IdleRestAnim="BloatIdle" AmbientSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieBreath' Mesh=SkeletalMesh'KFCharacterModelsOldSchool.Bloat' PrePivot=(Z=8.000000) Skins(0)=Texture'KFOldSchoolZeds_Textures.Bloat.BloatSkin' Mass=400.000000 RotationRate=(Yaw=45000,Roll=0) }