diff options
Diffstat (limited to 'src/uqm/commglue.c')
-rw-r--r-- | src/uqm/commglue.c | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/src/uqm/commglue.c b/src/uqm/commglue.c new file mode 100644 index 0000000..a7b514c --- /dev/null +++ b/src/uqm/commglue.c @@ -0,0 +1,421 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "commglue.h" + +#include "battle.h" + // For instantVictory +#include "races.h" + +#include <stdarg.h> +#include <stdlib.h> +#include <stddef.h> +#include <assert.h> +#include "libs/log.h" + +static int NPCNumberPhrase (int number, const char *fmt, UNICODE **ptrack); + +// The CallbackFunction is queued and executes synchronously +// on the Starcon2Main thread +void +NPCPhrase_cb (int index, CallbackFunction cb) +{ + UNICODE *pStr, buf[400]; + void *pClip, *pTimeStamp; + + switch (index) + { + case GLOBAL_PLAYER_NAME: + pStr = GLOBAL_SIS (CommanderName); + pClip = 0; + pTimeStamp = 0; + break; + case GLOBAL_SHIP_NAME: + pStr = GLOBAL_SIS (ShipName); + pClip = 0; + pTimeStamp = 0; + break; + case 0: + { + return; + } + default: + if (index < 0) + { // One of the alliance name variants + COUNT i; + STRING S; + + index -= GLOBAL_ALLIANCE_NAME; + + i = GET_GAME_STATE (NEW_ALLIANCE_NAME); + S = SetAbsStringTableIndex (CommData.ConversationPhrases, (index - 1) + i); + strcpy (buf, (UNICODE *)GetStringAddress (S)); + if (i == 3) + strcat (buf, GLOBAL_SIS (CommanderName)); + + pStr = buf; + pClip = 0; + pTimeStamp = 0; + } + else + { + pStr = (UNICODE *)GetStringAddress ( + SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) + ); + pClip = GetStringSoundClip ( + SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) + ); + pTimeStamp = GetStringTimeStamp ( + SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) + ); + } + break; + } + + SpliceTrack (pClip, pStr, pTimeStamp, cb); +} + +// Special case variant: prevents page breaks. +void +NPCPhrase_splice (int index) +{ + UNICODE *pStr; + void *pClip; + + assert (index >= 0); + if (index == 0) + return; + + pStr = (UNICODE *)GetStringAddress ( + SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1)); + pClip = GetStringSoundClip ( + SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1)); + + if (!pClip) + { // Just appending some text + SpliceTrack (NULL, pStr, NULL, NULL); + } + else + { // Splicing in some voice + UNICODE *tracks[] = {NULL, NULL}; + + tracks[0] = pClip; + SpliceMultiTrack (tracks, pStr); + } +} + +void +NPCNumber (int number, const char *fmt) +{ + UNICODE buf[32]; + + if (!fmt) + fmt = "%d"; + + if (CommData.AlienNumberSpeech) + { + NPCNumberPhrase (number, fmt, NULL); + return; + } + + // just splice in the subtitle text + snprintf (buf, sizeof buf, fmt, number); + SpliceTrack (NULL, buf, NULL, NULL); +} + +static int +NPCNumberPhrase (int number, const char *fmt, UNICODE **ptrack) +{ +#define MAX_NUMBER_TRACKS 20 + NUMBER_SPEECH speech = CommData.AlienNumberSpeech; + COUNT i; + int queued = 0; + int toplevel = 0; + UNICODE *TrackNames[MAX_NUMBER_TRACKS]; + UNICODE numbuf[60]; + const SPEECH_DIGIT* dig = NULL; + + if (!speech) + return 0; + + if (!ptrack) + { + toplevel = 1; + if (!fmt) + fmt = "%d"; + sprintf (numbuf, fmt, number); + ptrack = TrackNames; + } + + for (i = 0; i < speech->NumDigits; ++i) + { + int quot; + + dig = speech->Digits + i; + quot = number / dig->Divider; + + if (quot == 0) + continue; + quot -= dig->Subtrahend; + if (quot < 0) + continue; + + if (dig->StrDigits) + { + COUNT index; + + assert (quot < 10); + index = dig->StrDigits[quot]; + if (index == 0) + continue; + index -= 1; + + *ptrack++ = GetStringSoundClip (SetAbsStringTableIndex ( + CommData.ConversationPhrases, index + )); + queued++; + } + else + { + int ctracks = NPCNumberPhrase (quot, NULL, ptrack); + ptrack += ctracks; + queued += ctracks; + } + + if (dig->Names != 0) + { + SPEECH_DIGITNAME* name; + + for (name = dig->Names; name->Divider; ++name) + { + if (number % name->Divider <= name->MaxRemainder) + { + *ptrack++ = GetStringSoundClip ( + SetAbsStringTableIndex ( + CommData.ConversationPhrases, name->StrIndex - 1)); + queued++; + break; + } + } + } + else if (dig->CommonNameIndex != 0) + { + *ptrack++ = GetStringSoundClip (SetAbsStringTableIndex ( + CommData.ConversationPhrases, dig->CommonNameIndex - 1)); + queued++; + } + + number %= dig->Divider; + } + + if (toplevel) + { + if (queued == 0) + { // nothing queued, say "zero" + assert (number == 0); + *ptrack++ = GetStringSoundClip (SetAbsStringTableIndex ( + CommData.ConversationPhrases, dig->StrDigits[number] - 1)); + } + *ptrack++ = NULL; // term + + SpliceMultiTrack (TrackNames, numbuf); + } + + return queued; +} + +void +GetAllianceName (UNICODE *buf, RESPONSE_REF name_1) +{ + COUNT i; + STRING S; + + i = GET_GAME_STATE (NEW_ALLIANCE_NAME); + S = SetAbsStringTableIndex (CommData.ConversationPhrases, (name_1 - 1) + i); + // XXX: this should someday be changed so that the function takes + // the buffer size as an argument + strcpy (buf, (UNICODE *)GetStringAddress (S)); + if (i == 3) + { + strcat (buf, GLOBAL_SIS (CommanderName)); + strcat (buf, (UNICODE *)GetStringAddress (SetRelStringTableIndex (S, 1))); + } +} + +void +construct_response (UNICODE *buf, int R /* promoted from RESPONSE_REF */, ...) +{ + UNICODE *buf_start = buf; + UNICODE *name; + va_list vlist; + + va_start (vlist, R); + + do + { + COUNT len; + STRING S; + + S = SetAbsStringTableIndex (CommData.ConversationPhrases, R - 1); + + strcpy (buf, (UNICODE *)GetStringAddress (S)); + + len = strlen (buf); + + buf += len; + + name = va_arg (vlist, UNICODE *); + + if (name) + { + len = strlen (name); + strcpy (buf, name); + buf += len; + + /* + if ((R = va_arg (vlist, RESPONSE_REF)) == (RESPONSE_REF)-1) + name = 0; + */ + + R = va_arg(vlist, int); + if (R == ((RESPONSE_REF) -1)) + name = 0; + } + } while (name); + va_end (vlist); + + *buf = '\0'; + + // XXX: this should someday be changed so that the function takes + // the buffer size as an argument + if ((buf_start == shared_phrase_buf) && + (buf > shared_phrase_buf + sizeof (shared_phrase_buf))) + { + log_add (log_Fatal, "Error: shared_phrase_buf size exceeded," + " please increase!\n"); + exit (EXIT_FAILURE); + } +} + +void +setSegue (Segue segue) +{ + switch (segue) + { + case Segue_peace: + SET_GAME_STATE (BATTLE_SEGUE, 0); + break; + case Segue_hostile: + SET_GAME_STATE (BATTLE_SEGUE, 1); + break; + case Segue_victory: + instantVictory = TRUE; + SET_GAME_STATE (BATTLE_SEGUE, 1); + break; + case Segue_defeat: + SET_GAME_STATE (BATTLE_SEGUE, 0); + GLOBAL_SIS(CrewEnlisted) = (COUNT)~0; + GLOBAL(CurrentActivity) |= CHECK_RESTART; + break; + } +} + +Segue +getSegue (void) +{ + if (GET_GAME_STATE(BATTLE_SEGUE) == 0) { + if (GLOBAL_SIS(CrewEnlisted) == (COUNT)~0 && + (GLOBAL(CurrentActivity) & CHECK_RESTART)) { + return Segue_defeat; + } else { + return Segue_peace; + } + } else /* GET_GAME_STATE(BATTLE_SEGUE) == 1) */ { + if (instantVictory) { + return Segue_victory; + } else { + return Segue_hostile; + } + } +} + +LOCDATA* +init_race (CONVERSATION comm_id) +{ + switch (comm_id) + { + case ARILOU_CONVERSATION: + return init_arilou_comm (); + case BLACKURQ_CONVERSATION: + return init_blackurq_comm (); + case CHMMR_CONVERSATION: + return init_chmmr_comm (); + case COMMANDER_CONVERSATION: + if (!GET_GAME_STATE (STARBASE_AVAILABLE)) + return init_commander_comm (); + else + return init_starbase_comm (); + case DRUUGE_CONVERSATION: + return init_druuge_comm (); + case ILWRATH_CONVERSATION: + return init_ilwrath_comm (); + case MELNORME_CONVERSATION: + return init_melnorme_comm (); + case MYCON_CONVERSATION: + return init_mycon_comm (); + case ORZ_CONVERSATION: + return init_orz_comm (); + case PKUNK_CONVERSATION: + return init_pkunk_comm (); + case SHOFIXTI_CONVERSATION: + return init_shofixti_comm (); + case SLYLANDRO_CONVERSATION: + return init_slyland_comm (); + case SLYLANDRO_HOME_CONVERSATION: + return init_slylandro_comm (); + case SPATHI_CONVERSATION: + if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) + return init_spathi_comm (); + else + return init_spahome_comm (); + case SUPOX_CONVERSATION: + return init_supox_comm (); + case SYREEN_CONVERSATION: + return init_syreen_comm (); + case TALKING_PET_CONVERSATION: + return init_talkpet_comm (); + case THRADD_CONVERSATION: + return init_thradd_comm (); + case UMGAH_CONVERSATION: + return init_umgah_comm (); + case URQUAN_CONVERSATION: + return init_urquan_comm (); + case UTWIG_CONVERSATION: + return init_utwig_comm (); + case VUX_CONVERSATION: + return init_vux_comm (); + case YEHAT_REBEL_CONVERSATION: + return init_rebel_yehat_comm (); + case YEHAT_CONVERSATION: + return init_yehat_comm (); + case ZOQFOTPIK_CONVERSATION: + return init_zoqfot_comm (); + default: + return init_chmmr_comm (); + } +} |