Added initial support for basic sentences.txt on monsters.

This commit is contained in:
Marco Cawthorne 2020-03-26 11:24:33 +01:00
parent d20c3f1db3
commit db4ed5ac3d
29 changed files with 458 additions and 197 deletions

View file

@ -38,7 +38,11 @@ void CSQC_Ent_Update(float new)
Player_ReadEntity(new);
break;
case ENT_NPC:
NPC_ReadEntity(new);
CBaseNPC n = (CBaseNPC)self;
if (new) {
spawnfunc_CBaseNPC();
}
n.ReadEntity(readshort());
break;
case ENT_SPRITE:
Sprite_Animated();

View file

@ -461,7 +461,7 @@ CSQC_Parse_Event(void)
sound(t, CHAN_VOICE, msg, 1.0, ATTN_NORM, pit);
break;
case EV_SENTENCE:
Sentences_Parse();
CBaseNPC_ParseSentence();
break;
case EV_FADE:
Fade_Parse();

View file

@ -14,16 +14,31 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_npc
class CBaseNPC
{
float m_flSentenceTime;
sound_t *m_pSentenceQue;
int m_iSentenceCount;
int m_iSentencePos;
int body;
float frame_last;
virtual float() predraw;
virtual void(string) Speak;
virtual void(string) Sentence;
virtual void() ProcessWordQue;
virtual void(float flChanged) ReadEntity;
};
void
CBaseNPC::Speak(string msg)
{
sound(this, CHAN_VOICE, msg, 1.0, ATTN_NORM);
}
float
monster_npc::predraw(void)
CBaseNPC::predraw(void)
{
if (lerpfrac > 0) {
lerpfrac -= frametime * 5;
@ -44,59 +59,131 @@ monster_npc::predraw(void)
frame1time += clframetime;
bonecontrol5 = getchannellevel(this, CHAN_VOICE) * 20;
ProcessWordQue();
addentity(this);
return PREDRAW_NEXT;
}
void
NPC_ReadEntity(float new)
CBaseNPC::ProcessWordQue(void)
{
float fl;
monster_npc pl = (monster_npc)self;
if (new) {
spawnfunc_monster_npc();
pl.classname = "npc";
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_NONE;
pl.drawmask = MASK_ENGINE;
pl.customphysics = Empty;
setsize(pl, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
if (time < 2 || !m_iSentenceCount) {
return;
}
fl = readshort();
if (fl & NPC_MODELINDEX)
pl.modelindex = readshort();
if (fl & NPC_ORIGIN_X)
pl.origin[0] = readcoord();
if (fl & NPC_ORIGIN_Y)
pl.origin[1] = readcoord();
if (fl & NPC_ORIGIN_Z)
pl.origin[2] = readcoord();
if (fl & NPC_ANGLES_X)
pl.angles[0] = readfloat();
if (fl & NPC_ANGLES_Y)
pl.angles[1] = readfloat();
if (fl & NPC_ANGLES_Z)
pl.angles[2] = readfloat();
if (fl & NPC_VELOCITY_X)
pl.velocity[0] = readcoord();
if (fl & NPC_VELOCITY_Y)
pl.velocity[1] = readcoord();
if (fl & NPC_VELOCITY_Z)
pl.velocity[2] = readcoord();
if (fl & NPC_FRAME)
pl.frame = readbyte();
if (fl & NPC_SKIN)
pl.skin = readbyte();
if (fl & NPC_BODY)
pl.body = readbyte();
if (new || (fl & NPC_BODY)) {
setcustomskin(pl, "", sprintf("geomset 1 %i\n", pl.body));
if (m_flSentenceTime > time) {
return;
}
Speak(m_pSentenceQue[m_iSentencePos].m_strSnd);
dprint(sprintf("^2CBaseNPC: Speaking %s\n", m_pSentenceQue[m_iSentencePos].m_strSnd));
m_iSentencePos++;
setorigin(pl, pl.origin);
if (m_iSentenceCount == m_iSentenceCount) {
memfree(m_pSentenceQue);
m_iSentenceCount = 0;
m_iSentencePos = 0;
m_pSentenceQue = 0;
} else {
m_flSentenceTime = time + m_pSentenceQue[m_iSentenceCount - 1].len;
}
}
/* we'll pass it a sentences.txt word (e.g. !BA_TEST) and start queing it */
void
CBaseNPC::Sentence(string msg)
{
/* not defined */
if (msg == "") {
return;
}
if (m_iSentenceCount) {
dprint(sprintf("^1CBaseNPC::Sentence: Freeing que for new sentence\n", m_iSentenceCount));
memfree(m_pSentenceQue);
m_iSentenceCount = 0;
m_pSentenceQue = 0;
m_iSentencePos = 0;
}
m_iSentenceCount = tokenize(Sentences_GetSamples(msg));
dprint(sprintf("^2CBaseNPC::Sentence: Speaking %i word/s\n", m_iSentenceCount));
m_pSentenceQue = memalloc(sizeof(sound_t) * m_iSentenceCount);
for (int i = 0; i < m_iSentenceCount; i++) {
dprint(sprintf("^2CBaseNPC::Sentence: Constructing... %s\n", m_pSentenceQue[i].m_strSnd));
m_pSentenceQue[i].m_strSnd = sprintf("%s.wav", argv(i));
m_pSentenceQue[i].len = soundlength(m_pSentenceQue[i].m_strSnd);
m_pSentenceQue[i].m_flPitch = 100;
}
m_flSentenceTime = time;
}
void
CBaseNPC::ReadEntity(float fl)
{
if (fl & NPC_MODELINDEX)
modelindex = readshort();
if (fl & NPC_ORIGIN_X)
origin[0] = readcoord();
if (fl & NPC_ORIGIN_Y)
origin[1] = readcoord();
if (fl & NPC_ORIGIN_Z)
origin[2] = readcoord();
if (fl & NPC_ANGLES_X)
angles[0] = readfloat();
if (fl & NPC_ANGLES_Y)
angles[1] = readfloat();
if (fl & NPC_ANGLES_Z)
angles[2] = readfloat();
if (fl & NPC_VELOCITY_X)
velocity[0] = readcoord();
if (fl & NPC_VELOCITY_Y)
velocity[1] = readcoord();
if (fl & NPC_VELOCITY_Z)
velocity[2] = readcoord();
if (fl & NPC_FRAME)
frame = readbyte();
if (fl & NPC_SKIN)
skin = readbyte();
if (fl & NPC_BODY) {
body = readbyte();
setcustomskin(this, "", sprintf("geomset 1 %i\n", body));
}
setorigin(this, origin);
}
void
CBaseNPC::CBaseNPC(void)
{
solid = SOLID_SLIDEBOX;
movetype = MOVETYPE_NONE;
drawmask = MASK_ENGINE;
customphysics = Empty;
setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]);
}
/* our EV_SENTENCE event */
void
CBaseNPC_ParseSentence(void)
{
entity ent;
CBaseNPC targ;
string sentence;
float e;
/* parse packets */
e = readentitynum();
sentence = readstring();
ent = findfloat(world, entnum, e);
if (ent) {
targ = (CBaseNPC)ent;
targ.Sentence(sentence);
} else {
dprint(sprintf("^1CBaseNPC_ParseSentence: Entity %d not in PVS\n", e));
}
}

View file

@ -23,21 +23,35 @@
* we'll just default to those whenever there's no custom value set.
*/
typedef struct
{
string m_strSnd;
float m_flPitch;
} snt_t;
#define DYNAMIC_SENTENCES 0
typedef struct
{
string m_strID;
snt_t *m_samples;
int m_count;
string m_strSamples;
} sentences_t;
sentences_t *g_sentences;
int g_sentences_count;
#ifdef DYNAMIC_SENTENCES
sentences_t *g_sentences;
int g_sentences_count;
#else
sentences_t g_sentences[1024];
int g_sentences_count;
#endif
string g_sentences_path;
void
Sentences_Path(string word)
{
int c = tokenizebyseparator(word, "/");
if (c > 1) {
g_sentences_path = sprintf("%s/", argv(0));
} else {
g_sentences_path = "";
}
}
void
Sentences_Init(void)
@ -71,15 +85,18 @@ Sentences_Init(void)
/* starts of at 0, for every line increases */
int x = g_sentences_count;
/* default path is vox */
g_sentences_path = "vox/";
/* allocate memory and increase count */
#ifdef DYNAMIC_SENTENCES
g_sentences = memrealloc(g_sentences,
sizeof(sentences_t),
g_sentences_count,
++g_sentences_count);
/* allocate sentences */
g_sentences[x].m_count = c-1;
g_sentences[x].m_samples = memalloc(sizeof(snt_t) * (c-1));
#else
g_sentences_count++;
#endif
/* loop through the parts of the line */
for (i=0; i < c; i++) {
@ -87,41 +104,28 @@ Sentences_Init(void)
if (i==0) {
g_sentences[x].m_strID = strcat("!", argv(0));
} else {
/* TODO: handle pitch and VOX samples */
g_sentences[x].m_samples[i-1].m_strSnd =
strcat(argv(i), ".wav");
/* check whether or not our keyword contains a path */
Sentences_Path(argv(i));
//Sentencens_Pitch(argv(i));
g_sentences[x].m_strSamples =
sprintf(
"%s %s%s",
g_sentences[x].m_strSamples,
g_sentences_path,
argv(i)
);
}
}
print(sprintf("%s\n", g_sentences[x].m_strSamples));
}
/*for (int a=0; a < g_sentences_count; a++) {
print(sprintf("[^1SENTENCES^7] Found ^2%s\n",
g_sentences[a].m_strID));
for (int b = 0; b < g_sentences[a].m_count; b++) {
print(sprintf("\tSample ^2%s\n",
g_sentences[a].m_samples[b].m_strSnd));
}
}*/
}
void
Sentences_Parse(void)
string
Sentences_GetSamples(string msg)
{
string sentence;
entity target;
float pitch;
target = findfloat(world, entnum, readentitynum());
sentence = readstring();
pitch = readfloat();
print(sprintf("[^1SENTENCES^7] Playing %s\n", sentence));
for (int a = 0; a < g_sentences_count; a++) {
if (g_sentences[a].m_strID == sentence) {
sound(world, CHAN_VOICE,
g_sentences[a].m_samples[0].m_strSnd, 1.0,
ATTN_NONE);
for (int i = 0; i < g_sentences_count; i++) {
if (g_sentences[i].m_strID == msg) {
return g_sentences[i].m_strSamples;
}
}
}

View file

@ -53,8 +53,10 @@ void Sound_ParseLoopingEntity(entity sndent, float isNew)
}
typedef struct {
string sample;
typedef struct
{
string m_strSnd;
float m_flPitch;
float len;
} sound_t;
@ -70,8 +72,8 @@ void Sound_PlayVOX(string msg)
g_voxque = memalloc(sizeof(sound_t) * g_voxcount);
for (int i = 0; i < g_voxcount; i++) {
g_voxque[i].sample = sprintf("vox/%s.wav", argv(i));
g_voxque[i].len = soundlength(g_voxque[i].sample);
g_voxque[i].m_strSnd = sprintf("vox/%s.wav", argv(i));
g_voxque[i].len = soundlength(g_voxque[i].m_strSnd);
}
g_voxtime = time;
}
@ -83,7 +85,7 @@ void Sound_ProcessWordQue(void)
}
if (g_voxtime < time) {
localcmd(sprintf("play %s\n", g_voxque[g_voxpos].sample));
localcmd(sprintf("play %s\n", g_voxque[g_voxpos].m_strSnd));
g_voxpos++;
if (g_voxpos == g_voxcount) {

View file

@ -24,12 +24,12 @@ init.c
../sprite.cpp
../titles.c
../text.c
../sentences.c
../../gs-entbase/client.src
../sky.c
../sound.c
../sentences.c
../prints.c
../voice.c

View file

@ -8,6 +8,7 @@ server/defs.h
server/baseentity.cpp
server/basetrigger.cpp
server/basemonster.cpp
server/basenpc.cpp
server/basephysics.cpp
server/ambient_generic.cpp
server/cycler.cpp

View file

@ -43,20 +43,14 @@ class CBaseMonster:CBaseEntity
virtual void() Physics;
virtual void() IdleNoise;
virtual void() Gib;
virtual void(string) Speak;
virtual void(string) Sound;
virtual float(entity, float) SendEntity;
virtual void() ParentUpdate;
};
void CBaseMonster::Speak(string msg)
void CBaseMonster::Sound(string msg)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_SPEAK);
WriteEntity(MSG_MULTICAST, this);
WriteString(MSG_MULTICAST, msg);
WriteFloat(MSG_MULTICAST, m_flPitch);
msg_entity = this;
multicast(origin, MULTICAST_PVS);
sound(this, CHAN_VOICE, msg, 1.0, ATTN_NORM);
}
float CBaseMonster::SendEntity(entity ePEnt, float fChanged)

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/* NPCs are more advanced than regular monsters in that they express emotions
* and are able to interact more with the environment */
class CBaseNPC:CBaseMonster
{
/* our NPCs can have a unique pitch to their voice */
float m_flPitch;
/* sentences identifiers */
string m_talkAnswer; /* random answer to whenever a question is asked */
string m_talkAsk; /* asks a random generic question */
string m_talkAllyShot; /* asks to not shoot an ally further */
string m_talkGreet; /* greet other NPCs */
string m_talkIdle; /* idle chatter */
string m_talkSmelling; /* is something smelling bad? */
string m_talkStare; /* when NPC is being stared at */
string m_talkSurvived; /* we're near death */
string m_talkWounded; /* we've sustained light wounds */
/* things that NPCs will only say to the player */
string m_talkPlayerAsk; /* ask player some question */
string m_talkPlayerGreet; /* say hello to the player */
string m_talkPlayerIdle; /* idle chatter with the player */
string m_talkPlayerWounded1; /* slightly wounded player comment */
string m_talkPlayerWounded2; /* a bit worse */
string m_talkPlayerWounded3; /* yup, got thus far */
string m_talkUnfollow; /* when the player asks us to stop following */
string m_talkFollow; /* whenever player asks the NPC to follow */
string m_talkStopFollow; /* we have to stop following */
void() CBaseNPC;
virtual void(string) Speak;
virtual void(string) Sentence;
};
void
CBaseNPC::Sentence(string sentence)
{
string seq = Sentences_GetSamples(sentence);
print(sprintf("^2CBaseNPC::Sentence: Attempting %s\n", seq));
if (seq == "") {
return;
}
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_SENTENCE);
WriteEntity(MSG_MULTICAST, this);
WriteString(MSG_MULTICAST, Sentences_GetSamples(sentence));
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
CBaseNPC::CBaseNPC(void)
{
}

View file

@ -206,6 +206,7 @@ void initents(void)
Game_Worldspawn();
Decals_Init();
Sentences_Init();
entity respawntimer = spawn();
respawntimer.think = init_respawn;

View file

@ -19,6 +19,7 @@
../logging.c
../nodes.c
../skill.c
../sentences.c
../../gs-entbase/server.src
../valve/monster_apache.cpp

View file

@ -19,6 +19,7 @@
../logging.c
../nodes.c
../skill.c
../sentences.c
../../gs-entbase/server.src
../valve/monster_apache.cpp

View file

@ -19,6 +19,7 @@
../logging.c
../nodes.c
../skill.c
../sentences.c
../../gs-entbase/server.src
../valve/monster_rat.cpp
../valve/monster_scientist.cpp

View file

@ -18,6 +18,7 @@
../logging.c
../nodes.c
../skill.c
../sentences.c
../../gs-entbase/server.src
../valve/monster_rat.cpp
../valve/monster_scientist_dead.cpp

View file

@ -299,7 +299,7 @@ string sci_sndidle[] = {
"scientist/hopenominal.wav",
};
class monster_scientist:CBaseMonster
class monster_scientist:CBaseNPC
{
vector m_vecLastUserPos;
entity m_eUser;

View file

@ -20,6 +20,7 @@
../logging.c
../nodes.c
../skill.c
../sentences.c
../../gs-entbase/server.src

117
src/server/sentences.c Normal file
View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/* voice sentence samples for AI and other triggers that are supposed to talk.
* the formatting is messy as hell and I feel dirty for even bothering with all
* this to begin with.
*
* the server will send a short string identifer over and we'll look it up.
* what's annoying is that some NPCs got their own pitch overrides so I guess
* we'll just default to those whenever there's no custom value set.
*/
typedef struct
{
string m_strSnd;
float m_flPitch;
float len;
} sound_t;
string *g_sentences;
int g_sentences_count;
void
Sentences_Init(void)
{
filestream fs_sentences;
string temp;
int c, i;
fs_sentences = fopen("sound/sentences.txt", FILE_READ);
if (fs_sentences < 0) {
print("^1WARNING: ^7Could NOT load sound/sentences.txt");
return;
}
if (g_sentences_count > 0) {
print("^1WARNING: ^7Attempted to load sentences twice!");
return;
}
while ((temp = fgets(fs_sentences))) {
/* tons of comments/garbage in those files,
* so tokenize appropriately */
c = tokenize_console(temp);
/* not enough for an entry. */
if (c < 2) {
continue;
}
/* starts of at 0, for every line increases */
int x = g_sentences_count;
/* allocate memory and increase count */
g_sentences = memrealloc(g_sentences,
sizeof(string),
g_sentences_count,
++g_sentences_count);
g_sentences[x] = strcat("!", argv(0));
}
}
string
Sentences_GetSamples(string word)
{
int len;
int gc;
/* you never know what NPCs might do */
if (word == "") {
print("^1ERROR: No sentence supplied.\n");
return "";
}
/* check if the word is present at all */
for (int i = 0; i < g_sentences_count; i++) {
if (g_sentences[i] == word) {
print(sprintf("^2Sentences: Found %s\n", word));
return word;
}
}
/* it may be a random group of words. */
len = strlen(word);
for (int i = 0; i < g_sentences_count; i++) {
string sub = substring(g_sentences[i], 0, len);
if (sub == word) {
gc++;
}
}
/* if we've got one, choose a random sample of them */
if (gc) {
int r = floor(random(0, gc));
print(sprintf("^2Sentences: Choosing %s%i\n", word, r));
return sprintf("%s%i", word, r);
}
/* we've somehow messed up catastrophically */
print(sprintf("^1ERROR: Invalid sentence keyword %s\n", word));
return "";
}

View file

@ -18,6 +18,7 @@
../logging.c
../nodes.c
../skill.c
../sentences.c
../../gs-entbase/server.src
../../shared/decals.c
../../shared/effects.c

View file

@ -95,7 +95,7 @@ monster_alien_controller::Pain(int iHitBody)
}
int rand = floor(random(0,con_sndpain.length));
Speak(con_sndpain[rand]);
Sound(con_sndpain[rand]);
frame = CON_FLINCH + floor(random(0, 2));
m_flPainTime = time + 0.25f;
}
@ -109,7 +109,7 @@ monster_alien_controller::Death(int iHitBody)
/* the sound */
int rand = floor(random(0,con_sndpain.length));
Speak(con_sndpain[rand]);
Sound(con_sndpain[rand]);
}
/* set the functional differences */
@ -130,7 +130,7 @@ monster_alien_controller::IdleNoise(void)
m_flIdleTime = time + 2.0f + random(0,5);
int rand = floor(random(0, con_sndidle.length));
Speak(con_sndidle[rand]);
Sound(con_sndidle[rand]);
}
void

View file

@ -112,7 +112,7 @@ monster_alien_grunt::Pain(int iHitBody)
}
int rand = floor(random(0,ag_sndpain.length));
Speak(ag_sndpain[rand]);
Sound(ag_sndpain[rand]);
frame = AG_FLINCH + floor(random(0, 2));
m_flPainTime = time + 0.25f;
}
@ -135,7 +135,7 @@ monster_alien_grunt::Death(int iHitBody)
/* the sound */
int rand = floor(random(0,ag_sndpain.length));
Speak(ag_sndpain[rand]);
Sound(ag_sndpain[rand]);
}
/* set the functional differences */
@ -156,7 +156,7 @@ monster_alien_grunt::IdleNoise(void)
m_flIdleTime = time + 2.0f + random(0,5);
int rand = floor(random(0, ag_sndidle.length));
Speak(ag_sndidle[rand]);
Sound(ag_sndidle[rand]);
}
void

View file

@ -87,7 +87,7 @@ monster_alien_slave::Pain(int iHitBody)
}
int rand = floor(random(0,slv_sndpain.length));
Speak(slv_sndpain[rand]);
Sound(slv_sndpain[rand]);
frame = SLV_FLINCH + floor(random(0, 2));
m_flPainTime = time + 0.25f;
}
@ -110,7 +110,7 @@ monster_alien_slave::Death(int iHitBody)
/* the sound */
int rand = floor(random(0,slv_sndpain.length));
Speak(slv_sndpain[rand]);
Sound(slv_sndpain[rand]);
}
/* set the functional differences */

View file

@ -62,61 +62,19 @@ string barney_snddie[] = {
"barney/ba_die2.wav"
};
string barney_sndchitchat[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_sndhear[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_sndpain[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_sndsee[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_sndscream[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_sndstop[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_snduse[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_snduseno[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
string barney_sndidle[] = {
"barney/ba_pain1.wav",
"barney/ba_pain1.wav",
"barney/ba_pain1.wav"
};
class monster_barney:CBaseMonster
class monster_barney:CBaseNPC
{
vector m_vecLastUserPos;
entity m_eUser;
@ -173,8 +131,7 @@ void monster_barney::IdleChat(void)
return;
}
int rand = floor(random(0,barney_sndchitchat.length));
Speak(barney_sndchitchat[rand]);
Sentence(m_talkPlayerIdle);
m_flScreamTime = time + 5.0f + random(0,20);
}
@ -196,11 +153,7 @@ void monster_barney::Physics(void)
continue;
}
if (random() < 0.5) {
int rand = floor(random(0,barney_sndsee.length));
Speak(barney_sndsee[rand]);
}
Sentence(m_talkPlayerGreet);
m_iFlags |= BARNF_SEEN;
break;
}
@ -347,16 +300,12 @@ void monster_barney::PlayerUse(void)
m_iFlags |= BARNF_USED;
}
r = floor(random(0,barney_snduse.length));
Speak(barney_snduse[r]);
Sentence(m_talkFollow);
m_eUser = eActivator;
m_eRescuer = m_eUser;
m_vecLastUserPos = m_eUser.origin;
} else {
r = floor(random(0,barney_snduseno.length));
Speak(barney_snduseno[r]);
Sentence(m_talkUnfollow);
m_eUser = world;
}
}
@ -459,18 +408,26 @@ void monster_barney::monster_barney(void)
for (int i = 0; i < barney_sndscream.length; i++) {
precache_sound(barney_sndscream[i]);
}
for (int i = 0; i < barney_snduse.length; i++) {
precache_sound(barney_snduse[i]);
}
for (int i = 0; i < barney_snduseno.length; i++) {
precache_sound(barney_snduseno[i]);
}
for (int i = 0; i < barney_sndsee.length; i++) {
precache_sound(barney_sndsee[i]);
}
for (int i = 0; i < barney_sndidle.length; i++) {
precache_sound(barney_sndidle[i]);
}
m_talkAnswer = "!BA_ANSWER";
m_talkAsk = "";
m_talkAllyShot = "!BA_SCARED";
m_talkGreet = "";
m_talkIdle = "";
m_talkSmelling = "!BA_SMELL";
m_talkStare = "!BA_STARE";
m_talkSurvived = "!BA_ANSWER";
m_talkWounded = "!BA_WOUND";
m_talkPlayerAsk = "!BA_QUESTION";
m_talkPlayerGreet = "!BA_HELLO";
m_talkPlayerIdle = "!BA_IDLE";
m_talkPlayerWounded1 = "!BA_CUREA";
m_talkPlayerWounded2 = "!BA_CUREB";
m_talkPlayerWounded3 = "!BA_CUREC";
m_talkUnfollow = "!BA_WAIT";
m_talkFollow = "!BA_OK";
m_talkStopFollow = "!BA_STOP";
model = "models/barney.mdl";
netname = "Barney";

View file

@ -101,7 +101,7 @@ monster_headcrab::Pain(int iHitBody)
}
int rand = floor(random(0,hcb_sndpain.length));
Speak(hcb_sndpain[rand]);
Sound(hcb_sndpain[rand]);
frame = HCBA_FLINCH;
m_flPainTime = time + 0.25f;
}
@ -115,7 +115,7 @@ monster_headcrab::Death(int iHitBody)
/* the sound */
int rand = floor(random(0,hcb_sndpain.length));
Speak(hcb_sndpain[rand]);
Sound(hcb_sndpain[rand]);
}
/* set the functional differences */
@ -136,7 +136,7 @@ monster_headcrab::IdleNoise(void)
m_flIdleTime = time + 2.0f + random(0,5);
int rand = floor(random(0, hcb_sndidle.length));
Speak(hcb_sndidle[rand]);
Sound(hcb_sndidle[rand]);
}
void

View file

@ -119,7 +119,7 @@ monster_houndeye::Pain(int iHitBody)
}
int rand = floor(random(0,he_sndpain.length));
Speak(he_sndpain[rand]);
Sound(he_sndpain[rand]);
frame = HE_FLINCH + floor(random(0, 2));
m_flPainTime = time + 0.25f;
}
@ -133,7 +133,7 @@ monster_houndeye::Death(int iHitBody)
/* the sound */
int rand = floor(random(0,he_sndpain.length));
Speak(he_sndpain[rand]);
Sound(he_sndpain[rand]);
}
/* set the functional differences */
@ -154,7 +154,7 @@ monster_houndeye::IdleNoise(void)
m_flIdleTime = time + 2.0f + random(0,5);
int rand = floor(random(0, he_sndidle.length));
Speak(he_sndidle[rand]);
Sound(he_sndidle[rand]);
}
void

View file

@ -93,7 +93,7 @@ monster_ichthyosaur::Pain(int iHitBody)
}
int rand = floor(random(0,ichy_sndpain.length));
Speak(ichy_sndpain[rand]);
Sound(ichy_sndpain[rand]);
frame = ICHY_FLINCH + floor(random(0, 2));
m_flPainTime = time + 0.25f;
}
@ -119,7 +119,7 @@ monster_ichthyosaur::Death(int iHitBody)
/* the sound */
int rand = floor(random(0,ichy_sndpain.length));
Speak(ichy_sndpain[rand]);
Sound(ichy_sndpain[rand]);
}
/* set the functional differences */
@ -140,7 +140,7 @@ monster_ichthyosaur::IdleNoise(void)
m_flIdleTime = time + 2.0f + random(0,5);
int rand = floor(random(0, ichy_sndidle.length));
Speak(ichy_sndidle[rand]);
Sound(ichy_sndidle[rand]);
}
void

View file

@ -302,7 +302,7 @@ string sci_sndidle[] = {
"scientist/hopenominal.wav",
};
class monster_scientist:CBaseMonster
class monster_scientist:CBaseNPC
{
vector m_vecLastUserPos;
entity m_eUser;

View file

@ -126,7 +126,7 @@ monster_tentacle::IdleNoise(void)
m_flIdleTime = time + 2.0f + random(0,5);
int rand = floor(random(0, tent_sndidle.length));
Speak(tent_sndidle[rand]);
Sound(tent_sndidle[rand]);
}
void

View file

@ -128,7 +128,7 @@ monster_zombie::Pain(int iHitBody)
}
int rand = floor(random(0,zom_sndpain.length));
Speak(zom_sndpain[rand]);
Sound(zom_sndpain[rand]);
frame = ZOMA_FLINCH + floor(random(0, 2));
m_flPainTime = time + 0.25f;
}
@ -151,7 +151,7 @@ monster_zombie::Death(int iHitBody)
/* the sound */
int rand = floor(random(0,zom_sndpain.length));
Speak(zom_sndpain[rand]);
Sound(zom_sndpain[rand]);
}
/* set the functional differences */
@ -172,7 +172,7 @@ monster_zombie::IdleNoise(void)
m_flIdleTime = time + 2.0f + random(0,5);
int rand = floor(random(0, zom_sndidle.length));
Speak(zom_sndidle[rand]);
Sound(zom_sndidle[rand]);
}
void

View file

@ -18,6 +18,7 @@ defs.h
../logging.c
../nodes.c
../skill.c
../sentences.c
../../gs-entbase/server.src
../valve/monster_apache.cpp