Author Topic: Builtin Messages Overhaul  (Read 5643 times)

0 Members and 1 Guest are viewing this topic.

Offline Spoon

  • 212
  • ヾ(´︶`♡)ノ
Re: Builtin Messages Overhaul
Well the difference is that the VN parts are all pre set with variables and stuff.
This feature seems more about setting the mood for in mission persona's so they don't blab out at the most inappropriate moments.
Urutorahappī!!

[02:42] <@Axem> spoon somethings wrong
[02:42] <@Axem> critically wrong
[02:42] <@Axem> im happy with these missions now
[02:44] <@Axem> well
[02:44] <@Axem> with 2 of them

  

Offline karajorma

  • King Louie - Jungle VIP
  • Administrator
  • 214
    • Karajorma's Freespace FAQ
Re: Builtin Messages Overhaul
Okay boys and girls, here's a test build to play with. I'll go over how things work.

First you have to declare your list of moods in message.tbl. This goes between the #Message Frequencies (or top of the table if you don't have those) and #Personas sections.

Code: [Select]
;; This is a list of moods that the game will use for builtin
;; messages. Any message without a mood is treated as General

#Moods

$Mood: Happy
$Mood: Angry
$Mood: Vengeful

#End


#Personas


Next you have to define a mood for some or all of the messages in your table. Messages may remain with the default mood if you wish. You can also define a list of moods for which a message may not be played.

Code: [Select]

$Name: Attack Target
$Message: XSTR("Roger that, sir. Engaging your target.", 2737)
+Persona: Wingman 1
+Avi Name: Head-TP1
+Wave Name: 1_attack.wav

$Name: Attack Target
$Message: XSTR("Yes sir, I'll make the bastards pay for Capella!", 2737)
+Persona: Wingman 1
+Avi Name: Head-TP1
+Wave Name: 1_attack.wav
$Mood: Vengeful
$Exclude Mood: ( "Happy" )

$Name: Attack Target
$Message: XSTR("Yes sir. I just love killing Shivans!", 2737)
+Persona: Wingman 1
+Avi Name: Head-TP1
+Wave Name: 1_attack.wav
$Mood: Angry
$Exclude Mood: ( "Angry" "Vengeful" )


Builtin messages are selected by these criteria

1) If there is a message (or messages) for this persona that matches the mood (including no mood set) - one of those will be sent.
2) If there is no message that matches the mood, any message that isn't on the excluded list for this persona will be sent.
3) If only excluded messages for this persona match, one of those will be sent.
4) If there is no message from this persona, a matching message from any ship of the same species will be sent.
5) If that fails, any builtin message at all which is of the right type will be sent.

in cases 3-5 a message is written to the debug log.

You can change the mission mood using the new set-mission-mood SEXP.

Here's the code.
Code: [Select]
Index: code/fred2/sexp_tree.cpp
===================================================================
--- code/fred2/sexp_tree.cpp (revision 9214)
+++ code/fred2/sexp_tree.cpp (working copy)
@@ -2758,6 +2758,12 @@
  else
  return 0;
 
+ case OPF_MISSION_MOOD:
+ if (Builtin_moods.empty())
+ return 0;
+ else
+ return 1;
+
  default:
  Int3();
 
@@ -4385,6 +4391,10 @@
  list = get_listing_opf_ship_effect();
  break;
 
+ case OPF_MISSION_MOOD:
+ list = get_listing_opf_mission_moods();
+ break;
+
  default:
  Int3();  // unknown OPF code
  list = NULL;
@@ -5857,6 +5867,18 @@
  return head.next;
 }
 
+sexp_list_item *sexp_tree::get_listing_opf_mission_moods()
+{
+ sexp_list_item head;
+ for (SCP_vector<SCP_string>::iterator iter = Builtin_moods.begin(); iter != Builtin_moods.end(); ++iter) {
+ head.add_data_dup(iter->c_str());
+ }
+
+ return head.next;
+}
+
+
+
 // Deletes sexp_variable from sexp_tree.
 // resets tree to not include given variable, and resets text and type
 void sexp_tree::delete_sexp_tree_variable(const char *var_name)
Index: code/fred2/sexp_tree.h
===================================================================
--- code/fred2/sexp_tree.h (revision 9214)
+++ code/fred2/sexp_tree.h (working copy)
@@ -267,6 +267,7 @@
  sexp_list_item *get_listing_opf_hud_gauge();
  sexp_list_item *get_listing_opf_ship_effect();
  sexp_list_item *get_listing_opf_animation_type();
+ sexp_list_item *get_listing_opf_mission_moods();
 
  int m_mode;
  int item_index;
Index: code/mission/missionmessage.cpp
===================================================================
--- code/mission/missionmessage.cpp (revision 9214)
+++ code/mission/missionmessage.cpp (working copy)
@@ -35,6 +35,8 @@
 #include "network/multiutil.h"
 #include "mod_table/mod_table.h"
 
+SCP_vector<SCP_string> Builtin_moods;
+int Current_mission_mood;
 
 int Valid_builtin_message_types[MAX_BUILTIN_MESSAGE_TYPES];
 // here is the list of the builtin message names and the settings which control how frequently
@@ -417,6 +419,49 @@
  }
  }
 
+ if ( optional_string("$Mood:")) {
+ SCP_string buf;
+ bool found = false;
+
+ stuff_string(buf, F_NAME);
+ for (SCP_vector<SCP_string>::iterator iter = Builtin_moods.begin(); iter != Builtin_moods.end(); ++iter) {
+ if (iter->compare(buf) == 0) {
+ msg.mood = iter - Builtin_moods.begin();
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ // found a mood, but it's not in the list of moods at the start of the table
+ Warning(LOCATION, "Message.tbl has an entry for mood type %s, but this mood is not in the #Moods section of the table.", buf.c_str());
+ }
+ }
+ else {
+ msg.mood = 0;
+ }
+
+ if ( optional_string("$Exclude Mood:")) {
+ SCP_vector<SCP_string> buff;
+ bool found = false;
+
+ stuff_string_list(buff);
+ for (SCP_vector<SCP_string>::iterator parsed_moods = buff.begin(); parsed_moods != buff.end(); ++parsed_moods) {
+ for (SCP_vector<SCP_string>::iterator iter = Builtin_moods.begin(); iter != Builtin_moods.end(); ++iter) {
+ if (!stricmp(iter->c_str(), parsed_moods->c_str())) {
+ msg.excluded_moods.push_back(iter - Builtin_moods.begin());
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ // found a mood, but it's not in the list of moods at the start of the table
+ Warning(LOCATION, "Message.tbl has an entry for exclude mood type %s, but this mood is not in the #Moods section of the table.", parsed_moods->c_str());
+ }
+ }
+ }
+
  Num_messages++;
  Messages.push_back(msg);
 }
@@ -464,6 +509,21 @@
  }
 }
 
+void message_moods_parse()
+{
+
+ while (required_string_either("#End", "$Mood:")){
+ SCP_string buf;
+
+ required_string("$Mood:");
+ stuff_string(buf, F_NAME);
+
+ Builtin_moods.push_back(buf);
+ }
+
+ required_string("#End");
+}
+
 void parse_msgtbl()
 {
  int i, j;
@@ -499,11 +559,17 @@
 
  // now we can start parsing
  if (optional_string("#Message Frequencies")) {
- while ( required_string_either("#Personas", "$Name:")) {
+ while (!required_string_3("#Personas", "#Moods", "$Name:")) {
  message_frequency_parse();
  }
  }
 
+ Builtin_moods.push_back("Default");
+ if (optional_string("#Moods")) {
+ message_moods_parse();
+ }
+
+
  required_string("#Personas");
  while ( required_string_either("#Messages", "$Persona:")){
  persona_parse();
@@ -600,6 +666,8 @@
  table_read = 1;
  }
 
+ Current_mission_mood = 0;
+
  // reset the number of messages that we have for this mission
  Num_messages = Num_builtin_messages;
  Num_message_avis = Num_builtin_avis;
@@ -1816,9 +1884,12 @@
  nprintf (("messaging", "Couldn't find message id %s to send to player!\n", id ));
 }
 
-#define BUILTIN_MATCHES_TYPE 0
-#define BUILTIN_MATCHES_SPECIES 1
-#define BUILTIN_MATCHES_EXACTLY 2
+#define BUILTIN_MATCHES_TYPE 0
+#define BUILTIN_MATCHES_SPECIES 1
+#define BUILTIN_MATCHES_PERSONA_CHECK_MOOD 2
+#define BUILTIN_MATCHES_PERSONA_EXCLUDED 3
+#define BUILTIN_MATCHES_PERSONA 4
+#define BUILTIN_MATCHES_PERSONA_MOOD 5
 
 typedef struct matching_builtin {
  int type_of_match;
@@ -1911,9 +1982,28 @@
  // NOTE: doesn't need to be nested under the species condition above
  if ( (persona_index >= 0) && (Messages[i].persona_index == persona_index) ) {
  // condition 3: type + species + persona index match
- current_builtin->type_of_match =  BUILTIN_MATCHES_EXACTLY;
+ current_builtin->type_of_match =  BUILTIN_MATCHES_PERSONA_CHECK_MOOD;
  }
 
+ // check if the personas mood suits this particular message, first check if it is excluded
+ if (!Messages[i].excluded_moods.empty() && (current_builtin->type_of_match ==  BUILTIN_MATCHES_PERSONA_CHECK_MOOD)) {
+ for (SCP_vector<int>::iterator iter = Messages[i].excluded_moods.begin(); iter != Messages[i].excluded_moods.end(); ++iter) {
+ if (*iter == Current_mission_mood) {
+ current_builtin->type_of_match =  BUILTIN_MATCHES_PERSONA_EXCLUDED;
+ break;
+ }
+ }
+ }
+
+ if (current_builtin->type_of_match ==  BUILTIN_MATCHES_PERSONA_CHECK_MOOD) {
+ if (Current_mission_mood == Messages[i].mood) {
+ current_builtin->type_of_match =  BUILTIN_MATCHES_PERSONA_MOOD;
+ }
+ else {
+ current_builtin->type_of_match =  BUILTIN_MATCHES_PERSONA;
+ }
+ }
+
  if (current_builtin->type_of_match == best_match) {
  num_matching_builtins++;
  }
@@ -1928,14 +2018,17 @@
  }
  }
 
- if (best_match == BUILTIN_MATCHES_SPECIES) {
- nprintf(("messaging", "Couldn't find builtin message %s for persona %d\n", Builtin_messages[type].name, persona_index ));
- nprintf(("messaging", "using a message for any persona of that species\n"));
+ if (best_match == BUILTIN_MATCHES_PERSONA_EXCLUDED) {
+ mprintf(("MESSAGING", "Couldn't find builtin message %s for persona %d with a none excluded mood\n", Builtin_messages[type].name, persona_index ));
+ mprintf(("MESSAGING", "using an excluded message for this persona\n"));
+ }else if (best_match == BUILTIN_MATCHES_SPECIES) {
+ mprintf(("MESSAGING", "Couldn't find builtin message %s for persona %d\n", Builtin_messages[type].name, persona_index ));
+ mprintf(("MESSAGING", "using a message for any persona of that species\n"));
  } else if (best_match == BUILTIN_MATCHES_TYPE) {
- nprintf(("messaging", "Couldn't find builtin message %s for persona %d\n", Builtin_messages[type].name, persona_index ));
- nprintf(("messaging", "looking for message for any persona of any species\n"));
+ mprintf(("MESSAGING", "Couldn't find builtin message %s for persona %d\n", Builtin_messages[type].name, persona_index ));
+ mprintf(("MESSAGING", "looking for message for any persona of any species\n"));
  } else if (best_match < 0) {
- nprintf(("messaging", "Couldn't find any builtin message of type %d\n", type ));
+ mprintf(("MESSAGING", "Couldn't find any builtin message of type %d\n", type ));
  Int3();
  return;
  }
Index: code/mission/missionmessage.h
===================================================================
--- code/mission/missionmessage.h (revision 9214)
+++ code/mission/missionmessage.h (working copy)
@@ -63,6 +63,9 @@
  int min_delay;
 } builtin_message;
 
+extern SCP_vector<SCP_string> Builtin_moods;
+extern int Current_mission_mood;
+
 // this number in this define should match the number of elements in the next array
 #define MAX_BUILTIN_MESSAGE_TYPES 45
 
@@ -119,6 +122,8 @@
  char message[MESSAGE_LENGTH]; // actual message
  int persona_index; // which persona says this message
  int multi_team; // multiplayer team filter (important for TvT only)
+ int mood;
+ SCP_vector<int> excluded_moods;
 
  // unions for avi/wave information.  Because of issues with Fred, we are using
  // the union to specify either the index into the avi or wave arrays above,
Index: code/parse/sexp.cpp
===================================================================
--- code/parse/sexp.cpp (revision 9214)
+++ code/parse/sexp.cpp (working copy)
@@ -343,8 +343,10 @@
  { "disable-builtin-messages", OP_DISABLE_BUILTIN_MESSAGES, 0, INT_MAX,}, // Karajorma
  { "enable-builtin-messages", OP_ENABLE_BUILTIN_MESSAGES, 0, INT_MAX,}, // Karajorma
  { "set-persona", OP_SET_PERSONA, 2, INT_MAX,}, // Karajorma
- { "set-death-message", OP_SET_DEATH_MESSAGE, 1, 1 }, // Goober5000
+ { "set-death-message", OP_SET_DEATH_MESSAGE, 1, 1 }, // Goober5000
+ { "set-mission-mood", OP_SET_MISSION_MOOD, 1, 1 }, // Karajorma
 
+
  //AI Control Sub-Category
  { "add-goal", OP_ADD_GOAL, 2, 2, },
  { "remove-goal", OP_REMOVE_GOAL, 2, 2, }, // Goober5000
@@ -2656,6 +2658,23 @@
  }
  break;
 
+ case OPF_MISSION_MOOD:
+ if (type2 != SEXP_ATOM_STRING) {
+ return SEXP_CHECK_TYPE_MISMATCH;
+ }
+
+ for (i = 0; i < (int)Builtin_moods.size(); i++) {
+ if (!strcmp(Builtin_moods[i].c_str(), CTEXT(node))) {
+ break;
+ }
+ }
+
+ if (i == Builtin_moods.size()) {
+ return SEXP_CHECK_INVALID_MISSION_MOOD;
+ }
+
+ break;
+
  case OPF_FONT:
  if (type2 != SEXP_ATOM_STRING) {
  return SEXP_CHECK_TYPE_MISMATCH;
@@ -2977,8 +2996,7 @@
  if (get_effect_from_name(CTEXT(node)) == -1 ) {
  return SEXP_CHECK_INVALID_SHIP_EFFECT;
  }
- break;
-
+ break;
 
  default:
  Error(LOCATION, "Unhandled argument format");
@@ -12575,6 +12593,21 @@
  }
 }
 
+void sexp_set_mission_mood (int node)
+{
+ char *mood;
+
+ mood = CTEXT(node);
+ for (SCP_vector<SCP_string>::iterator iter = Builtin_moods.begin(); iter != Builtin_moods.end(); ++iter) {
+ if (!strcmp(iter->c_str(), mood)) {
+ Current_mission_mood = iter - Builtin_moods.begin();
+ return;
+ }
+ }
+
+ Warning(LOCATION, "Sexp-mission-mood attempted to set mood %s which does not exist in messages.tbl", mood);
+}
+
 int sexp_weapon_fired_delay(int node, int op_num)
 {
  ship *shipp;
@@ -21579,6 +21612,11 @@
  sexp_val = SEXP_TRUE;
  break;
 
+ case OP_SET_MISSION_MOOD:
+ sexp_set_mission_mood (node);
+ sexp_val = SEXP_TRUE;
+ break;
+
  case OP_SEND_MESSAGE_LIST:
  sexp_send_message_list(node);
  sexp_val = SEXP_TRUE;
@@ -23677,6 +23715,7 @@
  case OP_UNLOCK_AFTERBURNER:
  case OP_RESET_ORDERS:
  case OP_SET_PERSONA:
+ case OP_SET_MISSION_MOOD:
  case OP_CHANGE_SUBSYSTEM_NAME:
  case OP_SET_RESPAWNS:
  case OP_SET_AFTERBURNER_ENERGY:
@@ -24615,6 +24654,9 @@
  else
  return OPF_SHIP;
 
+ case OP_SET_MISSION_MOOD:
+ return OPF_MISSION_MOOD;
+
  case OP_SELF_DESTRUCT:
  return OPF_SHIP;
 
@@ -26153,6 +26195,9 @@
  case SEXP_CHECK_INVALID_ANIMATION_TYPE:
  return "Invalid animation type";
 
+ case SEXP_CHECK_INVALID_MISSION_MOOD:
+ return "Invalid mission mood";
+
  default:
  Warning(LOCATION, "Unhandled sexp error code %d!", num);
  return "Unhandled sexp error code!";
@@ -26925,6 +26970,7 @@
  case OP_DISABLE_BUILTIN_MESSAGES:
  case OP_SET_DEATH_MESSAGE:
  case OP_SET_PERSONA:
+ case OP_SET_MISSION_MOOD:
  return CHANGE_SUBCATEGORY_MESSAGING;
 
 
@@ -28338,6 +28384,12 @@
  "\tAll:\tName of ship to be silenced." },
 
  // Karajorma
+ { OP_SET_MISSION_MOOD, "set Mission Mood (Action operator)\r\n"
+ "\tSets the mood of the mission, this affects the choice of builtin messages sent by wingmen\r\n"
+ "Takes 1 argument...\r\n"
+ "\t1:\tMission mood (from messages.tbl) to use." },
+
+ // Karajorma
  { OP_SET_PERSONA, "Set Persona (Action operator)\r\n"
  "\tSets the persona of the supplied ship to the persona supplied\r\n"
  "Takes 2 or more arguments...\r\n"
Index: code/parse/sexp.h
===================================================================
--- code/parse/sexp.h (revision 9214)
+++ code/parse/sexp.h (working copy)
@@ -106,6 +106,7 @@
 #define OPF_DAMAGE_TYPE 79 // FUBAR - Damage type or <none>
 #define OPF_SHIP_EFFECT 80 // The E - per-ship effects, as defined in post-processing.tbl
 #define OPF_ANIMATION_TYPE 81 // Goober5000 - as defined in modelanim.h
+#define OPF_MISSION_MOOD 82 // Karajorma - Moods determine which builtin messages will be sent
 
 // Operand return types
 #define OPR_NUMBER 1 // returns number
@@ -699,6 +700,7 @@
 #define OP_DESTROY_INSTANTLY (0x0015 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Admiral MS
 #define OP_DESTROY_SUBSYS_INSTANTLY (0x0016 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Admiral MS
 #define OP_DEBUG (0x0017 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Karajorma
+#define OP_SET_MISSION_MOOD (0x0018 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Karajorma
 
 
 // defined for AI goals
@@ -956,6 +958,7 @@
 #define SEXP_CHECK_INVALID_AUDIO_VOLUME_OPTION -152
 #define SEXP_CHECK_INVALID_HUD_GAUGE -153
 #define SEXP_CHECK_INVALID_ANIMATION_TYPE -154
+#define SEXP_CHECK_INVALID_MISSION_MOOD -155
 
 #define TRAINING_CONTEXT_SPEED (1<<0)
 #define TRAINING_CONTEXT_FLY_PATH (1<<1)
« Last Edit: September 20, 2012, 03:14:21 am by karajorma »
Karajorma's Freespace FAQ. It's almost like asking me yourself.

[ Diaspora ] - [ Seeds Of Rebellion ] - [ Mind Games ]

 

Offline z64555

  • 210
  • Self-proclaimed controls expert
    • Minecraft
    • Steam
Re: Builtin Messages Overhaul
Maybe split/move this into test builds? Not sure what the MO is here...  :nervous:
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

 

Offline karajorma

  • King Louie - Jungle VIP
  • Administrator
  • 214
    • Karajorma's Freespace FAQ
Re: Builtin Messages Overhaul
I've updated the builds slightly. All messages which don't define a mood now automatically are given the mood "Default". This means that they can easily be excluded.
Karajorma's Freespace FAQ. It's almost like asking me yourself.

[ Diaspora ] - [ Seeds Of Rebellion ] - [ Mind Games ]