2020-03-26 03:24:33 -07:00
|
|
|
/*
|
2020-04-07 05:46:23 -07:00
|
|
|
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
2020-03-26 03:24:33 -07:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
|
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
void
|
|
|
|
CBaseNPC::WarnAllies(void)
|
|
|
|
{
|
|
|
|
for (entity b = world; (b = find(b, ::classname, classname));) {
|
|
|
|
if (vlen(b.origin - origin) < PLAYER_DETECT_RADIUS) {
|
|
|
|
CBaseNPC w = (CBaseNPC)b;
|
|
|
|
w.m_iFlags |= MONSTER_METPLAYER;
|
|
|
|
w.m_eFollowing = world;
|
|
|
|
w.m_eFollowingChain = world;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-26 03:24:33 -07:00
|
|
|
void
|
|
|
|
CBaseNPC::Sentence(string sentence)
|
|
|
|
{
|
|
|
|
string seq = Sentences_GetSamples(sentence);
|
|
|
|
|
|
|
|
if (seq == "") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
|
|
|
WriteByte(MSG_MULTICAST, EV_SENTENCE);
|
|
|
|
WriteEntity(MSG_MULTICAST, this);
|
2020-03-26 04:19:27 -07:00
|
|
|
WriteString(MSG_MULTICAST, seq);
|
2020-03-26 03:24:33 -07:00
|
|
|
msg_entity = this;
|
|
|
|
multicast(origin, MULTICAST_PVS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::Speak(string sentence)
|
|
|
|
{
|
|
|
|
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
|
|
|
WriteByte(MSG_MULTICAST, EV_SPEAK);
|
|
|
|
WriteEntity(MSG_MULTICAST, this);
|
|
|
|
WriteString(MSG_MULTICAST, sentence);
|
|
|
|
WriteFloat(MSG_MULTICAST, m_flPitch);
|
|
|
|
msg_entity = this;
|
|
|
|
multicast(origin, MULTICAST_PVS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-03-26 23:34:24 -07:00
|
|
|
CBaseNPC::TalkPlayerGreet(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
if (m_flNextSentence > time) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_iFlags & MONSTER_METPLAYER) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (entity p = world; (p = find(p, ::classname, "player"));) {
|
|
|
|
/* Find players in a specific radius */
|
|
|
|
if (vlen(p.origin - origin) < PLAYER_DETECT_RADIUS) {
|
|
|
|
/* If we can't physically see him, don't do anything */
|
|
|
|
traceline(origin, p.origin, FALSE, this);
|
|
|
|
if (trace_ent != p) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Sentence(m_talkPlayerGreet);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
m_iFlags |= MONSTER_METPLAYER;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkPlayerIdle(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
2020-11-24 03:29:29 -08:00
|
|
|
if (spawnflags & MSF_PREDISASTER)
|
2020-03-26 23:34:24 -07:00
|
|
|
return;
|
2020-11-24 03:29:29 -08:00
|
|
|
if (m_flNextSentence > time)
|
2020-03-26 23:34:24 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (entity p = world; (p = find(p, ::classname, "player"));) {
|
|
|
|
/* Find players in a specific radius */
|
|
|
|
if (vlen(p.origin - origin) < PLAYER_DETECT_RADIUS) {
|
|
|
|
/* If we can't physically see him, don't do anything */
|
|
|
|
traceline(origin, p.origin, FALSE, this);
|
|
|
|
if (trace_ent != p) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Sentence(m_talkPlayerIdle);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkPlayerAsk(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
2020-11-24 03:29:29 -08:00
|
|
|
if (spawnflags & MSF_PREDISASTER)
|
2020-03-26 23:34:24 -07:00
|
|
|
return;
|
2020-11-24 03:29:29 -08:00
|
|
|
if (m_flNextSentence > time)
|
2020-03-26 23:34:24 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (entity p = world; (p = find(p, ::classname, "player"));) {
|
|
|
|
/* Find players in a specific radius */
|
|
|
|
if (vlen(p.origin - origin) < PLAYER_DETECT_RADIUS) {
|
|
|
|
/* If we can't physically see him, don't do anything */
|
|
|
|
traceline(origin, p.origin, FALSE, this);
|
|
|
|
if (trace_ent != p) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Sentence(m_talkPlayerAsk);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkPlayerWounded1(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
if (m_flNextSentence > time) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base_health < health) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (entity p = world; (p = find(p, ::classname, "player"));) {
|
|
|
|
/* Find players in a specific radius */
|
|
|
|
if (vlen(p.origin - origin) < PLAYER_DETECT_RADIUS) {
|
|
|
|
/* If we can't physically see him, don't do anything */
|
|
|
|
traceline(origin, p.origin, FALSE, this);
|
|
|
|
if (trace_ent != p) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Sentence(m_talkPlayerWounded3);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkPlayerWounded2(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
if (m_flNextSentence > time) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((base_health / 2) < health) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (entity p = world; (p = find(p, ::classname, "player"));) {
|
|
|
|
/* Find players in a specific radius */
|
|
|
|
if (vlen(p.origin - origin) < PLAYER_DETECT_RADIUS) {
|
|
|
|
/* If we can't physically see him, don't do anything */
|
|
|
|
traceline(origin, p.origin, FALSE, this);
|
|
|
|
if (trace_ent != p) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Sentence(m_talkPlayerWounded3);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkPlayerWounded3(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
if (m_flNextSentence > time) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (entity p = world; (p = find(p, ::classname, "player"));) {
|
|
|
|
/* Find players in a specific radius */
|
|
|
|
if (vlen(p.origin - origin) < PLAYER_DETECT_RADIUS) {
|
|
|
|
/* If we can't physically see him, don't do anything */
|
|
|
|
traceline(origin, p.origin, FALSE, this);
|
|
|
|
if (trace_ent != p) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Sentence(m_talkPlayerWounded3);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkUnfollow(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
Sentence(m_talkUnfollow);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkFollow(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
Sentence(m_talkFollow);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::TalkStopFollow(void)
|
|
|
|
{
|
2020-03-29 02:49:35 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE)
|
|
|
|
return;
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
Sentence(m_talkStopFollow);
|
|
|
|
m_flNextSentence = time + 10.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::FollowPlayer(void)
|
2020-03-26 03:24:33 -07:00
|
|
|
{
|
2020-03-26 23:34:24 -07:00
|
|
|
v_angle = vectoangles(m_eFollowingChain.origin - origin);
|
|
|
|
v_angle[0] = 0;
|
|
|
|
v_angle[1] = Math_FixDelta(v_angle[1]);
|
|
|
|
v_angle[2] = 0;
|
|
|
|
|
|
|
|
/* Give up after 1024 units */
|
|
|
|
if (vlen(m_eFollowingChain.origin - origin) > 1024) {
|
|
|
|
m_eFollowing = world;
|
|
|
|
} else if (vlen(m_eFollowingChain.origin - origin) > 64) {
|
2020-11-23 12:39:40 -08:00
|
|
|
input_movevalues[0] = m_flChaseSpeed;
|
2020-03-26 23:34:24 -07:00
|
|
|
|
|
|
|
other = world;
|
|
|
|
traceline(origin, m_eFollowingChain.origin, MOVE_OTHERONLY, this);
|
|
|
|
|
|
|
|
/* Tracing failed, there's world geometry in the way */
|
|
|
|
if (trace_fraction < 1.0f) {
|
|
|
|
v_angle = vectoangles(m_vecLastUserPos - origin);
|
|
|
|
v_angle[0] = 0;
|
|
|
|
v_angle[1] = Math_FixDelta(v_angle[1]);
|
2020-03-29 03:56:46 -07:00
|
|
|
v_angle[2] = 0;
|
2020-03-26 23:34:24 -07:00
|
|
|
} else {
|
|
|
|
m_vecLastUserPos = m_eFollowingChain.origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Trace again to see if another hostage is in our path and if so
|
|
|
|
* follow them instead, this makes pathing easier */
|
|
|
|
traceline(origin, /*mins, maxs,*/ m_vecLastUserPos, FALSE, this);
|
|
|
|
if (trace_ent.classname == classname) {
|
|
|
|
CBaseNPC que = (CBaseNPC)trace_ent;
|
|
|
|
if (que.m_eFollowingChain == m_eFollowing) {
|
|
|
|
if (trace_ent != this) {
|
|
|
|
m_eFollowingChain = trace_ent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::PanicFrame(void)
|
|
|
|
{
|
|
|
|
m_iFlags |= MONSTER_METPLAYER;
|
|
|
|
maxspeed = 240;
|
|
|
|
input_movevalues = [maxspeed, 0, 0];
|
|
|
|
|
|
|
|
if (m_flTraceTime < time) {
|
|
|
|
traceline(origin, origin + (v_forward * 64), FALSE, this);
|
|
|
|
|
|
|
|
if (trace_fraction < 1.0f) {
|
|
|
|
m_flChangePath = 0.0f;
|
|
|
|
}
|
|
|
|
m_flTraceTime = time + 0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_flChangePath < time) {
|
|
|
|
float add;
|
|
|
|
vector pos;
|
|
|
|
|
|
|
|
pos = origin + [0,0,-18];
|
|
|
|
if (random() < 0.5) {
|
|
|
|
add = 45;
|
|
|
|
} else {
|
|
|
|
add = -45;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* test every 45 degrees */
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
v_angle[1] = Math_FixDelta(v_angle[1] + add);
|
|
|
|
makevectors(v_angle);
|
|
|
|
traceline(pos, pos + (v_forward * 64), FALSE, this);
|
|
|
|
if (trace_fraction >= 1.0f) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_flChangePath = time + floor(random(2,10));
|
|
|
|
}
|
|
|
|
}
|
2020-03-26 03:24:33 -07:00
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
void
|
|
|
|
CBaseNPC::FollowChain(void)
|
|
|
|
{
|
|
|
|
/* Deal with a hostage being rescued when it's following someone else */
|
|
|
|
if (m_eFollowingChain.classname == classname) {
|
|
|
|
if (m_eFollowingChain.solid == SOLID_NOT) {
|
|
|
|
m_eFollowingChain = m_eFollowing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Deal with the hostage losing its rescuer (death) */
|
|
|
|
if (m_eFollowing.health <= 0) {
|
|
|
|
m_eFollowing = world;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::Physics(void)
|
|
|
|
{
|
|
|
|
float spvel;
|
|
|
|
input_movevalues = [0,0,0];
|
|
|
|
input_impulse = 0;
|
|
|
|
input_buttons = 0;
|
2020-03-29 02:21:26 -07:00
|
|
|
input_timelength = frametime;
|
2020-08-03 14:39:57 -07:00
|
|
|
input_angles = v_angle;
|
2020-03-29 02:21:26 -07:00
|
|
|
|
2020-11-24 03:29:29 -08:00
|
|
|
/* make sure we're forgetting about enemies and attack states in sequence */
|
2020-09-10 04:36:19 -07:00
|
|
|
if (m_iSequenceState != SEQUENCESTATE_NONE) {
|
2020-11-24 03:29:29 -08:00
|
|
|
m_eEnemy = __NULL__;
|
|
|
|
m_iMState = MONSTER_IDLE;
|
2020-09-10 04:36:19 -07:00
|
|
|
}
|
|
|
|
|
2020-03-29 02:21:26 -07:00
|
|
|
/* override whatever we did above with this */
|
|
|
|
if (m_iSequenceState == SEQUENCESTATE_ENDING) {
|
2020-08-07 05:07:38 -07:00
|
|
|
input_angles = v_angle = angles = m_vecSequenceAngle;
|
2020-04-22 14:33:18 -07:00
|
|
|
SetFrame(m_flSequenceEnd);
|
2020-03-29 02:21:26 -07:00
|
|
|
} else {
|
|
|
|
if (style != MONSTER_DEAD) {
|
2020-11-23 12:39:40 -08:00
|
|
|
if (m_iSequenceState == SEQUENCESTATE_NONE) {
|
|
|
|
SeeThink();
|
|
|
|
AttackThink();
|
|
|
|
TalkPlayerGreet();
|
|
|
|
FollowChain();
|
|
|
|
|
|
|
|
if (m_eFollowing != world) {
|
|
|
|
FollowPlayer();
|
|
|
|
input_angles = angles = v_angle;
|
|
|
|
} else if (m_iFlags & MONSTER_FEAR) {
|
|
|
|
PanicFrame();
|
2020-03-29 02:21:26 -07:00
|
|
|
} else {
|
2020-11-23 12:39:40 -08:00
|
|
|
if (random() < 0.5) {
|
|
|
|
TalkPlayerAsk();
|
|
|
|
} else {
|
|
|
|
TalkPlayerIdle();
|
|
|
|
}
|
2020-03-29 02:21:26 -07:00
|
|
|
}
|
2020-03-26 23:34:24 -07:00
|
|
|
}
|
|
|
|
|
2020-03-30 04:51:48 -07:00
|
|
|
if (m_flAnimTime > time) {
|
2020-03-29 02:21:26 -07:00
|
|
|
input_movevalues = [0,0,0];
|
|
|
|
} else {
|
|
|
|
spvel = vlen(velocity);
|
|
|
|
|
|
|
|
if (spvel < 5) {
|
2020-04-22 14:33:18 -07:00
|
|
|
SetFrame(AnimIdle());
|
2020-03-29 02:21:26 -07:00
|
|
|
} else if (spvel <= 140) {
|
2020-04-22 14:33:18 -07:00
|
|
|
SetFrame(AnimWalk());
|
2020-03-29 02:21:26 -07:00
|
|
|
} else if (spvel <= 240) {
|
2020-04-22 14:33:18 -07:00
|
|
|
SetFrame(AnimRun());
|
2020-03-29 02:21:26 -07:00
|
|
|
}
|
2020-03-26 23:34:24 -07:00
|
|
|
}
|
|
|
|
}
|
2020-03-29 02:21:26 -07:00
|
|
|
CheckRoute();
|
|
|
|
WalkRoute();
|
|
|
|
runstandardplayerphysics(this);
|
2020-04-22 14:33:18 -07:00
|
|
|
SetOrigin(origin);
|
2020-03-26 23:34:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flags & FL_ONGROUND) && velocity[2] < -100) {
|
|
|
|
m_iFlags |= MONSTER_FALLING;
|
|
|
|
} else {
|
|
|
|
m_iFlags &= ~MONSTER_FALLING;
|
|
|
|
}
|
2020-03-29 02:21:26 -07:00
|
|
|
|
|
|
|
/* support for think/nextthink */
|
2020-03-30 01:40:38 -07:00
|
|
|
if (think && nextthink > 0.0f) {
|
2020-03-29 02:21:26 -07:00
|
|
|
if (nextthink < time) {
|
|
|
|
nextthink = 0.0f;
|
2020-03-30 01:00:37 -07:00
|
|
|
think();
|
2020-03-29 02:21:26 -07:00
|
|
|
}
|
|
|
|
}
|
2020-08-03 14:39:57 -07:00
|
|
|
|
2020-09-10 01:34:14 -07:00
|
|
|
m_flBaseTime = frame1time;
|
2020-08-03 14:39:57 -07:00
|
|
|
frame1time += frametime;
|
2020-09-10 01:34:14 -07:00
|
|
|
|
|
|
|
processmodelevents(modelindex, frame, m_flBaseTime,
|
2021-01-06 04:58:37 -08:00
|
|
|
frame1time, Game_ServerModelEvent);
|
2020-03-26 23:34:24 -07:00
|
|
|
}
|
|
|
|
|
2020-11-24 03:29:29 -08:00
|
|
|
void
|
|
|
|
CBaseNPC::Respawn(void)
|
2020-04-12 06:50:42 -07:00
|
|
|
{
|
|
|
|
CBaseMonster::Respawn();
|
|
|
|
m_eFollowing = world;
|
|
|
|
m_eFollowingChain = world;
|
|
|
|
}
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
void
|
2020-11-25 01:32:42 -08:00
|
|
|
CBaseNPC::OnPlayerUse(void)
|
2020-03-26 23:34:24 -07:00
|
|
|
{
|
|
|
|
if (m_iFlags & MONSTER_FEAR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* can't press use any non-allies */
|
|
|
|
if (!(m_iFlags & MONSTER_CANFOLLOW)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((m_eFollowing == world)) {
|
|
|
|
if (!(m_iFlags & MONSTER_USED)) {
|
|
|
|
m_iFlags |= MONSTER_USED;
|
|
|
|
}
|
|
|
|
|
|
|
|
TalkFollow();
|
|
|
|
m_eFollowing = eActivator;
|
|
|
|
m_eFollowingChain = m_eFollowing;
|
|
|
|
m_vecLastUserPos = m_eFollowing.origin;
|
|
|
|
} else {
|
|
|
|
TalkUnfollow();
|
|
|
|
m_eFollowing = world;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-10 19:33:42 -07:00
|
|
|
void
|
|
|
|
CBaseNPC::SpawnKey(string strKey, string strValue)
|
|
|
|
{
|
|
|
|
switch (strKey) {
|
|
|
|
case "UnUseSentence":
|
|
|
|
m_talkUnfollow = strcat("!", strValue);
|
|
|
|
break;
|
|
|
|
case "UseSentence":
|
|
|
|
m_talkFollow = strcat("!", strValue);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CBaseMonster::SpawnKey(strKey, strValue);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-26 23:34:24 -07:00
|
|
|
void
|
|
|
|
CBaseNPC::Hide(void)
|
|
|
|
{
|
|
|
|
m_eFollowing = world;
|
|
|
|
CBaseMonster::Hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CBaseNPC::CBaseNPC(void)
|
|
|
|
{
|
|
|
|
CBaseMonster::CBaseMonster();
|
|
|
|
m_eFollowing = world;
|
2020-03-26 03:24:33 -07:00
|
|
|
}
|