1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//=============================================================================
#include "cbase.h"
#include "tf_gamerules.h"
#include "tf_player.h"
#include "../merasmus.h"
#include "merasmus_staff_attack.h"
#include "merasmus_stunned.h"
CMerasmusStaffAttack::CMerasmusStaffAttack( CTFPlayer* pTarget )
{
m_hTarget = pTarget;
}
ActionResult< CMerasmus > CMerasmusStaffAttack::OnStart( CMerasmus *me, Action< CMerasmus > *priorAction )
{
// smooth out the bot's path following by moving toward a point farther down the path
m_path.SetMinLookAheadDistance( 100.0f );
int iLayer = me->AddGesture( ACT_MP_ATTACK_STAND_MELEE );
float flDuration = me->GetLayerDuration( iLayer );
m_staffSwingTimer.Start( flDuration );
m_hitTimer.Start( 0.5f * flDuration );
if ( RandomInt( 0, 2 ) == 0 )
{
CPVSFilter filter( me->WorldSpaceCenter() );
if ( RandomInt( 1, 5 ) == 1 )
{
me->PlayLowPrioritySound( filter, "Halloween.MerasmusStaffAttackRare" );
}
else
{
me->PlayLowPrioritySound( filter, "Halloween.MerasmusStaffAttack" );
}
}
return Continue();
}
ActionResult< CMerasmus > CMerasmusStaffAttack::Update( CMerasmus *me, float interval )
{
// Interupt if stunned
if ( me->HasStunTimer() )
{
return ChangeTo( new CMerasmusStunned, "Stun Interupt!" );
}
if ( m_hitTimer.HasStarted() && m_hitTimer.IsElapsed() )
{
m_hitTimer.Invalidate();
if ( m_hTarget != NULL )
{
Vector forward;
me->GetVectors( &forward, NULL, NULL );
Vector toVictim = m_hTarget->WorldSpaceCenter() - me->WorldSpaceCenter();
toVictim.NormalizeInPlace();
// looser tolerance as victim gets closer
const float closeRange = 100.0f;
float range = me->GetRangeTo( m_hTarget );
float closeness = ( range < closeRange ) ? 0.0f : ( range - closeRange ) / ( tf_merasmus_attack_range.GetFloat() - closeRange );
float hitAngle = 0.0f + closeness * 0.27f;
if ( DotProduct( forward, toVictim ) > hitAngle )
{
if ( me->IsRangeLessThan( m_hTarget, 0.9f * tf_merasmus_attack_range.GetFloat() ) )
{
if ( me->IsLineOfSightClear( m_hTarget ) )
{
// CHOP!
CTakeDamageInfo info( me, me, 70, DMG_CLUB, TF_DMG_CUSTOM_MERASMUS_DECAPITATION );
CalculateMeleeDamageForce( &info, toVictim, me->WorldSpaceCenter(), 5.0f );
m_hTarget->TakeDamage( info );
CPVSFilter filter( me->WorldSpaceCenter() );
me->PlayLowPrioritySound( filter, "Halloween.HeadlessBossAxeHitFlesh" );
me->PushPlayer( m_hTarget, 500.f );
}
}
}
}
}
if ( m_hTarget )
{
if ( me->IsRangeGreaterThan( m_hTarget, 100.f ) || !me->IsLineOfSightClear( m_hTarget ) )
{
if ( m_path.GetAge() > 1.0f )
{
CMerasmusPathCost cost( me );
m_path.Compute( me, m_hTarget, cost );
}
m_path.Update( me );
}
me->GetLocomotionInterface()->FaceTowards( m_hTarget->WorldSpaceCenter() );
}
if ( m_staffSwingTimer.IsElapsed() )
{
return Done();
}
return Continue();
}
|