(ambience_upate), likely with a different
hero proximity value.
+ SOUND_TRIGGER_VERBAL Invoked by the core when someone (or something)
+ is speaking.
+
The types of sound sound_triggers supported by a particular soundlib
implementation are specified in that library's soundlib file, which is usually
void (*sound_play_usersound)(char *filename, int32_t volume,
int32_t usidx);
void (*sound_ambience)(int32_t ambienceid, int32_t ambience_action,
- int32_t hero_proximity);
+ int32_t hero_proximity);
+ void (*sound_verbal)(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo);
};
-A sound library integration support file can implement one, two, three or
-four of the sound trigger types. The more types of sound_triggers the
+A sound library integration support file can implement one, two, three, four,
+five, or six of the sound trigger types. The more types of sound_triggers the
soundlib implements, the more full-featured the sound experience will be
during the game.
The values can be or'd together in the sound_triggers field initialization.
SOUND_TRIGGER_USERSOUNDS | SOUND_TRIGGER_HEROMUSIC
| SOUND_TRIGGER_ACHIEVEMENTS | SOUND_TRIGGER_SOUNDEFFECTS
+ | SOUND_TRIGGER_AMBIENCE | SOUND_TRIGGER_VERBAL
II. Interface Specification
If the distance of the hero from the source of the ambience does
matter, then a distance value will be in hero_proximity.
+sound_verbal(char *text, int32_t gender, int32_t tone, int32_t vol,
+ int32_t moreinfo);
+ -- NetHack will call this function when it wants to pass text of
+ spoken language by a character or creature within the game.
+ -- text is a transcript of what has been spoken.
+ -- gender indicates MALE or FEMALE or NEUTRAL (either MALE
+ or FEMALE) voice.
+ -- tone indicates the tone of the voice.
+ -- vol is the volume (1% - 100%) for the sound.
+ -- moreinfo is used to provide additional information to the soundlib.
+ -- there may be some accessibility uses for this function.
+
III. Global variables
ga.active_soundlib
a usersound mappings reference
+iflags.sounds is the master on/off swith to control whether any audio
+is produced by the soundlib interface
+
+iflags.voice is the master on/off switch for voices produced by
+the soundlib interface.
IV. Other related routines
SOUNDID(myprefix),
SOUND_TRIGGER_USERSOUNDS | SOUND_TRIGGER_HEROMUSIC
| SOUND_TRIGGER_ACHIEVEMENTS |SOUND_TRIGGER_SOUNDEFFECTS
- | SOUND_TRIGGER_AMBIENCE,
+ | SOUND_TRIGGER_AMBIENCE | SOUND_TRIGGER_VERBAL,
myprefix_init_nhsound,
myprefix_exit_nhsound,
myprefix_achievement,
myprefix_soundeffect,
myprefix_hero_playnotes,
myprefix_play_usersound,
- myprefix_ambience),
+ myprefix_ambience,
+ myprefix_verbal),
};
The first entry in this structure should be the SOUNDID(myprefix)
static void sample_play_usersound(char *, int32_t, int32_t);
static void sample_ambience(int32_t ambienceid, int32_t ambience_action,
int32_t hero_proximity);
+static void (*sound_verbal)(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo);
struct sound_procs sample_procs = {
SOUNDID(sample),
sample_hero_playnotes,
sample_play_usersound,
sample_ambience,
+ sample_verbal
};
static void
{
}
+static void
+sample_verbal(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo)
+{
+}
+
/* end of sample.c */
-- >8 --
coordxy *viz_rmax; /* max could see indices */
boolean vision_full_recalc;
+ /* new stuff */
+ struct sound_voice voice;
+
boolean havestate;
unsigned long magic; /* validate that structure layout is preserved */
};
extern char *stripchars(char *, const char *, const char *);
extern char *stripdigits(char *);
extern char *eos(char *);
+extern const char *c_eos(const char *);
extern unsigned Strlen_(const char *, const char *, int);
extern boolean str_start_is(const char *, const char *, boolean);
extern boolean str_end_is(const char *, const char *);
char *buf, size_t bufsz, int32_t);
#endif
extern char *base_soundname_to_filename(char *, char *, size_t, int32_t);
+extern void set_voice(struct monst *, int32_t, int32_t, int32_t);
+extern void sound_speak(const char *);
/* ### sp_lev.c ### */
long hilite_delta; /* number of moves to leave a temp hilite lit */
long unhilite_deadline; /* time when oldest temp hilite should be unlit */
#endif
+ boolean voices; /* enable text-to-speech or other talking */
boolean zerocomp; /* write zero-compressed save files */
boolean rlecomp; /* alternative to zerocomp; run-length encoding
* compression of levels when writing savefile */
#define OVERRIDE_MSGTYPE 2
#define SUPPRESS_HISTORY 4
#define URGENT_MESSAGE 8
+#define PLINE_VERBALIZE 16
+#define PLINE_SPEECH 32
/* get_count flags */
#define GC_NOFLAGS 0
NHOPTC(video_height, Advanced, 10, opt_in, set_gameview,
No, Yes, No, No, NoAlias, "video height")
#endif
+ NHOPTB(voices, Advanced, 0, opt_in, set_in_game,
+ Off, Yes, No, No, NoAlias, &iflags.voices, Term_Off)
#ifdef TTY_TILES_ESCCODES
NHOPTB(vt_tiledata, Advanced, 0, opt_in, set_in_config,
Off, Yes, No, No, NoAlias, &iflags.vt_tiledata, Term_False)
void (*sound_play_usersound)(char *filename, int32_t volume, int32_t idx);
void (*sound_ambience)(int32_t ambience_action, int32_t ambienceid,
int32_t proximity);
+ void (*sound_verbal)(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo);
+};
+
+struct sound_voice {
+ int32_t serialno;
+ int32_t gender;
+ int32_t tone;
+ int32_t volume;
+ int32_t moreinfo;
+ struct monst *mon;
+ const char *nameid;
};
extern struct sound_procs sndprocs;
#define SOUND_TRIGGER_ACHIEVEMENTS 0x0004L
#define SOUND_TRIGGER_SOUNDEFFECTS 0x0008L
#define SOUND_TRIGGER_AMBIENCE 0x0010L
- /* 27 free bits */
+#define SOUND_TRIGGER_VERBAL 0x0020L
+ /* 26 free bits */
extern struct sound_procs soundprocs;
amb_noambience,
};
+enum voice_moreinfo {
+ voice_nothing_special,
+ voice_talking_artifact = 0x0001,
+ voice_deity = 0x0002,
+ voice_oracle = 0x0004,
+ voice_throne = 0x0008,
+ voice_death = 0x0010
+};
+
enum achievements_arg2 {
sa2_zero_invalid, sa2_splashscreen, sa2_newgame_nosplash, sa2_restoregame,
sa2_xplevelup, sa2_xpleveldown, number_of_sa2_entries
(*soundprocs.sound_hero_playnotes)((instrument), (str), (vol)); \
} while(0)
-/* void (*sound_achievement)(schar, schar, int32_t); */
-
/* Player's perspective, not the hero's; no Deaf suppression */
#define SoundAchievement(arg1, arg2, avals) \
do { \
(*soundprocs.sound_achievement)((arg1), (arg2), (avals)); \
} while(0)
+/* sound_speak is in sound.c */
+#define SoundSpeak(text) \
+ do { \
+ if ((gp.pline_flags & (PLINE_VERBALIZE | PLINE_SPEECH)) != 0 \
+ && soundprocs.sound_verbal && iflags.voices \
+ && ((soundprocs.sound_triggers & SOUND_TRIGGER_VERBAL) != 0)) \
+ sound_speak(text); \
+ } while(0)
+
+/* set_voice is in sound.c */
+#define SetVoice(mon, tone, vol, moreinfo) \
+ do { \
+ set_voice(mon, tone, vol, moreinfo); \
+ } while(0)
+
/* void (*sound_achievement)(schar, schar, int32_t); */
#ifdef SOUNDLIBONLY
#define Soundeffect(seid, vol)
#define Hero_playnotes(instrument, str, vol)
#define SoundAchievement(arg1, arg2, avals)
+#define SoundSpeak(text)
+#define SetVoice(mon, tone, vol, moreinfo)
#ifdef SOUNDLIBONLY
#undef SOUNDLIBONLY
#endif
/* #import <Foundation/Foundation.h> */
#import <AppKit/AppKit.h>
+#define SPEECH_SOUNDS
+#ifdef SPEECH_SOUNDS
+#import <AVFoundation/AVFoundation.h>
+#endif
+
+
/*
* Sample sound interface for NetHack
*
static void macsound_hero_playnotes(int32_t, const char *, int32_t);
static void macsound_play_usersound(char *, int32_t, int32_t);
static void macsound_ambience(int32_t, int32_t, int32_t);
-
+static void macsound_verbal(char *, int32_t, int32_t, int32_t, int32_t);
static int affiliate(int32_t seid, const char *soundname);
+
+
/*
* Sound capabilities that can be enabled:
* SOUND_TRIGGER_USERSOUNDS | SOUND_TRIGGER_HEROMUSIC
struct sound_procs macsound_procs = {
SOUNDID(macsound),
SOUND_TRIGGER_HEROMUSIC | SOUND_TRIGGER_SOUNDEFFECTS
- | SOUND_TRIGGER_ACHIEVEMENTS,
+ | SOUND_TRIGGER_ACHIEVEMENTS
+#ifdef SND_SPEECH
+ | SOUND_TRIGGER_VERBAL,
+#endif
macsound_init_nhsound,
macsound_exit_nhsound,
macsound_achievement,
macsound_hero_playnotes,
macsound_play_usersound,
macsound_ambience,
+ macsound_verbal,
};
static void
}
+#ifdef SND_SPEECH
+#define SPEECHONLY
+#else
+#define SPEECHONLY UNUSED
+#endif
+
+static void
+macsound_verbal(char *text SPEECHONLY, int32_t gndr SPEECHONLY, int32_t tone_of_voice UNUSED, int32_t vol UNUSED, int32_t moreinfo UNUSED)
+{
+#ifdef SND_SPEECH
+ NSMutableString *speechstring;
+ AVSpeechUtterance *text2speechutt;
+ AVSpeechSynthesizer *synthesizer;
+
+ synthesizer = [[AVSpeechSynthesizer alloc]init];
+ speechstring = [NSMutableString stringWithUTF8String:text];
+ text2speechutt = [AVSpeechUtterance speechUtteranceWithString:speechstring];
+ text2speechutt.rate = 0.50f;
+ text2speechutt.pitchMultiplier = 0.8f;
+ text2speechutt.postUtteranceDelay = 0.2f;
+ text2speechutt.volume = (float) vol / 100;
+ if (gndr > 0)
+ text2speechutt.voice = [AVSpeechSynthesisVoice voiceWithIdentifier:@"com.apple.ttsbundle.siri_female_en-GB_compact"];
+ else
+ text2speechutt.voice = [AVSpeechSynthesisVoice voiceWithIdentifier:@"com.apple.ttsbundle.siri_male_en-GB_compact"];
+
+ [synthesizer speakUtterance:text2speechutt];
+#endif /* SND_SPEECH */
+}
+
static int
affiliate(int32_t id, const char *soundname)
{
static void windsound_play_usersound(char *, int32_t, int32_t);
static void windsound_ambience(int32_t ambienceid, int32_t ambience_action,
int32_t hero_proximity);
+static void windsound_verbal(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo);
+
/* supporting routines */
static void adjust_soundargs_for_compiler(int32_t *, DWORD *, char **);
SOUNDID(windsound),
SOUND_TRIGGER_USERSOUNDS | SOUND_TRIGGER_SOUNDEFFECTS
| SOUND_TRIGGER_HEROMUSIC | SOUND_TRIGGER_AMBIENCE
- | SOUND_TRIGGER_ACHIEVEMENTS,
+ | SOUND_TRIGGER_ACHIEVEMENTS | SOUND_TRIGGER_VERBAL,
windsound_init_nhsound,
windsound_exit_nhsound,
windsound_achievement,
windsound_hero_playnotes,
windsound_play_usersound,
windsound_ambience,
+ windsound_verbal,
};
static void
static void
windsound_ambience(int32_t ambienceid, int32_t ambience_action,
- int32_t hero_proximity)
+ int32_t hero_proximity)
+{
+}
+
+static void
+windsound_verbal(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo)
{
}
pline_The("new %s magically %s!", s, vtense(s, "ignite"));
else if (!otmp->lamplit && was_lamplit)
pline("%s out.", (obj->quan > 1L) ? "They go" : "It goes");
- if (obj->unpaid)
+ if (obj->unpaid) {
+ struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
+
+ SetVoice(shkp, 0, 80, 0);
verbalize("You %s %s, you bought %s!",
otmp->lamplit ? "burn" : "use",
(obj->quan > 1L) ? "them" : "it",
(obj->quan > 1L) ? "them" : "it");
+ }
if (obj->quan < 7L && otmp->spe == 7)
pline("%s now has seven%s candles attached.", The(xname(otmp)),
otmp->lamplit ? " lit" : "");
if (obj->otyp == POT_OIL)
makeknown(obj->otyp);
if (carried(obj) && obj->unpaid && costly_spot(u.ux, u.uy)) {
+ struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
+
/* if it catches while you have it, then it's your tough luck */
check_unpaid(obj);
+ SetVoice(shkp, 0, 80, 0);
verbalize("That's in addition to the cost of %s %s, of course.",
yname(obj),
(obj->quan == 1L) ? "itself" : "themselves");
if (obj->unpaid && costly_spot(u.ux, u.uy)
&& obj->age == 20L * (long) objects[obj->otyp].oc_cost) {
const char *ithem = (obj->quan > 1L) ? "them" : "it";
+ struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
+ SetVoice(shkp, 0, 80, 0);
verbalize("You burn %s, you bought %s!", ithem, ithem);
bill_dummy_object(obj);
}
Blind ? "" : " It gives off a dim light.");
if (obj->unpaid && costly_spot(u.ux, u.uy)) {
+ struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
+
/* Normally, we shouldn't both partially and fully charge
* for an item, but (Yendorian Fuel) Taxes are inevitable...
*/
check_unpaid(obj);
+ SetVoice(shkp, 0, 80, 0);
verbalize("That's in addition to the cost of the potion, of course.");
bill_dummy_object(obj);
}
/* Mark tinned tins. No spinach allowed... */
set_tin_variety(can, HOMEMADE_TIN);
if (carried(corpse)) {
- if (corpse->unpaid)
+ if (corpse->unpaid) {
+ struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
+
+ SetVoice(shkp, 0, 80, 0);
verbalize(you_buy_it);
+ }
useup(corpse);
} else {
- if (costly_spot(corpse->ox, corpse->oy) && !corpse->no_charge)
+ if (costly_spot(corpse->ox, corpse->oy) && !corpse->no_charge) {
+ struct monst *shkp = shop_keeper(*in_rooms(corpse->ox,
+ corpse->oy, SHOPBASE));
+ SetVoice(shkp, 0, 80, 0);
verbalize(you_buy_it);
+ }
useupf(corpse, 1L);
}
(void) hold_another_object(can, "You make, but cannot pick up, %s.",
if (!*line)
line = "NetHack rumors file closed for renovation.";
pline("%s:", Tobjnam(obj, "whisper"));
+ SetVoice((struct monst *) 0, 0, 80, voice_talking_artifact);
verbalize1(line);
return;
}
else
cmdq_clear(CQ_CANNED); /* 'res' is ESC */
} else {
+#ifdef SND_SPEECH
+ if ((gp.pline_flags & PLINE_SPEECH) != 0) {
+ sound_speak(query);
+ gp.pline_flags &= ~PLINE_SPEECH;
+ }
+#endif
res = (*windowprocs.win_yn_function)(query, resp, def);
if (addcmdq)
cmdq_add_key(CQ_REPEAT, res);
UNDEFINED_PTR, /* viz_rmin */
UNDEFINED_PTR, /* viz_rmax */
FALSE, /* vision_full_recalc */
+ UNDEFINED_VALUES, /* voice */
TRUE, /* havestate*/
IVMAGIC /* v_magic to validate that structure layout has been preserved */
};
mtmp = get_iter_mons(watchman_canseeu);
if (mtmp) {
+ SetVoice(mtmp, 0, 80, 0);
if (zap || gc.context.digging.warned) {
verbalize("Halt, vandal! You're under arrest!");
(void) angry_guards(!!Deaf);
} else if (mtmp->isshk
&& !(Deaf || helpless(mtmp)
|| mtmp->data->msound <= MS_ANIMAL)) {
- if (!alreadynamed(mtmp, monnambuf, buf))
+ if (!alreadynamed(mtmp, monnambuf, buf)) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("I'm %s, not %s.", shkname(mtmp), buf);
+ }
} else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk
|| mtmp->data == &mons[PM_GHOST]) {
if (!alreadynamed(mtmp, monnambuf, buf))
if (!robbed)
make_happy_shk(mtmp, FALSE);
} else {
+ SetVoice(mtmp, 0, 80, 0);
if (mtmp->mpeaceful) {
ESHK(mtmp)->credit += value;
You("have %ld %s in credit.", ESHK(mtmp)->credit,
verbalize("Thanks, scum!");
}
} else if (mtmp->ispriest) {
+ SetVoice(mtmp, 0, 80, 0);
if (mtmp->mpeaceful)
verbalize("Thank you for your contribution.");
else
out of the vault. If he did do that, player
could try fighting, then weasle out of being
killed by throwing his/her gold when losing. */
+ SetVoice(mtmp, 0, 80, 0);
verbalize(umoney ? "Drop the rest and follow me."
: hidden_gold(TRUE)
? "You still have hidden gold. Drop it now."
}
if (!mtmp->mpeaceful) {
+ SetVoice(mtmp, 0, 80, 0);
if (goldreqd)
verbalize("That's not enough, coward!");
else /* unbribeable (watchman) */
verbalize("I don't take bribes from scum like you!");
} else if (was_angry) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("That should do. Now beat it!");
} else {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("Thanks for the tip, %s.",
flags.female ? "lady" : "buddy");
}
struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
if (oracle) {
+ SetVoice(oracle, 0, 80, 0);
if (!oracle->mpeaceful)
verbalize("You're in Delphi, %s.", gp.plname);
else
char * stripdigits (char *)
unsigned Strlen_ (const char *str, const char *, int)
char * eos (char *)
+ const char * c_eos (const char *)
boolean str_start_is (const char *, const char *, boolean)
boolean str_end_is (const char *, const char *)
int str_lines_maxlen (const char *)
return s;
}
+const char *
+c_eos(const char *s)
+{
+ while (*s)
+ s++; /* s += strlen(s); */
+ return s;
+}
+
/* like strlen(3) but returns unsigned and panics if string is unreasonably long */
unsigned
Strlen_(const char *str, const char *file, int line){
if (mtmp && canseemon(mtmp) && M_AP_TYPE(mtmp) != M_AP_FURNITURE
&& M_AP_TYPE(mtmp) != M_AP_OBJECT) {
if (picktyp == CREDIT_CARD
- && (mtmp->isshk || mtmp->data == &mons[PM_ORACLE]))
+ && (mtmp->isshk || mtmp->data == &mons[PM_ORACLE])) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("No checks, no credit, no problem.");
- else
+ } else {
pline("I don't think %s would appreciate that.",
mon_nam(mtmp));
+ }
return PICKLOCK_LEARNED_SOMETHING;
} else if (mtmp && is_door_mappear(mtmp)) {
/* "The door actually was a <mimic>!" */
if (fx == tx && fy == ty)
break;
+ SetVoice(md, 0, 80, 0);
if ((mon = m_at(fx, fy)) != 0) /* save monster at this position */
verbalize1(md_exclamations());
else if (u_at(fx, fy))
remove_monster(fx, fy);
place_monster(md, fx, fy); /* display md with text below */
newsym(fx, fy);
+ SetVoice(md, 0, 80, 0);
verbalize("This place's too crowded. I'm outta here.");
remove_monster(fx, fy);
goto go_back;
message_seen = TRUE;
+ SetVoice(md, 0, 80, 0);
verbalize("%s, %s! %s.", Hello(md), gp.plname, info->display_txt);
if (info->message_typ) {
if (info->response_cmd)
new_omailcmd(obj, info->response_cmd);
- if (!next2u(md->mx, md->my))
+ if (!next2u(md->mx, md->my)) {
+ SetVoice(md, 0, 80, 0);
verbalize("Catch!");
+ }
display_nhwindow(WIN_MESSAGE, FALSE);
obj = hold_another_object(obj, "Oops!", (const char *) 0,
(const char *) 0);
if (!count) {
; /* nothing was created? */
} else if (mtmp->iswiz) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("Destroy the thief, my pet%s!", plur(count));
} else {
boolean one = (count == 1);
" looks pretty. May I have it?\"", ring,
xname, simpleonames, "ring");
makeknown(RIN_ADORNMENT);
+ SetVoice(mon, 0, 80, 0);
if (y_n(qbuf) == 'n')
continue;
} else
" looks pretty. Would you wear it for me?\"",
ring, xname, simpleonames, "ring");
makeknown(RIN_ADORNMENT);
+ SetVoice(mon, 0, 80, 0);
if (y_n(qbuf) == 'n')
continue;
} else {
if (uarm || uarmc) {
if (!Deaf) {
if (!(ld() && mon->female)) {
+ SetVoice(mon, 0, 80, 0);
verbalize("You're such a %s; I wish...",
flags.female ? "sweet lady" : "nice guy");
} else {
if (cost > umoney)
cost = umoney;
if (!cost) {
+ SetVoice(mon, 0, 80, 0);
verbalize("It's on the house!");
} else {
pline("%s takes %ld %s for services rendered!", noit_Monnam(mon),
if (Deaf) {
pline("%s takes off your %s.", seducer, str);
} else if (rn2(20) < ACURR(A_CHA)) {
+ SetVoice(mon, 0, 80, 0); /* y_n a.k.a. yn_function is set up for this */
Sprintf(qbuf, "\"Shall I remove your %s, %s?\"", str,
(!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart"));
if (y_n(qbuf) == 'n')
Sprintf(hairbuf, "let me run my fingers through your %s",
body_part(HAIR));
+ SetVoice(mon, 0, 80, 0);
verbalize("Take off your %s; %s.", str,
(obj == uarm)
? "let's get a little closer"
else
You_feel("%s booming voice:",
s_suffix(align_gname(alignment)));
+ SetVoice(mon, 0, 80, 0);
verbalize("Thou shalt pay for thine indiscretion!");
if (canspotmon(mon))
pline("%s appears before you.", Amonnam(mon));
if (canspotmon(mon)) {
if (!Deaf) {
pline("%s rebukes you, saying:", Monnam(mon));
+ SetVoice(mon, 0, 80, 0);
verbalize("Since you desire conflict, have some more!");
} else {
pline("%s vanishes!", Monnam(mon));
pline("A voice booms:");
else
You_feel("a booming voice:");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thy desire for conflict shall be fulfilled!");
/* send in some hostile angels instead */
lose_guardian_angel((struct monst *) 0);
pline("A voice whispers:");
else
You_feel("a soft voice:");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou hast been worthy of me!");
mm.x = u.ux;
mm.y = u.uy;
case OBJ_INVENT:
if (learn_bknown)
set_bknown(obj, 1);
+ if (shkp)
+ SetVoice(shkp, 0, 80, 0);
verbalize("You %s %s %s, you pay for %s!",
alteration_verbs[alter_type], those, simpleonames(obj),
them);
if (learn_bknown)
obj->bknown = 1; /* ok to bypass set_bknown() here */
if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
+ if (shkp)
+ SetVoice(shkp, 0, 80, 0);
verbalize("You %s %s, you pay for %s!",
alteration_verbs[alter_type], those, them);
bill_dummy_object(obj);
buf[0] = '\0';
if (humanoid(mon->data) || mon->isshk || mon->ispriest) {
if (is_watch(mon->data)) {
+ SetVoice(mon, 0, 80, 0);
verbalize("Halt! You're under arrest!");
(void) angry_guards(!!Deaf);
} else {
if (canspotmon(mon)) {
pline("%s yells:", Amonnam(mon));
} else {
- Soundeffect(se_someone_yells, 75);
+ /* Soundeffect(se_someone_yells, 75); */
You_hear("someone yell:");
}
+ SetVoice(mon, 0, 80, 0);
verbalize1(shout);
}
}
pline("%s flees from the painful light of %s.",
Monnam(mtmp), lsrc);
} else {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("Bright light!");
}
} else {
#ifdef MAIL_STRUCTURES
if (ptr == &mons[PM_MAIL_DAEMON]) {
- if (!Deaf && canseemon(mtmp))
+ if (!Deaf && canseemon(mtmp)) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("I'm late!");
+ }
mongone(mtmp);
return MMOVE_DIED;
}
if (mtmp->mpeaceful)
return; /* will drop to humanoid talk */
+ SetVoice(mtmp, 0, 80, 0);
verbalize("Talk? -- %s", mtmp->data == &mons[gu.urole.mnum]
? same_class_msg[rn2(3)]
: other_class_msg[rn2(3)]);
pline("%s speaks.", vis ? Monnam(mtmp) : Something);
/* I suspect few players will be upset that monsters */
/* can't wish for wands of death here.... */
+ SetVoice(mtmp, 0, 80, 0);
if (rn2(2)) {
verbalize("You freed me!");
mtmp->mpeaceful = 1;
return (DEADMONSTER(mtmp)) ? 1 : 2;
} /* case MUSE_SCR_EARTH */
case MUSE_CAMERA: {
- if (Hallucination)
+ if (Hallucination) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("Say cheese!");
- else
+ } else {
pline("%s takes a picture of you with %s!",
Monnam(mtmp), an(xname(otmp)));
+ }
gm.m_using = TRUE;
if (!Blind) {
You("are blinded by the flash of light!");
coffers = otmp;
if (coffers) {
+ SetVoice((struct monst *) 0, 0, 80, 0);
verbalize("Thank you for your contribution to reduce the debt.");
freeinv(goldob);
(void) add_to_container(coffers, goldob);
if ((gp.pline_flags & SUPPRESS_HISTORY) != 0
&& (windowprocs.wincap2 & WC2_SUPPRESS_HIST) != 0)
attr |= ATR_NOHISTORY;
-
putstr(WIN_MESSAGE, attr, line);
+ SoundSpeak(line);
}
static void vpline(const char *, va_list);
(void) strncpy(gp.prevmsg, line, BUFSZ), gp.prevmsg[BUFSZ - 1] = '\0';
if (msgtyp == MSGTYP_STOP)
display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */
-
pline_done:
+#ifdef SND_SPEECH
+ /* clear the SPEECH flag so caller never has to */
+ gp.pline_flags &= ~PLINE_SPEECH;
+#endif
--in_pline;
}
char *tmp;
va_start(the_args, line);
+ gp.pline_flags |= PLINE_VERBALIZE;
tmp = You_buf((int) strlen(line) + sizeof "\"\"");
Strcpy(tmp, "\"");
Strcat(tmp, line);
Strcat(tmp, "\"");
vpline(tmp, the_args);
+ gp.pline_flags &= ~PLINE_VERBALIZE;
va_end(the_args);
}
chance = (chance == 0) ? rn2(4) : 4;
/* 0,1,2,3,4: b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */
+ SetVoice(mtmp, 0, 80, 0);
switch (chance) {
case 0:
verbalize("I am in your debt. I will grant one wish!");
}
if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)) {
/* one more try for high altars */
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou cannot escape my wrath, mortal!");
summon_minion(resp_god, FALSE);
summon_minion(resp_god, FALSE);
summon_minion(resp_god, FALSE);
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Destroy %s, my servants!", uhim());
}
}
? "hast strayed from the path"
: "art arrogant",
gy.youmonst.data->mlet == S_HUMAN ? "mortal" : "creature");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou must relearn thy lessons!");
(void) adjattrib(A_WIS, -1, FALSE);
losexp((char *) 0);
case 7:
case 8:
godvoice(resp_god, (char *) 0);
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou durst %s me?",
(on_altar() && (a_align(u.ux, u.uy) != resp_god))
? "scorn"
switch (u.ualign.type) {
case A_LAWFUL:
u.uevent.uhand_of_elbereth = 1;
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("I crown thee... The Hand of Elbereth!");
livelog_printf(LL_DIVINEGIFT,
"was crowned \"The Hand of Elbereth\" by %s",
in_hand = u_wield_art(ART_VORPAL_BLADE);
already_exists = exist_artifact(LONG_SWORD,
artiname(ART_VORPAL_BLADE));
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou shalt be my Envoy of Balance!");
livelog_printf(LL_DIVINEGIFT, "became %s Envoy of Balance",
s_suffix(u_gname()));
what = (((already_exists && !in_hand) || class_gift != STRANGE_OBJECT)
? "take lives"
: "steal souls");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou art chosen to %s for My Glory!", what);
livelog_printf(LL_DIVINEGIFT, "was chosen to %s for the Glory of %s",
what, u_gname());
if (!u.uevent.uopened_dbridge && !u.uevent.gehennom_entered) {
if (u.uevent.uheard_tune < 1) {
godvoice(g_align, (char *) 0);
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Hark, %s!", (gy.youmonst.data->mlet == S_HUMAN)
? "mortal"
: "creature");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize(
"To enter the castle, thou must play the right tune!");
u.uevent.uheard_tune++;
u.ublessed++;
pline(msg, "my protection");
}
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Use it wisely in my name!");
break;
}
pline("An invisible choir sings, and you are bathed in radiance...");
godvoice(altaralign, "Mortal, thou hast done well!");
display_nhwindow(WIN_MESSAGE, FALSE);
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize(
"In return for thy service, I grant thee the gift of Immortality!");
You("ascend to the status of Demigod%s...",
: "Despite your deafness, you seem to hear",
align_gname(altaralign),
!Deaf ? "?) whispers" : " say");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou shalt pay, infidel!");
/* higher luck is more likely to be reduced; as it approaches -5
the chance to lose another point drops down, eventually to 0 */
msg1 = buf;
}
if (msg1 && can_speak && !Deaf) {
+ SetVoice(priest, 0, 80, 0);
verbalize1(msg1);
if (msg2)
verbalize1(msg2);
priest->mcanmove = 1;
}
priest->mpeaceful = 0;
+ SetVoice(priest, 0, 80, 0);
verbalize1(cranky_msg[rn2(3)]);
return;
}
/* you desecrated the temple and now you want to chat? */
if (priest->mpeaceful && *in_rooms(priest->mx, priest->my, TEMPLE)
&& !has_shrine(priest)) {
+ SetVoice(priest, 0, 80, 0);
verbalize(
"Begone! Thou desecratest this holy place with thy presence.");
priest->mpeaceful = 0;
pline("%s asks you for a contribution for the temple.",
Monnam(priest));
if ((offer = bribe(priest)) == 0) {
+ SetVoice(priest, 0, 80, 0);
verbalize("Thou shalt regret thine action!");
if (coaligned)
adjalign(-1);
} else if (offer < (u.ulevel * 200)) {
if (money_cnt(gi.invent) > (offer * 2L)) {
+ SetVoice(priest, 0, 80, 0);
verbalize("Cheapskate.");
} else {
+ SetVoice(priest, 0, 80, 0);
verbalize("I thank thee for thy contribution.");
/* give player some token */
exercise(A_WIS, TRUE);
}
} else if (offer < (u.ulevel * 400)) {
+ SetVoice(priest, 0, 80, 0);
verbalize("Thou art indeed a pious individual.");
if (money_cnt(gi.invent) < (offer * 2L)) {
if (coaligned && u.ualign.record <= ALGN_SINNED)
&& (!(HProtection & INTRINSIC)
|| (u.ublessed < 20
&& (u.ublessed < 9 || !rn2(u.ublessed))))) {
+ SetVoice(priest, 0, 80, 0);
verbalize("Thou hast been rewarded for thy devotion.");
if (!(HProtection & INTRINSIC)) {
HProtection |= FROMOUTSIDE;
} else
u.ublessed++;
} else {
+ SetVoice(priest, 0, 80, 0);
verbalize("Thy selfless generosity is deeply appreciated.");
if (money_cnt(gi.invent) < (offer * 2L) && coaligned) {
if (strayed && (gm.moves - u.ucleansed) > 5000L) {
/* Awaken the prisoner */
if (canseemon(mtmp))
pline("%s speaks:", Monnam(mtmp));
+ SetVoice(mtmp, 0, 80, 0);
verbalize("I'm finally free!");
mtmp->mstrategy &= ~STRAT_WAITMASK;
mtmp->mpeaceful = 1;
*/
if (Verbose(3, do_genocide))
pline("A thunderous voice booms through the caverns:");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("No, mortal! That will not be done.");
}
continue;
(!rn2(4) ? "offhandedly "
: (!rn2(3) ? "casually "
: (rn2(2) ? "nonchalantly " : ""))));
+ SetVoice((struct monst *) 0, 0, 80, voice_oracle);
verbalize1(line);
/* [WIS exercized by getrumor()] */
return;
* Try to intimidate him into paying his bill
*/
boolean not_upset = !eshkp->surcharge;
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize(not_upset ? "%s! Please pay before leaving."
: "%s! Don't you leave without paying!",
gp.plname);
- else
+ } else {
pline("%s %s that you need to pay before leaving%s",
Shknam(shkp),
not_upset ? "points out" : "makes it clear",
not_upset ? "." : "!");
+ }
return;
}
if (Invis) {
pline("%s senses your presence.", Shknam(shkp));
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("Invisible customers are not welcome!");
- else
+ } else {
pline("%s stands firm as if %s knows you are there.",
Shknam(shkp), noit_mhe(shkp));
+ }
return;
}
rt = gr.rooms[*enterstring - ROOMOFFSET].rtype;
if (ANGRY(shkp)) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("So, %s, you dare return to %s %s?!", gp.plname,
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
- else
+ } else {
pline("%s seems %s over your return to %s %s!",
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
noit_mhis(shkp), shtypes[rt - SHOPBASE].name);
+ }
} else if (eshkp->surcharge) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("Back again, %s? I've got my %s on you.",
gp.plname, mbodypart(shkp, EYE));
- else
+ } else {
pline_The("atmosphere at %s %s seems unwelcoming.",
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
+ }
} else if (eshkp->robbed) {
if (!Deaf) {
Soundeffect(se_mutter_imprecations, 50);
Shknam(shkp), noit_mhis(shkp));
}
} else {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ set_voice(shkp, 0, 80, 0);
verbalize("%s, %s! Welcome%s to %s %s!", Hello(shkp), gp.plname,
eshkp->visitct++ ? " again" : "",
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
- else
+ } else {
You("enter %s %s%s!",
s_suffix(shkname(shkp)),
shtypes[rt - SHOPBASE].name,
eshkp->visitct++ ? " again" : "");
+ }
}
/* can't do anything about blocking if teleported in */
if (!inside_shop(u.ux, u.uy)) {
if (!Blind)
makeknown(DWARVISH_MATTOCK);
}
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize(not_upset
? "Will you please leave your %s%s outside?"
: "Leave the %s%s outside.",
tool, plur(cnt));
- else
+ } else {
pline("%s %s to let you in with your %s%s.",
Shknam(shkp),
not_upset ? "is hesitant" : "refuses",
tool, plur(cnt));
+ }
should_block = TRUE;
} else if (u.usteed) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize(not_upset ? "Will you please leave %s outside?"
: "Leave %s outside.",
y_monnam(u.usteed));
- else
+ } else {
pline("%s %s to let you in while you're riding %s.",
Shknam(shkp),
not_upset ? "doesn't want" : "refuses",
y_monnam(u.usteed));
+ }
should_block = TRUE;
} else {
should_block =
/* if you bring a sack of N picks into a shop to sell,
don't repeat this N times when they're taken out */
if (gm.moves != pickmovetime) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("You sneaky %s! Get out of here with that pick!",
cad(FALSE));
- else
+ } else {
pline("%s %s your pick!",
Shknam(shkp),
haseyes(shkp->data) ? "glares at"
: "is dismayed because of");
+ }
}
pickmovetime = gm.moves;
}
update_inventory(); /* Done in dopayobj() if itemize. */
}
if (!ANGRY(shkp) && paid) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("Thank you for shopping in %s %s%s",
s_suffix(shkname(shkp)),
shtypes[eshkp->shoptype - SHOPBASE].name,
!eshkp->surcharge ? "!" : ".");
- else
+ } else {
pline("%s nods%s at you for shopping in %s %s%s",
Shknam(shkp), !eshkp->surcharge ? " appreciatively" : "",
noit_mhis(shkp), shtypes[eshkp->shoptype - SHOPBASE].name,
!eshkp->surcharge ? "!" : ".");
+ }
}
return ECMD_TIME;
}
} else if (quan < bp->bquan && !consumed) { /* partly used goods */
obj->quan = bp->bquan - save_quan; /* used up amount */
if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("%s for the other %s before buying %s.",
ANGRY(shkp) ? "Pay" : "Please pay",
simpleonames(obj), /* short name suffices */
Shknam(shkp),
(obj->spe < 7) ? "horrified" : "concerned");
} else {
+ SetVoice(shkp, 0, 80, 0);
verbalize("No thanks, I'd hang onto that if I were you.");
- if (obj->spe < 7)
+ if (obj->spe < 7) {
+ SetVoice(shkp, 0, 80, 0);
verbalize(
"You'll need %d%s candle%s to go along with it.",
(7 - obj->spe), (obj->spe > 0) ? " more" : "",
plur(7 - obj->spe));
+ }
/* [what if hero is already carrying enough candles?
should Izchak explain how to attach them instead?] */
}
} else {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("I won't stock that. Take it out of here!");
- else
+ } else {
pline("%s shakes %s %s in refusal.",
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HEAD));
+ }
}
}
return TRUE;
Strcat(buf, "; only");
}
obj->quan = 1L; /* fool xname() into giving singular */
+ set_voice(shkp, 0, 80, 0);
pline("%s %ld %s %s %s%s.\"", buf, ltmp, currency(ltmp),
(save_quan > 1L) ? "per"
: (contentscount && !obj->unpaid)
obj->quan = save_quan;
}
} else if (!silent) {
- if (ltmp)
+ if (ltmp) {
+ set_voice(shkp, 0, 80, 0);
pline_The("list price of %s%s%s is %ld %s%s.",
(contentscount && !obj->unpaid) ? the_contents_of : "",
the(xname(obj)),
(contentscount && obj->unpaid) ? and_its_contents : "",
ltmp, currency(ltmp), (obj->quan > 1L) ? " each" : "");
- else
+ } else {
pline("%s does not notice.", Shknam(shkp));
+ }
}
}
eshkp = ESHK(shkp);
if (ANGRY(shkp)) { /* they become shop-objects, no pay */
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("Thank you, scum!");
- else
+ } else {
pline("%s smirks with satisfaction.", Shknam(shkp));
+ }
subfrombill(obj, shkp);
return;
}
offer += cgold;
if ((eshkp->robbed -= offer < 0L))
eshkp->robbed = 0L;
- if (offer && !Deaf && !muteshk(shkp))
+ if (offer && !Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize(
"Thank you for your contribution to restock this recently plundered shop.");
+ }
subfrombill(obj, shkp);
return;
}
/* if it is the shk's pos, you hit and anger him */
&& (shkp->mx != x || shkp->my != y)) {
if (mnearto(shkp, x, y, TRUE, RLOC_NOMSG) == 2
- && !Deaf && !muteshk(shkp))
+ && !Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("Out of my way, scum!");
+ }
if (cansee(x, y)) {
pline("%s nimbly%s catches %s.", Shknam(shkp),
(x == shkp->mx && y == shkp->my) ? "" : " reaches over and",
* a slang connotation which could be applicable if hero
* has Passes_walls ability.
*/
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("Get your junk out of my wall!");
+ }
unplacebc(); /* pick 'em up */
placebc(); /* put 'em down */
}
}
if (eshkp->following) {
if (strncmp(eshkp->customer, gp.plname, PL_NSIZ)) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("%s, %s! I was looking for %s.", Hello(shkp),
gp.plname, eshkp->customer);
+ }
eshkp->following = 0;
return 0;
}
if (gm.moves > gf.followmsg + 4) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("%s, %s! Didn't you forget to pay?",
Hello(shkp), gp.plname);
- else
+ } else {
pline("%s holds out %s upturned %s.",
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HAND));
+ }
gf.followmsg = gm.moves;
if (!rn2(9)) {
pline("%s doesn't like customers who don't pay.",
if (!fall) {
if (lang == 2) {
if (!Deaf && !muteshk(shkp)) {
- if (u.utraptype == TT_PIT)
+ SetVoice(shkp, 0, 80, 0);
+ if (u.utraptype == TT_PIT) {
verbalize(
"Be careful, %s, or you might fall through the floor.",
flags.female ? "madam" : "sir");
- else
+ } else {
verbalize("%s, do not damage the floor here!",
flags.female ? "Madam" : "Sir");
+ }
}
}
if (Role_if(PM_KNIGHT)) {
if (MON_AT(x, y)) {
if (!animal) {
if (!Deaf && !muteshk(shkp)) {
- Soundeffect(se_angry_voice, 75);
+ /* Soundeffect(se_angry_voice, 75); */
You_hear("an angry voice:");
+ SetVoice(shkp, 0, 80, 0);
verbalize("Out of my way, scum!");
}
wait_synch();
if (animal && !helpless(shkp))
yelp(shkp);
} else if (pursue || uinshp || !um_dist(x, y, 1)) {
- if (!Deaf)
+ if (!Deaf) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("How dare you %s my %s?", dmgstr,
dugwall ? "shop" : "door");
- else
+ } else {
pline("%s is %s that you decided to %s %s %s!",
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
dmgstr, noit_mhis(shkp), dugwall ? "shop" : "door");
+ }
} else {
if (!Deaf) {
pline("%s shouts:", Shknam(shkp));
+ SetVoice(shkp, 0, 80, 0);
verbalize("Who dared %s my %s?", dmgstr,
dugwall ? "shop" : "door");
} else {
}
} else {
if (!animal) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("Oh, yes! You'll pay!");
- else
+ } else {
pline("%s lunges %s %s toward your %s!",
Shknam(shkp), noit_mhis(shkp),
mbodypart(shkp, HAND), body_part(NECK));
+ }
} else
growl(shkp);
hot_pursuit(shkp);
} else if (cnt == 1) {
if (!cost) {
/* "<doname(obj)>, no charge" */
+ SetVoice(shkp, 0, 80, 0);
verbalize("%s!", upstart(buf)); /* buf contains the string */
} else {
/* print cost in slightly different format, so can't reuse buf;
cost and contentsonly are already set up */
Sprintf(buf, "%s%s", contentsonly ? the_contents_of : "",
doname(first_obj));
+ SetVoice(shkp, 0, 80, 0);
verbalize("%s, price %ld %s%s%s", upstart(buf), cost,
currency(cost), (first_obj->quan > 1L) ? " each" : "",
contentsonly ? "." : shk_embellish(first_obj, cost));
noit_mhe(shkp), eshk->robbed ? "non-paying" : "rude");
} else if (eshk->following) {
if (strncmp(eshk->customer, gp.plname, PL_NSIZ)) {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("%s %s! I was looking for %s.",
Hello(shkp), gp.plname, eshk->customer);
+ }
eshk->following = 0;
} else {
- if (!Deaf && !muteshk(shkp))
+ if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize("%s %s! Didn't you forget to pay?",
Hello(shkp), gp.plname);
- else
+ } else {
pline("%s taps you on the %s.",
Shknam(shkp), body_part(ARM));
+ }
}
} else if (eshk->billct) {
register long total = addupbill(shkp) + eshk->debit;
}
if (!Deaf && !muteshk(shkp)) {
+ SetVoice(shkp, 0, 80, 0);
verbalize(fmt, arg1, arg2, tmp, currency(tmp));
exercise(A_WIS, TRUE); /* you just got info */
}
|| (floor_absorber && !costly_spot(x, y)))) {
amount = bp->price;
bill_dummy_object(obj_absorbed);
+ SetVoice(shkp, 0, 80, 0);
verbalize("You owe me %ld %s for my %s that you %s with your%s",
amount, currency(amount), obj_typename(obj_absorbed->otyp),
ANGRY(shkp) ? "had the audacity to mix" : "just mixed",
/* Magical voice not affected by deafness */
pline("A voice echoes:");
+ SetVoice((struct monst *) 0, 0, 80, voice_throne);
verbalize("Thine audience hath been summoned, %s!",
flags.female ? "Dame" : "Sire");
while (cnt--)
case 8:
/* Magical voice not affected by deafness */
pline("A voice echoes:");
+ SetVoice((struct monst *) 0, 0, 80, voice_throne);
verbalize("By thine Imperious order, %s...",
flags.female ? "Dame" : "Sire");
do_genocide(5); /* REALLY|ONTHRONE, see do_genocide() */
case 9:
/* Magical voice not affected by deafness */
pline("A voice echoes:");
+ SetVoice((struct monst *) 0, 0, 80, voice_throne);
verbalize(
"A curse upon thee for sitting upon this most holy throne!");
if (Luck > 0) {
{
if ((mtmp->msleeping || is_animal(mtmp->data))
&& mon_in_room(mtmp, ZOO)) {
- int hallu = Hallucination ? 1 : 0;
+ int hallu = Hallucination ? 1 : 0, selection = rn2(2) + hallu;
static const char *const zoo_msg[3] = {
"a sound reminiscent of an elephant stepping on a peanut.",
"a sound reminiscent of a seal barking.", "Doctor Dolittle!",
};
- You_hear1(zoo_msg[rn2(2) + hallu]);
+ You_hear1(zoo_msg[selection]);
return TRUE;
}
return FALSE;
} else if (mtmp->data->msound >= MS_HUMANOID) {
if (!canspotmon(mtmp))
map_invisible(mtmp->mx, mtmp->my);
+ SetVoice(mtmp, 0, 80, 0);
verbalize("I'm hungry.");
} else {
/* this is pretty lame but is better than leaving out the block
}
} break;
case MS_ARREST:
- if (mtmp->mpeaceful)
+ if (mtmp->mpeaceful) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("Just the facts, %s.", flags.female ? "Ma'am" : "Sir");
- else {
+ } else {
static const char *const arrest_msg[3] = {
"Anything you say can be used against you.",
"You're under arrest!", "Stop in the name of the Law!",
if (pline_msg) {
pline("%s %s", Monnam(mtmp), pline_msg);
} else if (mtmp->mcan && verbl_msg_mcan) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize1(verbl_msg_mcan);
} else if (verbl_msg) {
/* more 3.6 tribute */
/* Death talks in CAPITAL LETTERS
and without quotation marks */
char tmpbuf[BUFSZ];
-
pline1(ucase(strcpy(tmpbuf, verbl_msg)));
+ SetVoice((struct monst *) 0, 0, 80, voice_death);
+ sound_speak(tmpbuf);
} else {
+ SetVoice(mtmp, 0, 80, 0);
verbalize1(verbl_msg);
}
}
(void (*)(int32_t, const char *, int32_t)) 0, /* hero_playnotes */
(void (*)(char *, int32_t, int32_t)) 0, /* play_usersound */
(void (*)(int32_t, int32_t, int32_t)) 0, /* ambience */
+ (void (*)(char *, int32_t, int32_t, int32_t, int32_t)) 0, /* verbal */
};
/* The order of these array entries must match the
static void nosound_soundeffect(int32_t, int32_t);
static void nosound_play_usersound(char *, int32_t, int32_t);
static void nosound_ambience(int32_t, int32_t, int32_t);
-{
-}
+static void nosound_verbal(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo);
static void
nosound_init_nhsound(void)
int32_t hero_proximity)
{
}
+
+static void
+nosound_verbal(char *text, int32_t gender, int32_t tone,
+ int32_t vol, int32_t moreinfo)
+{
+}
#endif
#ifdef SND_SOUNDEFFECTS_AUTOMAP
return buf;
}
+#ifdef SND_SPEECH
+#define SPEECHONLY
+#else
+#define SPEECHONLY UNUSED
+#endif
+
+void
+set_voice(struct monst *mtmp SPEECHONLY, int32_t tone SPEECHONLY, int32_t volume SPEECHONLY, int32_t moreinfo SPEECHONLY)
+{
+#ifdef SND_SPEECH
+ int32_t gender = (mtmp && mtmp->female) ? FEMALE : MALE;
+
+ if (gv.voice.nameid)
+ free((genericptr_t) gv.voice.nameid);
+ gv.voice.gender = gender;
+ gv.voice.serialno = mtmp ? mtmp->m_id
+ : ((moreinfo & voice_talking_artifact) != 0) ? 3
+ : ((moreinfo & voice_deity) != 0) ? 4 : 2;
+ gv.voice.tone = tone;
+ gv.voice.volume = volume;
+ gv.voice.moreinfo = moreinfo;
+ gv.voice.nameid = (const char *) 0;
+ gp.pline_flags |= PLINE_SPEECH;
+#endif
+}
+
+void
+sound_speak(const char *text SPEECHONLY)
+{
+#ifdef SND_SPEECH
+ const char *cp1, *cp2;
+ char *cpdst;
+ char buf[BUFSZ + BUFSZ];
+
+ if (!text || (text && *text == '\0'))
+ return;
+ if (iflags.voices && soundprocs.sound_verbal
+ && (soundprocs.sound_triggers & SOUND_TRIGGER_VERBAL)) {
+ cp1 = text;
+ cpdst = buf;
+ cp2 = c_eos(cp1);
+ cp2--; /* last non-NUL */
+ *cpdst = '\0';
+ if ((gp.pline_flags & PLINE_VERBALIZE) != 0) {
+ if (*cp1 == '"')
+ cp1++;
+ if (*cp2 == '"')
+ cp2--;
+ }
+ /* cp1 -> 1st, cp2 -> last non-nul) */
+ if ((unsigned)(cp2 - cp1) < (sizeof buf - 1U)) {
+ while (cp1 <= cp2) {
+ *cpdst = *cp1;
+ cp1++;
+ cpdst++;
+ }
+ *cpdst = '\0';
+ }
+ (*soundprocs.sound_verbal)(buf, gv.voice.gender, gv.voice.tone,
+ gv.voice.volume, gv.voice.moreinfo);
+ }
+#endif
+}
+
/*sounds.c*/
}
if (newlev <= -10) {
You("arrive in heaven.");
+ SetVoice((struct monst *) 0, 0, 80, voice_deity);
verbalize("Thou art early, but we'll admit thee.");
gk.killer.format = NO_KILLER_PREFIX;
Strcpy(gk.killer.name, "went to heaven prematurely");
siblings ? "Their" : "Its",
flags.female ? "mommy" : "daddy", egg->spe ? "." : "?");
} else if (mon->data->mlet == S_DRAGON && !Deaf) {
+ SetVoice(mon, 0, 80, 0);
verbalize("Gleep!"); /* Mything eggs :-) */
}
break;
mhm->damage = 0;
} else {
if (Role_if(PM_HEALER)) {
- if (!Deaf && !(gm.moves % 5))
+ if (!Deaf && !(gm.moves % 5)) {
+ SetVoice(magr, 0, 80, 0);
verbalize("Doc, I can't help you unless you cooperate.");
+ }
mhm->damage = 0;
} else
hitmsg(magr, mattk);
mhm->done = TRUE;
return;
}
- if (Verbose(4, mhitm_ad_dgst) && !Deaf)
+ if (Verbose(4, mhitm_ad_dgst) && !Deaf) {
+ /* Soundeffect? */
+ SetVoice(magr, 0, 80, 0);
verbalize("Burrrrp!");
+ }
mhm->damage = mdef->mhp;
/* Use up amulet of life saving */
if ((obj = mlifesaver(mdef)) != 0)
if (u.uswallow) {
/* can't interrogate hero, don't interrogate engulfer */
- if (!Deaf)
+ if (!Deaf) {
+ SetVoice(guard, 0, 80, 0);
verbalize("What's going on here?");
+ }
if (!spotted)
pline_The("other presence vanishes.");
mongone(guard);
if (U_AP_TYPE == M_AP_OBJECT || u.uundetected) {
if (U_AP_TYPE == M_AP_OBJECT
&& gy.youmonst.mappearance != GOLD_PIECE)
- if (!Deaf)
+ if (!Deaf) {
+ SetVoice(guard, 0, 80, 0);
verbalize("Hey! Who left that %s in here?",
mimic_obj_name(&gy.youmonst));
+ }
/* You're mimicking some object or you're hidden. */
pline("Puzzled, %s turns around and leaves.", mhe(guard));
mongone(guard);
/* [we ought to record whether this this message has already
been given in order to vary it upon repeat visits, but
discarding the monster and its egd data renders that hard] */
- if (Deaf)
+ if (Deaf) {
pline("%s huffs and turns to leave.", noit_Monnam(guard));
- else
+ } else {
+ SetVoice(guard, 0, 80, 0);
verbalize("I'll be back when you're ready to speak to me!");
+ }
mongone(guard);
return;
}
if (!Blind)
pline("%s waves goodbye.", noit_Monnam(guard));
} else {
+ SetVoice(guard, 0, 80, 0);
verbalize(
"Oh, yes, of course. Sorry to have disturbed you.");
}
pline("%s mouths something and looks very angry!",
noit_Monnam(guard));
} else {
+ SetVoice(guard, 0, 80, 0);
verbalize(
"Back from the dead, are you? I'll remedy that!");
}
}
return;
}
- if (Deaf)
+ if (Deaf) {
pline("%s doesn't %srecognize you.", noit_Monnam(guard),
(Blind) ? "" : "appear to ");
- else
+ } else {
+ SetVoice(guard, 0, 80, 0);
verbalize("I don't know you.");
+ }
umoney = money_cnt(gi.invent);
if (!umoney && !hidden_gold(TRUE)) {
- if (Deaf)
+ if (Deaf) {
pline("%s stomps%s.", noit_Monnam(guard),
(Blind) ? "" : " and beckons");
- else
+ } else {
+ SetVoice(guard, 0, 80, 0);
verbalize("Please follow me.");
+ }
} else {
if (!umoney) {
if (Deaf) {
pline("%s glares at you%s.", noit_Monnam(guard),
gi.invent ? "r stuff" : "");
} else {
+ SetVoice(guard, 0, 80, 0);
verbalize("You have hidden gold.");
}
}
noit_Monnam(guard), noit_mhis(guard),
noit_mhis(guard));
} else {
+ SetVoice(guard, 0, 80, 0);
verbalize(
"Most likely all your gold was stolen from this vault.");
+ SetVoice(guard, 0, 80, 0);
verbalize("Please drop that gold and follow me.");
}
EGD(guard)->dropgoldcnt++;
struct monst *mtmp = m_at(nx, ny);
if (mtmp && mtmp != grd) {
- if (!Deaf)
+ if (!Deaf) {
+ SetVoice(grd, 0, 80, 0);
verbalize("Out of my way, scum!");
+ }
if (!rloc(mtmp, RLOC_ERR | RLOC_MSG) || MON_AT(nx, ny))
m_into_limbo(mtmp);
}
return -1; /* teleported guard - treat as monster */
if (egrd->witness) {
- if (!Deaf)
+ if (!Deaf) {
+ SetVoice(grd, 0, 80, 0);
verbalize("How dare you %s that gold, scoundrel!",
(egrd->witness & GD_EATGOLD) ? "consume" : "destroy");
+ }
egrd->witness = 0;
grd->mpeaceful = 0;
return -1;
u_carry_gold ? (!umoney ? "drop that hidden gold and "
: "drop that gold and ")
: "");
+ SetVoice(grd, 0, 80, 0);
if (egrd->dropgoldcnt || !u_carry_gold)
verbalize("I repeat, %s", buf);
else
if (egrd->warncnt == 7) {
m = grd->mx;
n = grd->my;
- if (!Deaf)
+ if (!Deaf) {
+ SetVoice(grd, 0, 80, 0);
verbalize("You've been warned, knave!");
+ }
grd->mpeaceful = 0;
mnexto(grd, RLOC_NOMSG);
levl[m][n].typ = egrd->fakecorr[0].ftyp;
gd_letknow(grd);
return -1;
} else {
- if (!Deaf)
+ if (!Deaf) {
+ SetVoice(grd, 0, 80, 0);
verbalize("Well, begone.");
+ }
egrd->gddone = 1;
return gd_move_cleanup(grd, semi_dead, FALSE);
}
pline("%s holds out %s palm demandingly!",
noit_Monnam(grd), noit_mhis(grd));
} else {
+ SetVoice(grd, 0, 80, 0);
verbalize("Drop all your gold, scoundrel!");
}
return 0;
pline("%s rubs %s hands with enraged delight!",
noit_Monnam(grd), noit_mhis(grd));
} else {
+ SetVoice(grd, 0, 80, 0);
verbalize("So be it, rogue!");
}
grd->mpeaceful = 0;
}
if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) {
if (!egrd->gddone && !rn2(10) && !Deaf && !u.uswallow
- && !(u.ustuck && !sticks(gy.youmonst.data)))
+ && !(u.ustuck && !sticks(gy.youmonst.data))) {
+ SetVoice(grd, 0, 80, 0);
verbalize("Move along!");
+ }
restfakecorr(grd);
return 0; /* didn't move */
}
set_malign(mtmp);
if (!Deaf) {
pline("A voice booms out...");
+ SetVoice(mtmp, 0, 80, 0);
verbalize("So thou thought thou couldst %s me, fool.", verb);
}
}
if (Deaf)
return;
if (mtmp->iswiz) {
- if (!rn2(5)) /* typical bad guy action */
+ if (!rn2(5)) { /* typical bad guy action */
pline("%s laughs fiendishly.", Monnam(mtmp));
- else if (u.uhave.amulet && !rn2(SIZE(random_insult)))
+ } else if (u.uhave.amulet && !rn2(SIZE(random_insult))) {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("Relinquish the amulet, %s!",
random_insult[rn2(SIZE(random_insult))]);
- else if (u.uhp < 5 && !rn2(2)) /* Panic */
+ } else if (u.uhp < 5 && !rn2(2)) { /* Panic */
+ SetVoice(mtmp, 0, 80, 0);
verbalize(rn2(2) ? "Even now thy life force ebbs, %s!"
: "Savor thy breath, %s, it be thy last!",
random_insult[rn2(SIZE(random_insult))]);
- else if (mtmp->mhp < 5 && !rn2(2)) /* Parthian shot */
+ } else if (mtmp->mhp < 5 && !rn2(2)) { /* Parthian shot */
+ SetVoice(mtmp, 0, 80, 0);
verbalize(rn2(2) ? "I shall return." : "I'll be back.");
- else
+ } else {
+ SetVoice(mtmp, 0, 80, 0);
verbalize("%s %s!",
random_malediction[rn2(SIZE(random_malediction))],
random_insult[rn2(SIZE(random_insult))]);
+ }
} else if (is_lminion(mtmp)
&& !(mtmp->isminion && EMIN(mtmp)->renegade)) {
com_pager("angel_cuss"); /* TODO: the Hallucination msg */
#LFLAGS += -lm
#endif # WANT_TESTSOUND
+ifeq "$(HAVE_SNDLIB)" "1"
+ifeq "$(WANT_SPEECH)" "1"
+SNDCFLAGS+= -DSND_SPEECH
+endif # WANT_SPEECH
+endif # HAVE_SNDLIB
+
# HAVE_SNDLIB or NEEDS_SND_USERSOUNDS or NEEDS_SND_SEAUTOMAP
# would have to be set prior to this. Any of them could have
# been set just above, or they could have been set in
SNDLIBSRC = ../sound/macsound/macsound.m
SNDLIBOBJ = macsound.o
LFLAGS += -framework AppKit
+#ifdef WANT_SPEECH
+LFLAGS += -framework AVFoundation
+#endif
endif
#
void NetHackQtBind::qtsound_ambience(int32_t ambienceid UNUSED, int32_t ambience_action UNUSED, int32_t proximity UNUSED)
{
}
+void NetHackQtBind::qtsound_verbal(char *text UNUSED, int32_t gender UNUSED, int32_t tone UNUSED, int32_t vol UNUSED, int32_t moreinfo UNUSED)
+{
+}
#endif
#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
nethack_qt_::NetHackQtBind::qtsound_hero_playnotes,
nethack_qt_::NetHackQtBind::qtsound_play_usersound,
nethack_qt_::NetHackQtBind::qtsound_ambience,
+ nethack_qt_::NetHackQtBind::qtsound_verbal,
};
#endif /* SND_LIB_QTSOUND and !QT_NO_SOUND */
static void qtsound_hero_playnotes(int32_t instrument, const char *str, int32_t volume);
static void qtsound_play_usersound(char *, int32_t, int32_t);
static void qtsound_ambience(int32_t, int32_t, int32_t);
+ static void qtsound_verbal(char *text, int32_t gender, int32_t tone, int32_t vol, int32_t moreinfo);
#endif
private: