166 lines
5.1 KiB
Ucode
166 lines
5.1 KiB
Ucode
/*
|
|
--------------------------------------------------------------
|
|
KF_BreakerBoxNPC_SE
|
|
--------------------------------------------------------------
|
|
|
|
Enhanced version of KF_BreakerBoxNPC:
|
|
- TickEvent can be set by map author.
|
|
- Doesn't trigger TickEvent when inactive
|
|
- can retain visibility while inactive
|
|
- can be started active
|
|
- Min and max threat rating
|
|
- Threat rating for ScrN Balance mod
|
|
|
|
|
|
Author : PooSH
|
|
Original Author: Alex Quick
|
|
|
|
--------------------------------------------------------------
|
|
*/
|
|
class KF_BreakerBoxNPC_SE extends KF_BreakerBoxNPC;
|
|
|
|
var(Events) name TickEvent;
|
|
var(AI) float MinAIThreatRating, MaxAIThreatRating; // only if parent method return value > 0
|
|
|
|
// used in AssessThreatTo()
|
|
var protected transient KFMonsterController LastThreatMonster;
|
|
var protected transient float LastThreatTime, LastThreat;
|
|
|
|
|
|
// restrict healing
|
|
function bool GiveHealth(int HealAmount, int HealMax)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
function bool HealDamage(int Amount, Controller Healer, class<DamageType> DamageType)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
simulated function PostBeginPlay()
|
|
{
|
|
Super(KF_StoryNPC_Static).PostbeginPlay();
|
|
|
|
CheckHealthCondition(self);
|
|
}
|
|
|
|
function GetEvents(out array<name> TriggeredEvents, out array<name> ReceivedEvents)
|
|
{
|
|
super.GetEvents(TriggeredEvents, ReceivedEvents);
|
|
|
|
if( TickEvent != '' )
|
|
TriggeredEvents[TriggeredEvents.length] = TickEvent;
|
|
}
|
|
|
|
|
|
function SetActive(bool On)
|
|
{
|
|
Super(KF_StoryNPC_Static).SetActive(On);
|
|
}
|
|
|
|
simulated function Tick(float DeltaTime)
|
|
{
|
|
Super(KF_StoryNPC_Static).Tick(DeltaTime);
|
|
|
|
if( TickEvent != '' && bActive && !bDestroyed && Level.TimeSeconds - LastTriggerEventTime > 1.0)
|
|
{
|
|
LastTriggerEventTime = Level.TimeSeconds;
|
|
TriggerEvent(TickEvent, self, self);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Monster threat assessment functionality
|
|
|
|
Changes by PooSH:
|
|
1) KFGameType.bUseZEDThreatAssessment set to true, i.e. in regular game new AssessThreatTo()
|
|
function will be used too.
|
|
2) Distance between monster and player will always be in place.
|
|
3) AssessThreatTo will always return value > 0. Because zeds should not ignore players.
|
|
4) Added randomization - zeds can choose different targets in the same circumstances.
|
|
5) Blood smell. Wounded players will attract zeds slightly more than their healthy teammates.
|
|
|
|
* @param Monster Monster's controller, for which we are calculating the threat level
|
|
* @param CheckDistance Not used!
|
|
* @return threat level between 0 and 100, where 100 is the max threat level.
|
|
*
|
|
* @author PooSH
|
|
*/
|
|
function float AssessThreatTo(KFMonsterController Monster, optional bool CheckDistance)
|
|
{
|
|
local float DistancePart, RandomPart, TacticalPart;
|
|
local float DistanceSquared; // squared distance is calculated faster
|
|
|
|
if ( !Level.Game.IsA('ScrnStoryGameInfo') ) {
|
|
LastThreat = super.AssessThreatTo(Monster, CheckDistance);
|
|
// don't use MinAIThreatRating for vanilla game, cuz then zeds won't focus on players at all
|
|
if ( LastThreat > MaxAIThreatRating )
|
|
LastThreat = MaxAIThreatRating;
|
|
return LastThreat;
|
|
}
|
|
|
|
// the following code is for ScrnBalance only
|
|
|
|
if(Monster == none || KFMonster(Monster.Pawn) == none)
|
|
{
|
|
return -1.f;
|
|
}
|
|
|
|
if(bNoThreatToZEDs ||
|
|
TeamIndex == 255 ||
|
|
Health <= 0 ||
|
|
!bActive ||
|
|
!bDamageable ||
|
|
(!IsThreateningTo(Monster.Pawn)) )
|
|
{
|
|
return -1.f;
|
|
}
|
|
|
|
if ( LastThreatMonster == Monster && LastThreatTime == Level.TimeSeconds )
|
|
return LastThreat; // threat level for the given monster has been calculated already during the current tick
|
|
|
|
DistanceSquared = VSizeSquared(Monster.Pawn.Location - Location);
|
|
|
|
DistancePart = 65.0;
|
|
RandomPart = MaxAIThreatRating * 0.35;
|
|
|
|
// TacticalPart is useless for static NPCs
|
|
/*
|
|
// let zeds smell blood within 25m radius - wounded players attract zeds more
|
|
if ( DistanceSquared < 1562500.0 )
|
|
TacticalPart += RandomPart * 0.40 * (HealthMax - Health) / HealthMax;
|
|
// more chance to attack the same enemy multiple times
|
|
if ( Monster.Enemy == self || Monster.Target == self )
|
|
TacticalPart += RandomPart * 0.25;
|
|
// more chance to focus on the player, who are attacking the monster
|
|
if ( KFMonster(Monster.Pawn).LastDamagedBy == self)
|
|
TacticalPart += RandomPart * 0.25;
|
|
RandomPart = 100.0 - DistancePart - TacticalPart;
|
|
*/
|
|
|
|
// If target is closer than 1 meter, max DistancePart value will be used,
|
|
// otherwise DistancePart is lowering by 10% per meter
|
|
// 1 meter = 50 ups (2500 squared)
|
|
if ( DistanceSquared > 2500.0 )
|
|
DistancePart /= 1.0 + DistanceSquared / 250000.0;
|
|
RandomPart *= frand();
|
|
|
|
// save threat level for this tick
|
|
LastThreatMonster = Monster;
|
|
LastThreatTime = Level.TimeSeconds;
|
|
LastThreat = DistancePart + TacticalPart + RandomPart;
|
|
//LastThreat *= InventoryThreatModifier();
|
|
LastThreat += BaseAIThreatRating;
|
|
LastThreat = fclamp(LastThreat, MinAIThreatRating, MaxAIThreatRating);
|
|
return LastThreat;
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
MaxAIThreatRating=40.000000
|
|
bWorldGeometry=True
|
|
bBlockHitPointTraces=True
|
|
}
|