Author Topic: Alter Ship Flag  (Read 2562 times)

0 Members and 1 Guest are viewing this topic.

Offline karajorma

  • King Louie - Jungle VIP
  • Administrator
  • 214
    • Karajorma's Freespace FAQ
So....This is largely based on earlier work by FUBAR. All I did is take the code he wanted to add to all the Ship Flag SEXPs (invulnerable, guardian, etc) and condense it down into a single SEXP. Doing this (using a mixture of FUBAR and my code) has two main advantages over the current ship flag SEXPs

1) I can implement FUBARs system for allowing you to apply ship flags to wings or even entire teams who aren't currently in the mission.
2) When new ship flags are added to the code, they can be made to work without needing to add new SEXPs. An addition to a couple of arrays and they'd instantly start working.

Anyway, builds are here and code is attached. Play about with the alter-ship-flag SEXP if you want to try this.

Basically it allows you to use this SEXP

Alter-ship-flag
-Invulnerable
-False (set the ship as no longer invulnerable)
-True (apply this flag to ships who haven't arrived yet)
-Alpha 1
-Beta
-Hostile

Code: [Select]
Index: code/fred2/sexp_tree.cpp
===================================================================
--- code/fred2/sexp_tree.cpp (revision 9244)
+++ code/fred2/sexp_tree.cpp (working copy)
@@ -2641,6 +2641,7 @@
  case OPF_HUD_GAUGE:
  case OPF_SHIP_EFFECT:
  case OPF_ANIMATION_TYPE:
+ case OPF_SHIP_FLAG:
  return 1;
 
  case OPF_SHIP:
@@ -4394,6 +4395,10 @@
  case OPF_MISSION_MOOD:
  list = get_listing_opf_mission_moods();
  break;
+
+ case OPF_SHIP_FLAG:
+ list = get_listing_opf_ship_flags();
+ break;
 
  default:
  Int3();  // unknown OPF code
@@ -5877,8 +5882,24 @@
  return head.next;
 }
 
+sexp_list_item *sexp_tree::get_listing_opf_ship_flags()
+{
+ int i;
+ sexp_list_item head;
+ // object flags
+ for ( i = 0; i < MAX_OBJECT_FLAG_NAMES; i++) {
+ head.add_data_dup(Object_flag_names[i].flag_name);
+ }
+ // ship flags
+ for ( i = 0; i < MAX_SHIP_FLAG_NAMES; i++) {
+ head.add_data_dup(Ship_flag_names[i].flag_name);
+ }
 
+ 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 9244)
+++ code/fred2/sexp_tree.h (working copy)
@@ -268,6 +268,7 @@
  sexp_list_item *get_listing_opf_ship_effect();
  sexp_list_item *get_listing_opf_animation_type();
  sexp_list_item *get_listing_opf_mission_moods();
+ sexp_list_item *get_listing_opf_ship_flags();
 
  int m_mode;
  int item_index;
Index: code/object/object.cpp
===================================================================
--- code/object/object.cpp (revision 9244)
+++ code/object/object.cpp (working copy)
@@ -92,6 +92,18 @@
 //XSTR:ON
 };
 
+obj_flag_name Object_flag_names[] = {
+ {OF_INVULNERABLE, "invulnerable", 1, },
+ {OF_PROTECTED, "protect-ship", 1, },
+ {OF_BEAM_PROTECTED, "beam-protect-ship", 1, },
+ {OF_NO_SHIELDS, "no-shields", 1, },
+ {OF_TARGETABLE_AS_BOMB, "targetable-as-bomb", 1, },
+ {OF_FLAK_PROTECTED, "flak-protect-ship", 1, },
+ {OF_LASER_PROTECTED, "laser-protect-ship", 1, },
+ {OF_MISSILE_PROTECTED, "missile-protect-ship", 1, },
+ {OF_IMMOBILE, "immobile", 1, },
+};
+
 //-----------------------------------------------------------------------------
 // Scan the object list, freeing down to num_used objects
 // Returns number of slots freed.
Index: code/object/object.h
===================================================================
--- code/object/object.h (revision 9244)
+++ code/object/object.h (working copy)
@@ -49,6 +49,7 @@
 #define MAX_OBJECT_TYPES 16
 
 #define UNUSED_OBJNUM (-MAX_OBJECTS*2) // Newer systems use this instead of -1 for invalid object.
+#define TOKEN_LENGTH 32
 
 extern char *Object_type_names[MAX_OBJECT_TYPES];
 
@@ -126,6 +127,15 @@
 #define OF_TEMP_MARKED (1<<30) // Temporarily marked (Fred).
 #define OF_HIDDEN (1<<31) // Object is hidden (not shown) and can't be manipulated
 
+typedef struct obj_flag_name {
+ int flag;
+ char flag_name[TOKEN_LENGTH];
+ int flag_list;
+} obj_flag_name;
+
+#define MAX_OBJECT_FLAG_NAMES 9
+extern obj_flag_name Object_flag_names[];
+
 struct dock_instance;
 
 typedef struct object {
Index: code/parse/sexp.cpp
===================================================================
--- code/parse/sexp.cpp (revision 9244)
+++ code/parse/sexp.cpp (working copy)
@@ -446,6 +446,7 @@
  { "ship-subsys-vanish", OP_SHIP_SUBSYS_VANISHED, 3, INT_MAX }, // FUBAR
  { "ship-subsys-ignore_if_dead", OP_SHIP_SUBSYS_IGNORE_IF_DEAD, 3, INT_MAX }, // FUBAR
  { "awacs-set-radius", OP_AWACS_SET_RADIUS, 3, 3 },
+ { "set-ship-flag", OP_ALTER_SHIP_FLAG, 3, INT_MAX }, // Karajorma
 
  //Cargo Sub-Category
  { "transfer-cargo", OP_TRANSFER_CARGO, 2, 2, },
@@ -2677,6 +2678,32 @@
 
  break;
 
+ case OPF_SHIP_FLAG:
+ {
+ bool found = false;
+ for ( i = 0; i < MAX_OBJECT_FLAG_NAMES; i++) {
+ if (!stricmp(Object_flag_names[i].flag_name, CTEXT(node))) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ for ( i = 0; i < MAX_SHIP_FLAG_NAMES; i++) {
+ if (!stricmp(Ship_flag_names[i].flag_name, CTEXT(node))) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ return SEXP_CHECK_INVALID_SHIP_FLAG;
+ }
+
+ break;
+ }
+
  case OPF_FONT:
  if (type2 != SEXP_ATOM_STRING) {
  return SEXP_CHECK_TYPE_MISMATCH;
@@ -4437,11 +4464,51 @@
  wing *wingp;
  waypoint *waypointp;
  int team;
+
+ void clear();
 }
 object_ship_wing_point_team;
 
+void object_ship_wing_point_team::clear()
+{
+ object_name = NULL;
+ type = OSWPT_TYPE_NONE;
+
+ p_objp = NULL;
+ objp = NULL;
+ shipp = NULL;
+ waypointp = NULL;
+ wingp = NULL;
+ team = -1;
+}
+
+void sexp_object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship *shipp, bool set_parse_flag_too = false);
+void sexp_object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship_obj *so, bool set_parse_flag_too = false);
+void sexp_get_object_ship_wing_point_team(object_ship_wing_point_team *oswpt, char *object_name, bool set_parse_flag_too = false);
+
+void object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship *shipp, bool set_parse_flag_too)
+{
+ oswpt->clear();
+
+ oswpt->shipp = shipp;
+ oswpt->object_name = oswpt->shipp->ship_name;
+ oswpt->objp = &Objects[shipp->objnum];
+ oswpt->type = OSWPT_TYPE_SHIP;
+
+ if (set_parse_flag_too) {
+ oswpt->p_objp = mission_parse_get_arrival_ship(oswpt->object_name);
+ }
+}
+
+
+void object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship_obj *so, bool set_parse_flag_too)
+{
+ object_ship_wing_point_team_set_ship(oswpt, &Ships[Objects[so->objnum].instance], set_parse_flag_too);
+}
+
+
 // Goober5000
-void sexp_get_object_ship_wing_point_team(object_ship_wing_point_team *oswpt, char *object_name)
+void sexp_get_object_ship_wing_point_team(object_ship_wing_point_team *oswpt, char *object_name, bool set_parse_flag_too)
 {
  int team, ship_num, wing_num;
  waypoint *wpt;
@@ -4450,16 +4517,9 @@
  Assert(oswpt != NULL);
  Assert(object_name != NULL);
 
+ oswpt->clear();
  oswpt->object_name = object_name;
- oswpt->type = OSWPT_TYPE_NONE;
 
- oswpt->p_objp = NULL;
- oswpt->objp = NULL;
- oswpt->shipp = NULL;
- oswpt->waypointp = NULL;
- oswpt->wingp = NULL;
- oswpt->team = -1;
-
  if(!stricmp(object_name, SEXP_NONE_STRING))
  {
  oswpt->type = OSWPT_TYPE_NONE;
@@ -4483,6 +4543,10 @@
 
  // if we have a team type, pick the first ship of that team
  team = sexp_determine_team(object_name);
+ if (team == -1) {
+ // try it another way
+ team = iff_lookup(object_name);
+ }
  if (team >= 0)
  {
  for (ship_obj *so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
@@ -4516,7 +4580,9 @@
  oswpt->shipp = &Ships[ship_num];
  oswpt->objp = &Objects[oswpt->shipp->objnum];
 
- return;
+ if (!set_parse_flag_too) {
+ return;
+ }
  }
 
 
@@ -4524,7 +4590,9 @@
  p_objp = mission_parse_get_arrival_ship(object_name);
  if (p_objp != NULL)
  {
- oswpt->type = OSWPT_TYPE_PARSE_OBJECT;
+ if (oswpt->type != OSWPT_TYPE_SHIP) {
+ oswpt->type = OSWPT_TYPE_PARSE_OBJECT;
+ }
 
  oswpt->p_objp = p_objp;
 
@@ -12191,7 +12259,6 @@
  }
 }
 
-// Goober5000
 // generic function for all those sexps that set flags
 void sexp_deal_with_ship_flag(int node, bool process_subsequent_nodes, int object_flag, int object_flag2, int ship_flag, int ship_flag2, int p_object_flag, int p_object_flag2, bool set_it, bool send_multiplayer = false, bool include_players_in_ship_lookup = false)
 {
@@ -12413,6 +12480,383 @@
  }
  }
 }
+
+void sexp_alter_ship_flag_helper(object_ship_wing_point_team &oswpt, bool future_ships, int object_flag, int object_flag2, int ship_flag, int ship_flag2, int parse_obj_flag, int parse_obj_flag2, bool set_flag)
+{
+ ship_obj *so;
+ object_ship_wing_point_team oswpt2;
+ p_object *p_objp;
+
+ switch (oswpt.type)
+ {
+ case OSWPT_TYPE_NONE:
+ case OSWPT_TYPE_EXITED:
+ return;
+
+ case OSWPT_TYPE_TEAM:
+ Assert (oswpt.team >= 0);
+ oswpt2.clear();
+ for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ){
+ if (Ships[Objects[so->objnum].instance].team == oswpt.team) {
+ object_ship_wing_point_team_set_ship(&oswpt2, so, future_ships);
+
+ // recurse
+ sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+ }
+
+ if (future_ships) {
+ for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp)) {
+ if (p_objp->team == oswpt.team) {
+ oswpt2.p_objp = p_objp;
+ oswpt2.type = OSWPT_TYPE_PARSE_OBJECT;
+ sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+ }
+ }
+ break;
+
+ case OSWPT_TYPE_WING:
+ case OSWPT_TYPE_WING_NOT_PRESENT:
+ // if the wing isn't here, and we're only dealing with ships which are, we're done.
+ if  (!future_ships){
+ if (oswpt.type == OSWPT_TYPE_WING_NOT_PRESENT) {
+ return;
+ }
+ }
+ else {
+ for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp)) {
+ if (p_objp->wingnum == WING_INDEX(oswpt.wingp)) {
+ oswpt2.p_objp = p_objp;
+ oswpt2.type = OSWPT_TYPE_PARSE_OBJECT;
+ sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+ }
+ }
+
+ for (int i = 0; i < oswpt.wingp->current_count; i++) {
+ object_ship_wing_point_team_set_ship(&oswpt2, &Ships[oswpt.wingp->ship_index[i]], future_ships);
+ sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+
+ break;
+
+ // finally! If we actually have a ship, we can set its flags!
+ case OSWPT_TYPE_SHIP:
+ // see if we have an object flag to set
+ if (object_flag)
+ {
+ // set or clear?
+ if (set_flag)
+ oswpt.objp->flags |= object_flag;
+ else
+ oswpt.objp->flags &= ~object_flag;
+ }
+
+ // see if we have an object flag2 to set
+ if (object_flag2)
+ {
+ // Add code here when have flag2 settings
+ }
+
+ // see if we have a ship flag to set
+ if (ship_flag)
+ {
+ // set or clear?
+ if (set_flag)
+ oswpt.shipp->flags |= ship_flag;
+ else
+ oswpt.shipp->flags &= ~ship_flag;
+ }
+
+ // see if we have a ship flag2 to set
+ if (ship_flag2)
+ {
+ // set or clear?
+ if (set_flag)
+ oswpt.shipp->flags2 |= ship_flag2;
+ else
+ oswpt.shipp->flags2 &= ~ship_flag2;
+ }
+
+ // the lock afterburner SEXP also needs to set a physics flag
+ if (ship_flag2 == SF2_AFTERBURNER_LOCKED) {
+ if (set_flag) {
+ afterburners_stop(oswpt.objp, 1);
+ }
+ }
+
+ // no break statement. We want to fall through.
+
+ case OSWPT_TYPE_PARSE_OBJECT:
+ if (!future_ships) {
+ return;
+ }
+
+ // see if we have a p_object flag to set
+ if (parse_obj_flag && oswpt.p_objp != NULL)
+ {
+ // set or clear?
+ if (set_flag)
+ oswpt.p_objp->flags |= parse_obj_flag;
+ else
+ oswpt.p_objp->flags &= ~parse_obj_flag;
+ }
+
+ // see if we have a p_object flag2 to set
+ if (parse_obj_flag2 && oswpt.p_objp != NULL)
+ {
+ // set or clear?
+ if (set_flag)
+ oswpt.p_objp->flags2 |= parse_obj_flag2;
+ else
+ oswpt.p_objp->flags2 &= ~parse_obj_flag2;
+ }
+ break;
+
+
+ }
+
+}
+
+void alter_flag_for_all_ships(bool future_ships, int object_flag, int object_flag2, int ship_flag, int ship_flag2, int parse_obj_flag, int parse_obj_flag2, bool set_flag)
+{
+ ship_obj *so;
+ p_object *p_objp;
+ object_ship_wing_point_team oswpt;
+
+ // set all the ships present in the mission
+ for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
+ object_ship_wing_point_team_set_ship(&oswpt, so, future_ships);
+
+ sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+
+ // set up all the ships which have yet to arrive
+ if (future_ships) {
+ oswpt.clear();
+ for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
+ {
+ oswpt.p_objp = p_objp;
+ oswpt.type = OSWPT_TYPE_PARSE_OBJECT;
+ sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+ }
+}
+
+void sexp_alter_ship_flag(int node)
+{
+ char *flag_name;
+ int object_flag = 0;
+ int object_flag2 = 0;
+ int ship_flags = 0;
+ int ship_flags2 = 0;
+ int parse_obj_flag = 0;
+ int parse_obj_flag2 = 0;
+ bool set_flag = false;
+ bool send_multi = false;
+ bool future_ships = false;
+ int i;
+ object_ship_wing_point_team oswpt;
+
+ flag_name = CTEXT(node);
+ for ( i = 0; i < MAX_OBJECT_FLAG_NAMES; i++) {
+ if (!stricmp(Object_flag_names[i].flag_name, flag_name)) {
+ // make sure the list writes to the correct list of flags!
+ if (Object_flag_names[i].flag_list == 1) {
+ object_flag = Object_flag_names[i].flag;
+ }
+ else if (Object_flag_names[i].flag_list == 2) {
+ object_flag2 = Object_flag_names[i].flag;
+ }
+ break;
+ }
+ }
+
+ for ( i = 0; i < MAX_SHIP_FLAG_NAMES; i++) {
+ if (!stricmp(Ship_flag_names[i].flag_name, flag_name)) {
+ // make sure the list writes to the correct list of flags!
+ if (Ship_flag_names[i].flag_list == 1) {
+ ship_flags = Object_flag_names[i].flag;
+ }
+ else if (Ship_flag_names[i].flag_list == 2) {
+ ship_flags2 = Ship_flag_names[i].flag;
+ // only ship flags2 and above need to be sent the game handles the first set of flags elsewhere
+ send_multi = true;
+ }
+ break;
+ }
+ }
+
+ // parse files already have a list of names in the same order as the flags, so we can do something slightly different here.
+ for ( i = 0; i < MAX_PARSE_OBJECT_FLAGS; i++) {
+ if (!stricmp(Parse_object_flags[i], flag_name)) {
+ parse_obj_flag = (1 << i);
+ break;
+ }
+ }
+
+ for ( i = 0; i < MAX_PARSE_OBJECT_FLAGS_2; i++) {
+ if (!stricmp(Parse_object_flags_2[i], flag_name)) {
+ parse_obj_flag2 = (1 << i);
+ break;
+ }
+ }
+
+ node = CDR(node);
+ if (is_sexp_true(node)) {
+ set_flag = true;
+ }
+
+ node = CDR(node);
+ if (is_sexp_true(node)) {
+ future_ships = true;
+ }
+
+
+ // start the multiplayer packet
+ if (send_multi && MULTIPLAYER_MASTER) {
+ multi_start_callback();
+ multi_send_int(object_flag);
+ /* Uncommenting this will break compatibility with earlier builds but it is pointless to send it until object_flag2
+ is actually used by the engine
+ */
+ // multi_send_int(object_flag2);
+ multi_send_int(ship_flags);
+ multi_send_int(ship_flags2);
+ multi_send_int(parse_obj_flag);
+ multi_send_int(parse_obj_flag2);
+ multi_send_bool(set_flag);
+ multi_send_bool(future_ships);
+ }
+
+ node = CDR(node);
+
+ // no 4th argument means do this to every ship in the mission (and if the flag is set, every ship that will be too).
+ if (node == -1) {
+ // send a message to the clients saying there were no more arguments
+ multi_send_bool(false);
+
+ alter_flag_for_all_ships(future_ships, object_flag, object_flag2, ship_flags, ship_flags2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+
+
+ else {
+ // send a message to the clients saying there are more arguments
+ multi_send_bool(true);
+
+ while (node != -1) {
+ sexp_get_object_ship_wing_point_team(&oswpt, CTEXT(node), future_ships);
+
+ // no point in setting these flags at all
+ if (oswpt.type == OSWPT_TYPE_NONE || oswpt.type == OSWPT_TYPE_EXITED ) {
+ node = CDR(node);
+ continue;
+ }
+
+ sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flags, ship_flags2, parse_obj_flag, parse_obj_flag2, set_flag);
+ node = CDR(node);
+
+ multi_send_int(oswpt.type);
+
+ switch (oswpt.type) {
+ case OSWPT_TYPE_SHIP:
+ multi_send_ship(oswpt.shipp);
+ break;
+
+ case OSWPT_TYPE_PARSE_OBJECT:
+ multi_send_parse_object(oswpt.p_objp);
+ break;
+
+ case OSWPT_TYPE_WING_NOT_PRESENT:
+ case OSWPT_TYPE_WING:
+ multi_send_ushort(oswpt.wingp->net_signature);
+ break;
+
+ case OSWPT_TYPE_TEAM:
+ multi_send_int(oswpt.team);
+ break;
+ }
+ }
+ }
+ multi_end_callback();
+}
+
+
+
+void multi_sexp_alter_ship_flag()
+{
+ int object_flag = 0;
+ int object_flag2 = 0;
+ int ship_flag = 0;
+ int ship_flag2 = 0;
+ int parse_obj_flag = 0;
+ int parse_obj_flag2 = 0;
+ bool set_flag = false;
+ bool future_ships = true;
+ bool process_data = false;
+ int type = -1;
+ object_ship_wing_point_team oswpt;
+ ushort wing_sig;
+
+ multi_get_int(object_flag);
+ // multi_get_int(object_flag2);
+ multi_get_int(ship_flag);
+ multi_get_int(ship_flag2);
+ multi_get_int(parse_obj_flag);
+ multi_get_int(parse_obj_flag2);
+ multi_get_bool(set_flag);
+ multi_get_bool(future_ships);
+
+ // if any of the above failed so will this loop
+ if (!multi_get_bool(process_data))
+ {
+ return;
+ }
+
+ // no more data means do this to every ship in the mission
+ if (!process_data) {
+ alter_flag_for_all_ships(future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+ else {
+ while (multi_get_int(type)) {
+ oswpt.clear();
+ oswpt.type = type;
+
+ switch (oswpt.type) {
+ case OSWPT_TYPE_SHIP:
+ multi_get_ship(oswpt.shipp);
+ break;
+
+ case OSWPT_TYPE_PARSE_OBJECT:
+ multi_get_parse_object(oswpt.p_objp);
+ break;
+
+ case OSWPT_TYPE_WING_NOT_PRESENT:
+ case OSWPT_TYPE_WING:
+ multi_get_ushort(wing_sig);
+ for (int i = 0; i < Num_wings; i++) {
+ if (Wings[i].net_signature == wing_sig) {
+ oswpt.wingp = &Wings[i];
+ break;
+ }
+ }
+
+ if (oswpt.wingp == NULL) {
+ Warning(LOCATION, "Unable to get wing to apply flags to in multi_sexp_alter_ship_flag()");
+ }
+ break;
+
+ case OSWPT_TYPE_TEAM:
+ multi_get_int(oswpt.team);
+ break;
+ }
+ sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, set_flag);
+ }
+ }
+}
+
+
 // modified by Goober5000; now it should work properly
 // function to deal with breaking/fixing the warp engines on ships/wings.
 // --repairable is true when we are breaking the warp drive (can be repaired)
@@ -21378,6 +21822,11 @@
  sexp_val = SEXP_TRUE;
  break;
 
+ case OP_ALTER_SHIP_FLAG:
+ sexp_alter_ship_flag(node);
+ sexp_val = SEXP_TRUE;
+ break;
+
  case OP_SHIP_VULNERABLE:
  case OP_SHIP_INVULNERABLE:
  sexp_ships_invulnerable(node, (op_num == OP_SHIP_INVULNERABLE));
@@ -23003,6 +23452,10 @@
  multi_sexp_deal_with_ship_flag();
  break;
 
+ case OP_ALTER_SHIP_FLAG:
+ multi_sexp_alter_ship_flag();
+ break;
+
  case OP_SET_AFTERBURNER_ENERGY:
  multi_sexp_set_energy_pct();
  break;
@@ -23784,6 +24237,7 @@
  case OP_SET_THRUSTERS:
  case OP_SET_PLAYER_THROTTLE_SPEED:
  case OP_DEBUG:
+ case OP_ALTER_SHIP_FLAG:
  return OPR_NULL;
 
  case OP_AI_CHASE:
@@ -24042,6 +24496,14 @@
  case OP_GET_DAMAGE_CAUSED:
  case OP_GET_THROTTLE_SPEED:
  return OPF_SHIP;
+
+ case OP_ALTER_SHIP_FLAG:
+ if(argnum == 0)
+ return OPF_SHIP_FLAG;
+ if(argnum == 1 || argnum == 2)
+ return OPF_BOOL;
+ else
+ return OPF_SHIP_WING_TEAM;
 
  case OP_SET_PLAYER_THROTTLE_SPEED:
  if(argnum == 0)
@@ -26240,6 +26702,9 @@
  case SEXP_CHECK_INVALID_MISSION_MOOD:
  return "Invalid mission mood";
 
+ case SEXP_CHECK_INVALID_SHIP_FLAG:
+ return "Invalid ship flag";
+
  default:
  Warning(LOCATION, "Unhandled sexp error code %d!", num);
  return "Unhandled sexp error code!";
@@ -27113,6 +27578,7 @@
  case OP_SHIP_SUBSYS_VANISHED:
  case OP_SHIP_SUBSYS_IGNORE_IF_DEAD:
  case OP_AWACS_SET_RADIUS:
+ case OP_ALTER_SHIP_FLAG:
  return CHANGE_SUBCATEGORY_SUBSYSTEMS;
 
  case OP_TRANSFER_CARGO:
@@ -29237,6 +29703,14 @@
  "\tCauses the specified hud gauge to flash to draw the player's attention to it.\r\n\r\n"
  "Takes 1 argument...\r\n"
  "\t1:\tName of hud gauge to flash." },
+
+ { OP_ALTER_SHIP_FLAG, "alter-ship-flag\r\n"
+ "\tSets a ships flag and/or parse flag.\r\n\r\n"
+ "Takes 4 or more arguments...\r\n"
+ "\t1:\tShip flag name\r\n"
+ "\t2:\tTrue if turning on, false if turning off\r\n"
+ "\t3:\tTrue\\False - Apply this flag to future waves of this wing. Apply to ship if not present\r\n"
+ "\tRest:\t (optional)Name of ships. If not supplied, will work on all ships in the mission" },
 
  { OP_SHIP_VISIBLE, "ship-visible\r\n"
  "\tCauses the ships listed in this sexpression to be visible with player sensors.\r\n\r\n"
Index: code/parse/sexp.h
===================================================================
--- code/parse/sexp.h (revision 9244)
+++ code/parse/sexp.h (working copy)
@@ -107,6 +107,7 @@
 #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
+#define OPF_SHIP_FLAG 83 // Karajorma - The name of a ship flag
 
 // Operand return types
 #define OPR_NUMBER 1 // returns number
@@ -702,7 +703,8 @@
 #define OP_DEBUG (0x0017 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Karajorma
 #define OP_SET_MISSION_MOOD (0x0018 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Karajorma
 #define OP_NAV_SELECT (0x0019 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Talon1024
-#define OP_NAV_DESELECT (0x0020 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Talon1024
+#define OP_NAV_DESELECT (0x001a | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Talon1024
+#define OP_ALTER_SHIP_FLAG (0x001b | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Karajorma
 
 // defined for AI goals
 #define OP_AI_CHASE (0x0000 | OP_CATEGORY_AI | OP_NONCAMPAIGN_FLAG)
@@ -960,6 +962,7 @@
 #define SEXP_CHECK_INVALID_HUD_GAUGE -153
 #define SEXP_CHECK_INVALID_ANIMATION_TYPE -154
 #define SEXP_CHECK_INVALID_MISSION_MOOD -155
+#define SEXP_CHECK_INVALID_SHIP_FLAG -156
 
 #define TRAINING_CONTEXT_SPEED (1<<0)
 #define TRAINING_CONTEXT_FLY_PATH (1<<1)
Index: code/ship/ship.cpp
===================================================================
--- code/ship/ship.cpp (revision 9244)
+++ code/ship/ship.cpp (working copy)
@@ -355,6 +355,22 @@
  { "capital+", WIF2_CAPITAL_PLUS, 1 }
 };
 
+// Constant for flag, Name of flag, In flags or flags2
+ship_flag_name Ship_flag_names[] = {
+ {SF_VAPORIZE, "vaporize", 1, },
+ {SF_WARP_BROKEN, "afterburners-locked", 1, },
+ {SF_WARP_NEVER, "primaries-locked", 1, },
+ //{SF_HIDDEN_FROM_SENSORS, "hidden-from-sensors", 1, },
+ //{SF2_STEALTH, "stealth", 2, },
+ //{SF2_FRIENDLY_STEALTH_INVIS, "friendly-stealth-invisible", 2, },
+ {SF2_AFTERBURNER_LOCKED, "afterburners-locked", 2, },
+ {SF2_PRIMARIES_LOCKED, "primaries-locked", 2, },
+ {SF2_SECONDARIES_LOCKED, "secondaries-locked", 2, },
+ {SF2_NO_SUBSPACE_DRIVE, "no-subspace-drive", 2, },
+ {SF2_DONT_COLLIDE_INVIS, "don't-collide-invisible", 2, },
+ {SF2_NO_ETS, "no-ets", 2, },
+};
+
 const int num_ai_tgt_weapon_flags = sizeof(ai_tgt_weapon_flags) / sizeof(flag_def_list);
 
 SCP_vector <ai_target_priority> Ai_tp_list;
Index: code/ship/ship.h
===================================================================
--- code/ship/ship.h (revision 9244)
+++ code/ship/ship.h (working copy)
@@ -405,7 +405,16 @@
  float aggregate_current_hits; // current count of hits for all subsystems of this type.
 } ship_subsys_info;
 
+// Karajorma - Used by the alter-ship-flag SEXP as an alternative to having lots of ship flag SEXPs
+typedef struct ship_flag_name {
+ int flag; // the actual ship flag constant as given by the define below
+ char flag_name[TOKEN_LENGTH]; // the name written to the mission file for its corresponding parse_object flag
+ int flag_list; // is this flag in the 1st or 2nd ship flags list?
+} ship_flag_name;
 
+#define MAX_SHIP_FLAG_NAMES 9
+extern ship_flag_name Ship_flag_names[];
+
 // states for the flags variable within the ship structure
 // low bits are for mission file savable flags..
 // FRED needs these to be the low-order bits with no holes,

[attachment deleted by a basterd]
Karajorma's Freespace FAQ. It's almost like asking me yourself.

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

 

Offline mjn.mixael

  • Cutscene Master
  • 212
  • Chopped liver
    • Steam
    • Twitter
afterburners-locked and primaries-locked are both listed twice in FRED on build 9280.
Cutscene Upgrade Project - Mainhall Remakes - Between the Ashes
Youtube Channel - P3D Model Box
Between the Ashes is looking for committed testers, PM me for details.
Freespace Upgrade Project See what's happening.

 

Offline karajorma

  • King Louie - Jungle VIP
  • Administrator
  • 214
    • Karajorma's Freespace FAQ
Interesting, I'll check that.

I hope everyone is enjoying the bigger events window. :D

EDIT : Doh! I see where that mistake came from... I simply copied those two lines multiple times and then went through the parse object flags to correct them to right names. But break-warp and never-warp don't have parse object names since you only set them via SEXP.

Fix will be in the next nightly build (Yay! Been waiting a year to start saying that again!)
« Last Edit: October 25, 2012, 07:27:11 pm by karajorma »
Karajorma's Freespace FAQ. It's almost like asking me yourself.

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