*~P@))X >AUaD9|-muPNoneVectoroffsetReqMinHitDistanceDamageEmitter BoneName bCompletedSubDamageBones DamageModbFatalAdvancedEmitterMinRangeMaxbAdded AnimNameObjRef UpdateFocus RForearm DebugLog LForearmEngineCoreBD2004ZombiesRunF DOTZEngineBeginAdvancedEngineUserMeshXDOTZCharacters RUpperArmAdditionalAnimPkgControllerClass RelativeTime LUpperArm BodyTexturesPerform_Error_Stop HeadTexturesUnClaimPositionbAlwaysRelevant ShouldStrafeDONE GroundSpeedX RangeVector shouldWalkYZCollisionRadius BeginPlaySpecialDamageRunRRunBHealth bCanStrafeBaseMovementRateJawRunLJumpFNamesRCalfJumpBLCalfHeadJump BeginState WalkingPctWalksAnimWalkForward AnimWalkBack AnimWalkLeftJumpLJumpRAnimJumpRight AnimJumpLeft AnimJumpBackAnimJumpForward AnimJumpAnimWalkRight SameTeamAs KeepGoingEnemyIsVisible RelativeSize SeePlayerMove ReqBonesMeleeAttackAnimFindBestPathToward bFunctional DamageDelay EndState HunterOtisClaimPosition DeathSoundsHunterJackSladeExclaimSystem TimeElapsedSetInventoryLimit StopFiringEnemyNotVisible Swimming GiveWeaponInfectionEffect isBehindMe AttackingReachedDestination TakeDamageSetCombatTimerEngaged_ChargeDEBAIT TrySpotEnemyPerform_MoveToLocation SetPawnClassTimedFireWeaponAtEnemyRelativeVelocityTextureWeaponFireAgainMaxShotPeriodFadeOutStartSizeRange MaxAimRange IsFiringMaxSecondsOfLOSSetInfectionStateMinShotPeriod MaxNumShotsPossessLifetimeRangeSpinParticles GameplaySecondsBeforeInactiveInitialParticlesPerSecondAutomaticInitialSpawningRespawnDeadParticlesSetFocalPointNearLocation UseSizeScaleUseRegularSizeScale SizeScale AcquireEnemyEngaged_OutFromCover UniformSize ZombieOtis OnHeardNoisePlayerControllerReport_EyeSighted NeedToTurnWillFriendlyFireBDHunterAIControllerNotEngaged_WanderOnThreatSpottedMoveToLocationEngaged_GetLOSDoInfectionDamageEngaged_HideFromEnemyVerifyShootingPositionWeightStagePositionTryClearObstacleTimerEngaged_HuntEnemyEngaged_AdvanceMove iRandRangeUseRandomSubdivisionTrySeekTarget MultiTimer CanAttackGetLocalPlayerControllerSeeking RefireRateBotFire MaxParticles ZombieJackDMColorStartSpinRangeSpinsPerSecondRangeReport_UnSightedEngaged_RecoverEnemyContinue_Engaged_GetLOSStartLocationShapecalculateStagePosnLOSIsBlockedContinueWanderFadeOutStartTime DrawStyleCleanupNotEngagedWanderFailedPerform_MeleeAttack ChanceToHitUpdateEnemyInfoContinue_Engaged_TakeCoverEngaged_TakeCoverContinue_Engaged_OutFromCoverContinue_EngagedChargeContinue_Engaged_HuntEnemyAttackTwoHandcalculateStagePosnBlocksLOSCalculateMissVectorScalePickDestinationContinue_Engaged_AdvanceMoveGetMaxFiringRange FireWeaponAtWanderSetRandomFocalPointLocationFollowOrder_NonePositionHasLOFToEnemy Destroyed DoSpecialStartVelocityRange EndChargeDoDisinfectionInitWorldToScreenPerform_Engaged_StandGround DisplayDebug ChargeFailed SelectActiongetAttackPointOnBumpFixFOVPerform_Engaged_TakeCoverPositionProvidesCoverFromEnemyPursue bJumpCapableIncrementFlashCountRequest_HidingPositionReport_EnemySpotted AttackRightB Scripting OnKilledTakeFallingDamage PlayTakeHitTouchingWaterVolumeSetRelaxAttributesDormantFollowOrder_TakePositionFollowOrder_HoldPosition OnHitMover leaveStage OnHitWall ShakeViewFollowOrder_TakeCoverWeaponStopFireCrouch PlayFiringBringUp AdjustAroundDistanceFromMeMinimumDistanceToThreatDistanceToDeadBuddiesDeadZombiePawnBaseChangedWeapon GetLOSFailedTakeCoverFailed debugTickDiedbCanPickupInventoryNextOnTakingDamage OnLostSightPutDownOnWitnessedKillIsHumanControlledNumberOfLinesOfSightToThreatsOnThreatHeardRUNXDOTZPlayerControllerProperDistanceToBuddiesNumberOfLinesOfSightToBuddiesDistanceToNearestFreeCoverSpot AmmoNameAltFireAnimName HitAnimNameCrouchIdleAnimNameStandIdleAnimName FireAnimNamePawnAnimationPackageBlockingLineOfFireOfBuddiesBlockedLineOfFireByBuddies"ProjDistToBuddiesAsSeenFromThreatbDamageKicksViewbAlwaysPlayDying AimToMissGetTweakedFireSpotRagdollLifeSpan AimToHit ItemNameNotEngaged_AtRest BloodEmitterPerform_NotEngaged_Wander InitAIRoleUseColorScaleSpawnExclaimManagersetLastHitTime AttackLeftBPLAYER_INFECTEDPerform_MoveTowardPositionStartLocationPolarRangeMoveToPositionContinue_MoveToLocationEngaged_StandGroundUseRotationFromisTargetDestroyedNotEngaged_FireAtTargetPerform_Engaged_RecoverEnemyInfectedEventGETLOSSTANDUP PostLoadFinishedStrafeFLEEEngaged_SupressionFireTextureUSubdivisionsTextureVSubdivisionsPostNetBeginPlayTravelPostAcceptUseVelocityScaleVelocityScalegetWeaponFireRateTestDirectionPickStrafeDirEngaged_StrafeMoveKeepPanickingEngaged_Panic Error_Stop drawCoverHitHeadbInfiniteAmmoPickClosestBetterSpotSetCombatAttributesiMultiPlayerCorpseSecsbNoDamageEffectsPath DontBeStupid EAT_STUFFSMASH_OBSTACLE StartChargegetSmashActorgetChargeDurationBDHunterAIRole ShouldCharge OfficialName GetHitAnimFall StandIdlePostBeginPlay PlayHitSound ViewKick FallDownSetTeamAttachments CalcHitPart NearWall DeSelectPostNetReceive CheckShadowSetBoredomTimer WaterVolumeAdvancedPlayAnimHidePhysicsVolumeChangePerform_Engaged_HideFromEnemyBDPlayerPawnBaseBDLeadPipeHunter DestroyPawnLeaveScriptingBDHuntedInvasionbLightChanged bSelectedBDGlockHunter BDBatHunterZoneiLeaf ZoneNumber DebugFlags BDAxeHunterRegion MeleeWeaponGiveDefaultInventoryBD2004ZombiePawnBaseBD2004YoungAdultMaleBD2004YoungAdultFemaleBD2004TeenagerMaleStdDamageAmountAltDamageAmountGetAttackLocationBD2004TeenagerFemaleBD2004SkeletonMaledoSmashBD2004SeniorMale CrouchIdle CrawlIdleBD2004SeniorFemaleBD2004NurseFemaleBD2004MiddleAgedMaleBD2004MiddleAgedFemaleBD2004HospitalPatientMaleBD2004HoboMaleBD2004HoboFemaleBD2004GoreMaleBD2004GoreFemaleBD2004CopMaleZombieFistWeaponOtisZombieFistWeaponZombieFistAmmunition AttackLeftC AttackLeftA AttackRightC AttackRightA CrawlBoredinfectionFreqinfectionDamageBoredCrawlingMeleeAttacks MeleeAttacksSpawningSoundProbabilityTick HearNoise NotifyBumpNotifyHitWall PreBeginPlay DOTZGameMinWanderDelay AttackRangeMaxWanderDelaySpawningSoundSoundsLastSeekRefreshTimeMaxChargingZombiesInAttackRangebAllowedToChargeMaxTimeBetweenCharges ColorScale ProbabilityWeightBoredStandingAnimListBoredCrawlAnimListMinTimeBetweenChargesMinChargeDistMaxChargeDistSoundFootStepSound FootStepDirtFootStepMetalFootStepPlant FootStepRockFootStepWater FootStepWood bDoFootsteps HitSoundsPitchCrawlAttackRightCrawlAttackBiteCrawlAttackFall AttackBiteBDMiniExplosionAIType PreSaveGame SetCreator ActorToFace Perform_NotEngaged_FireAtTargetmaxDistToCrouchForCover RecoverEnemySO_AttackTarget SO_TakeCoverSO_HoldPositionSO_TakeUpPositionSO_NonePerform_Engaged_SupressionFire lastHitTimePerform_Engaged_ChargePerform_Engaged_StrafeMovePerform_Engaged_HuntEnemyPerform_Engaged_PanicDOTZGrenadeWeaponDOTZGunWeaponPickDestinationOldCLAIMED_POSITION_PENALTYPerform_Engaged_AdvanceMovem_NeedForNearbyGoalm_NeedForClosingInm_NeedToAvoidCorpsesm_NeedForIntelm_NeedCohesionm_NeedForContactm_NeedForCoverm_BlockingPenaltym_BlockedPenaltym_BunchPenaltyEnemyDistractDistanceEnemyDistractDurationOnRegainedSight DrawHUDDebugMaxAimVelocityOnEnemyAcquiredTakePositionSuceedederrorStopSucceededadvanceMoveSucceededPanicSucceededHuntSucceededstrafeMoveSucceededVolumeChargeSucceededTakeCoverSucceededsupressionFireSucceededoutFromCoverSucceededHideFromEnemySucceededGetLOSSucceededRecoverEnemySucceededFireAtTargetSucceededStandGroundSucceededMoveToPositionSucceededNotEngagedWanderSucceededNotEngagedAtRestSucceededacquireEnemySucceededawakenSucceeded MaxSkillOdds MinNumShotsbRangedAttackCapabledrawEnemyTargetPerform_Eating GlockWeapon M16WeaponRevolverWeapon RifleWeaponShotgunWeapon SniperWeapon ReflexTimeMaxLostContactTime drawPosnLOSdrawPositionWeightsdrawExperimentalGriddebugDrawVerifiedPositionsdebugDrawFireConedebugDrawBlockedLOF BBParticlesdebugDrawBlockingLOFReport_KilledReport_EnemyLost OpponentDiedVGSPAIControllerfOddsOfStrafeMoveMinTimeBetweenStrafeMove FallSoundbUseNotifyFootStep KilledByNotifyHitMoverPrimaryFleshImpactSecondaryFleshImpactPerform_Engaged_OutFromCoverBotSelectAction TriggerEvent SoakStop LocationOrder_TakeUpPosition joinStageOrder_HoldPositionOrder_TakeCoverOrder_AttackTarget Order_NoneRadiusStageOrder_AlertNewEnemyPerform_NotEngaged_AtRestStageOrder_JoinStageStageOrder_TakeUpPositionStageOrder_AwakenReport_InPositionMoveToLocationSucceededMoveToLocationFailedKarma Lighting CollisionForce LightColor MovementResetHasAmmo PawnDiedStageOrder_HoldPositionRestartPlayerRequest_ShootingPositionbUnlit FreeScriptStageOrder_TakeCoverNoLongerOnGoodPosition FollowOrderRequest_PercentEyeSighted AdjustAim Emitters AutoResetRestart AssessThreatTimeTillResetRange NotifyKilledStageOrder_AttackTargetStageOrder_NonegetLastHitTimeReceiveWarningdamageAttitudeTo InitRoleInitGameReplicationInfo LoseEnemy WarnTarget WasKilledBy LostContactClientSwitchToBestWeapon PickTeam ClientFlashStageOrder_Hibernate PointRegion Acceleration configurePerform_Engaged_GetLOSReport_TargetDestroyedTeambAllowedToSwitchTeamsfellYPosSetPosDrawDebugLine SetDrawColorAnimBlendParams PositionbAdjustFromWalls DrawText bCanJumpbStasis SightRadius DefaultFOVJumpZ MinHitWallShakeStagePosition MaxFallSpeedBaseEyeHeight aimerrorKilledOldPos PathList FearCostDestBotLookDir bAdjustingbEnemyInfoValidfPhysicsbEnemyAcquired bSoakingbHiddenCollisionHeightbFire bAltFire AdjustLoc MoveTimer MoveTarget FocalPointFocusEnemyTarget LastSeenPosFireLastSeeingPosWall LastSeenTime RouteGoal RouteDistMonitoredPawn HitActorEffectiveSpeed bestDistFireDirpick ScriptTextACWjiS projStart Rotation Velocity ReturnValue RandRangeTimeFiredAmmunitionIdaPawn KungFuModeiStateWeapon LevelInfo GameInfo ReachSpec ProjectilePlayerReplicationInfo bInfectedthreatGameReplicationInfo Ammunition VGSPAIBaseOpponentFactoryExclaimManager AIControllerDebaitAdaptersScheduledExclamationAIRole SpecialFXSmoke ExplosionSunspotDOTZXDestructionDOTZXCharactersPlayerPainSounds NoiseMakerSeenshooter projSpeed Controller DamageTypePhysicsVolume LastAnchorAnchorbStopAtLedges TeamInfo bAvoidLedgesbForcebWantsToCrouch ViewDistflagsSkillDOTZAIController DOTZAIRoleDOTZInfectionDamageDOTZMeleeAmmunitionDOTZPlayerControllerBase SkelHeadbFinishedFireXDOTZPawnBaseNetModeDOTZMeleeWeapon bLeadTargetProjectileClassbDebugLogging bDoAltFire lastState bMeleeWeaponAccuracyIndicator FireAnimbCanDamageSelf TimeSeconds PlayerOwnerCurrentVictim KilledPawn HUD_HACKNavigationPointCoronasHitAnimKillerhitPartbSuppressRoleNotificationsbCanSeePotEnemy newFocus bImmediatepotentialEnemyMaxTime NewStrength ThreatValuebThreatVisible NewThreatSideDir OtherDir superResult oldEnemytargAimDir returnVal skillOdds relVelocitylosTime enemyRight HitFriendtmpValtotal FireSpot MissVectorMissDirtargetDistance bFireSuccess newStage oldPoint oldDirVector wallDist ViewSpotbCanSeebCheckedReach bAllowDetouroldMoveTargetbogie numAvailLOST_SIGHT_TIMERUNGHOST_TIMERFOCUS_UPDATE_INTERVAL FOCUS_TIMERSIGHT_CHECK_TIMERslop exclaimMgrchargeEndTime moveSlopmoveDestinationPanicStartTimebHavePanickedwanderDestinationLastWanderTimeLastTakeCoverTime LastHideTime bStrafeDir strafeTargetLastStrafeMoveTimeTakeUpPositioncurStageOrder EStageOrderclaimedPosition currentStagenumMoveAttemptstimerID shootDesttmpDist myAIRole curBehaviourlastPawnPhysics myCreator pendingFocus maxDuration tmpTarget ShootTarget AcquireTimeminDistLoseEnemyCheckTime strafeDir VisibleEnemyEnemyVisibilityCacheTimebEnemyIsVisibleCacheEnemyInSightTime NumShotsToGobStopFireAnimationbFireAtLastLocationRandFocusChangeDuration panicDestLastFocusChangeTime bestPositionspecdpbestDP numPathsSpeed fromSpot DEBUG_FIRING oldPosition oldWeightoldDist AIDebugFlags FEAR_PENALTY PanicRangeLastAdvanceMoveTime screenPosMissVectorScalebMeleeAttackCapablegridNumcolSizesignxSignySign GoalScript baseWeight baseDist newPosition StageName bHibernatingStagePositions StageAgentsEnemies InitialStagefProjDistToBuddiesfDistToBuddies fDistToCover bIsClaimed StandLOF HoldSpot bSchedulednextExclamationLastMsgoutHitLocation BBPGibLeg BBPGibJawBBPGibForearm BBPGibBicepBBPBloodFistsPrimaryBBPDestructionBBPBloodFistsSecondary ExplosionsExplosionsGrenade DOTZTHumans JackSladeOtisBodyShaderCOtisBodyShaderBOtisJackSladeBodyShaderBJackSladeBodyShaderCOtisHeadShaderCOtisHeadShaderBJackSladeHeadShaderCJackSladeHeadShaderBOtisBodyShaderAOtisHeadShaderAJackSladeHeadShaderAJackSladeBodyShaderA DOTZTZombiesFemaleNurseBodyShaderA FemaleNurseFemaleNurseHeadShaderAFemaleYoungAdultMaleMiddleAgedFemaleYoungAdultBodyShaderAFemaleYoungAdultHeadShaderAFemaleHoboHeadShaderAFemaleHoboBodyShaderAMaleYoungAdultHeadShaderAMaleGoreHeadShaderAMaleGoreBodyShaderAFemaleGoreHeadShaderAFemaleGoreBodyShaderAMaleSkeletonHeadShaderAMaleCopHeadShaderAMaleCopBodyShaderAMaleSkeletonBodyShaderA FemaleHoboMaleYoungAdult FemaleGore MaleGore MaleSkeletonMaleCopMaleMiddleAgedBodyShaderA MaleSeniorFemaleMiddleAgedBodyShaderAFemaleMiddleAgedHeadShaderAFemaleMiddleAgedMaleMiddleAgedHeadShaderAMaleSeniorBodyShaderAMaleSeniorHeadShaderAMaleHospitalPatientHeadShaderAMaleHospitalPatientBodyShaderAMaleHoboHeadShaderAMaleHoboBodyShaderAFemaleTeenagerHeadShaderAFemaleTeenagerBodyShaderAMaleHospitalPatient MaleHoboFemaleTeenager MaleTeenagerMaleTeenagerHeadShaderAMaleTeenagerBodyShaderA FemaleSeniorFemaleSeniorBodyShaderAFemaleSeniorHeadShaderAMaleYoungAdultBodyShaderAMaleYoungAdultBodyShaderCMaleMiddleAgedHeadShaderCFemaleNurseBodyShaderBFemaleNurseBodyShaderCFemaleNurseHeadShaderBFemaleNurseHeadShaderCFemaleNurseBodyShaderDFemaleNurseBodyShaderEFemaleNurseHeadShaderDFemaleNurseHeadShaderEFemaleNurseHeadShaderFFemaleNurseHeadShaderGFemaleNurseHeadShaderHFemaleNurseHeadShaderIFemaleNurseHeadShaderJFemaleYoungAdultBodyShaderBFemaleYoungAdultBodyShaderCFemaleYoungAdultBodyShaderDFemaleYoungAdultBodyShaderEFemaleYoungAdultHeadShaderBFemaleYoungAdultHeadShaderCFemaleYoungAdultHeadShaderDFemaleYoungAdultHeadShaderEFemaleYoungAdultHeadShaderFFemaleYoungAdultHeadShaderGFemaleYoungAdultHeadShaderHFemaleYoungAdultHeadShaderIFemaleYoungAdultHeadShaderJMaleMiddleAgedHeadShaderBMaleMiddleAgedHeadShaderDMaleMiddleAgedHeadShaderEMaleMiddleAgedHeadShaderFMaleMiddleAgedHeadShaderGMaleMiddleAgedHeadShaderHMaleMiddleAgedHeadShaderIMaleMiddleAgedHeadShaderJMaleMiddleAgedBodyShaderBMaleMiddleAgedBodyShaderCMaleMiddleAgedBodyShaderDMaleMiddleAgedBodyShaderEMaleSeniorHeadShaderBMaleSeniorHeadShaderCMaleSeniorHeadShaderDMaleSeniorHeadShaderEMaleSeniorHeadShaderFMaleSeniorHeadShaderGMaleSeniorHeadShaderHMaleSeniorHeadShaderIMaleSeniorHeadShaderJMaleSeniorBodyShaderBMaleSeniorBodyShaderCMaleSeniorBodyShaderDMaleSeniorBodyShaderEFemaleMiddleAgedHeadShaderBFemaleMiddleAgedHeadShaderCFemaleMiddleAgedHeadShaderDFemaleMiddleAgedHeadShaderEFemaleMiddleAgedHeadShaderFFemaleMiddleAgedHeadShaderGFemaleMiddleAgedHeadShaderHFemaleMiddleAgedHeadShaderIFemaleMiddleAgedHeadShaderJFemaleMiddleAgedBodyShaderBFemaleMiddleAgedBodyShaderCFemaleMiddleAgedBodyShaderDFemaleMiddleAgedBodyShaderEFemaleTeenagerBodyShaderBFemaleTeenagerBodyShaderCFemaleTeenagerBodyShaderDFemaleTeenagerBodyShaderEFemaleTeenagerHeadShaderBFemaleTeenagerHeadShaderCFemaleTeenagerHeadShaderDFemaleTeenagerHeadShaderEFemaleTeenagerHeadShaderFFemaleTeenagerHeadShaderGFemaleTeenagerHeadShaderHFemaleTeenagerHeadShaderIFemaleTeenagerHeadShaderJMaleHoboBodyShaderBMaleHoboBodyShaderCMaleHoboBodyShaderDMaleHoboBodyShaderEMaleHoboHeadShaderBMaleHoboHeadShaderCMaleHoboHeadShaderDMaleHoboHeadShaderEMaleHoboHeadShaderFMaleHoboHeadShaderGMaleHoboHeadShaderHMaleHoboHeadShaderIMaleHoboHeadShaderJMaleHospitalPatientBodyShaderBMaleHospitalPatientBodyShaderCMaleHospitalPatientBodyShaderDMaleHospitalPatientBodyShaderEMaleHospitalPatientHeadShaderBMaleHospitalPatientHeadShaderCMaleHospitalPatientHeadShaderDMaleHospitalPatientHeadShaderEMaleHospitalPatientHeadShaderFMaleHospitalPatientHeadShaderGMaleHospitalPatientHeadShaderHMaleHospitalPatientHeadShaderIMaleHospitalPatientHeadShaderJMaleTeenagerBodyShaderBMaleTeenagerBodyShaderCMaleTeenagerBodyShaderDMaleTeenagerBodyShaderEMaleTeenagerHeadShaderBMaleTeenagerHeadShaderCMaleTeenagerHeadShaderDMaleTeenagerHeadShaderEMaleTeenagerHeadShaderFMaleTeenagerHeadShaderGMaleTeenagerHeadShaderHMaleTeenagerHeadShaderIMaleTeenagerHeadShaderJFemaleSeniorBodyShaderBFemaleSeniorBodyShaderCFemaleSeniorBodyShaderDFemaleSeniorBodyShaderEFemaleSeniorHeadShaderBFemaleSeniorHeadShaderCFemaleSeniorHeadShaderDFemaleSeniorHeadShaderEFemaleSeniorHeadShaderFFemaleSeniorHeadShaderGFemaleSeniorHeadShaderHFemaleSeniorHeadShaderIFemaleSeniorHeadShaderJMaleSkeletonBodyShaderBMaleSkeletonBodyShaderCMaleSkeletonBodyShaderDMaleSkeletonBodyShaderEMaleCopBodyShaderBMaleCopBodyShaderCMaleCopBodyShaderDMaleCopBodyShaderEMaleCopHeadShaderBMaleCopHeadShaderCMaleCopHeadShaderDMaleCopHeadShaderEMaleCopHeadShaderFMaleCopHeadShaderGMaleCopHeadShaderHMaleCopHeadShaderIMaleCopHeadShaderJMaleSkeletonHeadShaderBMaleSkeletonHeadShaderCMaleSkeletonHeadShaderDMaleSkeletonHeadShaderEMaleSkeletonHeadShaderFMaleSkeletonHeadShaderGMaleSkeletonHeadShaderHMaleSkeletonHeadShaderIMaleSkeletonHeadShaderJFemaleGoreBodyShaderBFemaleGoreBodyShaderCFemaleGoreBodyShaderDFemaleGoreBodyShaderEFemaleGoreHeadShaderBFemaleGoreHeadShaderCFemaleGoreHeadShaderDFemaleGoreHeadShaderEFemaleGoreHeadShaderFFemaleGoreHeadShaderGFemaleGoreHeadShaderHFemaleGoreHeadShaderIFemaleGoreHeadShaderJMaleGoreBodyShaderBMaleGoreBodyShaderCMaleGoreBodyShaderDMaleGoreBodyShaderEMaleGoreHeadShaderBMaleGoreHeadShaderCMaleGoreHeadShaderDMaleGoreHeadShaderEMaleGoreHeadShaderFMaleGoreHeadShaderGMaleGoreHeadShaderHMaleGoreHeadShaderIMaleGoreHeadShaderJMaleYoungAdultBodyShaderBMaleYoungAdultBodyShaderDMaleYoungAdultBodyShaderEMaleYoungAdultHeadShaderBMaleYoungAdultHeadShaderCMaleYoungAdultHeadShaderDMaleYoungAdultHeadShaderEMaleYoungAdultHeadShaderFMaleYoungAdultHeadShaderGMaleYoungAdultHeadShaderHMaleYoungAdultHeadShaderIMaleYoungAdultHeadShaderJFemaleHoboBodyShaderBFemaleHoboBodyShaderCFemaleHoboBodyShaderDFemaleHoboBodyShaderEFemaleHoboHeadShaderBFemaleHoboHeadShaderCFemaleHoboHeadShaderDFemaleHoboHeadShaderEFemaleHoboHeadShaderFFemaleHoboHeadShaderGFemaleHoboHeadShaderHFemaleHoboHeadShaderIFemaleHoboHeadShaderJZombieDeathSoundsPlayerPainDeath1PlayerPainDeath2PlayerPainDeath3PlayerPainDeath4PlayerPainDeath5PlayerPainGrunt1PlayerPainGrunt2PlayerPainGrunt3PlayerPainGrunt4ZombieMovementSoundsMovementFootstepGeneric1MovementFootstepGeneric2MovementFootstepGeneric3MovementFootstepWater1MovementFootstepWater2MovementFootstepWater3 DeathMale16 DeathMale01 DeathMale02 DeathMale03 DeathMale05 DeathMale08 DeathMale09 DeathMale11 DeathMale12 DeathMale14DeathFemale09DeathFemale03DeathFemale04DeathFemale05DeathFemale07DeathFemale08VelDirCanvas InteractionLevelShaderMoverPawnResult StartTimebOnlySpectatorFists SkeletalMeshSpriteEmitterActorPlayerCountYawMatchID PRIArrayConsoleRoleClassPackage TimeLimitHitLeft HitRightRemainingTime bTeamGame PawnClass TeamIndex instigatedByHumanPawnBase E_HitPartWEAPON_NAME_YWEAPON_NAME_CENTRE bForceRun numLooks SeekLocationLastSeekInstigatorCurrentObstacleCurrentAttackPointNumClearAttemptsClearStartTime EatTarget MAX_EAT_DISTFailedEatAttemptsDistToEatTarget EatingTime MAX_EAT_TIMELastHeardEnemyTimeREACQUIRE_DELAYNumChargingZombiesLastChargeTimeChargeStartTime bIsChargingChargeDuration bIgnoreBumps bActivatedSTART_REACQUIRE_TIMER CHARGE_TIMERPRE_CHARGE_TIMERTHINK_AGAIN_TIMER MELEE_RANGEDONT_BE_STUPID_TIMER obstacle BlueCountDOTZMPGameBase DOTZInvasionConst RedCountdt Smashable AttackPointAdvancedMPGameBase TextBufferObjectStandardMaleBaseStandardFemaleBase PlayerOtisPSpotEnum FunctionStateYL DurationdistRotatorEndHitLocStruct StrPropertyDirHitBackStructPropertyStartArrayPropertydisinfectioncounterInfectedFOVMaxINFECTIONTIMERDISINFECTIONTIMERWEAPON_UP_TIMERWEAPON_DOWN_TIMERDESTROY_TIMER bWasInfected DOTZAZombies DOTZAHumansHuntedClassProperty NamePropertyObjectPropertyFloatPropertyFriendZombieAIController HitFrontFIRINGBLENDBONE DestinationIZombieWeaponszattack BoolPropertyViewKickMagnitude hitblend LoudnessExtent Momentum HitLocationDamage NewVolume HitNormalEventInstigatorOtherposStageSingleFireRateDelta AltFireAnim LatentFloatAdvancedPlayerController IntProperty InstigatorAdvancedWeapon EPhysics ByteProperty AdvancedPawn enemyDirBurned HunterBot BD3PZombiesSpriteEmitter53SpriteEmitter54SpriteEmitter55SpriteEmitter56SpriteEmitter57Xv@I@W N UB!@Tq GsH$sH$v}v}L9v}L9JqL9ebL9sH$sH$sH$sH$v}sH$v}sH$sH$sH$sH$v}sH$v}L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9sH$sH$sH$v}sH$v}sH$v}sH$v}L9JesH$sH$v}v}sH$sH$v}v}v}sH$v}v}v}v}sH$sH$sH$v}v}v}v}JqL9L9L9L9L9L9v}33sH$33L9L93333ɰ{ʅL9L9333ɰ{ʨ3333܈Jq܈3܈Jq Ic  L9L9ɰ{ʅL9sH$CѣL9L9JeJeɰ{ʒsH$sH$v}L9v}L9L9Jqɰ{ʘv}L9sH$sH$L9L9L9L9JeJeɇ$ɇ$Jeɇ$JesH$sH$v}L9v}L9ɰ{ʙJq܈L9L9ɰ{ʅL9L9L9L9L9L9L9JqL9L9L9ɰ{ʅL9L9L9L9L9L9L9v}v}v}L9L9L9L9L9L9L9L9L9ɰ{ʙJqɰ{ʏɰ{ʙJqL9L9a"L9a"L9ɰ{ʅL9L9ɰ{ʒsH$L9sH$sH$v}sH$v}sH$L9sH$L9L9Jqɰ{ʏɰ{ʅL9ebL9sH$L9L9sH$L9sH$L9sH$L9L9Jqɰ{ʒsH$܈L9L9ɰ{ʏɰ{ʒsH$L9ɰ{ʅL9L9L9a"sH$ɰ{ʅL9L9ɰ{ʅL9L9ebɰ{ʆebL9L9L9L9ɰ{ʅL9ɰ{ʅL9L9ɰ{ʙJqɰ{ʏɰ{ʒsH$sH$v}sH$L9JeJeJeɇ$L9L9v}L9ɰ{ʅL9L9L9L9L9JqL9L9L9L9JqL9L9v}v}L9a"L9a"eb܈L9a"L9a"L9a"L9a"-3-3eb-3lJebebebebL9ebebL9ebL9ebebebeb-3eb-3lJebL9L9L9L9L9L9L9L9L9L9L9JqL9L9L9a"L9L9a"L9a"L9a"L9L9L9JqL9L9a"L9L9L9sH$sH$sH$L9L9ɰ{ʅL9L9sH$ɰ{ʏɰ{ʙJqɰ{ʒsH$܈sH$JqJqJqL9܈ɰ{ʏɰ{ʅL9L9ɰ{ʏɰ{ʒsH$JqJqJqL9L9JqsH$L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9L9ɰ{ʏɰ{ʏɰ{ʏɰ{ʒsH$܈L9L9܈L9L9܈sߊsߊsߊɰ{ʒsH$ɰ{ʅL9L9܈܈ɰ{ʅL9L9v}L9v}v}v}sH$v}sH$L9v}sH$v}sH$sH$sH$sH$sH$sH$sH$L9v}sH$L9v}sH$L9v}L9L9L9ɰ{ʅL9L9L9L9sH$sH$ɰ{ʏɰ{ʏɰ{ʏɰ{ʏɰ{ʒsH$ɰ{ʏɰ{ʼ܈ɰ{ʏɰ{ʼ܈Jqɰ{oCaO$?N$?ED"" ~$?w$AC$L>z$@El$C|$A\$>]$@@i$@h$zDg$?f$?e$?d$?c$?b$?a$?`$?_$?^$?\"'T$GOL$C[T gGPi FL ~MiqbrfV {@{d _\~#hLQm(UOiluCO-]W7ZWO VbvKUB\xLTM)EYHYlbP\wbg d=%`aGvKf1w@ {iBY6hOrt@pj IcJqa"a"Jqpjpj Ic Ic Ic Icpj鉪a"ZsߊsߊJqpjJqpjZ"Y"qgJ"K^`\$@Y ^Y GSYX^@+$C!(1$ARA`@n|DK6w w zBY7u"t@pj IcJqa"a"Jqpj鉪a"ZsߊsߊJqpjJqpjqgJ"K_ YM]DOTZAHumans.HumanStandardS]DOTZAZombies.ZombieStandardSrY[sYX`\$xYyYzY{Y|Y}Y~YGSYX^@+$C!(1$AONl?W%0-T'9?S9?, =% Vrq }'ttrq NN,r\.-( .-'NN,N\}q { UE R@\CQStICDP|UKJ{TVz^Wx} .rjaQu~8akYoY<M[IyIB~FX lCDH4MgWAXNF[Prpejc}as_vc kNlmnopqrstHezx S2wfȜ-abc"P~"(^{*US bE tL  cu+S~TJOQX 5Wb  r5* N65 6 9? z5a/!_5a/!\ w5 L5'q!j ] ` P r"* 9"a/!\"a/!_ er"T"a/!l"a/!O"a/!zd"q!h! hcG Z kQ nbd dX9r*,rM9?&a/!la/!Oa/!zM. '5   ..  '( zI _BIl g b ] U gSmOWLڙJq333HL9ebTJqTJqJq IcL9L9L9HL9HHHHHHHHHHHL9a"HHJqJqJqHHHJqzkHH63HzkHzkHzkHzkHzkHHHHL9HebHL9THebHL9HL9THHebHL9q GebHL9HL9HL9ebHHHL9HL9HL9HJqHebebL9HHL9a"HHHHHHHL9HL9HL9HL9HL9HHHL9HL9HL9HL9HHHHHebebHL9HJqebebebJqebHL9ebHL9ebHebebHJqebebebL9HL9L9L9HHJqL9L9L9Hoaf"e$?g$?j$@k" v$Du$Bt$pAn$Amu"}PQM SI E `@ZX Vch 'aS cce{ iaGj`mn3poiVQ^]q|LxXqACwRQPONAdGHJNyU0LmhnOQRfT^ZZ\w^_`q]nkm9fpe[ qZC#r*r*'?bEe'(  idX @[r* r*']%w*bDL>(D Yd'( [2 8A%,A&,  z>N IU3r>*P> g9>  99? L>99? L>99? L>99? L>-Z 9?&fw> w*-Z 9?,Z9333?   > L>>F >pppassess threat 9U  for 9V>  [sRJ]g0` rr-mr`-mb-m r:p`@r:r:*P: -\k-] W: H:w* a: 2 6A%,A&, jZtULcrU EU )m- (-[z-( `$m|IA 2 4A%,A&, ]bu.R^j @j (8 j68-b  6---\8-L?- '6U686U68U-9?%U9?  ի9?,b?8U x|gf)9?)rrb?jw*I 9?% `$w* R-'r-m'` {sBj\-YsZAwt* rsZtsa"?( 2 3A%,A&, J|Ik hcl @K"mW Aj+n' kCX(']h訨9VCOULDN'T FIND PATH TO:9VFrom 9VNoPathToTakeUpI$%I$w*] un BkPrW CpVs[ DH ^sMI $KK #$jK 1$kK ?$pK KK EGG wu r*'-L'vw*W C9?%'v t9?%'\'  G'( FIGx@F HSe8yS _!\w*1   e* |"tt* W u!e S 2 8A%,A&, J_|$Timer!&-[ s Lm}# -[ aa`' MscTimedFireWeaponAtEnemy() at9Us&Qr* )9?b)fa=' { r* Hma=' NR_8R"-i-i(d6-H~R 2 2A%,A&, ORq 2 2A%,A&, eD A'?Z?%Z T;HG9r;*;jr;* w;Can't fire at9V;with focus9V&(;w*{Rbc]Dvi(7Unable to fire weapon:9V&( 2 4A%,A&, UXf7[-t fXWeapon.CanAttack() returned9T-t&-t it2 2A%,A&, XWS?E99 6EEEVW 6VVVEV{n? jiaPmi YiJ.i<rJ*(pJ'YrJ(iuJ(( E2 2A%,A&, 2 0A%,A&, \b{P'r* r*u_ 9?,<  <?<^?<7   @   77?17nRO)OOZ?x?u<7OChanceToHit:9Uxskill:9Uurange:9U<relative velocity9U7los time9UO&x u2 4A%,A&, 2 9A%,A&, 2 .A%,A&, 2 .A%,A&, 2 -A%,A&, aVTtL#AAA0aGMTV'w0*w.0*w.0*P.0R.0OG'( SlUa O&Uf lf gqPbN4-gPh nh-g Gokh 16384sP IifEYw* Xjr*hwr* r ri `$ ?EPPf w* w**  9?  b`$ ??Pf w* w**  9?  b`$??w*w*pb  hEZ>r*AimToMiss on invalid target&9P4#?  6R|9P4AimToMiss on enemy that isn't visible:9Y|&|_@  m=Z  m=Z@69?,k @E-B 4CEk BCq9Pk4T4kHDq9PD#?H4AimToMiss on visible enemy:9Yq&q xe/Gr),r*C[w* pv!eaW @@( wzlXWya/!_z%6ya/!\z%wzyIJN vkp 0x00000001@xTVF&rx|$px' eUw}lbW~a/!_}%6~a/!\}%w}~FGH ~MH2a,(a,( }{1 BO0aV:?(a<( H|f1rD[D  DE`[E<PEd:w.d*p.d(  J]H=r*AimToHit on invalid target&9PW/[J-O WXJ/ OXTW/eY/  TW/eYp9P/WAimToHit enemy:9Yp&p KKSU C6% J9?%pSbelPS `$`$?BSJ F/I@s--(G%a,(.h(.Zi9:9:$a,9?t(@AC wTeb)T ,Z V<t.. V:.*D ,a T G[WT C:ppReceivedWarning from 9VW9VW NBhJ qhY #?Y{ e%]hueoZhue {Pjf ac(, ? _^ja jPw{ Z[w.*.VH!_ $9D9?7H $9D9?7H $9D9?7H #$9D9?7H ($ 9D9?7He?,  T{!-'a,9?a'  MSvr*Nr*No target to fire at&-i'd({Starting burst&G- 'S  fFiring weapon at9V&`$?R'- j-y--1 RSSupress A- j-y-Cannot fire.&R%Hr f(re)firing weapon at9V&- j-y--1 RSSupress B- j-y-CAN'T ATTACK&-i'd( yVQk-(G%a,(.h(.Z.^ L>#zDzDzD YZF-'Glg*## s.9?,x.9?,G,Q R'a %#w*-(* WB]j׮+ rB* B-' \@}K{.-!--@ .--@. h-y-'l-fh*a,9?a' XyJxܯbef ef?@*'|6|6|b #?99|y ezvRAVN z @N9? T?N@E _IgfIa/!dq!fYYa!f w*a<?(aV:(q!I ZwH $bef r* ef?@*']w #?}9P]6}6}b  #?99}] @`tOX}-'Va!fVw*a!`a<(aV:( bb{u  ]O_8YQ99+ #?(QOPauQ+(+(rP*((Q#?O?(9?*'b$+(+ ('1b$+(+ (' Q9?,' d]l  w*  PfeH369:9:$b?69?@6g@@9?,d@9?l9D9?`@*# %\#w.*.Ww*?6Po333>=TD#?`G# A?633b? lvwq?q@ v =@9? T@9?,o?@HC@E gz:d/a/!J(,(,(-T(S9D.h( hY6| ka+tYQ9:9:$Q-V--V-. h-   aXJY1-r bWb-ow.*rYzattempting to path find to9Vattempt #9Szto dest9Vz&z,Giving up on path through9Vto9V(&w*'p- 9:9:$gpCOULDN'T FIND BEST PATH TO 9VNo Path to 9V( o 26ysxhQ??s;D AY{ 25jq.p -T ps)' rq)Restq!_ tx_=b@w*H99 9? bW-HbJD_zDaa@@@@ B2: # # v_7 wmT:>8Tm* Y nG]>NA%DA,:9:n&A%\A9?\ uZaY^sWander3*w*Q%Q7Q-Z?9?ZLQQ'']L3LNDrD*7D&can't wander from hereN37DD'wandering to9V3u | 3849302} 3982834~ 26Q  24zu? k3p zw*'NoWander-Enemyy X3('a!Vq!V!Uq!V'NoWanderPathy% A Vh'aa=?'aa ).u U"P_ @ hMovingq!j B D JVCr* i-T C j4Vi- r*aa ).{a ).~ E kqkbjq!X ,B 39201F k5eW 9?,bq!X!*v cq!X!U I X4MoveToLocationadb moving directly to9Xa .bUr*can't find path to9X-w*:   falling back to9Va)\=>bUa>Ow*w !*w*moving to9V a ).a=>kDoneMovingToLocation # # *UJ z.| K T7=DStandGround0wH;q!l L P l^0d8 #a  .aa=} TBL -1' N [QA *-1( O _TW'8T_%r_ g 120M KoOPerform_NotEngaged_FireAtTargetFireAtTarget q!o R T nx S X oNotEngaged_FireAtTargetaa?'a?@nG rw* d  rG  *| _8"FireAtTarget timers V sr* u{ r * H 9Vfired at9V m~a=' W iT{8Ti   d eKJ<7&?,zDzDe,9?7, e ,,9?7?,9?zD,zD U p|RecoverEnemy? 9?,T [b q!q!] bw*q!q!L T  Z ^ qvxaa . !Aa ).=Qp{ A.L]P] Q:w* R 9?, \ pT"'8Tp%rp [ [c  NGetLOS['@w*]C r*][zRNoLOSSpotA%NoLOSSpotB% r _ ` r# V4X('*a!Yq!Y!r1q!YT'NoGetLOSPath% b |5 ,a=| E a LA< f QA z&w* k Vha uHide'3w*]`Xr*NoHideSpot% X('a![q![!f `$q!['NoHidePath% g l [ wp-'a )(1Qh|y fXj Q &w* k i B E" w* p k [ >+w*R R-( h [ YTakeCoverZ\%-'q!~!r -('w*]`r*NoCoverSpot-'% } m } vtX('Er  ex-'q!~!I'NoCoverPath% n } 0a=}%  o u ~ da= !*ei- r*aa )(a )(Qa=}qv *Irr Q {&w* k q B " w* p s [ I+w*R RGw*-( t e 8ed p Ed0 iOutFromCover\w*Lq!M!s-( 'UDE%(E7SES-LSPS PUUPMSEtAwM*]MaNoOutFromCoverSpot% z MvF*a,(a,( y {m) BdM(aV:?(a<( Q x fn)v ] \4X('*a!Mq!M!U1q!MZ'NoOutFromCoverPath% | ~ Mu Ri- r*'aa )(ra )(Qa=x *sU Qr &w* k } S *SupressionFireq!w @ G w {Xdaa=sa9?R~w HB  -1' B [  -1( C RT Z'8TR%rR U dM9;d D e 8e*' F s qr* 9{m R]Dmvi( A I ~  J H YU tUCharge&Y9?%Y AcY'q!n! H  39202K @ f  9?, kuq!n!*cVq!n!*bq!n!UX('q!n!UVq!n!* M n T"@\i- r*aa ).a ).@Charge-donea *UN V %Strafe@q!A  O Z( & Z^@^Kay^  ի?Z (wK* y^Z9?,b$  (   dw*!  9?     9?s  9:9:$6s-H9Uss^ R bMq%-(X%a,(.h(.Zi9:9:$a,9?Z(bce V Ne,!N ,Z V<t.. V:.*D ,a N fyt `U0`:[7&?f C`?f9?7& Z ll |0-P'9?N9?, =% Qrc  oorc ll,ra.-( .-' la_ac L  1.5^P p@M *p99#?-O-OJ-Op9?pp@@XNoStrafeDir% j f;ac(, ? L^a Pw^ Z[w.*'.VH'!L $'9D9?7H $'9D9?7H $'9D9?7H #$'9D9?7H ($ '9D9?7He'?,  Y ] Au 6.aaX.~cr*Rb$  !uStrafeRecoverda=L>ի9?, aa.s uMcBc ,=-'-'-(-( \ [k ;-l-'r* -(-( >j9?%-' [ W L2Hunting'A ^ A 2N4X('*a!`q!`!U1q!`LNoHuntPath% _ a ` 4Taa ).(QAr U<b Q ]4w* R ` d B 6k r*(9  Q'Pb@'gb`@@'( c X 7UPanic*-l'`' `$=q!C e z C@ :D`Ea )(E,B !vq *,v@]T 98T] gg oE :o%o7noln  n  l lAAl@noX@((NoPanicDir% k { l Q p Z  m i {[ >gA3rA*A v%M  c%4c7AgcAIgwg g  M*wv*?9?v[w{IceMw{*{eNoPanicDir% q n }  r FgfFa/!dq!fYYa!f w*a<?(aV:(q!F s tX}-'Va!fVw*a!`a<(aV:( u bw  D \V%9[7&?g t\?g9?7& v deM69:9:$b?69?K6gKK9?,dK9?l9D9?`K*# %\#w.*.Ww*d?6Po333>=dTDdd#?`G# A?633b? w ]B w*  x z0nd/a/!J(,(,(-P(N9D.h( | Y,& o B5 0C" w* p y [: C-+w*R R f B]V LFAdvanceMoveBBrB*roOGyr]BoB  'HroBWNoNewTacticalSpot%]WF  ~ a!YQ9:9:$Q-V--V-. h-  W  39203  26F  25{ Ft H[4X('*a!aq!a!U1q!aY'NoAdvanceMovePath% @ B a .KaZi- r*'aa ).a ).QFSp UC Q J&w* k A E Z SN r* Y%Y7XYbrX* r*HX  H9?X9?HY XG 3849302H 3982834J  26D m@ nP2wm*m@k.bwk*k@md*q!y K  24^  120I x Qpw* m$*Gw*r. *E d'nw6*6Z L k Sx M Q y S P ` vS O B Sa N i HTR % `UJwHAw* #q!D S U D V,aa@o B YVECw* # # T YS W3g  SY }  68695 V $k X-H r* S #?i6? $369?,},69?, $ $$$$a9Wa$-69?,},6+9?%$aE$aѨ9U$369?,},69?,-)6 9?&$a &XY U; \  -H P@ $$$STAGE:r*None9W  Stage order:I $SO_None $SO_TakeUpPosition9V 4$SO_HoldPosition W$SO_TakeCover Unrecognized order:9RIaP@Performing:7w*hitChance:9U{enemyDist9U  aP@pppEnemy:9VShootTarget:9V FocalPoint:9XaP@UP [ ] ` ~ld7/,<& c yP . c&!x. c&!Y. c&!H. c&!I. c&!J. c&!K. c&!L. c&!M. c,!Z1 a/!l &gBD2004Zombies.ZombieFistweapono a/!\ gDOTZWeapons.Fistweapon a/!O *gBD2004Zombies.ZombieFistweaponOtis a/!_ gDOTZWeapons.Fistweapon \ Ww b;9-H9`%`K%9VW![ W WPe l B 2-:a/!Q$&r %rBD2004Zombies.ZombieJackDM "-:a/!Q$&r #rBD2004Zombies.ZombieOtis -:a/!Q$%r #rBD2004Zombies.HunterOtis G-:a/!Q$%r (rBD2004Zombies.HunterJackSlade -(r %rBD2004Zombies.ZombieJackDM -(r #rBD2004Zombies.HunterOtis - ( a e ~ c;3w*  $$$E d F ew*RfPg # A $$$ # A $$$ # A$$$ f ]E h r* ]%]7=]\=%= = #?9?,2$$$= = #?9?,2$$$] \h  g ^P l^%^7#^%%%,9:#&%%# # #?9?,2#?9?, 9?%$$$Cw%  *# # #?9?,2#?9?, 9?%$$$# # #?9?,2#?9?, 9?%$$$%A^ i m k ] \%g\7V\%d]c\|dc$$ W _*- ( , j _Q qw*_%_7`_a]`aCa` ` #?9?,29Ca$$_ S// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 //----------------------------------------------------------- // //----------------------------------------------------------- class ZombieOtis extends BD2004ZombiePawnBase placeable; uo OBY6p ̕#u" Y]DOTZAHumans.HumanStandardS]DOTZAZombies.ZombieStandardS]DOTZAHumans.3PLeadPipeS]DOTZAHumans.3PFireAxeS]DOTZAHumans.3PBaseballBatS^Y &Y $Y  [// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 //----------------------------------------------------------- // //----------------------------------------------------------- class ZombieJackDM extends BD2004ZombiePawnBase placeable; n gRs,g,G%G,v&,G,z9D9?&9?,9?G9?,F%Fgb%bgF{#?9?9?F9?v#?9?9?b9?z* {6*9?9D6*?9?9?6*9?9D6*?9?9?**#?9?,2$$$bFnG% uq lBY6s =*iu" Y]DOTZAHumans.HumanStandardS]DOTZAZombies.ZombieStandardS]DOTZAHumans.3PLeadPipeS]DOTZAHumans.3PFireAxeS]DOTZAHumans.3PBaseballBatS^Y &Y $Y  W class ZombieFistWeaponOtis extends DOTZMeleeWeapon config(user); /***************************************************************** * PlayFiring * Normal fire has occured by this point, we just need to make it look * like it has now, so play an animation. ***************************************************************** */ simulated function PlayFiring(){ local DOTZPlayerControllerBase PlayerOwner; PlayerOwner = DOTZPlayerControllerBase(Instigator.Controller); if (bDoAltFire == true){ PlayAnim(AltFireAnim, SingleFireRate); } else { PlayAnim(FireAnim, SingleFireRate); } IncrementFlashCount(); } //=========================================================================== // DefaultProperties //=========================================================================== t o Q2u 0YϔJfL9OBT]DOTZAZombies.ZombieStandardSbRXQFPFU] Zombie HandsNw^] Zombie Hands S class ZombieFistWeapon extends DOTZMeleeWeapon config(user); /***************************************************************** * PlayFiring * Normal fire has occured by this point, we just need to make it look * like it has now, so play an animation. ***************************************************************** */ simulated function PlayFiring(){ local DOTZPlayerControllerBase PlayerOwner; PlayerOwner = DOTZPlayerControllerBase(Instigator.Controller); if (bDoAltFire == true){ PlayAnim(AltFireAnim, SingleFireRate); } else { PlayAnim(FireAnim, SingleFireRate); } IncrementFlashCount(); } //=========================================================================== // DefaultProperties //=========================================================================== v m R2w 苇JfL9OBT]DOTZAZombies.ZombieStandardSfRXQEPFU] Zombie HandsNw^] Zombie Hands O// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 class ZombieFistAmmunition extends DOTZMeleeAmmunition; [// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 /***************************************************************** * Otis - * * The mesh specification for the lead action figure * * @version $1.0$ * @author Jesse (Jesse@digitalextremes.com) * @date 2004 ***************************************************************** */ class HunterOtis extends BDPlayerPawnBase placeable; /** */ function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { if ( instigatedBy.isA( 'HunterJackSlade')) damage = 0; if ( instigatedBy.isA( 'HunterOtis')) damage = 0; super.TakeDamage( damage, instigatedBy, hitlocation, momentum, damageType ); } //=========================================================================== // DefaultProperties //=========================================================================== hy t\BY6z  EhOrL9L9 Yl]DOTZAHumans.3PFireAxeS]DOTZAHumans.3PBaseballBatS]DOTZAHumans.HumanStandardS&Y$Y!e// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 /***************************************************************** * JackSlade - * * The mesh specification for the lead action figure * * @version $1.0$ * @author Jesse (Jesse@digitalextremes.com) * @date 2004 ***************************************************************** */ class HunterJackSlade extends BDPlayerPawnBase placeable; /** */ function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { if ( instigatedBy.isA( 'HunterJackSlade')) damage = 0; if ( instigatedBy.isA( 'HunterOtis')) damage = 0; super.TakeDamage( damage, instigatedBy, hitlocation, momentum, damageType ); } //=========================================================================== // DefaultProperties //=========================================================================== r Su%7\  9?,2#?$$$  9?,2#?$$$ h{ z_BY6} HhOrL9L9 Yl]DOTZAHumans.3PFireAxeS]DOTZAHumans.3PBaseballBatS]DOTZAHumans.HumanStandardS&Y$Y! | T%wA?w*Y@@  m=  a    m=9P#?$$$  a    m=9P#$$$?  a  @@9P#?$$$  a  @@9P#$$$ ~ ?U8{?%?7t?9?%? ? 9?,2#?$$$? Z// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 /***************************************************************** * JackSlade - * * The mesh specification for the lead action figure * * @version $1.0$ * @author Jesse (Jesse@digitalextremes.com) * @date 2004 ***************************************************************** */ class BDPlayerPawnBase extends HumanPawnBase; var int infectionDamage; var int infectionFreq; var name InfectedEvent; var int disinfectioncounter; const InfectedFOVMax = 120; const INFECTIONTIMER = 24; const DISINFECTIONTIMER = 26; const WEAPON_UP_TIMER = 3982834; const WEAPON_DOWN_TIMER = 3849302; const HUD_HACK = 25; const DESTROY_TIMER = 26; var int iMultiPlayerCorpseSecs; var bool bWasInfected; var bool bNoDamageEffects; var int StartTime; /***************************************************************** * PostNetReceive * Here we handle when data from the server comes in. ***************************************************************** */ simulated event PostNetReceive(){ if (Level.NetMode == NM_Client){ if (bWasInfected != bInfected){ bWasInfected = bInfected; DOTZPlayerControllerBase(Controller).InfectionEffect(bInfected); } } super.PostNetReceive(); } function PostBeginPlay(){ super.PostBeginPlay(); } simulated function PostNetBeginPlay(){ super.PostNetBeginPlay(); if (Controller.IsA('XdotzPlayerController') == false){ WEAPON_NAME_CENTRE += 40; WEAPON_NAME_Y += 40; } bNoDamageEffects = false; StartTime = Level.TimeSeconds; DOTZPlayerControllerBase(Controller).InfectionEffect(false); } function TakeFallingDamage(){ local float Shake, EffectiveSpeed; if (Velocity.Z < -0.5 * MaxFallSpeed) { if ( Role == ROLE_Authority ) { MakeNoise(1.0); if (Velocity.Z < -1 * MaxFallSpeed) { EffectiveSpeed = Velocity.Z; if ( TouchingWaterVolume() ) EffectiveSpeed = FMin(0, EffectiveSpeed + 100); if ( EffectiveSpeed < -1 * MaxFallSpeed ){ TakeDamage(-160 * (EffectiveSpeed + MaxFallSpeed)/MaxFallSpeed, None, Location, vect(0,0,0), class'Fell'); if (health > 0 ){ FallDown(vect(-1,0,0)); if(PlayerController(Controller) != none){ AdvancedPlayerController(Controller).Fall(); // camera effect } } } } } if ( Controller != None ) { Shake = FMin(1, -1 * Velocity.Z/MaxFallSpeed); Controller.ShakeView(0.175 + 0.1 * Shake, 850 * Shake, Shake * vect(0,0,1.5), 120000, vect(0,0,10), 1); } } else if (Velocity.Z < -1.4 * JumpZ) MakeNoise(0.5); } /***************************************************************** * Begin Play * This will take away the arrow above player, to stop server blog. ***************************************************************** */ simulated function SetTeamAttachments(){ if (PlayerReplicationInfo != none) { return; } } /***************************************************************** * CheckShadow * overridden to prevent shadowness on the player in a single player * game ***************************************************************** */ simulated function CheckShadow(){ /*if (Level.NetMode != NM_StandAlone){ super.CheckShadow(); } */ } /***************************************************************** * PostLoad * Reset the infection state ***************************************************************** */ function PostLoad() { super.PostLoad(); // log(self $ "postload"); SetInfectionState( bInfected, true ); if (IsInState('Swimming')){ if (Weapon != none){ Weapon.PlayAnim('Deselect'); SetMultiTimer( WEAPON_UP_TIMER, 0, false ); SetMultiTimer( WEAPON_DOWN_TIMER, 0, false ); } } } /***************************************************************** * PhysicsVolumeChange ***************************************************************** */ event PhysicsVolumeChange( PhysicsVolume NewVolume ){ // Log(NewVolume); if ( NewVolume.Isa('WaterVolume') ) { GotoState('Swimming'); } else if ( IsInState('Swimming') && Weapon !=None ) { SetMultiTimer( WEAPON_UP_TIMER, 0.5, false ); SetMultiTimer( WEAPON_DOWN_TIMER, 0, false ); GotoState(''); } super.PhysicsVolumeChange( NewVolume); } /***************************************************************** * SetInfectionState ***************************************************************** */ function SetInfectionState(bool iState, optional bool bForce ){ //no sense doing stuff if you already done it'afore //... unless you're re-initializing because of load game... if ( !bForce ) { if (bInfected == iState ){ return; } else { bInfected = iState; } } // Log(self $ " setinfectionstate: " $ iState); DOTZPlayerControllerBase(Controller).InfectionEffect(bInfected); //DOTZPlayerControllerBase(Controller).MotionBlurOn(); //always trigger events, and set timers on the client if (bInfected == true){ if (!bForce){ TriggerEvent( InfectedEvent, self, none); } SetMultiTimer(INFECTIONTIMER,infectionFreq,true); } } /***************************************************************** * DoInfectionDamage ***************************************************************** */ function DoInfectionDamage(){ if (bInfected == true){ disinfectioncounter++; TakeDamage(infectionDamage, none,vect(0,0,0),vect(0,0,0), class'DOTZInfectionDamage'); if (PlayerController(Controller).DefaultFOV < InfectedFOVMax ){ PlayerController(Controller).DefaultFOV += 6; } if (disinfectioncounter > 3){ DoDisinfection(); } } } /* function PreSave(){ super.PreSave(); log("PreSave"); DOTZPlayerControllerBase(Controller).InfectionEffect(false); } function PostSave(){ super.PostSave(); log("PostSave"); DOTZPlayerControllerBase(Controller).InfectionEffect(bInfected); } */ /***************************************************************** * ***************************************************************** */ function DoDisinfection(){ bInfected = false; disinfectioncounter=0; SetMultiTimer(INFECTIONTIMER,0,false); DOTZPlayerControllerBase(Controller).InfectionEffect(false); //DOTZPlayerControllerBase(Controller).MotionBlurOff(); PlayerController(Controller).FixFOV(); //DOTZHealthBar(MyLifeBar).SetInfected( bInfected ); PlayerController(controller).ClientFlash(0.2, vect(1000,1000,1000 )); } /***************************************************************** * TravelPostAccept ***************************************************************** */ function TravelPostAccept(){ super.TravelPostAccept(); // Log("Travel post accept called on the player"); if (bInfected == true){ SetMultiTimer(INFECTIONTIMER,infectionFreq,true); } } /***************************************************************** * PlayTakeHit * Overridden to prevent the hit noises from infection damage ***************************************************************** */ function PlayTakeHit(vector HitLoc, int Damage, class damageType) { local name HitAnim; local E_HitPart hitPart; //turn off the boredom timer SetBoredomTimer(false); // AnimBlendParams(TAKEHITCHANNEL,1); AnimBlendParams(TAKEHITCHANNEL,1,,,FIRINGBLENDBONE ); hitPart = calcHitPart( hitLoc ); Spawn(BloodEmitter,,,HitLoc); //this is the added line, the reason for overridding if (damageType != class'DOTZInfectionDamage'){ PlayHitSound(); } ViewKick(ViewKickMagnitude); //try and use a weapon specific hit animation first if (AdvancedWeapon(Weapon) != none){ HitAnim = AdvancedWeapon(Weapon).GetHitanim(); //Log("you win: " $ hitanim); } if (HitAnim == ''){ switch ( hitPart ) { case HIT_Back: HitAnim = HitBack[int(Frand()*HitBack.length)]; break; case HIT_Head: HitAnim = HitHead[int(Frand()*HitHead.length)]; break; case HIT_Chest: HitAnim = HitFront[int(Frand()*HitFront.length)]; break; case HIT_Left: HitAnim = HitLeft[int(Frand()*HitLeft.length)]; break; case HIT_Right: default: HitAnim = HitRight[int(Frand()*HitRight.length)]; break; } } // PlayAnim(HitAnim,1,hitblend,TAKEHITCHANNEL); AdvancedPlayAnim(HitAnim,1,hitblend,TAKEHITCHANNEL); } /***************************************************************** * TakeDamage ***************************************************************** */ function TakeDamage(int Damage,Pawn instigatedBy, Vector Hitlocation, vector momentum, class damageType){ // Log( self @ "" $ DamageType ) ; if (bNoDamageEffects == true || Level.TimeSeconds - StartTime < 5){ return; } //already dead igmore further damage so you don't //chunk up and prevent the death animation from playing if (Health < 0){ return; } if (DamageType == class'DOTZInfectionDamage') { SetInfectionState(true); } //fire should burn the zombies much worse else if (DamageType == class'Burned') { // Log( self @ "Damage was: " $ Damage ) ; Damage = Damage / 4; // Log( self @ "Damage reset to : " $ Damage ) ; } //can't hurt yourself with some weapons if (InstigatedBy == self && AdvancedWeapon(Weapon).bCanDamageSelf == false){ return; } //you are much tougher in kungfu mode if (DOTZPlayerControllerBase(Controller).KungFuMode == true){ Damage = Damage / 3; } Super.TakeDamage(Damage,instigatedBy, Hitlocation, momentum, damageType); } /***************************************************************** * MultiTimer ***************************************************************** */ function MultiTimer(int ID){ switch ( ID ) { case INFECTIONTIMER: DoInfectionDamage(); break; case WEAPON_UP_TIMER: Weapon.BringUp(); AdvancedWeapon(Weapon).AccuracyIndicator = AdvancedWeapon(Weapon).default.AccuracyIndicator; break; case WEAPON_DOWN_TIMER: AdvancedWeapon(Weapon).AccuracyIndicator = none; Weapon.PutDown(); break; case DESTROY_TIMER: Destroy(); break; default: Super.MultiTimer(ID); } } /**************************************************************** * Died **************************************************************** */ function Died( Controller killer, class damageType, vector hitLocation ) { //almost like do disinfection, but we leave the health bar, and //don't do the 'heal' flash bInfected = false; disinfectioncounter=0; SetMultiTimer(INFECTIONTIMER,0,false); //AdvancedPlayerController(Controller).MotionBlurOff(); DOTZPlayerControllerBase(Controller).InfectionEffect(false); PlayerController(Controller).FixFOV(); // Log(self $ " has ded"); if (Level.NetMode != NM_Standalone){ SetMultiTimer(DESTROY_TIMER,iMultiPlayerCorpseSecs,false); // Log(self $ " has ded"); // LifeSpan=5; } super.Died(killer, damageType, hitlocation); } state Swimming{ /***************************************************************** * BeginState ***************************************************************** */ function BeginState(){ SetMultiTimer( WEAPON_DOWN_TIMER, 0.5, false ); SetMultiTimer( WEAPON_UP_TIMER, 0, false ); } /***************************************************************** * ChangedWeapon ***************************************************************** */ function ChangedWeapon(){ } } /***************************************************************** * Destroyed ***************************************************************** */ function Destroyed(){ SetMultiTimer(INFECTIONTIMER,0,false); SetMultiTimer(DISINFECTIONTIMER,0,false); // Log(self $ " has been destroyed"); Super.Destroyed(); } //=========================================================================== // DefaultProperties //===========================================================================  2WD}2%27C29?%2 2 9?,d#?$$$2 U//============================================================================= // MyMiniExplosion. //============================================================================= class BDMiniExplosion extends BBPDestruction placeable; //Big thank you to Hawkzz for getting the size right. //Thank you to Trin for the Net Fix A ViR~:99 V  ?  P jW67&?ha#? &j&zD&9?7& j h&&9?7&&9??&zD C |b_|U|& B F@G /'~)IGVaK Y hijklL O Z $@ $pAn(D SowJ` rs"th:[ "@ b K S L F TbgTS l J RHs1aOGj% j7!j~]!r!P!- ~R(!  Q\!b!  baab}!j-r}*(' H e%L  \ ]\2%kklmnopqrstlkWlVmUnMoLpKqGrxswtvlk F// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 /** * OtisAIController - * * @version $Rev: 4874 $ * @author Jesse LaChapelle (jesse@digitalextremes.com) * @date June 2004 */ class BDLeadPipeHunter extends BDHunterAIController; //=========================================================================== // //=========================================================================== /** */ function Possess( Pawn p ) { super.Possess( p ); p.GiveWeapon( "Hunted.HumanLeadPipeWeapon" ); } /** */ function bool SameTeamAs(Controller C) { // only zombies return (BDHunterAIController(c) != None); } //=========================================================================== // Otis-death game logic... //=========================================================================== /*function bool FireWeaponAt(Actor A) { //DebugLog( "Trying to fire at" @ A ); if ( A == None ) A = Enemy; Target = A; if ( (Pawn.Weapon != None) && Pawn.Weapon.HasAmmo() && !Pawn.Weapon.IsFiring() ) { NumShotsToGo = iRandRange(MinNumShots,MaxNumShots); CalculateMissVectorScale(); return WeaponFireAgain(Pawn.Weapon.RefireRate(),false); } else { DebugLog( "Unable to fire weapon:" @ Pawn.weapon, DEBUG_FIRING ); return false; } } */ //=========================================================================== // Default Properties //=========================================================================== !R j jB!T jbTL9oCa"~$L?w$?z$zD|$@@s// Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 /** * ZombieAIRole - * * @version $Rev: 5272 $ * @author Jesse LaChapelle (jesse@digitalextremes.com) * @author Neil Gower (neilg@digitalextremes.com) * @date June 2004 */ class BDHunterAIRole extends DOTZAIRole; //=========================================================================== // Settings //=========================================================================== var int AttackRange; var float MinWanderDelay; var float MaxWanderDelay; //=========================================================================== // internal data //=========================================================================== // wander var protected int numLooks; // seek var protected Vector SeekLocation; var protected Actor LastSeekInstigator; var protected float LastSeekRefreshTime; // obstacle smashing var protected Smashable CurrentObstacle; var protected AttackPoint CurrentAttackPoint; var protected int NumClearAttempts; var protected float ClearStartTime; // eating var protected Actor EatTarget; const MAX_EAT_DIST = 100; var protected int FailedEatAttempts; var protected float DistToEatTarget; var int EatingTime; const MAX_EAT_TIME = 10; // enemy mgmt var protected float LastHeardEnemyTime; const REACQUIRE_DELAY = 1.5; // charging var protected int NumChargingZombies; // using default value as a class var. var protected const int MaxChargingZombies; var protected const float MaxChargeDist; var protected const float MinChargeDist; var protected float MinTimeBetweenCharges; var protected float MaxTimeBetweenCharges; var protected float LastChargeTime; var protected float ChargeStartTime; var protected bool bIsCharging; var protected float ChargeDuration; var protected bool bIgnoreBumps; var() bool bAllowedToCharge; // other var protected bool bActivated; const START_REACQUIRE_TIMER = 68694; const CHARGE_TIMER = 8375093; const PRE_CHARGE_TIMER = 8375094; const THINK_AGAIN_TIMER = 92843; const MELEE_RANGE = 150; const DONT_BE_STUPID_TIMER = 29384; var BDHunterAIController HunterBot; //=========================================================================== // Events of interest... //=========================================================================== function OnTakingDamage(Pawn Other, float Damage) { super.OnTakingDamage( other, damage ); //in multiplayer, if some other human shoots you then go after them instead if (Level.NetMode != NM_StandAlone && BDHunterAIController(Other.Controller)==None){ if ( other.isA('HunterJackSlade') || other.isA('HunterOtis')) return; bot.enemy = Other; } } /** * Called whenever an enemy pawn is in sight. */ function OnThreatSpotted( Pawn threat ) { // // Log( self @ "OnThreatSpotted" @ threat ) ; if ( threat == None ) return; //TODO: this probably needs fancying up. Possibly only switch if // closer, or human controlled... // zombies have stiff necks, they can't look up and down very far... if ( abs(threat.location.z - bot.pawn.location.z) > 2048 ) { return; } if (threat.isA('HunterJackSlade') || threat.isA('HunterOtis')){ return; } if ( threat != bot.Enemy ) { bot.AcquireEnemy(threat, true); } GotoState( 'Attacking' ); } /** * */ function OnThreatHeard( Pawn threat ) { // // Log( self @ "OnThreatHeard not used by ZombieAIRole" ) ; } /** * Called when something does a MakeNoise(). Instead of directly * acquiring the enemy at this point (as the base class does), start * seeking, in an effort to cause an OnThreatSpotted(). */ function OnHeardNoise( float Loudness, Actor NoiseMaker ) { // // Log( self @ "OnHeardNoise" @ loudness @ noiseMaker ) ; if ( noiseMaker == None ) return; if ( NoiseMaker.isA('HunterOtis') || NoiseMaker.isA('HunterJackSlade')) return; if ( NoiseMaker == bot.Enemy ) lastHeardEnemyTime = Level.timeSeconds; if ( NoiseMaker.isA('ZombieJackDM') || NoiseMaker.isA('ZombieOtis')|| NoiseMaker.isA('ZombiePawnBase')) { //FIXME this may be a little wrong, don't want to reset seek state... if ( TrySeekTarget(NoiseMaker) ) GotoState( 'Seeking', 'BEGIN' ); } } /** * It's all over for this zombie... */ function OnKilled( Controller killer ) { super.OnKilled( killer ); EndCharge(); } /** * Mmmmm... tasty carrion to feed on... */ function OnWitnessedKill( Controller killer, Pawn victim ) { super.OnWitnessedKill( killer, victim ); } //=========================================================================== // High level AI scripts/plans... //=========================================================================== /** * Sets a to be the new seek target, if it is better than the current * target. * * @returns true - target is now a, false otherwise. */ function bool TrySeekTarget( Actor a ) { // do some easy checks... if ( LastSeekInstigator == none // if we don't have a seek target... || (LastSeekInstigator == a // or refreshing current target... && Level.TimeSeconds - lastSeekRefreshTime > 1) || a.IsA('ZombieJackDM') || a.isA('ZombieOtis') ||a.isA('ZombiePawnBase') ) { // or it's a hero... LastSeekInstigator = a; LastSeekRefreshTime = Level.TimeSeconds; SeekLocation = a.Location; return true; } // check if the new seek target is closer than the current seek // target... if ( VSize(bot.Pawn.Location - a.location) <= VSize(bot.Pawn.Location - SeekLocation) ) { LastSeekInstigator = a; SeekLocation = a.Location; bot.updateFocus( a ); return true; } // new target didn't meet any criteria to override the current one. return false; } /** */ function TryClearObstacle( Actor obstacle ) { local Pawn potentialEnemy; // if it's an enemy, kill it! potentialEnemy = Pawn(obstacle); if ( obstacle.isA('HunterJackSlade') || obstacle.isA('HunterOtis')) return; if ( potentialEnemy != None && !bot.SameTeamAs(potentialEnemy.controller) ) { bot.acquireEnemy(potentialEnemy, true); GotoState( 'Attacking' ); return; } // check if it's smashable... currentObstacle = Smashable(obstacle); if ( currentObstacle != None ) { // // Log( self @ "hulk smash!" ) ; numClearAttempts = 0; GotoState( 'DoSpecial', 'SMASH_OBSTACLE' ); } else { // // Log( self @ obstacle @ "not smashable" ) ; } //FIXME: need a way to resume after clearing the obstacle. } /** * Determines whether it's appropriate to charge at the enemy now. */ function bool ShouldCharge() { local bool result; return true; } //=========================================================================== // Wander - no (known) threats nearby, nothing in particular to do but // wander around in an undead stupor. //=========================================================================== auto state Wander { function BeginState() { // // Log( self @ "entering wander state" ) ; } function EndState() { // // Log( self @ "leaving wander state" ) ; } function NotEngagedWanderFailed() { GotoState( 'Attacking' ); } BEGIN: while ( true ) { // // Log( self @ "wandering" ) ; Sleep( 1 ); // look around randomly... numLooks = RandRange( 1, 5 ); while ( numLooks > 0 ) { bot.SetRandomFocalPointLocation( 2000 ); Sleep( RandRange(10, 30) ); --numLooks; } // // Log( self @ "doing the wander behaviour" ) ; // find a new place to stand around... bot.Perform_NotEngaged_Wander(); WaitForNotification(); // now just stand there for a while... Sleep( RandRange(MinWanderDelay, MaxWanderDelay) ); } } //=========================================================================== // Seeking - no enemy directly accessible, but something of interest // to seek towards, such as an attractor or the sound of a player. //=========================================================================== state Seeking { function BeginState() { // // Log( self @ "entering seeking state" ) ; // entering this state implies there is something to seek // towards... // if ( !(LastSeekInstigator != None ) ) { Log( "(" $ self $ ") assertion violated: (LastSeekInstigator != None )", 'DEBUG' ); assert( LastSeekInstigator != None ); }// ; } function EndState() { // // Log( self @ "leaving seeking state" ) ; // stop moving! bot.Perform_Error_Stop(); } /** * Bumping into things may interrupt the seeking... */ function OnBump( Actor other ) { // // Log( self @ "OnBump" @ other ) ; TryClearObstacle( other ); } /** */ function OnHitWall( Actor other ) { // // Log( self @ "OnHitWall" @ other ) ; TryClearObstacle( other ); } /** */ function OnHitMover( Actor other ) { // // Log( self @ "OnHitMover" @ other ) ; TryClearObstacle( other ); } BEGIN: // move to SeekLocation... // // Log( self @ "seeking to" @ seekLocation ) ; bot.Perform_MoveToLocation( seekLocation, 128 ); WaitForNotification(); //TODO: maybe we arrived at an eat point? chow down! //FIXME: assumes we made it to the location... LastSeekInstigator = None; // if we didn't end up in the attack state already, go back to // wandering around until something new comes up to seek... GotoState( 'Wander' ); } //=========================================================================== // Attacking - engaged with an enemy, give 'em what for! //=========================================================================== state Attacking { function BeginState() { // // Log( self @ "entering attack state" ) ; LastSeekInstigator = bot.enemy; bot.updateFocus( bot.enemy ); bot.SetCombatTimer(); } function EndState() { // // Log( self @ "leaving attack state" ) ; bot.SetTimer( 0, false ); } /** * Lost sight of the enemy, try to recover him... */ function OnLostSight() { // // Log( self @ "OnLostSight" @ bot.Enemy ) ; SetMultiTimer( START_REACQUIRE_TIMER, REACQUIRE_DELAY, false ); } /** * Attack isn't working. :-( */ function ChargeFailed() { //SetMultiTimer( START_REACQUIRE_TIMER, REACQUIRE_DELAY, false ); } /** */ function OnBump( Actor other ) { local Pawn enemy; if ( bIgnoreBumps ) return; if ( other.isA('HunterOtis') || other.isA('HunterJackSlade')) return; enemy = Pawn( other ); if ( enemy != none && enemy.IsHumanControlled() ) { bIgnoreBumps = true; // should set it back again after some time... bot.WeaponFireAgain(bot.Pawn.Weapon.RefireRate(),false); } } // // Zombies are very single-minded, and ignore many inputs when // attacking... // function OnThreatSpotted( Pawn threat ) { if ( threat == bot.Enemy ) { // // Log( self @ "reacquired" @ threat ) ; SetMultiTimer( START_REACQUIRE_TIMER, 0, false ); } else { // // Log( self @ "ignoring OnThreatSpotted" @ threat ) ; } } function OnHeardNoise( float Loudness, Actor NoiseMaker) { // // Log( self @ "ignoring HearNoise" @ loudness ) ; if ( NoiseMaker == bot.Enemy ) lastHeardEnemyTime = Level.timeSeconds; } function bool TrySeekTarget( Actor a ) { return false; } /** * @returns a little bit less than the amount of time it should take to * charge the enemy. */ function float getChargeDuration() { local float dist; dist = VSize(bot.enemy.location - bot.pawn.location) * 0.8; return dist/bot.pawn.GroundSpeed; } BEGIN: while ( true ) { // // Log( self @ "attacking" ) ; // Charge! if ( shouldCharge() ) { StartCharge(); chargeDuration = getChargeDuration(); // // Log( self @ "charge should take" @ chargeDuration @ "seconds" ) ; if ( chargeDuration > 1.5 ) { // some wild flailing along the way... SetMultiTimer( PRE_CHARGE_TIMER, 0.2, false ); } // timer will trigger an attack just before the bot reaches the // enemy, so that it overlaps with the running. SetMultiTimer( CHARGE_TIMER, chargeDuration, false ); bIgnoreBumps = false; bot.Perform_MoveToLocation( bot.pawn.location + ( (bot.enemy.location - bot.pawn.location)*0.9 ), MELEE_RANGE ); WaitForNotification(); EndCharge(); } // normal attack else { if ( VSize(bot.enemy.location - bot.pawn.location) < MELEE_RANGE ) { bIgnoreBumps = true; bot.Perform_MeleeAttack(); WaitForNotification(); bIgnoreBumps = false; } else { // move to a spot in front of the enemy... bot.Perform_MoveToLocation( bot.pawn.location + ( (bot.enemy.location - bot.pawn.location)*0.8 ), MELEE_RANGE ); // wait a bit and then re-think this action, since moves can // take a really long time... WaitForNotification( 2 ); } } //if you just killed enemy, eat 'im! //NOTE: should probably check range to the body here... if ( bot.Enemy.Health <= 0 ) { EatTarget = bot.Enemy; GotoState( 'DoSpecial', 'EAT_STUFF' ); } //FIXME: do we need this? Sleep( 0.3 ); } } //=========================================================================== // Performing some special activity... //=========================================================================== state DoSpecial { function BeginState() { EatingTime = Level.TimeSeconds; // // Log( self @ "entering special state" ) ; } function EndState() { // // Log( self @ "leaving special state" ) ; bot.target = none; bot.Focus = none; bot.updateFocus( None ); } // Zombies are very single-minded, and ignore many inputs when // doing special stuff... function OnThreatSpotted( Pawn threat ) { // // Log( self @ "ignoring OnThreatSpotted" @ threat ) ; if (Level.TimeSeconds - EatingTime > MAX_EAT_TIME){ super.OnThreatSpotted(threat); } } function OnHeardNoise( float Loudness, Actor NoiseMaker) { // // Log( self @ "ignoring HearNoise" @ loudness ) ; if ( NoiseMaker == bot.Enemy ) lastHeardEnemyTime = Level.timeSeconds; if (Level.TimeSeconds - EatingTime > MAX_EAT_TIME){ super.OnHeardNoise( Loudness, NoiseMaker); } } BEGIN: // if you didn't pick a specific thing to do, we're done! Goto( 'DONE' ); SMASH_OBSTACLE: // // Log( self @ "smashing" ) ; // get into position... currentAttackPoint = currentObstacle.getAttackPoint( bot.pawn ); if ( currentAttackPoint == None ) Goto( 'DONE' ); bot.Perform_MoveToLocation( currentAttackPoint.getAttackLocation() ); WaitForNotification(); // face the right way... bot.Target = currentObstacle.getSmashActor(); Bot.Focus = currentObstacle.getSmashActor(); Sleep( 1 ); // wait for rotation // start attacking ... for ( numClearAttempts = 0; numClearAttempts < 5; ++numClearAttempts ) { // // Log( self @ "Attacking obstacle" ) ; bot.Perform_MeleeAttack(); WaitForNotification(); if ( currentObstacle.getAttackPoint(bot.pawn) == none ) break; } if ( currentObstacle.getAttackPoint(bot.pawn) != none ) { // if the obstacle is still in place, smash it good! currentObstacle.doSmash( bot.pawn ); } bot.target = none; bot.Focus = none; goto( 'DONE' ); EAT_STUFF: // // Log( self @ "Eating stuff" ) ; failedEatAttempts = 0; while ( failedEatAttempts < 5 ) { if ( EatTarget == none && bot.enemy.Health <= 0 ) { EatTarget = bot.enemy; } if ( EatTarget != none ) { distToEatTarget = VSize(EatTarget.location - bot.pawn.location); if ( distToEatTarget > MAX_EAT_DIST) { // zombies love to eat, so they run towards food. HunterBot.bForceRun = true; Sleep( RandRange( 0.1, 0.7 ) ); // // Log( self @ "GRABBING A BITE:" @ eatTarget @ eatTarget.location ) ; bot.Perform_MoveToLocation( eatTarget.location, MAX_EAT_DIST ); WaitForNotification( 1 ); bot.Pawn.Velocity = vect( 0,0,0 ); bot.Pawn.Acceleration = vect( 0,0,0 ); HunterBot.bForceRun = false; } bot.target = eatTarget; bot.Focus = eatTarget; if (VSize(EatTarget.location - bot.pawn.location ) <= MAX_EAT_DIST){ DOTZAIController(bot).Perform_Eating(); } else { // bail out if you're not getting any closer to the target... if ( distToEatTarget - VSize(EatTarget.location - bot.Pawn.Location) < 128 ){ // a little hack to make the zombie walk away... LastSeekInstigator = EatTarget; SeekLocation = Vect(0,0,1) * bot.Pawn.Location + ( Vect(-1,-1,0) * Normal(bot.Pawn.Location - eatTarget.location) * RandRange(0.5, 1.5) * 512 ); goto( 'DONE' ); } ++failedEatAttempts; } Sleep( 0.3 ); } else goto( 'DONE' ); } Goto( 'DONE' ); DONE: // // Log( self @ "done DoSpecial" ) ; bot.Target = none; if ( bot.enemy != none ) GotoState( 'Attacking' ); else if ( LastSeekInstigator != none ) GotoState( 'Seeking' ); else GotoState( 'Wander' ); } //=========================================================================== // HELPERS //=========================================================================== /** */ function init( VGSPAIController c ) { super.init( c ); HunterBot = BDHunterAIController( c ); SetMultiTimer( DONT_BE_STUPID_TIMER, 6.0 + RandRange(0, 2.5), false ); } /** */ function MultiTimer( int timerID ) { switch ( timerID ) { //TODO: might be better to be in a separate state for "just lost contact", // which can more quickly reacquire... case START_REACQUIRE_TIMER: global.TrySeekTarget( bot.enemy ); GotoState( 'Seeking' ); break; case PRE_CHARGE_TIMER: case CHARGE_TIMER: // asynchronous attack, hopefully timed a little before reaching the // enemy... bot.WeaponFireAgain(bot.Pawn.Weapon.RefireRate(),false); break; case THINK_AGAIN_TIMER: // interrupt movement to allow bot a chance to reassess the situation. bot.MoveTimer = -1; break; case DONT_BE_STUPID_TIMER: DontBeStupid(); break; default: super.MultiTimer( timerID ); } } /** * Periodically override zombie behaviour, in hopes of avoiding stupid * situations. */ function DontBeStupid() { local Pawn player; // // Log( self @ "Checking for stupid situations... if you are not in multiplayer mode" ) ; if (Level.NetMode == NM_Standalone){ player = Level.GetLocalPlayerController().pawn; if ( player.isA('HunterJackSlade') || player.isA('HunterOtis')) return; if ( player == none ) return; // ignore the player if he's too far up... if ( abs(player.location.z - bot.pawn.location.z) < 2048 ) { // if the player IS the enemy, and you can attack, then get on it! if ( player == bot.Enemy && GetStateName() != 'Attacking' && bot.actorReachable(bot.Enemy)) { GotoState( 'Attacking' ); } // if the player isn't the enemy, but you can see and reach him, then // start attacking! if ( player != bot.Enemy && bot.CanSee(player) && bot.actorReachable(bot.Enemy)) { bot.AcquireEnemy(player, true); GotoState( 'Attacking' ); } } SetMultiTimer( DONT_BE_STUPID_TIMER, 4.0 + RandRange(0, 2.5), false ); } } /** * Bookkeeping for when a charge starts */ function StartCharge() { ChargeStartTime = Level.TimeSeconds; default.LastChargeTime = ChargeStartTime; HunterBot.bForceRun = true; bIsCharging = true; default.NumChargingZombies = default.NumChargingZombies + 1; } /** * Bookkeeping for when a charge ends. Safe to call even when not charging. */ function EndCharge() { if ( !bIsCharging ) return; default.NumChargingZombies = default.NumChargingZombies - 1; bIsCharging = false; HunterBot.bForceRun = True; } /** * InAttackRange */ function bool InAttackRange(actor enemy){ //NOTE: maybe migrate this to the ZombieGropeWeapon? if(VSize(bot.pawn.location - enemy.location) < 150){ return true; } else { return false; } } /** * Realtime onscreen debug info... */ function DisplayDebug( Canvas c, out float YL, out float YPos ) { super.DisplayDebug( c, YL, YPos ); c.SetPos(4, YPos); C.DrawText( "LastSeekInstigator:" @ LastSeekInstigator @ "SeekLocation:" @ SeekLocation ); YPos += YL; C.SetPos(4,YPos); } /** */ function PreBeginPlay() { super.PreBeginPlay(); // make sure charging is possibe at the beginning of the game... ChargeStartTime = Level.TimeSeconds - MinTimeBetweenCharges; LastChargeTime = ChargeStartTime; } //=============================================================== // Default Properties //=============================================================== O 2s ~ // Copyright (C) 2005 Brainbox Games. All Rights Reserved. // September 27, 2005 /** * The main controller class for AI characters using the DEBAIT * framework. The controller is responsible for low level behaviours, * like aiming, dodging, and moving, as well as reporting information * to the stage. The stage handles higher level coordination, * especially between characters. The AIRole handles the intermediate * logic required to translate orders into sequences of behaviours. * * TODO: * - make sure all behaviours report completion properly, like * TakePosition does. * * * @author Mike Horgan (mikeh@digitalextremes.com) * @author Neil Gower (neilg@digitalextremes.com) * @author Jesse LaChapelle (jesse@digitalextremes.com) * @version $Revision: 1.118 $ * @date June 2003 */ class BDHunterAIController extends DOTZAIController; //---------------------- // Behaviour properties //---------------------- // Awareness settings // //How long must the enemy be out of sight before considering him lost var float MaxLostContactTime; //How long is the typical time between acquiring LOS and shooting var float ReflexTime; // Melee Attack settings (doesn't use the combat timer) // var bool bMeleeAttackCapable; // Ranged Attack settings // var bool bRangedAttackCapable; //How many bullets in a typical burst of fire. var int MinNumShots, MaxNumShots; //How long between bursts of fire var float MinShotPeriod, MaxShotPeriod; // maximum chance-to-hit factor due to skill... var float MaxSkillOdds; //AimRelated //aim approaches 0 as enemy's distance approaches this var float MaxAimRange; //aim approaches 0 as enemy's relative lateral velocity approaches this var float MaxAimVelocity; //aim approaches 1 as enemy stays in sight this long. var float MaxSecondsOfLOS; //The scale used to aim away from the targets center, which ought to //shrink with accuracy. var float MissVectorScale; // Data for StrafeMove behaviour var float fOddsOfStrafeMove; // don't tactical move until at least this much time has passed var float MinTimeBetweenStrafeMove; //Data for AdvanceMove var float LastAdvanceMoveTime; //how far the character will travel while panicking? var float PanicRange; // How long to focus on the enemy rather than the target when damaged var float EnemyDistractDuration; // Min distance between this character and current enemy before // switching focus from ShootTarget to Enemy. var float EnemyDistractDistance; //Position selection behaviour tweaks var float m_BunchPenalty; var float m_BlockedPenalty; var float m_BlockingPenalty; var float m_NeedForCover; var float m_NeedForContact; var float m_NeedCohesion; var float m_NeedForIntel; var float m_NeedToAvoidCorpses; var float m_NeedForClosingIn; var float m_NeedForNearbyGoal; // This is added to nearby navigation points when a pawn gets killed, // and is reduced every second by 5% by the GameInfo. Thus it's often // desirable to make this penalty bigger if you want it to last longer. const FEAR_PENALTY = 16384; //--------------------------- // Other editable properties //--------------------------- // enable debugging output var() bool bDebugLogging; // a bit-mask to reduce the quantity of debugging output, and related // consts... var() int AIDebugFlags; const DEBUG_FIRING = 0x00000001; // value added to path cost when passing through a claimed position var() const int CLAIMED_POSITION_PENALTY; //--------------------- // Internal properties //--------------------- // How often to change focus var float LastFocusChangeTime; var float RandFocusChangeDuration; // Firing Control related var bool bFireAtLastLocation; var bool bStopFireAnimation; var int NumShotsToGo; var bool bForceRun; // Enemy Management var float EnemyInSightTime; var bool bEnemyIsVisibleCache; var float EnemyVisibilityCacheTime; var pawn VisibleEnemy; var float LoseEnemyCheckTime; var float AcquireTime; // an actor to shoot at if there's no enemy var Actor ShootTarget; var Actor tmpTarget; var Actor pendingFocus; var private OpponentFactory myCreator; var private Name lastState; var private EPhysics lastPawnPhysics; var private float lastHitTime; // time (seconds) pawn last took damage. var String curBehaviour; //for debugging, should reflect current decision; var bool bHibernating; // AI Behaviour Modifier (Grunt, Leader, Medic) var AIRole myAIRole; var class AIType; // navigation var int numMoveAttempts; // Stage related var Stage currentStage; var StagePosition claimedPosition; // Order Management enum EStageOrder { SO_None, SO_TakeUpPosition, SO_HoldPosition, SO_TakeCover, SO_AttackTarget }; var EStageOrder curStageOrder; // Data for TakeUpPosition Order var StagePosition TakeUpPosition; // Data for StrafeMove behaviour var float LastStrafeMoveTime; //Last time at which we made a tactical move var Vector strafeTarget; var bool bStrafeDir; //Data for Hide behaviour var float LastHideTime; //Data for TakeCover behaviour var float maxDistToCrouchForCover; var float LastTakeCoverTime; //Data for Wander var float LastWanderTime; var Actor wanderDestination; // Data for Panic behaviour var bool bHavePanicked; //Only panic once. var float PanicStartTime; // data for move behaviour var vector moveDestination; var float moveSlop; // data for charge action var float chargeEndTime; //Exclamations var ExclaimManager exclaimMgr; const SIGHT_CHECK_TIMER = 39201; const FOCUS_TIMER = 39202; const FOCUS_UPDATE_INTERVAL = 1.5; const UNGHOST_TIMER = 39203; const LOST_SIGHT_TIMER = 68695; //NOTE this shouldn't really be here, but it breaks the scripted sequences // without it. function SelectAction() { myAIRole.botSelectAction(); } //---------------- // Implementation //---------------- /** */ function float getLastHitTime() { return lastHitTime; } /** */ function setLastHitTime() { lastHitTime = Level.TimeSeconds; } /** */ function BeginPlay() { Super.BeginPlay(); } function Possess(Pawn aPawn){ super.Possess(aPawn); SpawnExclaimManager(); } /** * Called from Pawn.possess(), which is in PostBeginPlay() for * statically placed pawns. */ function Restart() { Super.Restart(); initAIRole(); SetMultiTimer( SIGHT_CHECK_TIMER, 3, true ); } /** */ function SpawnExclaimManager() { exclaimMgr = Spawn(class'ExclaimManager',self); exclaimMgr.init(self); } /** * Ensures that this controller has an AI role object that's ready to * go. */ function InitAIRole() { if ( myAIRole == None ) { if ( AIType == None ) AIType = class'AIRole'; myAIRole = Spawn(AIType,self); } myAIRole.init(self); } /** */ function Destroyed() { Super.Destroyed(); Cleanup(); if(exclaimMgr != None) { exclaimMgr.Destroy(); } if(myAIRole != None) { myAIRole.Destroy(); } } /** */ state Scripting { /** */ function BeginState() { //log( "@@@@@@@@@@@@@@@ Starting scripting state!!" ); myAIRole.GotoState( 'Scripting' ); } /** */ function EndState() { //log( "@@@@@@@@@@@@@@@ Ending scripting state!!" ); super.EndState(); } function LeaveScripting() { super.LeaveScripting(); GoalScript = none; myAIRole.GotoState( 'InitRole' ); } } //=========================== // Opponent Factory interface //=========================== /** * this is called from the OpponentFactory when it sets up a new NPC */ function configure( OpponentFactory f, Stage initialStage ) { DebugLog( self $ " configured with " $ f $ ", " $ initialStage ); myCreator = f; if ( initialStage != None ) initialStage.joinStage( self ); ClientSwitchToBestWeapon(); } /** */ function SetCreator(OpponentFactory f) { if(myCreator != None) return; myCreator = f; } /** */ event PreSaveGame() { myCreator = None; currentStage = None; } //=========================================================================== // Stage Orders - these orders are the stage's interface to the bots. // By following the orders, the bots should appear to be // coordinated and intelligent in their actions. However, the // orders still leave lots of latitude for personality and // variations in *how* they are executed. // // Controllers communicate success and failure back to the stage // using the Report_* methods, as specified below... //=========================================================================== /** * Stage is going to maintain bookeeping, but bot is free to do what * it likes. * * success: N/A * failure: N/A */ function StageOrder_None() { myAIRole.Order_None(); } /** * Go to the specified position. Wandering away from the position * after arriving and reporting is okay, as long as it doesn't * contradict new orders. Staying in the general vicinity of the * position is prefered. * * success: Report_InPosition() * failure: Report_PositionUnreachable() */ function StageOrder_TakeUpPosition( StagePosition pos ) { myAIRole.Order_TakeUpPosition( pos ); } /** * Stay in the current position. Bot can shoot, hide, or whatever * else seems appropriate in the moment. * * success: N/A * failure: Report_AbandonedPosition() */ function StageOrder_HoldPosition() { myAIRole.Order_HoldPosition(); } /** * Get out of the line of fire by going to (or staying at) pos. May * require crouching at the destination. If no position is specified, * the bot should choose a location itself. * * success: Report_Covered() * failure: Report_Exposed() */ function StageOrder_TakeCover( optional StagePosition pos ) { myAIROle.Order_TakeCover( pos ); } /** * Attack the specified actor. The bot should not change targets * unless directed to do so by the stage. Thus it is important for * the bot to report if it is under attack from another enemy, so that * the stage will be able to promptly tell the bot to change enemies * (if it suits the strategy of the stage). * * success: Report_TargetDestroyed() * failure: Report_FailedAttack() */ function StageOrder_AttackTarget( Actor target ) { myAIRole.Order_AttackTarget( target ); } //NOTE The rest of these are kind of odd orders, maybe obselete? /** * Treat the specified pawn as your current enemy? * NOTE obselete? implied by attack target? */ function StageOrder_AlertNewEnemy(Pawn bogie, bool bCanSee) { AcquireEnemy(bogie, bCanSee); } /** * */ //NOTE right now, only newStage should call this. use newStage.joinStage() function StageOrder_JoinStage( Stage newStage ) { if ( currentStage != None ) { currentStage.leaveStage( self, RSN_JoinedOtherStage ); } currentStage = newStage; if ( Enemy != None && currentStage != None ) { currentStage.Report_EnemySpotted( Enemy, self ); } } /** * called to put NPC into a dormant (minimal performance hit) mode */ function StageOrder_Hibernate() { // do nothing if already asleep. if ( bHibernating ) return; // hibernate the pawn bHibernating = true; curBehaviour = "stasis"; lastPawnPhysics = Pawn.Physics; Pawn.SetPhysics(PHYS_None); Pawn.bStasis = true; pawn.bHidden = true; // hibernate the controller bStasis = true; GotoState('Dormant'); } /** * called to undo hibernate() */ function StageOrder_Awaken() { // do nothing if already awake if ( !bHibernating ) return; // awaken the pawn Pawn.bStasis = false; Pawn.SetPhysics( lastPawnPhysics ); // awaken the controller bStasis = false; pawn.bHidden = false; bHibernating = false; myAIRole.awakenSucceeded(); } //================= //Stage interfacing //================= /** * called from stage when providing a shooting position to make sure it * meets bot's requirements **/ function bool VerifyShootingPosition(StagePosition position) { if ( Enemy == None || position == None ) return false; if( VSize(Enemy.Location - posi