Initial support for scripted_sentence and sentences.txt. It doesn't do anything fancy yet.
This commit is contained in:
parent
13f4044481
commit
0f3cc9c5f5
8 changed files with 261 additions and 42 deletions
|
@ -106,6 +106,7 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
|
|||
DSP_Init();
|
||||
CSQC_RendererRestarted("init");
|
||||
Titles_Init();
|
||||
Sentences_Init();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -443,6 +444,9 @@ CSQC_Parse_Event(void)
|
|||
pit = readfloat();
|
||||
sound(t, CHAN_VOICE, msg, 1.0, ATTN_NORM, pit);
|
||||
break;
|
||||
case EV_SENTENCE:
|
||||
Sentences_Parse();
|
||||
break;
|
||||
case EV_FADE:
|
||||
Fade_Parse();
|
||||
break;
|
||||
|
|
|
@ -34,6 +34,7 @@ enum {
|
|||
EV_CAMERATRIGGER,
|
||||
EV_ORBITUARY,
|
||||
EV_SPEAK,
|
||||
EV_SENTENCE,
|
||||
EV_CHAT,
|
||||
EV_CHAT_TEAM,
|
||||
EV_CHAT_VOX,
|
||||
|
|
|
@ -6,6 +6,7 @@ client/fade.cpp
|
|||
client/sprite.cpp
|
||||
client/titles.cpp
|
||||
client/text.cpp
|
||||
client/sentences.cpp
|
||||
client/env_cubemap.cpp
|
||||
client/env_glow.cpp
|
||||
client/env_sound.cpp
|
||||
|
|
|
@ -29,36 +29,40 @@ vector g_vecCubePos;
|
|||
void CMap_Check(void);
|
||||
void CMap_Shoot(void);
|
||||
|
||||
class env_cubemap:CBaseEntity {
|
||||
class
|
||||
env_cubemap:CBaseEntity
|
||||
{
|
||||
int m_iSize;
|
||||
|
||||
void() env_cubemap;
|
||||
virtual void(string, string) SpawnKey;
|
||||
};
|
||||
|
||||
void env_cubemap::SpawnKey(string strField, string strKey)
|
||||
void
|
||||
env_cubemap::SpawnKey(string strField, string strKey)
|
||||
{
|
||||
switch (strField) {
|
||||
case "scale":
|
||||
m_iSize = stoi(strKey);
|
||||
if (m_iSize <= 16) {
|
||||
m_iSize = 16;
|
||||
} else if (m_iSize <= 32) {
|
||||
m_iSize = 32;
|
||||
} else if (m_iSize <= 64) {
|
||||
m_iSize = 64;
|
||||
} else if (m_iSize <= 128) {
|
||||
m_iSize = 128;
|
||||
} else {
|
||||
m_iSize = 256;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CBaseEntity::SpawnKey(strField, strKey);
|
||||
case "scale":
|
||||
m_iSize = stoi(strKey);
|
||||
if (m_iSize <= 16) {
|
||||
m_iSize = 16;
|
||||
} else if (m_iSize <= 32) {
|
||||
m_iSize = 32;
|
||||
} else if (m_iSize <= 64) {
|
||||
m_iSize = 64;
|
||||
} else if (m_iSize <= 128) {
|
||||
m_iSize = 128;
|
||||
} else {
|
||||
m_iSize = 256;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CBaseEntity::SpawnKey(strField, strKey);
|
||||
}
|
||||
}
|
||||
|
||||
void env_cubemap::env_cubemap(void)
|
||||
void
|
||||
env_cubemap::env_cubemap(void)
|
||||
{
|
||||
m_iSize = 32;
|
||||
Init();
|
||||
|
@ -71,30 +75,31 @@ CMap_Check
|
|||
Checks whether or not a specific cubemap file was dumped, goes to the next
|
||||
=================
|
||||
*/
|
||||
void CMap_Shoot(void)
|
||||
void
|
||||
CMap_Shoot(void)
|
||||
{
|
||||
string strReflectcube;
|
||||
if ( self.owner ) {
|
||||
if (self.owner) {
|
||||
env_cubemap tmp = (env_cubemap) self.owner;
|
||||
print( "^3Cubemap processing...\n" );
|
||||
print("^3Cubemap processing...\n");
|
||||
g_vecCubePos = tmp.origin;
|
||||
strReflectcube = sprintf(
|
||||
"env/%s_%d_%d_%d.dds",
|
||||
mapname,
|
||||
g_vecCubePos[0],
|
||||
g_vecCubePos[1],
|
||||
g_vecCubePos[2]);
|
||||
"env/%s_%d_%d_%d.dds",
|
||||
mapname,
|
||||
g_vecCubePos[0],
|
||||
g_vecCubePos[1],
|
||||
g_vecCubePos[2]);
|
||||
localcmd(sprintf(
|
||||
"screenshot_cubemap %s %i\n",
|
||||
strReflectcube,
|
||||
tmp.m_iSize));
|
||||
"screenshot_cubemap %s %i\n",
|
||||
strReflectcube,
|
||||
tmp.m_iSize));
|
||||
self.think = CMap_Check;
|
||||
self.nextthink = time;
|
||||
} else {
|
||||
print( "^2Cubemaps done...\n" );
|
||||
localcmd( "mod_findcubemaps\nvid_reload\n" );
|
||||
print("^2Cubemaps done...\n");
|
||||
localcmd("mod_findcubemaps\nvid_reload\n");
|
||||
g_iCubeProcess = FALSE;
|
||||
remove( self );
|
||||
remove(self);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,16 +110,19 @@ CMap_Check
|
|||
Checks whether or not a specific cubemap file was dumped, goes to the next
|
||||
=================
|
||||
*/
|
||||
void CMap_Check(void)
|
||||
void
|
||||
CMap_Check(void)
|
||||
{
|
||||
if (whichpack(sprintf(
|
||||
"textures/env/%s_%d_%d_%d.dds",
|
||||
mapname,
|
||||
g_vecCubePos[0],
|
||||
g_vecCubePos[1],
|
||||
g_vecCubePos[2]))) {
|
||||
self.owner = find( self.owner, classname, "env_cubemap" );
|
||||
"textures/env/%s_%d_%d_%d.dds",
|
||||
mapname,
|
||||
g_vecCubePos[0],
|
||||
g_vecCubePos[1],
|
||||
g_vecCubePos[2])))
|
||||
{
|
||||
self.owner = find(self.owner, classname, "env_cubemap");
|
||||
self.think = CMap_Shoot;
|
||||
self.nextthink = time + 0.25f; /* because sigh */
|
||||
}
|
||||
self.nextthink = time;
|
||||
}
|
||||
|
@ -126,7 +134,8 @@ CMap_Build
|
|||
Called upon 'buildcubemaps'
|
||||
=================
|
||||
*/
|
||||
void CMap_Build(void)
|
||||
void
|
||||
CMap_Build(void)
|
||||
{
|
||||
if (g_iCubeProcess == TRUE) {
|
||||
return;
|
||||
|
|
128
src/gs-entbase/client/sentences.cpp
Normal file
128
src/gs-entbase/client/sentences.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* 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;
|
||||
} snt_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string m_strID;
|
||||
snt_t *m_samples;
|
||||
int m_count;
|
||||
} sentences_t;
|
||||
|
||||
sentences_t *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(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));
|
||||
|
||||
/* loop through the parts of the line */
|
||||
for (i=0; i < c; i++) {
|
||||
/* first entry is the id, prefix with ! as well */
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 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) {
|
||||
print("Time to play...\n");
|
||||
sound(world, CHAN_VOICE,
|
||||
g_sentences[a].m_samples[0].m_strSnd, 1.0,
|
||||
ATTN_NONE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -61,7 +61,7 @@ Titles_Init(void)
|
|||
fs_titles = fopen("titles.txt", FILE_READ);
|
||||
|
||||
if (fs_titles < 0) {
|
||||
print("^1WARNING: ^7Could NOT load titles.lst");
|
||||
print("^1WARNING: ^7Could NOT load titles.txt");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,5 +59,6 @@ server/monster_furniture.cpp
|
|||
server/monster_generic.cpp
|
||||
server/monstermaker.cpp
|
||||
server/multisource.cpp
|
||||
server/scripted_sentence.cpp
|
||||
server/scripted_sequence.cpp
|
||||
#endlist
|
||||
|
|
75
src/gs-entbase/server/scripted_sentence.cpp
Normal file
75
src/gs-entbase/server/scripted_sentence.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class scripted_sentence:CBaseTrigger
|
||||
{
|
||||
string m_strSpeaker;
|
||||
string m_strSentence;
|
||||
float m_flDelay;
|
||||
float m_flWait;
|
||||
float m_flPitch;
|
||||
|
||||
void() scripted_sentence;
|
||||
virtual void() Trigger;
|
||||
virtual void() Respawn;
|
||||
};
|
||||
|
||||
void scripted_sentence::Trigger(void)
|
||||
{
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EV_SENTENCE);
|
||||
WriteEntity(MSG_MULTICAST, find(world, ::classname, m_strSpeaker));
|
||||
WriteString(MSG_MULTICAST, m_strSentence);
|
||||
WriteFloat(MSG_MULTICAST, m_flPitch);
|
||||
msg_entity = this;
|
||||
multicast(origin, MULTICAST_PHS);
|
||||
}
|
||||
|
||||
/* TODO: Make this redundant */
|
||||
void scripted_sentence::Respawn(void)
|
||||
{
|
||||
solid = SOLID_TRIGGER;
|
||||
#ifdef GS_DEVELOPER
|
||||
alpha = 0.5f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void scripted_sentence::scripted_sentence(void)
|
||||
{
|
||||
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
|
||||
switch (argv(i)) {
|
||||
case "entity":
|
||||
m_strSpeaker = argv(i+1);
|
||||
case "sentence":
|
||||
m_strSentence = argv(i+1);
|
||||
break;
|
||||
case "pitch":
|
||||
m_flPitch = stof(argv(i+1));
|
||||
break;
|
||||
case "delay":
|
||||
m_flDelay = stof(argv(i+1));
|
||||
break;
|
||||
case "wait":
|
||||
m_flWait = stof(argv(i+1));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CBaseTrigger::CBaseTrigger();
|
||||
scripted_sentence::Respawn();
|
||||
}
|
Loading…
Reference in a new issue