FS2_Open
Open source remastering of the Freespace 2 engine
sexp.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 // Parse a symbolic expression.
13 // These are identical to Lisp functions.
14 // It uses a very baggy format, allocating 16 characters per token, regardless
15 // of how many are used.
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <assert.h>
22 #include <limits.h>
23 #if defined _MSC_VER && _MSC_VER < 1600
24  #include "globalincs/msvc/stdint.h"
25 #else
26  #include <stdint.h>
27 #endif
28 
29 #include "ai/aigoals.h"
30 #include "asteroid/asteroid.h"
31 #include "autopilot/autopilot.h"
32 #include "camera/camera.h"
33 #include "cmdline/cmdline.h"
34 #include "debugconsole/console.h"
35 #include "fireball/fireballs.h" // for explosion stuff
36 #include "freespace2/freespace.h"
38 #include "gamesnd/eventmusic.h" // for change-soundtrack
39 #include "gamesnd/gamesnd.h"
40 #include "globalincs/alphacolors.h"
41 #include "globalincs/linklist.h"
42 #include "globalincs/systemvars.h"
43 #include "globalincs/version.h"
44 #include "graphics/2d.h"
45 #include "graphics/font.h"
46 #include "hud/hud.h"
47 #include "hud/hudartillery.h"
48 #include "hud/hudconfig.h"
49 #include "hud/hudescort.h"
50 #include "hud/hudets.h"
51 #include "hud/hudmessage.h"
52 #include "hud/hudparse.h"
53 #include "hud/hudshield.h"
54 #include "hud/hudsquadmsg.h" // for the order sexp
55 #include "iff_defs/iff_defs.h"
56 #include "io/keycontrol.h"
57 #include "io/timer.h"
58 #include "jumpnode/jumpnode.h"
59 #include "localization/localize.h"
60 #include "math/fvi.h"
61 #include "menuui/techmenu.h" // for intel stuff
64 #include "mission/missiongoals.h"
65 #include "mission/missionlog.h"
66 #include "mission/missionmessage.h"
67 #include "mission/missionparse.h" // for p_object definition
69 #include "missionui/redalert.h"
70 #include "mod_table/mod_table.h"
71 #include "nebula/neb.h"
72 #include "nebula/neblightning.h"
73 #include "network/multi.h"
74 #include "network/multi_obj.h"
75 #include "network/multi_sexp.h"
76 #include "network/multi_team.h"
77 #include "network/multimsgs.h"
78 #include "network/multiutil.h"
79 #include "object/objcollide.h"
80 #include "object/objectdock.h"
81 #include "object/objectshield.h"
82 #include "object/objectsnd.h"
83 #include "object/waypoint.h"
84 #include "parse/generic_log.h"
85 #include "parse/lua.h"
86 #include "parse/parselo.h"
87 #include "parse/scripting.h"
88 #include "parse/sexp.h"
89 #include "playerman/player.h"
90 #include "render/3d.h"
91 #include "ship/afterburner.h"
92 #include "ship/awacs.h"
93 #include "ship/ship.h"
94 #include "ship/shiphit.h"
95 #include "sound/audiostr.h"
96 #include "sound/ds.h"
97 #include "sound/sound.h"
98 #include "starfield/starfield.h"
99 #include "starfield/supernova.h"
100 #include "stats/medals.h"
101 #include "weapon/beam.h"
102 #include "weapon/emp.h"
103 #include "weapon/shockwave.h"
104 #include "weapon/weapon.h"
105 
106 #ifndef NDEBUG
107 #include "hud/hudmessage.h"
108 #endif
109 
110 
111 
112 
113 
114 #define TRUE 1
115 #define FALSE 0
116 
117 
119 // Operator, Identity, Min / Max arguments
120  //Arithmetic Category
121  { "+", OP_PLUS, 2, INT_MAX, SEXP_ARITHMETIC_OPERATOR, },
122  { "-", OP_MINUS, 2, INT_MAX, SEXP_ARITHMETIC_OPERATOR, },
123  { "*", OP_MUL, 2, INT_MAX, SEXP_ARITHMETIC_OPERATOR, },
124  { "/", OP_DIV, 2, INT_MAX, SEXP_ARITHMETIC_OPERATOR, },
125  { "mod", OP_MOD, 2, INT_MAX, SEXP_ARITHMETIC_OPERATOR, },
126  { "rand", OP_RAND, 2, 3, SEXP_ARITHMETIC_OPERATOR, },
127  { "rand-multiple", OP_RAND_MULTIPLE, 2, 3, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
128  { "abs", OP_ABS, 1, 1, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
129  { "min", OP_MIN, 1, INT_MAX, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
130  { "max", OP_MAX, 1, INT_MAX, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
131  { "avg", OP_AVG, 1, INT_MAX, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
132  { "pow", OP_POW, 2, 2, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
133  { "signum", OP_SIGNUM, 1, 1, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
134  { "set-bit", OP_SET_BIT, 2, 2, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
135  { "unset-bit", OP_UNSET_BIT, 2, 2, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
136  { "is-bit-set", OP_IS_BIT_SET, 2, 2, SEXP_BOOLEAN_OPERATOR, }, // Goober5000
137  { "bitwise-and", OP_BITWISE_AND, 2, INT_MAX, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
138  { "bitwise-or", OP_BITWISE_OR, 2, INT_MAX, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
139  { "bitwise-not", OP_BITWISE_NOT, 1, 1, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
140  { "bitwise-xor", OP_BITWISE_XOR, 2, 2, SEXP_ARITHMETIC_OPERATOR, }, // Goober5000
141 
142  //Logical Category
143  { "true", OP_TRUE, 0, 0, SEXP_BOOLEAN_OPERATOR, },
144  { "false", OP_FALSE, 0, 0, SEXP_BOOLEAN_OPERATOR, },
145  { "and", OP_AND, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
146  { "and-in-sequence", OP_AND_IN_SEQUENCE, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
147  { "or", OP_OR, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
148  { "not", OP_NOT, 1, 1, SEXP_BOOLEAN_OPERATOR, },
149  { "xor", OP_XOR, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Goober5000
150  { "=", OP_EQUALS, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
151  { "!=", OP_NOT_EQUAL, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Goober5000
152  { ">", OP_GREATER_THAN, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
153  { ">=", OP_GREATER_OR_EQUAL, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Goober5000
154  { "<", OP_LESS_THAN, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
155  { "<=", OP_LESS_OR_EQUAL, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Goober5000
156  { "string-equals", OP_STRING_EQUALS, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
157  { "string-greater-than", OP_STRING_GREATER_THAN, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
158  { "string-less-than", OP_STRING_LESS_THAN, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
159  { "perform-actions", OP_PERFORM_ACTIONS, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Goober5000
160  { "has-time-elapsed", OP_HAS_TIME_ELAPSED, 1, 1, SEXP_BOOLEAN_OPERATOR, },
161 
162  //Event/Goals Category
163  { "is-goal-true-delay", OP_GOAL_TRUE_DELAY, 2, 2, SEXP_BOOLEAN_OPERATOR, },
164  { "is-goal-false-delay", OP_GOAL_FALSE_DELAY, 2, 2, SEXP_BOOLEAN_OPERATOR, },
165  { "is-goal-incomplete", OP_GOAL_INCOMPLETE, 1, 1, SEXP_BOOLEAN_OPERATOR, },
166  { "is-event-true", OP_EVENT_TRUE, 1, 1, SEXP_BOOLEAN_OPERATOR, },
167  { "is-event-true-delay", OP_EVENT_TRUE_DELAY, 2, 3, SEXP_BOOLEAN_OPERATOR, },
168  { "is-event-true-msecs-delay", OP_EVENT_TRUE_MSECS_DELAY, 2, 3, SEXP_BOOLEAN_OPERATOR, },
169  { "is-event-false", OP_EVENT_FALSE, 1, 1, SEXP_BOOLEAN_OPERATOR, },
170  { "is-event-false-delay", OP_EVENT_FALSE_DELAY, 2, 3, SEXP_BOOLEAN_OPERATOR, },
171  { "is-event-false-msecs-delay", OP_EVENT_FALSE_MSECS_DELAY, 2, 3, SEXP_BOOLEAN_OPERATOR, },
172  { "is-event-incomplete", OP_EVENT_INCOMPLETE, 1, 1, SEXP_BOOLEAN_OPERATOR, },
173  { "is-previous-goal-true", OP_PREVIOUS_GOAL_TRUE, 2, 3, SEXP_BOOLEAN_OPERATOR, },
174  { "is-previous-goal-false", OP_PREVIOUS_GOAL_FALSE, 2, 3, SEXP_BOOLEAN_OPERATOR, },
175  { "is-previous-goal-incomplete", OP_PREVIOUS_GOAL_INCOMPLETE, 2, 3, SEXP_BOOLEAN_OPERATOR, },
176  { "is-previous-event-true", OP_PREVIOUS_EVENT_TRUE, 2, 3, SEXP_BOOLEAN_OPERATOR, },
177  { "is-previous-event-false", OP_PREVIOUS_EVENT_FALSE, 2, 3, SEXP_BOOLEAN_OPERATOR, },
178  { "is-previous-event-incomplete", OP_PREVIOUS_EVENT_INCOMPLETE, 2, 3, SEXP_BOOLEAN_OPERATOR, },
179 
180  //Objectives Category
181  { "is-destroyed", OP_IS_DESTROYED, 1, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
182  { "is-destroyed-delay", OP_IS_DESTROYED_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
183  { "was-destroyed-by-delay", OP_WAS_DESTROYED_BY_DELAY, 3, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
184  { "is-subsystem-destroyed", OP_IS_SUBSYSTEM_DESTROYED, 2, 2, SEXP_BOOLEAN_OPERATOR, },
185  { "is-subsystem-destroyed-delay", OP_IS_SUBSYSTEM_DESTROYED_DELAY, 3, 3, SEXP_BOOLEAN_OPERATOR, },
186  { "is-disabled", OP_IS_DISABLED, 1, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
187  { "is-disabled-delay", OP_IS_DISABLED_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
188  { "is-disarmed", OP_IS_DISARMED, 1, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
189  { "is-disarmed-delay", OP_IS_DISARMED_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
190  { "has-docked", OP_HAS_DOCKED, 3, 3, SEXP_BOOLEAN_OPERATOR, },
191  { "has-docked-delay", OP_HAS_DOCKED_DELAY, 4, 4, SEXP_BOOLEAN_OPERATOR, },
192  { "has-undocked", OP_HAS_UNDOCKED, 3, 3, SEXP_BOOLEAN_OPERATOR, },
193  { "has-undocked-delay", OP_HAS_UNDOCKED_DELAY, 4, 4, SEXP_BOOLEAN_OPERATOR, },
194  { "has-arrived", OP_HAS_ARRIVED, 1, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
195  { "has-arrived-delay", OP_HAS_ARRIVED_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
196  { "has-departed", OP_HAS_DEPARTED, 1, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
197  { "has-departed-delay", OP_HAS_DEPARTED_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
198  { "are-waypoints-done", OP_WAYPOINTS_DONE, 2, 2, SEXP_BOOLEAN_OPERATOR, },
199  { "are-waypoints-done-delay", OP_WAYPOINTS_DONE_DELAY, 3, 4, SEXP_BOOLEAN_OPERATOR, },
200  { "is-nav-visited", OP_NAV_IS_VISITED, 1, 1, SEXP_BOOLEAN_OPERATOR, }, // Kazan
201  { "ship-type-destroyed", OP_SHIP_TYPE_DESTROYED, 2, 2, SEXP_BOOLEAN_OPERATOR, },
202  { "percent-ships-destroyed", OP_PERCENT_SHIPS_DESTROYED, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
203  { "percent-ships-disabled", OP_PERCENT_SHIPS_DISABLED, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
204  { "percent-ships-disarmed", OP_PERCENT_SHIPS_DISARMED, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
205  { "percent-ships-departed", OP_PERCENT_SHIPS_DEPARTED, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
206  { "percent-ships-arrived", OP_PERCENT_SHIPS_ARRIVED, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
207  { "depart-node-delay", OP_DEPART_NODE_DELAY, 3, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
208  { "destroyed-or-departed-delay", OP_DESTROYED_DEPARTED_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
209 
210  //Status Category
211  //Mission Sub-Category
212  { "num-ships-in-battle", OP_NUM_SHIPS_IN_BATTLE, 0, INT_MAX, SEXP_INTEGER_OPERATOR, }, //phreak modified by FUBAR
213  { "num-ships-in-wing", OP_NUM_SHIPS_IN_WING, 1, INT_MAX, SEXP_INTEGER_OPERATOR, }, // Karajorma
214  { "directive-value", OP_DIRECTIVE_VALUE, 1, 2, SEXP_INTEGER_OPERATOR, }, // Karajorma
215 
216  //Player Sub-Category
217  { "was-promotion-granted", OP_WAS_PROMOTION_GRANTED, 0, 1, SEXP_BOOLEAN_OPERATOR, },
218  { "was-medal-granted", OP_WAS_MEDAL_GRANTED, 0, 1, SEXP_BOOLEAN_OPERATOR, },
219  { "skill-level-at-least", OP_SKILL_LEVEL_AT_LEAST, 1, 1, SEXP_BOOLEAN_OPERATOR, },
220  { "num_kills", OP_NUM_KILLS, 1, 1, SEXP_INTEGER_OPERATOR, },
221  { "num_assists", OP_NUM_ASSISTS, 1, 1, SEXP_INTEGER_OPERATOR, },
222  { "num_type_kills", OP_NUM_TYPE_KILLS, 2, 2, SEXP_INTEGER_OPERATOR, },
223  { "num_class_kills", OP_NUM_CLASS_KILLS, 2, 2, SEXP_INTEGER_OPERATOR, },
224  { "ship_score", OP_SHIP_SCORE, 1, 1, SEXP_INTEGER_OPERATOR, },
225  { "time-elapsed-last-order", OP_LAST_ORDER_TIME, 2, 2, SEXP_INTEGER_OPERATOR, },
226  { "player-is-cheating", OP_PLAYER_IS_CHEATING_BASTARD, 0, 0, SEXP_BOOLEAN_OPERATOR, },
227 
228  //Multiplayer Sub-Category
229  { "num-players", OP_NUM_PLAYERS, 0, 0, SEXP_INTEGER_OPERATOR, },
230  { "team-score", OP_TEAM_SCORE, 1, 1, SEXP_INTEGER_OPERATOR, },
231  { "ship-deaths", OP_SHIP_DEATHS, 1, 1, SEXP_INTEGER_OPERATOR, },
232  { "respawns-left", OP_RESPAWNS_LEFT, 1, 1, SEXP_INTEGER_OPERATOR, },
233  { "is-player", OP_IS_PLAYER, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Karajorma
234 
235  //Ship Status Sub-Category
236  { "is-in-mission", OP_IS_IN_MISSION, 1, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Goober5000
237  { "is-ship-visible", OP_IS_SHIP_VISIBLE, 1, 1, SEXP_BOOLEAN_OPERATOR, },
238  { "is-ship-stealthy", OP_IS_SHIP_STEALTHY, 1, 1, SEXP_BOOLEAN_OPERATOR, },
239  { "is-friendly-stealth-visible", OP_IS_FRIENDLY_STEALTH_VISIBLE, 1, 1, SEXP_BOOLEAN_OPERATOR, },
240  { "is-iff", OP_IS_IFF, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
241  { "is-ai-class", OP_IS_AI_CLASS, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
242  { "is-ship-type", OP_IS_SHIP_TYPE, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
243  { "is-ship-class", OP_IS_SHIP_CLASS, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
244  { "is-facing", OP_IS_FACING, 3, 4, SEXP_BOOLEAN_OPERATOR, },
245  { "is_tagged", OP_IS_TAGGED, 1, 1, SEXP_BOOLEAN_OPERATOR, },
246  { "has-been-tagged-delay", OP_HAS_BEEN_TAGGED_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
247  { "are-ship-flags-set", OP_ARE_SHIP_FLAGS_SET, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Karajorma
248 
249  //Shields, Engines and Weapons Sub-Category
250  { "has-primary-weapon", OP_HAS_PRIMARY_WEAPON, 3, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Karajorma
251  { "has-secondary-weapon", OP_HAS_SECONDARY_WEAPON, 3, INT_MAX, SEXP_BOOLEAN_OPERATOR, }, // Karajorma
252  { "is-primary-selected", OP_IS_PRIMARY_SELECTED, 2, 2, SEXP_BOOLEAN_OPERATOR, },
253  { "is-secondary-selected", OP_IS_SECONDARY_SELECTED, 2, 2, SEXP_BOOLEAN_OPERATOR, },
254  { "primary-fired-since", OP_PRIMARY_FIRED_SINCE, 3, 3, SEXP_INTEGER_OPERATOR, }, // Karajorma
255  { "secondary-fired-since", OP_SECONDARY_FIRED_SINCE, 3, 3, SEXP_INTEGER_OPERATOR, }, // Karajorma
256  { "primary-ammo-pct", OP_PRIMARY_AMMO_PCT, 2, 2, SEXP_INTEGER_OPERATOR, },
257  { "secondary-ammo-pct", OP_SECONDARY_AMMO_PCT, 2, 2, SEXP_INTEGER_OPERATOR, },
258  { "get-primary-ammo", OP_GET_PRIMARY_AMMO, 2, 2, SEXP_INTEGER_OPERATOR, }, // Karajorma
259  { "get-secondary-ammo", OP_GET_SECONDARY_AMMO, 2, 2, SEXP_INTEGER_OPERATOR, }, // Karajorma
260  { "get-num-countermeasures", OP_GET_NUM_COUNTERMEASURES, 1, 1, SEXP_INTEGER_OPERATOR, }, // Karajorma
261  { "weapon-energy-pct", OP_WEAPON_ENERGY_LEFT, 1, 1, SEXP_INTEGER_OPERATOR, },
262  { "afterburner-energy-pct", OP_AFTERBURNER_LEFT, 1, 1, SEXP_INTEGER_OPERATOR, },
263  { "shield-recharge-pct", OP_SHIELD_RECHARGE_PCT, 1, 1, SEXP_INTEGER_OPERATOR, },
264  { "weapon-recharge-pct", OP_WEAPON_RECHARGE_PCT, 1, 1, SEXP_INTEGER_OPERATOR, },
265  { "engine-recharge-pct", OP_ENGINE_RECHARGE_PCT, 1, 1, SEXP_INTEGER_OPERATOR, },
266  { "shield-quad-low", OP_SHIELD_QUAD_LOW, 2, 2, SEXP_INTEGER_OPERATOR, },
267  { "get-throttle-speed", OP_GET_THROTTLE_SPEED, 1, 1, SEXP_INTEGER_OPERATOR, }, // Karajorma
268  { "current-speed", OP_CURRENT_SPEED, 1, 1, SEXP_INTEGER_OPERATOR, },
269 
270  //Cargo Sub-Category
271  { "is-cargo-known", OP_IS_CARGO_KNOWN, 1, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
272  { "is-cargo-known-delay", OP_CARGO_KNOWN_DELAY, 2, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
273  { "cap-subsys-cargo-known-delay", OP_CAP_SUBSYS_CARGO_KNOWN_DELAY, 3, INT_MAX, SEXP_BOOLEAN_OPERATOR, },
274  { "is-cargo", OP_IS_CARGO, 2, 3, SEXP_BOOLEAN_OPERATOR, },
275 
276  //Damage Sub-Category
277  { "shields-left", OP_SHIELDS_LEFT, 1, 1, SEXP_INTEGER_OPERATOR, },
278  { "hits-left", OP_HITS_LEFT, 1, 1, SEXP_INTEGER_OPERATOR, },
279  { "hits-left-subsystem", OP_HITS_LEFT_SUBSYSTEM, 2, 3, SEXP_INTEGER_OPERATOR, },
280  { "hits-left-subsystem-generic", OP_HITS_LEFT_SUBSYSTEM_GENERIC, 2, 2, SEXP_INTEGER_OPERATOR, }, // Goober5000
281  { "hits-left-subsystem-specific", OP_HITS_LEFT_SUBSYSTEM_SPECIFIC, 2, 2, SEXP_INTEGER_OPERATOR, }, // Goober5000
282  { "sim-hits-left", OP_SIM_HITS_LEFT, 1, 1, SEXP_INTEGER_OPERATOR, }, // Turey
283  { "get-damage-caused", OP_GET_DAMAGE_CAUSED, 2, INT_MAX, SEXP_INTEGER_OPERATOR, },
284 
285  //Distance and Coordinates Sub-Category
286  { "distance", OP_DISTANCE, 2, 2, SEXP_INTEGER_OPERATOR, },
287  { "distance-ship-subsystem", OP_DISTANCE_SUBSYSTEM, 3, 3, SEXP_INTEGER_OPERATOR, }, // Goober5000
288  { "distance-to-nav", OP_NAV_DISTANCE, 1, 1, SEXP_INTEGER_OPERATOR, }, // Kazan
289  { "num-within-box", OP_NUM_WITHIN_BOX, 7, INT_MAX, SEXP_INTEGER_OPERATOR, }, //WMC
290  { "is-in-box", OP_IS_IN_BOX, 7, 8, SEXP_INTEGER_OPERATOR, }, //Sushi
291  { "special-warp-dist", OP_SPECIAL_WARP_DISTANCE, 1, 1, SEXP_INTEGER_OPERATOR, },
292  { "get-object-x", OP_GET_OBJECT_X, 1, 5, SEXP_INTEGER_OPERATOR, }, // Goober5000
293  { "get-object-y", OP_GET_OBJECT_Y, 1, 5, SEXP_INTEGER_OPERATOR, }, // Goober5000
294  { "get-object-z", OP_GET_OBJECT_Z, 1, 5, SEXP_INTEGER_OPERATOR, }, // Goober5000
295  { "get-object-pitch", OP_GET_OBJECT_PITCH, 1, 1, SEXP_INTEGER_OPERATOR, }, // Goober5000
296  { "get-object-bank", OP_GET_OBJECT_BANK, 1, 1, SEXP_INTEGER_OPERATOR, }, // Goober5000
297  { "get-object-heading", OP_GET_OBJECT_HEADING, 1, 1, SEXP_INTEGER_OPERATOR, }, // Goober5000
298  { "get-object-speed-x", OP_GET_OBJECT_SPEED_X, 1, 2, SEXP_INTEGER_OPERATOR, },
299  { "get-object-speed-y", OP_GET_OBJECT_SPEED_Y, 1, 2, SEXP_INTEGER_OPERATOR, },
300  { "get-object-speed-z", OP_GET_OBJECT_SPEED_Z, 1, 2, SEXP_INTEGER_OPERATOR, },
301 
302  //Variables Sub-Category
303  { "string-to-int", OP_STRING_TO_INT, 1, 1, SEXP_INTEGER_OPERATOR, }, // Karajorma
304  { "string-get-length", OP_STRING_GET_LENGTH, 1, 1, SEXP_INTEGER_OPERATOR, }, // Goober5000
305 
306  //Other Sub-Category
307  { "script-eval-num", OP_SCRIPT_EVAL_NUM, 1, 1, SEXP_INTEGER_OPERATOR, },
308  { "script-eval-string", OP_SCRIPT_EVAL_STRING, 2, 2, SEXP_ACTION_OPERATOR, },
309 
310  //Time Category
311  { "time-ship-destroyed", OP_TIME_SHIP_DESTROYED, 1, 1, SEXP_INTEGER_OPERATOR, },
312  { "time-ship-arrived", OP_TIME_SHIP_ARRIVED, 1, 1, SEXP_INTEGER_OPERATOR, },
313  { "time-ship-departed", OP_TIME_SHIP_DEPARTED, 1, 1, SEXP_INTEGER_OPERATOR, },
314  { "time-wing-destroyed", OP_TIME_WING_DESTROYED, 1, 1, SEXP_INTEGER_OPERATOR, },
315  { "time-wing-arrived", OP_TIME_WING_ARRIVED, 1, 1, SEXP_INTEGER_OPERATOR, },
316  { "time-wing-departed", OP_TIME_WING_DEPARTED, 1, 1, SEXP_INTEGER_OPERATOR, },
317  { "mission-time", OP_MISSION_TIME, 0, 0, SEXP_INTEGER_OPERATOR, },
318  { "mission-time-msecs", OP_MISSION_TIME_MSECS, 0, 0, SEXP_INTEGER_OPERATOR, }, // Goober5000
319  { "time-docked", OP_TIME_DOCKED, 3, 3, SEXP_INTEGER_OPERATOR, },
320  { "time-undocked", OP_TIME_UNDOCKED, 3, 3, SEXP_INTEGER_OPERATOR, },
321 
322  //Conditionals Category
323  { "cond", OP_COND, 1, INT_MAX, SEXP_CONDITIONAL_OPERATOR,},
324  { "when", OP_WHEN, 2, INT_MAX, SEXP_CONDITIONAL_OPERATOR,},
325  { "when-argument", OP_WHEN_ARGUMENT, 3, INT_MAX, SEXP_CONDITIONAL_OPERATOR,}, // Goober5000
326  { "every-time", OP_EVERY_TIME, 2, INT_MAX, SEXP_CONDITIONAL_OPERATOR,}, // Goober5000
327  { "every-time-argument", OP_EVERY_TIME_ARGUMENT, 3, INT_MAX, SEXP_CONDITIONAL_OPERATOR,}, // Goober5000
328  { "if-then-else", OP_IF_THEN_ELSE, 3, INT_MAX, SEXP_CONDITIONAL_OPERATOR,}, // Goober5000
329  { "any-of", OP_ANY_OF, 1, INT_MAX, SEXP_ARGUMENT_OPERATOR, }, // Goober5000
330  { "every-of", OP_EVERY_OF, 1, INT_MAX, SEXP_ARGUMENT_OPERATOR, }, // Goober5000
331  { "random-of", OP_RANDOM_OF, 1, INT_MAX, SEXP_ARGUMENT_OPERATOR, }, // Goober5000
332  { "random-multiple-of", OP_RANDOM_MULTIPLE_OF, 1, INT_MAX, SEXP_ARGUMENT_OPERATOR, }, // Karajorma
333  { "number-of", OP_NUMBER_OF, 2, INT_MAX, SEXP_ARGUMENT_OPERATOR, }, // Goober5000
334  { "in-sequence", OP_IN_SEQUENCE, 1, INT_MAX, SEXP_ARGUMENT_OPERATOR, }, // Karajorma
335  { "for-counter", OP_FOR_COUNTER, 2, 3, SEXP_ARGUMENT_OPERATOR, }, // Goober5000
336  { "invalidate-argument", OP_INVALIDATE_ARGUMENT, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
337  { "invalidate-all-arguments", OP_INVALIDATE_ALL_ARGUMENTS, 0, 0, SEXP_ACTION_OPERATOR, }, // Karajorma
338  { "validate-argument", OP_VALIDATE_ARGUMENT, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
339  { "validate-all-arguments", OP_VALIDATE_ALL_ARGUMENTS, 0, 0, SEXP_ACTION_OPERATOR, }, // Karajorma
340  { "do-for-valid-arguments", OP_DO_FOR_VALID_ARGUMENTS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
341  { "num-valid-arguments", OP_NUM_VALID_ARGUMENTS, 0, 0, SEXP_ACTION_OPERATOR, }, // Karajorma
342 
343  //Change Category
344  //Messaging Sub-Category
345  { "send-message", OP_SEND_MESSAGE, 3, 3, SEXP_ACTION_OPERATOR, },
346  { "send-message-list", OP_SEND_MESSAGE_LIST, 4, INT_MAX, SEXP_ACTION_OPERATOR, },
347  { "send-random-message", OP_SEND_RANDOM_MESSAGE, 3, INT_MAX, SEXP_ACTION_OPERATOR, },
348  { "scramble-messages", OP_SCRAMBLE_MESSAGES, 0, INT_MAX, SEXP_ACTION_OPERATOR, },
349  { "unscramble-messages", OP_UNSCRAMBLE_MESSAGES, 0, INT_MAX, SEXP_ACTION_OPERATOR, },
350  { "disable-builtin-messages", OP_DISABLE_BUILTIN_MESSAGES, 0, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
351  { "enable-builtin-messages", OP_ENABLE_BUILTIN_MESSAGES, 0, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
352  { "set-persona", OP_SET_PERSONA, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
353  { "set-death-message", OP_SET_DEATH_MESSAGE, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
354  { "set-mission-mood", OP_SET_MISSION_MOOD, 1, 1, SEXP_ACTION_OPERATOR, }, // Karajorma
355 
356 
357  //AI Control Sub-Category
358  { "add-goal", OP_ADD_GOAL, 2, 2, SEXP_ACTION_OPERATOR, },
359  { "remove-goal", OP_REMOVE_GOAL, 2, 2, SEXP_ACTION_OPERATOR, }, // Goober5000
360  { "add-ship-goal", OP_ADD_SHIP_GOAL, 2, 2, SEXP_ACTION_OPERATOR, },
361  { "add-wing-goal", OP_ADD_WING_GOAL, 2, 2, SEXP_ACTION_OPERATOR, },
362  { "clear-goals", OP_CLEAR_GOALS, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
363  { "clear-ship-goals", OP_CLEAR_SHIP_GOALS, 1, 1, SEXP_ACTION_OPERATOR, },
364  { "clear-wing-goals", OP_CLEAR_WING_GOALS, 1, 1, SEXP_ACTION_OPERATOR, },
365  { "good-rearm-time", OP_GOOD_REARM_TIME, 2, 2, SEXP_ACTION_OPERATOR, },
366  { "good-secondary-time", OP_GOOD_SECONDARY_TIME, 4, 4, SEXP_ACTION_OPERATOR, },
367  { "change-ai-class", OP_CHANGE_AI_CLASS, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
368  { "player-use-ai", OP_PLAYER_USE_AI, 0, 0, SEXP_ACTION_OPERATOR, }, // Goober5000
369  { "player-not-use-ai", OP_PLAYER_NOT_USE_AI, 0, 0, SEXP_ACTION_OPERATOR, }, // Goober5000
370  { "set-player-orders", OP_SET_PLAYER_ORDERS, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
371  { "cap-waypoint-speed", OP_CAP_WAYPOINT_SPEED, 2, 2, SEXP_ACTION_OPERATOR, },
372 
373  //Ship Status Sub-Category
374  { "protect-ship", OP_PROTECT_SHIP, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
375  { "unprotect-ship", OP_UNPROTECT_SHIP, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
376  { "beam-protect-ship", OP_BEAM_PROTECT_SHIP, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
377  { "beam-unprotect-ship", OP_BEAM_UNPROTECT_SHIP, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
378  { "turret-protect-ship", OP_TURRET_PROTECT_SHIP, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
379  { "turret-unprotect-ship", OP_TURRET_UNPROTECT_SHIP, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
380  { "ship-invisible", OP_SHIP_INVISIBLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
381  { "ship-visible", OP_SHIP_VISIBLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
382  { "ship-stealthy", OP_SHIP_STEALTHY, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
383  { "ship-unstealthy", OP_SHIP_UNSTEALTHY, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
384  { "friendly-stealth-invisible", OP_FRIENDLY_STEALTH_INVISIBLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
385  { "friendly-stealth-visible", OP_FRIENDLY_STEALTH_VISIBLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
386  { "primitive-sensors-set-range", OP_PRIMITIVE_SENSORS_SET_RANGE, 2, 2, SEXP_ACTION_OPERATOR, }, // Goober5000
387  { "ship-targetable-as-bomb", OP_SHIP_BOMB_TARGETABLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
388  { "ship-untargetable-as-bomb", OP_SHIP_BOMB_UNTARGETABLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
389  { "kamikaze", OP_KAMIKAZE, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Sesquipedalian
390  { "change-iff", OP_CHANGE_IFF, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
391  { "change-iff-color", OP_CHANGE_IFF_COLOR, 6, INT_MAX, SEXP_ACTION_OPERATOR, },
392  { "add-remove-escort", OP_ADD_REMOVE_ESCORT, 2, 2, SEXP_ACTION_OPERATOR, },
393  { "ship-change-alt-name", OP_SHIP_CHANGE_ALT_NAME, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
394  { "ship-change-callsign", OP_SHIP_CHANGE_CALLSIGN, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
395  { "ship-tag", OP_SHIP_TAG, 3, 8, SEXP_ACTION_OPERATOR, }, // Goober5000
396  { "ship-untag", OP_SHIP_UNTAG, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
397  { "set-arrival-info", OP_SET_ARRIVAL_INFO, 2, 7, SEXP_ACTION_OPERATOR, }, // Goober5000
398  { "set-departure-info", OP_SET_DEPARTURE_INFO, 2, 6, SEXP_ACTION_OPERATOR, }, // Goober5000
399 
400  //Shields, Engines and Weapons Sub-Category
401  { "set-weapon-energy", OP_SET_WEAPON_ENERGY, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
402  { "set-shield-energy", OP_SET_SHIELD_ENERGY, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
403  { "set-player-throttle-speed", OP_SET_PLAYER_THROTTLE_SPEED, 2, 2, SEXP_ACTION_OPERATOR, }, // CommanderDJ
404  { "set-afterburner-energy", OP_SET_AFTERBURNER_ENERGY, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
405  { "set-subspace-drive", OP_SET_SUBSPACE_DRIVE, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
406  { "set-primary-weapon", OP_SET_PRIMARY_WEAPON, 3, 5, SEXP_ACTION_OPERATOR, }, // Karajorma
407  { "set-secondary-weapon", OP_SET_SECONDARY_WEAPON, 3, 5, SEXP_ACTION_OPERATOR, }, // Karajorma
408  { "set-primary-ammo", OP_SET_PRIMARY_AMMO, 3, 4, SEXP_ACTION_OPERATOR, }, // Karajorma
409  { "set-secondary-ammo", OP_SET_SECONDARY_AMMO, 3, 4, SEXP_ACTION_OPERATOR, }, // Karajorma
410  { "set-num-countermeasures", OP_SET_NUM_COUNTERMEASURES, 2, 2, SEXP_ACTION_OPERATOR, }, // Karajorma
411  { "lock-primary-weapon", OP_LOCK_PRIMARY_WEAPON, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
412  { "unlock-primary-weapon", OP_UNLOCK_PRIMARY_WEAPON, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
413  { "lock-secondary-weapon", OP_LOCK_SECONDARY_WEAPON, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
414  { "unlock-secondary-weapon", OP_UNLOCK_SECONDARY_WEAPON, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
415  { "lock-afterburner", OP_LOCK_AFTERBURNER, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // KeldorKatarn
416  { "unlock-afterburner", OP_UNLOCK_AFTERBURNER, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // KeldorKatarn
417  { "shields-on", OP_SHIELDS_ON, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Sesquipedalian
418  { "shields-off", OP_SHIELDS_OFF, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Sesquipedalian
419  { "force-glide", OP_FORCE_GLIDE, 2, 2, SEXP_ACTION_OPERATOR, }, // The E
420  { "disable-ets", OP_DISABLE_ETS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // The E
421  { "enable-ets", OP_ENABLE_ETS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // The E
422  { "break-warp", OP_WARP_BROKEN, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
423  { "fix-warp", OP_WARP_NOT_BROKEN, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
424  { "never-warp", OP_WARP_NEVER, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
425  { "allow-warp", OP_WARP_ALLOWED, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
426  { "special-warpout-name", OP_SET_SPECIAL_WARPOUT_NAME, 2, 2, SEXP_ACTION_OPERATOR, },
427  { "get-ets-value", OP_GET_ETS_VALUE, 2, 2, SEXP_ACTION_OPERATOR, }, // niffiwan
428  { "set-ets-values", OP_SET_ETS_VALUES, 4, INT_MAX, SEXP_ACTION_OPERATOR, }, // niffiwan
429 
430  //Subsystems and Health Sub-Category
431  { "ship-invulnerable", OP_SHIP_INVULNERABLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
432  { "ship-vulnerable", OP_SHIP_VULNERABLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
433  { "ship-guardian", OP_SHIP_GUARDIAN, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
434  { "ship-no-guardian", OP_SHIP_NO_GUARDIAN, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
435  { "ship-guardian-threshold", OP_SHIP_GUARDIAN_THRESHOLD, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
436  { "ship-subsys-guardian-threshold", OP_SHIP_SUBSYS_GUARDIAN_THRESHOLD, 3, INT_MAX, SEXP_ACTION_OPERATOR, },
437  { "self-destruct", OP_SELF_DESTRUCT, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
438  { "destroy-instantly", OP_DESTROY_INSTANTLY, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Admiral MS
439  { "destroy-subsys-instantly", OP_DESTROY_SUBSYS_INSTANTLY, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Admiral MS
440  { "sabotage-subsystem", OP_SABOTAGE_SUBSYSTEM, 3, 3, SEXP_ACTION_OPERATOR, },
441  { "repair-subsystem", OP_REPAIR_SUBSYSTEM, 3, 4, SEXP_ACTION_OPERATOR, },
442  { "ship-copy-damage", OP_SHIP_COPY_DAMAGE, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
443  { "set-subsystem-strength", OP_SET_SUBSYSTEM_STRNGTH, 3, 4, SEXP_ACTION_OPERATOR, },
444  { "subsys-set-random", OP_SUBSYS_SET_RANDOM, 3, INT_MAX, SEXP_ACTION_OPERATOR, },
445  { "lock-rotating-subsystem", OP_LOCK_ROTATING_SUBSYSTEM, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
446  { "free-rotating-subsystem", OP_FREE_ROTATING_SUBSYSTEM, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
447  { "reverse-rotating-subsystem", OP_REVERSE_ROTATING_SUBSYSTEM, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
448  { "rotating-subsys-set-turn-time", OP_ROTATING_SUBSYS_SET_TURN_TIME, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
449  { "trigger-submodel-animation", OP_TRIGGER_SUBMODEL_ANIMATION, 4, 6, SEXP_ACTION_OPERATOR, }, // Goober5000
450  { "change-subsystem-name", OP_CHANGE_SUBSYSTEM_NAME, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
451  { "ship-subsys-targetable", OP_SHIP_SUBSYS_TARGETABLE, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
452  { "ship-subsys-untargetable", OP_SHIP_SUBSYS_UNTARGETABLE, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
453  { "ship-subsys-no-replace", OP_SHIP_SUBSYS_NO_REPLACE, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
454  { "ship-subsys-no-live-debris", OP_SHIP_SUBSYS_NO_LIVE_DEBRIS, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
455  { "ship-subsys-vanish", OP_SHIP_SUBSYS_VANISHED, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
456  { "ship-subsys-ignore_if_dead", OP_SHIP_SUBSYS_IGNORE_IF_DEAD, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
457  { "awacs-set-radius", OP_AWACS_SET_RADIUS, 3, 3, SEXP_ACTION_OPERATOR, },
458  { "alter-ship-flag", OP_ALTER_SHIP_FLAG, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
459 
460  //Cargo Sub-Category
461  { "transfer-cargo", OP_TRANSFER_CARGO, 2, 2, SEXP_ACTION_OPERATOR, },
462  { "exchange-cargo", OP_EXCHANGE_CARGO, 2, 2, SEXP_ACTION_OPERATOR, },
463  { "set-cargo", OP_SET_CARGO, 2, 3, SEXP_ACTION_OPERATOR, },
464  { "jettison-cargo-delay", OP_JETTISON_CARGO, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
465  { "set-docked", OP_SET_DOCKED, 4, 4, SEXP_ACTION_OPERATOR, }, // Sushi
466  { "cargo-no-deplete", OP_CARGO_NO_DEPLETE, 1, 2, SEXP_ACTION_OPERATOR, },
467  { "set-scanned", OP_SET_SCANNED, 1, 2, SEXP_ACTION_OPERATOR, },
468  { "set-unscanned", OP_SET_UNSCANNED, 1, 2, SEXP_ACTION_OPERATOR, },
469 
470  //Armor and Damage Types Sub-Category
471  { "set-armor-type", OP_SET_ARMOR_TYPE, 4, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
472  { "weapon-set-damage-type", OP_WEAPON_SET_DAMAGE_TYPE, 4, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
473  { "ship-set-damage-type", OP_SHIP_SET_DAMAGE_TYPE, 4, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
474  { "ship-set-shockwave-damage-type", OP_SHIP_SHOCKWAVE_SET_DAMAGE_TYPE, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // FUBAR
475  { "field-set-damage-type", OP_FIELD_SET_DAMAGE_TYPE, 2, 2, SEXP_ACTION_OPERATOR, }, // FUBAR
476 
477  //Beams and Turrets Sub-Category
478  { "fire-beam", OP_BEAM_FIRE, 3, 5, SEXP_ACTION_OPERATOR, },
479  { "fire-beam-at-coordinates", OP_BEAM_FIRE_COORDS, 5, 9, SEXP_ACTION_OPERATOR, },
480  { "beam-create", OP_BEAM_FLOATING_FIRE, 7, 14, SEXP_ACTION_OPERATOR, },
481  { "beam-free", OP_BEAM_FREE, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
482  { "beam-free-all", OP_BEAM_FREE_ALL, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
483  { "beam-lock", OP_BEAM_LOCK, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
484  { "beam-lock-all", OP_BEAM_LOCK_ALL, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
485  { "turret-free", OP_TURRET_FREE, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
486  { "turret-free-all", OP_TURRET_FREE_ALL, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
487  { "turret-lock", OP_TURRET_LOCK, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
488  { "turret-lock-all", OP_TURRET_LOCK_ALL, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
489  { "turret-tagged-only", OP_TURRET_TAGGED_ONLY_ALL, 1, 1, SEXP_ACTION_OPERATOR, },
490  { "turret-tagged-clear", OP_TURRET_TAGGED_CLEAR_ALL, 1, 1, SEXP_ACTION_OPERATOR, },
491  { "turret-tagged-specific", OP_TURRET_TAGGED_SPECIFIC, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, //phreak
492  { "turret-tagged-clear-specific", OP_TURRET_TAGGED_CLEAR_SPECIFIC, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, //phreak
493  { "turret-change-weapon", OP_TURRET_CHANGE_WEAPON, 5, 5, SEXP_ACTION_OPERATOR, }, //WMC
494  { "turret-set-direction-preference",OP_TURRET_SET_DIRECTION_PREFERENCE, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, //FUBAR
495  { "turret-set-rate-of-fire", OP_TURRET_SET_RATE_OF_FIRE, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, //FUBAR
496  { "turret-set-optimum-range", OP_TURRET_SET_OPTIMUM_RANGE, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, //FUBAR
497  { "turret-set-target-priorities", OP_TURRET_SET_TARGET_PRIORITIES, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, //FUBAR
498  { "turret-set-target-order", OP_TURRET_SET_TARGET_ORDER, 2, 2+NUM_TURRET_ORDER_TYPES, SEXP_ACTION_OPERATOR, }, //WMC
499  { "ship-turret-target-order", OP_SHIP_TURRET_TARGET_ORDER, 1, 1+NUM_TURRET_ORDER_TYPES, SEXP_ACTION_OPERATOR, }, //WMC
500  { "turret-subsys-target-disable", OP_TURRET_SUBSYS_TARGET_DISABLE, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
501  { "turret-subsys-target-enable", OP_TURRET_SUBSYS_TARGET_ENABLE, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
502  { "turret-set-primary-ammo", OP_TURRET_SET_PRIMARY_AMMO, 4, 4, SEXP_ACTION_OPERATOR, }, // DahBlount
503  { "turret-set-secondary-ammo", OP_TURRET_SET_SECONDARY_AMMO, 4, 4, SEXP_ACTION_OPERATOR, }, // DahBlount
504  { "turret-get-primary-ammo", OP_TURRET_GET_PRIMARY_AMMO, 3, 3, SEXP_INTEGER_OPERATOR, }, // DahBlount
505  { "turret-get-secondary-ammo", OP_TURRET_GET_SECONDARY_AMMO, 3, 3, SEXP_INTEGER_OPERATOR, }, // DahBlount
506 
507  //Models and Textures Sub-Category
508  { "change-ship-class", OP_CHANGE_SHIP_CLASS, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
509  { "deactivate-glow-maps", OP_DEACTIVATE_GLOW_MAPS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //-Bobboau
510  { "activate-glow-maps", OP_ACTIVATE_GLOW_MAPS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //-Bobboau
511  { "deactivate-glow-points", OP_DEACTIVATE_GLOW_POINTS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //-Bobboau
512  { "activate-glow-points", OP_ACTIVATE_GLOW_POINTS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //-Bobboau
513  { "deactivate-glow-point-bank", OP_DEACTIVATE_GLOW_POINT_BANK, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, //-Bobboau
514  { "activate-glow-point-bank", OP_ACTIVATE_GLOW_POINT_BANK, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, //-Bobboau
515  { "set-thrusters-status", OP_SET_THRUSTERS, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // The E
516  { "don't-collide-invisible", OP_DONT_COLLIDE_INVISIBLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
517  { "collide-invisible", OP_COLLIDE_INVISIBLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
518  { "add-to-collision-group", OP_ADD_TO_COLGROUP, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // The E
519  { "remove-from-collision-group", OP_REMOVE_FROM_COLGROUP, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
520  { "get-collision-group", OP_GET_COLGROUP_ID, 1, 1, SEXP_ACTION_OPERATOR, },
521  { "change-team-color", OP_CHANGE_TEAM_COLOR, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // The E
522 
523  //Coordinate Manipulation Sub-Category
524  { "set-object-position", OP_SET_OBJECT_POSITION, 4, 4, SEXP_ACTION_OPERATOR, }, // WMC
525  { "set-object-orientation", OP_SET_OBJECT_ORIENTATION, 4, 4, SEXP_ACTION_OPERATOR, }, // Goober5000
526  { "set-object-facing", OP_SET_OBJECT_FACING, 4, 6, SEXP_ACTION_OPERATOR, }, // Goober5000
527  { "set-object-facing-object", OP_SET_OBJECT_FACING_OBJECT, 2, 4, SEXP_ACTION_OPERATOR, }, // Goober5000
528  { "set-object-speed-x", OP_SET_OBJECT_SPEED_X, 2, 3, SEXP_ACTION_OPERATOR, }, // WMC
529  { "set-object-speed-y", OP_SET_OBJECT_SPEED_Y, 2, 3, SEXP_ACTION_OPERATOR, }, // WMC
530  { "set-object-speed-z", OP_SET_OBJECT_SPEED_Z, 2, 3, SEXP_ACTION_OPERATOR, }, // WMC
531  { "ship-maneuver", OP_SHIP_MANEUVER, 10, 10, SEXP_ACTION_OPERATOR, }, // Wanderer
532  { "ship-rot-maneuver", OP_SHIP_ROT_MANEUVER, 6, 6, SEXP_ACTION_OPERATOR, }, // Wanderer
533  { "ship-lat-maneuver", OP_SHIP_LAT_MANEUVER, 6, 6, SEXP_ACTION_OPERATOR, }, // Wanderer
534  { "set-immobile", OP_SET_IMMOBILE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
535  { "set-mobile", OP_SET_MOBILE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
536 
537  //Mission and Campaign Sub-Category
538  { "invalidate-goal", OP_INVALIDATE_GOAL, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
539  { "validate-goal", OP_VALIDATE_GOAL, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
540  { "red-alert", OP_RED_ALERT, 0, 0, SEXP_ACTION_OPERATOR, },
541  { "end-mission", OP_END_MISSION, 0, 3, SEXP_ACTION_OPERATOR, }, //-Sesquipedalian
542  { "force-jump", OP_FORCE_JUMP, 0, 0, SEXP_ACTION_OPERATOR, }, // Goober5000
543  { "next-mission", OP_NEXT_MISSION, 1, 1, SEXP_ACTION_OPERATOR, },
544  { "end-campaign", OP_END_CAMPAIGN, 0, 1, SEXP_ACTION_OPERATOR, },
545  { "end-of-campaign", OP_END_OF_CAMPAIGN, 0, 0, SEXP_ACTION_OPERATOR, },
546  { "set-debriefing-toggled", OP_SET_DEBRIEFING_TOGGLED, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
547  { "allow-treason", OP_ALLOW_TREASON, 1, 1, SEXP_ACTION_OPERATOR, }, // Karajorma
548  { "grant-promotion", OP_GRANT_PROMOTION, 0, 0, SEXP_ACTION_OPERATOR, },
549  { "grant-medal", OP_GRANT_MEDAL, 1, 1, SEXP_ACTION_OPERATOR, },
550  { "allow-ship", OP_ALLOW_SHIP, 1, 1, SEXP_ACTION_OPERATOR, },
551  { "allow-weapon", OP_ALLOW_WEAPON, 1, 1, SEXP_ACTION_OPERATOR, },
552  { "tech-add-ships", OP_TECH_ADD_SHIP, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
553  { "tech-add-weapons", OP_TECH_ADD_WEAPON, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
554  { "tech-add-intel", OP_TECH_ADD_INTEL, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
555  { "tech-add-intel-xstr", OP_TECH_ADD_INTEL_XSTR, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
556  { "tech-reset-to-default", OP_TECH_RESET_TO_DEFAULT, 0, 0, SEXP_ACTION_OPERATOR, }, // Goober5000
557  { "change-player-score", OP_CHANGE_PLAYER_SCORE, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
558  { "change-team-score", OP_CHANGE_TEAM_SCORE, 2, 2, SEXP_ACTION_OPERATOR, }, // Karajorma
559  { "set-respawns", OP_SET_RESPAWNS, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
560 
561  //Music and Sound Sub-Category
562  { "change-soundtrack", OP_CHANGE_SOUNDTRACK, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
563  { "play-sound-from-table", OP_PLAY_SOUND_FROM_TABLE, 4, 4, SEXP_ACTION_OPERATOR, }, // Goober5000
564  { "play-sound-from-file", OP_PLAY_SOUND_FROM_FILE, 1, 3, SEXP_ACTION_OPERATOR, }, // Goober5000
565  { "close-sound-from-file", OP_CLOSE_SOUND_FROM_FILE, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
566  { "pause-sound-from-file", OP_PAUSE_SOUND_FROM_FILE, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
567  { "set-sound-environment", OP_SET_SOUND_ENVIRONMENT, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Taylor
568  { "update-sound-environment", OP_UPDATE_SOUND_ENVIRONMENT, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Taylor
569  { "adjust-audio-volume", OP_ADJUST_AUDIO_VOLUME, 1, 3, SEXP_ACTION_OPERATOR, },
570 
571  //HUD Sub-Category
572  { "hud-disable", OP_HUD_DISABLE, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
573  { "hud-disable-except-messages", OP_HUD_DISABLE_EXCEPT_MESSAGES, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
574  { "hud-set-custom-gauge-active", OP_HUD_SET_CUSTOM_GAUGE_ACTIVE, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
575  { "hud-set-retail-gauge-active", OP_HUD_SET_RETAIL_GAUGE_ACTIVE, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
576  { "hud-set-text", OP_HUD_SET_TEXT, 2, 2, SEXP_ACTION_OPERATOR, }, //WMCoolmon
577  { "hud-set-text-num", OP_HUD_SET_TEXT_NUM, 2, 2, SEXP_ACTION_OPERATOR, }, //WMCoolmon
578  { "hud-set-message", OP_HUD_SET_MESSAGE, 2, 2, SEXP_ACTION_OPERATOR, }, //The E
579  { "hud-set-directive", OP_HUD_SET_DIRECTIVE, 2, 2, SEXP_ACTION_OPERATOR, }, //The E
580  { "hud-set-frame", OP_HUD_SET_FRAME, 2, 2, SEXP_ACTION_OPERATOR, }, //WMCoolmon
581  { "hud-set-coords", OP_HUD_SET_COORDS, 3, 3, SEXP_ACTION_OPERATOR, }, //WMCoolmon
582  { "hud-set-color", OP_HUD_SET_COLOR, 4, 4, SEXP_ACTION_OPERATOR, }, //WMCoolmon
583  { "hud-display-gauge", OP_HUD_DISPLAY_GAUGE, 2, 2, SEXP_ACTION_OPERATOR, },
584  { "hud-gauge-set-active", OP_HUD_GAUGE_SET_ACTIVE, 2, 2, SEXP_ACTION_OPERATOR, }, //Deprecated
585  { "hud-activate-gauge-type", OP_HUD_ACTIVATE_GAUGE_TYPE, 2, 2, SEXP_ACTION_OPERATOR, }, //Deprecated
586  { "hud-clear-messages", OP_HUD_CLEAR_MESSAGES, 0, 0, SEXP_ACTION_OPERATOR, }, // swifty
587  { "hud-set-max-targeting-range", OP_HUD_SET_MAX_TARGETING_RANGE, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000
588 
589  //Nav Sub-Category
590  { "add-nav-waypoint", OP_NAV_ADD_WAYPOINT, 3, 4, SEXP_ACTION_OPERATOR, }, //kazan
591  { "add-nav-ship", OP_NAV_ADD_SHIP, 2, 2, SEXP_ACTION_OPERATOR, }, //kazan
592  { "del-nav", OP_NAV_DEL, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
593  { "hide-nav", OP_NAV_HIDE, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
594  { "restrict-nav", OP_NAV_RESTRICT, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
595  { "unhide-nav", OP_NAV_UNHIDE, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
596  { "unrestrict-nav", OP_NAV_UNRESTRICT, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
597  { "set-nav-visited", OP_NAV_SET_VISITED, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
598  { "unset-nav-visited", OP_NAV_UNSET_VISITED, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
599  { "set-nav-carry", OP_NAV_SET_CARRY, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //kazan
600  { "unset-nav-carry", OP_NAV_UNSET_CARRY, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //kazan
601  { "set-nav-needslink", OP_NAV_SET_NEEDSLINK, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //kazan
602  { "unset-nav-needslink", OP_NAV_UNSET_NEEDSLINK, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, //kazan
603  { "is-nav-linked", OP_NAV_ISLINKED, 1, 1, SEXP_BOOLEAN_OPERATOR, }, //kazan
604  { "use-nav-cinematics", OP_NAV_USECINEMATICS, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
605  { "use-autopilot", OP_NAV_USEAP, 1, 1, SEXP_ACTION_OPERATOR, }, //kazan
606  { "select-nav", OP_NAV_SELECT, 1, 1, SEXP_ACTION_OPERATOR, }, //Talon1024
607  { "unselect-nav", OP_NAV_UNSELECT, 0, 0, SEXP_ACTION_OPERATOR, }, //Talon1024
608 
609  //Cutscene Sub-Category
610  { "set-cutscene-bars", OP_CUTSCENES_SET_CUTSCENE_BARS, 0, 1, SEXP_ACTION_OPERATOR, },
611  { "unset-cutscene-bars", OP_CUTSCENES_UNSET_CUTSCENE_BARS, 0, 1, SEXP_ACTION_OPERATOR, },
612  { "fade-in", OP_CUTSCENES_FADE_IN, 0, 4, SEXP_ACTION_OPERATOR, },
613  { "fade-out", OP_CUTSCENES_FADE_OUT, 0, 4, SEXP_ACTION_OPERATOR, },
614  { "set-camera", OP_CUTSCENES_SET_CAMERA, 0, 1, SEXP_ACTION_OPERATOR, },
615  { "set-camera-position", OP_CUTSCENES_SET_CAMERA_POSITION, 3, 6, SEXP_ACTION_OPERATOR, },
616  { "set-camera-facing", OP_CUTSCENES_SET_CAMERA_FACING, 3, 6, SEXP_ACTION_OPERATOR, },
617  { "set-camera-facing-object", OP_CUTSCENES_SET_CAMERA_FACING_OBJECT, 1, 4, SEXP_ACTION_OPERATOR, },
618  { "set-camera-rotation", OP_CUTSCENES_SET_CAMERA_ROTATION, 3, 6, SEXP_ACTION_OPERATOR, },
619  { "set-camera-host", OP_CUTSCENES_SET_CAMERA_HOST, 1, 2, SEXP_ACTION_OPERATOR, },
620  { "set-camera-target", OP_CUTSCENES_SET_CAMERA_TARGET, 1, 2, SEXP_ACTION_OPERATOR, },
621  { "set-camera-fov", OP_CUTSCENES_SET_CAMERA_FOV, 1, 5, SEXP_ACTION_OPERATOR, },
622  { "set-fov", OP_CUTSCENES_SET_FOV, 1, 1, SEXP_ACTION_OPERATOR, },
623  { "get-fov", OP_CUTSCENES_GET_FOV, 0, 0, SEXP_INTEGER_OPERATOR, },
624  { "reset-fov", OP_CUTSCENES_RESET_FOV, 0, 0, SEXP_ACTION_OPERATOR, },
625  { "reset-camera", OP_CUTSCENES_RESET_CAMERA, 0, 1, SEXP_ACTION_OPERATOR, },
626  { "show-subtitle", OP_CUTSCENES_SHOW_SUBTITLE, 4, 13, SEXP_ACTION_OPERATOR, },
627  { "show-subtitle-text", OP_CUTSCENES_SHOW_SUBTITLE_TEXT, 6, 13, SEXP_ACTION_OPERATOR, },
628  { "show-subtitle-image", OP_CUTSCENES_SHOW_SUBTITLE_IMAGE, 8, 10, SEXP_ACTION_OPERATOR, },
629  { "clear-subtitles", OP_CLEAR_SUBTITLES, 0, 0, SEXP_ACTION_OPERATOR, },
630  { "lock-perspective", OP_CUTSCENES_FORCE_PERSPECTIVE, 1, 2, SEXP_ACTION_OPERATOR, },
631  { "set-camera-shudder", OP_SET_CAMERA_SHUDDER, 2, 2, SEXP_ACTION_OPERATOR, },
632  { "supernova-start", OP_SUPERNOVA_START, 1, 1, SEXP_ACTION_OPERATOR, },
633  { "supernova-stop", OP_SUPERNOVA_STOP, 0, 0, SEXP_ACTION_OPERATOR, }, //CommanderDJ
634  { "set-motion-debris-override", OP_SET_MOTION_DEBRIS, 1, 1, SEXP_ACTION_OPERATOR, }, // The E
635 
636  //Background and Nebula Sub-Category
637  { "mission-set-nebula", OP_MISSION_SET_NEBULA, 1, 1, SEXP_ACTION_OPERATOR, }, // Sesquipedalian
638  { "mission-set-subspace", OP_MISSION_SET_SUBSPACE, 1, 1, SEXP_ACTION_OPERATOR, },
639  { "add-background-bitmap", OP_ADD_BACKGROUND_BITMAP, 8, 9, SEXP_ACTION_OPERATOR, }, // phreak
640  { "remove-background-bitmap", OP_REMOVE_BACKGROUND_BITMAP, 1, 1, SEXP_ACTION_OPERATOR, }, // phreak
641  { "add-sun-bitmap", OP_ADD_SUN_BITMAP, 5, 6, SEXP_ACTION_OPERATOR, }, // phreak
642  { "remove-sun-bitmap", OP_REMOVE_SUN_BITMAP, 1, 1, SEXP_ACTION_OPERATOR, }, // phreak
643  { "nebula-change-storm", OP_NEBULA_CHANGE_STORM, 1, 1, SEXP_ACTION_OPERATOR, }, // phreak
644  { "nebula-toggle-poof", OP_NEBULA_TOGGLE_POOF, 2, 2, SEXP_ACTION_OPERATOR, }, // phreak
645  { "nebula-change-pattern", OP_NEBULA_CHANGE_PATTERN, 1, 1, SEXP_ACTION_OPERATOR, }, // Axem
646  { "set-skybox-model", OP_SET_SKYBOX_MODEL, 1, 8, SEXP_ACTION_OPERATOR, }, // taylor
647  { "set-skybox-orientation", OP_SET_SKYBOX_ORIENT, 3, 3, SEXP_ACTION_OPERATOR, }, // Goober5000
648  { "set-ambient-light", OP_SET_AMBIENT_LIGHT, 3, 3, SEXP_ACTION_OPERATOR, }, // Karajorma
649 
650  //Jump Node Sub-Category
651  { "set-jumpnode-name", OP_JUMP_NODE_SET_JUMPNODE_NAME, 2, 2, SEXP_ACTION_OPERATOR, }, //CommanderDJ
652  { "set-jumpnode-color", OP_JUMP_NODE_SET_JUMPNODE_COLOR, 5, 5, SEXP_ACTION_OPERATOR, },
653  { "set-jumpnode-model", OP_JUMP_NODE_SET_JUMPNODE_MODEL, 3, 3, SEXP_ACTION_OPERATOR, },
654  { "show-jumpnode", OP_JUMP_NODE_SHOW_JUMPNODE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
655  { "hide-jumpnode", OP_JUMP_NODE_HIDE_JUMPNODE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
656 
657  //Special Effects Sub-Category
658  { "set-post-effect", OP_SET_POST_EFFECT, 2, 2, SEXP_ACTION_OPERATOR, }, // Hery
659  { "ship-effect", OP_SHIP_EFFECT, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // Valathil
660  { "ship-create", OP_SHIP_CREATE, 5, 8, SEXP_ACTION_OPERATOR, }, // WMC
661  { "weapon-create", OP_WEAPON_CREATE, 5, 10, SEXP_ACTION_OPERATOR, }, // Goober5000
662  { "ship-vanish", OP_SHIP_VANISH, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
663  { "ship-vaporize", OP_SHIP_VAPORIZE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
664  { "ship-no-vaporize", OP_SHIP_NO_VAPORIZE, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
665  { "set-explosion-option", OP_SET_EXPLOSION_OPTION, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // Goober5000
666  { "explosion-effect", OP_EXPLOSION_EFFECT, 11, 13, SEXP_ACTION_OPERATOR, }, // Goober5000
667  { "warp-effect", OP_WARP_EFFECT, 12, 12, SEXP_ACTION_OPERATOR, }, // Goober5000
668  { "remove-weapons", OP_REMOVE_WEAPONS, 0, 1, SEXP_ACTION_OPERATOR, }, // Karajorma
669  { "set-time-compression", OP_CUTSCENES_SET_TIME_COMPRESSION, 1, 3, SEXP_ACTION_OPERATOR, },
670  { "reset-time-compression", OP_CUTSCENES_RESET_TIME_COMPRESSION, 0, 0, SEXP_ACTION_OPERATOR, },
671  { "call-ssm-strike", OP_CALL_SSM_STRIKE, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, // X3N0-Life-Form
672 
673  //Variable Category
674  { "modify-variable", OP_MODIFY_VARIABLE, 2, 2, SEXP_ACTION_OPERATOR, },
675  { "get-variable-by-index", OP_GET_VARIABLE_BY_INDEX, 1, 1, SEXP_INTEGER_OPERATOR, }, // Goober5000
676  { "set-variable-by-index", OP_SET_VARIABLE_BY_INDEX, 2, 2, SEXP_ACTION_OPERATOR, }, // Goober5000
677  { "copy-variable-from-index", OP_COPY_VARIABLE_FROM_INDEX, 2, 2, SEXP_ACTION_OPERATOR, }, // Goober5000
678  { "copy-variable-between-indexes", OP_COPY_VARIABLE_BETWEEN_INDEXES, 2, 2, SEXP_ACTION_OPERATOR, }, // Goober5000
679  { "int-to-string", OP_INT_TO_STRING, 2, 2, SEXP_ACTION_OPERATOR, }, // Goober5000
680  { "string-concatenate", OP_STRING_CONCATENATE, 3, 3, SEXP_ACTION_OPERATOR, }, // Goober5000
681  { "string-get-substring", OP_STRING_GET_SUBSTRING, 4, 4, SEXP_ACTION_OPERATOR, }, // Goober5000
682  { "string-set-substring", OP_STRING_SET_SUBSTRING, 5, 5, SEXP_ACTION_OPERATOR, }, // Goober5000
683 
684  //Other Sub-Category
685  { "damaged-escort-priority", OP_DAMAGED_ESCORT_LIST, 3, INT_MAX, SEXP_ACTION_OPERATOR, }, //phreak
686  { "damaged-escort-priority-all", OP_DAMAGED_ESCORT_LIST_ALL, 1, MAX_COMPLETE_ESCORT_LIST, SEXP_ACTION_OPERATOR, }, // Goober5000
687  { "set-support-ship", OP_SET_SUPPORT_SHIP, 6, 7, SEXP_ACTION_OPERATOR, }, // Goober5000
688  { "script-eval", OP_SCRIPT_EVAL, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
689  { "script-eval-block", OP_SCRIPT_EVAL_BLOCK, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
690  { "multi-eval", OP_SCRIPT_EVAL_MULTI, 2, INT_MAX, SEXP_ACTION_OPERATOR, },
691  { "debug", OP_DEBUG, 2, 2, SEXP_ACTION_OPERATOR, }, // Karajorma
692  { "do-nothing", OP_NOP, 0, 0, SEXP_ACTION_OPERATOR, },
693 
694  //AI Goals Category
695  { "ai-chase", OP_AI_CHASE, 2, 3, SEXP_GOAL_OPERATOR, },
696  { "ai-chase-wing", OP_AI_CHASE_WING, 2, 3, SEXP_GOAL_OPERATOR, },
697  { "ai-chase-any", OP_AI_CHASE_ANY, 1, 1, SEXP_GOAL_OPERATOR, },
698  { "ai-guard", OP_AI_GUARD, 2, 2, SEXP_GOAL_OPERATOR, },
699  { "ai-guard-wing", OP_AI_GUARD_WING, 2, 2, SEXP_GOAL_OPERATOR, },
700  { "ai-destroy-subsystem", OP_AI_DESTROY_SUBSYS, 3, 4, SEXP_GOAL_OPERATOR, },
701  { "ai-disable-ship", OP_AI_DISABLE_SHIP, 2, 3, SEXP_GOAL_OPERATOR, },
702  { "ai-disarm-ship", OP_AI_DISARM_SHIP, 2, 3, SEXP_GOAL_OPERATOR, },
703  { "ai-warp", OP_AI_WARP, 2, 2, SEXP_GOAL_OPERATOR, },
704  { "ai-warp-out", OP_AI_WARP_OUT, 1, 1, SEXP_GOAL_OPERATOR, },
705  { "ai-dock", OP_AI_DOCK, 4, 4, SEXP_GOAL_OPERATOR, },
706  { "ai-undock", OP_AI_UNDOCK, 1, 2, SEXP_GOAL_OPERATOR, },
707  { "ai-waypoints", OP_AI_WAYPOINTS, 2, 2, SEXP_GOAL_OPERATOR, },
708  { "ai-waypoints-once", OP_AI_WAYPOINTS_ONCE, 2, 2, SEXP_GOAL_OPERATOR, },
709  { "ai-ignore", OP_AI_IGNORE, 2, 2, SEXP_GOAL_OPERATOR, },
710  { "ai-ignore-new", OP_AI_IGNORE_NEW, 2, 2, SEXP_GOAL_OPERATOR, },
711  { "ai-stay-near-ship", OP_AI_STAY_NEAR_SHIP, 2, 2, SEXP_GOAL_OPERATOR, },
712  { "ai-evade-ship", OP_AI_EVADE_SHIP, 2, 2, SEXP_GOAL_OPERATOR, },
713  { "ai-keep-safe-distance", OP_AI_KEEP_SAFE_DISTANCE, 1, 1, SEXP_GOAL_OPERATOR, },
714  { "ai-stay-still", OP_AI_STAY_STILL, 2, 2, SEXP_GOAL_OPERATOR, },
715  { "ai-play-dead", OP_AI_PLAY_DEAD, 1, 1, SEXP_GOAL_OPERATOR, },
716  { "ai-form-on-wing", OP_AI_FORM_ON_WING, 1, 1, SEXP_GOAL_OPERATOR, },
717 
718  { "goals", OP_GOALS_ID, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
719 
720  //Training Category
721  { "key-pressed", OP_KEY_PRESSED, 1, 2, SEXP_BOOLEAN_OPERATOR, },
722  { "key-reset", OP_KEY_RESET, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
723  { "key-reset-multiple", OP_KEY_RESET_MULTIPLE, 1, INT_MAX, SEXP_ACTION_OPERATOR, },
724  { "ignore-key", OP_IGNORE_KEY, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, // Karajorma
725  { "targeted", OP_TARGETED, 1, 3, SEXP_BOOLEAN_OPERATOR, },
726  { "node-targeted", OP_NODE_TARGETED, 1, 2, SEXP_BOOLEAN_OPERATOR, }, // FUBAR
727  { "missile-locked", OP_MISSILE_LOCKED, 1, 3, SEXP_BOOLEAN_OPERATOR, }, // Sesquipedalian
728  { "speed", OP_SPEED, 1, 1, SEXP_BOOLEAN_OPERATOR, },
729  { "facing", OP_FACING, 2, 2, SEXP_BOOLEAN_OPERATOR, },
730  { "facing-waypoint", OP_FACING2, 2, 2, SEXP_BOOLEAN_OPERATOR, },
731  { "order", OP_ORDER, 2, 3, SEXP_BOOLEAN_OPERATOR, },
732  { "query-orders", OP_QUERY_ORDERS, 3, 6, SEXP_BOOLEAN_OPERATOR, }, // Karajorma
733  { "reset-orders", OP_RESET_ORDERS, 0, 0, SEXP_ACTION_OPERATOR, }, // Karajorma
734  { "waypoint-missed", OP_WAYPOINT_MISSED, 0, 0, SEXP_BOOLEAN_OPERATOR, },
735  { "waypoint-twice", OP_WAYPOINT_TWICE, 0, 0, SEXP_BOOLEAN_OPERATOR, },
736  { "path-flown", OP_PATH_FLOWN, 0, 0, SEXP_BOOLEAN_OPERATOR, },
737  { "training-msg", OP_TRAINING_MSG, 1, 4, SEXP_ACTION_OPERATOR, },
738  { "flash-hud-gauge", OP_FLASH_HUD_GAUGE, 1, 1, SEXP_ACTION_OPERATOR, },
739  { "primaries-depleted", OP_PRIMARIES_DEPLETED, 1, 1, SEXP_BOOLEAN_OPERATOR, },
740  { "secondaries-depleted", OP_SECONDARIES_DEPLETED, 1, 1, SEXP_BOOLEAN_OPERATOR, },
741  { "special-check", OP_SPECIAL_CHECK, 1, 1, SEXP_ACTION_OPERATOR, },
742  { "set-training-context-fly-path", OP_SET_TRAINING_CONTEXT_FLY_PATH, 2, 2, SEXP_ACTION_OPERATOR, },
743  { "set-training-context-speed", OP_SET_TRAINING_CONTEXT_SPEED, 2, 2, SEXP_ACTION_OPERATOR, },
744 };
745 
769 };
770 
772 {
773  "LEAD_INDICATOR",
774  "ORIENTATION_TEE",
775  "HOSTILE_TRIANGLE",
776  "TARGET_TRIANGLE",
777  "MISSION_TIME",
778  "RETICLE_CIRCLE",
779  "THROTTLE_GAUGE",
780  "RADAR",
781  "TARGET_MONITOR",
782  "CENTER_RETICLE",
783  "TARGET_MONITOR_EXTRA_DATA",
784  "TARGET_SHIELD_ICON",
785  "PLAYER_SHIELD_ICON",
786  "ETS_GAUGE",
787  "AUTO_TARGET",
788  "AUTO_SPEED",
789  "WEAPONS_GAUGE",
790  "ESCORT_VIEW",
791  "DIRECTIVES_VIEW",
792  "THREAT_GAUGE",
793  "AFTERBURNER_ENERGY",
794  "WEAPONS_ENERGY",
795  "WEAPON_LINKING_GAUGE",
796  "TARGER_MINI_ICON",
797  "OFFSCREEN_INDICATOR",
798  "TALKING_HEAD",
799  "DAMAGE_GAUGE",
800  "MESSAGE_LINES",
801  "MISSILE_WARNING_ARROW",
802  "CMEASURE_GAUGE",
803  "OBJECTIVES_NOTIFY_GAUGE",
804  "WINGMEN_STATUS",
805  "OFFSCREEN RANGE",
806  "KILLS GAUGE",
807  "ATTACKING TARGET COUNT",
808  "TEXT FLASH",
809  "MESSAGE BOX",
810  "SUPPORT GUAGE",
811  "LAG GUAGE"
812 };
813 
814 
815 void sexp_set_skybox_model_preload(char *name); // taylor
817 char *Skybox_flags[] = {
818  "force-clamp",
819  "add-lighting",
820  "no-transparency",
821  "add-zbuffer",
822  "add-culling",
823  "no-glowmaps",
824 };
825 
827 int Sexp_useful_number; // a variable to pass useful info in from external modules
829 int Num_operators = sizeof(Operators) / sizeof(sexp_oper);
831 int Sexp_clipboard = -1; // used by Fred
841 
842 #define SEXP_NODE_INCREMENT 250
845 
847 sexp_variable Block_variables[MAX_SEXP_VARIABLES]; // used for compatibility with retail.
848 
850 
852 
854 int Players_mlocked = UNINITIALIZED; // for is-missile-locked - Sesquipedalian
858 
859 // for play-music - Goober5000
861 void sexp_stop_music(int fade = 1);
862 
863 // for sound environments - Goober5000/Taylor
864 #define SEO_VOLUME 0
865 #define SEO_DECAY_TIME 1
866 #define SEO_DAMPING 2
868 char *Sound_environment_option[] = { "volume", "decay time", "damping" };
870 
871 // for adjust-audio-volume - The E
872 char *Adjust_audio_options[] = { "Music", "Voice", "Effects" };
874 int audio_volume_option_lookup(char *text);
875 
876 int hud_gauge_type_lookup(char* name);
877 
878 // for explosions - Goober5000
879 #define EO_DAMAGE 0
880 #define EO_BLAST 1
881 #define EO_INNER_RADIUS 2
882 #define EO_OUTER_RADIUS 3
883 #define EO_SHOCKWAVE_SPEED 4
884 #define EO_DEATH_ROLL_TIME 5
885 int sexp_explosion_option_lookup(char *text);
886 char *Explosion_option[] = { "damage", "blast", "inner radius", "outer radius", "shockwave speed", "death roll time" };
888 
889 int get_sexp();
890 void build_extended_sexp_string(SCP_string &accumulator, int cur_node, int level, int mode);
891 void update_sexp_references(const char *old_name, const char *new_name, int format, int node);
892 int sexp_determine_team(char *subj);
893 int extract_sexp_variable_index(int node);
894 void init_sexp_vars();
895 int eval_num(int node);
896 
897 // for handling variables
898 void add_block_variable(const char *text, const char *var_name, int type, int index);
899 void sexp_modify_variable(int node);
900 int sexp_get_variable_by_index(int node);
901 void sexp_set_variable_by_index(int node);
902 void sexp_copy_variable_from_index(int node);
904 
908 
909 // Goober5000
911 bool is_blank_argument_op(int op_const);
912 bool is_blank_of_op(int op_const);
913 
914 int get_handler_for_x_of_operator(int node);
915 
916 //Karajorma
917 int get_generic_subsys(char *subsy_name);
918 bool ship_class_unchanged(int ship_index);
920 
921 int get_effect_from_name(char* name);
922 
923 #define NO_OPERATOR_INDEX_DEFINED -2
924 #define NOT_A_SEXP_OPERATOR -1
925 
926 // Karajorma - some useful helper methods
927 player * get_player_from_ship_node(int node, bool test_respawns = false);
928 ship * sexp_get_ship_from_node(int node);
929 
930 // hud-display-gauge magic values
931 #define SEXP_HUD_GAUGE_WARPOUT "warpout"
932 
933 // event log stuff
937 // Goober5000 - arg_item class stuff, borrowed from sexp_list_item class stuff -------------
938 void arg_item::add_data(char *str)
939 {
940  arg_item *item, *ptr;
941 
942  // create item
943  item = new arg_item;
944  item->text = str;
946 
947  // prepend item to existing list
948  ptr = this->next;
949  this->next = item;
950  item->next = ptr;
951 }
952 
953 void arg_item::add_data_dup(char *str)
954 {
955  arg_item *item, *ptr;
956 
957  // create item
958  item = new arg_item;
959  item->text = vm_strdup(str);
960  item->flags |= ARG_ITEM_F_DUP;
962 
963  // prepend item to existing list
964  ptr = this->next;
965  this->next = item;
966  item->next = ptr;
967 }
968 
970 {
971  arg_item *item, *ptr;
972 
973  // create item
974  item = new arg_item;
975  item->text = str;
976  item->flags |= ARG_ITEM_F_DUP;
978 
979  // prepend item to existing list
980  ptr = this->next;
981  this->next = item;
982  item->next = ptr;
983 }
984 
986 {
987  if (this->next != NULL) {
988  if (this->next->nesting_level >= Sexp_current_argument_nesting_level) {
989  return this->next;
990  }
991  }
992 
993  return NULL;
994 }
995 
997 {
998  arg_item *ptr;
999 
1000  // contiually delete first item of list
1001  while (this->next != NULL)
1002  {
1003  ptr = this->next->next;
1004 
1005  if (this->next->flags & ARG_ITEM_F_DUP)
1006  vm_free(this->next->text);
1007  delete this->next;
1008 
1009  this->next = ptr;
1010  }
1011 }
1012 
1014 {
1015  arg_item *ptr;
1016 
1017  // contiually delete first item of list
1018  while (this->next != NULL && this->next->nesting_level >= Sexp_current_argument_nesting_level )
1019  {
1020  ptr = this->next->next;
1021 
1022  if (this->next->flags & ARG_ITEM_F_DUP)
1023  vm_free(this->next->text);
1024  delete this->next;
1025 
1026  this->next = ptr;
1027  }
1028 }
1029 
1031 {
1032  return (this->next == NULL);
1033 }
1034 //-------------------------------------------------------------------------------------------------
1035 
1037 {
1038  if (Num_sexp_nodes == 0 || Sexp_nodes == NULL)
1039  return;
1040 
1041  nprintf(("SEXP", "Reinitializing sexp nodes...\n"));
1042  nprintf(("SEXP", "Entered function with %d nodes.\n", Num_sexp_nodes));
1043 
1044  // usually, the persistent nodes are grouped at the beginning of the array;
1045  // so we ought to be able to free all the subsequent nodes
1046  int i, last_persistent_node = -1;
1047 
1048  for (i = 0; i < Num_sexp_nodes; i++)
1049  {
1050  if (Sexp_nodes[i].type & SEXP_FLAG_PERSISTENT)
1051  last_persistent_node = i; // keep track of it
1052  else
1053  Sexp_nodes[i].type = SEXP_NOT_USED; // it's not needed
1054  }
1055 
1056  nprintf(("SEXP", "Last persistent node index is %d.\n", last_persistent_node));
1057 
1058  // if all the persistent nodes are gone, free all the nodes
1059  if (last_persistent_node == -1)
1060  {
1061  vm_free(Sexp_nodes);
1062  Sexp_nodes = NULL;
1063  Num_sexp_nodes = 0;
1064  }
1065  // if there's enough of a difference to make it worthwhile, free some nodes
1066  else if (Num_sexp_nodes - (last_persistent_node + 1) > 2 * SEXP_NODE_INCREMENT)
1067  {
1068  // round it up to the next evenly divisible size
1069  Num_sexp_nodes = (last_persistent_node + 1);
1070  Num_sexp_nodes += SEXP_NODE_INCREMENT - (Num_sexp_nodes % SEXP_NODE_INCREMENT);
1071 
1072  Sexp_nodes = (sexp_node *) vm_realloc(Sexp_nodes, sizeof(sexp_node) * Num_sexp_nodes);
1073  Verify(Sexp_nodes != NULL);
1074  }
1075 
1076  nprintf(("SEXP", "Exited function with %d nodes.\n", Num_sexp_nodes));
1077 }
1078 
1079 static void sexp_nodes_close()
1080 {
1081  // free all sexp nodes... should only be done on game shutdown
1082  if (Sexp_nodes != NULL)
1083  {
1084  vm_free(Sexp_nodes);
1085  Sexp_nodes = NULL;
1086  Num_sexp_nodes = 0;
1087  }
1088 }
1089 
1091 {
1092  // Goober5000
1093  Sexp_replacement_arguments.clear();
1094  Sexp_applicable_argument_list.expunge();
1095  Sexp_current_argument_nesting_level = 0;
1097 
1098  static bool done_sexp_atexit = false;
1099  if (!done_sexp_atexit)
1100  {
1101  atexit(sexp_nodes_close);
1102  done_sexp_atexit = true;
1103  }
1104 
1105  sexp_nodes_init();
1106  init_sexp_vars();
1108 
1110  Assert(Locked_sexp_false != -1);
1111  Sexp_nodes[Locked_sexp_false].type = SEXP_ATOM; // fix bypassing value
1113 
1115  Assert(Locked_sexp_true != -1);
1116  Sexp_nodes[Locked_sexp_true].type = SEXP_ATOM; // fix bypassing value
1117  Sexp_nodes[Locked_sexp_true].value = SEXP_KNOWN_TRUE;
1118 }
1119 
1123 int alloc_sexp(char *text, int type, int subtype, int first, int rest)
1124 {
1125  int node;
1126  int sexp_const = get_operator_const(text);
1127 
1128  if ((sexp_const == OP_TRUE) && (type == SEXP_ATOM) && (subtype == SEXP_ATOM_OPERATOR))
1129  return Locked_sexp_true;
1130 
1131  else if ((sexp_const == OP_FALSE) && (type == SEXP_ATOM) && (subtype == SEXP_ATOM_OPERATOR))
1132  return Locked_sexp_false;
1133 
1134  node = find_free_sexp();
1135 
1136  // need more sexp nodes?
1137  if (node == Num_sexp_nodes || node == -1)
1138  {
1139  int old_size = Num_sexp_nodes;
1140 
1142 
1143  // allocate in blocks of SEXP_NODE_INCREMENT
1144  Num_sexp_nodes += SEXP_NODE_INCREMENT;
1145  Sexp_nodes = (sexp_node *) vm_realloc(Sexp_nodes, sizeof(sexp_node) * Num_sexp_nodes);
1146 
1147  Verify(Sexp_nodes != NULL);
1148  nprintf(("SEXP", "Bumping dynamic sexp node limit from %d to %d...\n", old_size, Num_sexp_nodes));
1149 
1150  // clear all the new sexp nodes we just allocated
1151  memset(&Sexp_nodes[old_size], 0, sizeof(sexp_node) * SEXP_NODE_INCREMENT); //-V512
1152 
1153  // our new sexp is the first out of the ones we just created
1154  node = old_size;
1155  }
1156 
1157  Assert(node != Locked_sexp_true);
1158  Assert(node != Locked_sexp_false);
1159  Assert(strlen(text) < TOKEN_LENGTH);
1160  Assert(type >= 0);
1161 
1162  strcpy_s(Sexp_nodes[node].text, text);
1163  Sexp_nodes[node].type = type;
1164  Sexp_nodes[node].subtype = subtype;
1165  Sexp_nodes[node].first = first;
1166  Sexp_nodes[node].rest = rest;
1167  Sexp_nodes[node].value = SEXP_UNKNOWN;
1168  Sexp_nodes[node].flags = SNF_DEFAULT_VALUE; // Goober5000
1169  Sexp_nodes[node].op_index = NO_OPERATOR_INDEX_DEFINED;
1170 
1171  return node;
1172 }
1173 
1174 static int Sexp_hwm = 0;
1175 
1177 {
1178  int i, f = 0, p = 0;
1179 
1180  for (i = 0; i < Num_sexp_nodes; i++)
1181  {
1182  if (Sexp_nodes[i].type == SEXP_NOT_USED)
1183  f++;
1184  else if (Sexp_nodes[i].type & SEXP_FLAG_PERSISTENT)
1185  p++;
1186  }
1187 
1188  if (Num_sexp_nodes - f > Sexp_hwm)
1189  {
1190  nprintf(("Sexp", "Sexp nodes: Free=%d, Used=%d, Persistent=%d\n", f, Num_sexp_nodes - f, p));
1191  Sexp_hwm = Num_sexp_nodes - f;
1192  }
1193 
1194  return f;
1195 }
1196 
1201 {
1202  int i;
1203 
1204  // sanity
1205  if (Num_sexp_nodes == 0 || Sexp_nodes == NULL)
1206  return -1;
1207 
1208  for (i = 0; i < Num_sexp_nodes; i++)
1209  {
1210  if (Sexp_nodes[i].type == SEXP_NOT_USED)
1211  return i;
1212  }
1213 
1214  return -1;
1215 }
1216 
1221 {
1222  if (n == -1){
1223  return;
1224  }
1225 
1226  // total hack because of the true/false locked sexps -- we should make those persistent as well
1227  if ( (n == Locked_sexp_true) || (n == Locked_sexp_false) ){
1228  return;
1229  }
1230 
1231  Assert( !(Sexp_nodes[n].type & SEXP_FLAG_PERSISTENT) );
1232  Sexp_nodes[n].type |= SEXP_FLAG_PERSISTENT;
1233 
1234  sexp_mark_persistent(Sexp_nodes[n].first);
1235  sexp_mark_persistent(Sexp_nodes[n].rest);
1236 
1237 }
1238 
1243 {
1244  if (n == -1){
1245  return;
1246  }
1247 
1248  if ( (n == Locked_sexp_true) || (n == Locked_sexp_false) ){
1249  return;
1250  }
1251 
1252  Assert( Sexp_nodes[n].type & SEXP_FLAG_PERSISTENT );
1253  Sexp_nodes[n].type &= ~SEXP_FLAG_PERSISTENT;
1254 
1255  sexp_unmark_persistent(Sexp_nodes[n].first);
1256  sexp_unmark_persistent(Sexp_nodes[n].rest);
1257 }
1258 
1263 {
1264  Assert((num >= 0) && (num < Num_sexp_nodes));
1265  Assert(Sexp_nodes[num].type != SEXP_NOT_USED); // make sure it is actually used
1266  Assert(!(Sexp_nodes[num].type & SEXP_FLAG_PERSISTENT));
1267 
1268  if ((num == Locked_sexp_true) || (num == Locked_sexp_false))
1269  return 0;
1270 
1271  Sexp_nodes[num].type = SEXP_NOT_USED;
1272  return 1;
1273 }
1274 
1281 int free_sexp(int num)
1282 {
1283  int i, rest, count = 0;
1284 
1285  Assert((num >= 0) && (num < Num_sexp_nodes));
1286  Assert(Sexp_nodes[num].type != SEXP_NOT_USED); // make sure it is actually used
1287  Assert(!(Sexp_nodes[num].type & SEXP_FLAG_PERSISTENT));
1288 
1289  if ((num == Locked_sexp_true) || (num == Locked_sexp_false))
1290  return 0;
1291 
1292  Sexp_nodes[num].type = SEXP_NOT_USED;
1293  count++;
1294 
1295  i = Sexp_nodes[num].first;
1296  while (i != -1)
1297  {
1298  count += free_sexp(i);
1299  i = Sexp_nodes[i].rest;
1300  }
1301 
1302  rest = Sexp_nodes[num].rest;
1303  for (i = 0; i < Num_sexp_nodes; i++)
1304  {
1305  if (Sexp_nodes[i].first == num)
1306  Sexp_nodes[i].first = rest;
1307 
1308  if (Sexp_nodes[i].rest == num)
1309  Sexp_nodes[i].rest = rest;
1310  }
1311 
1312  return count; // total elements freed up.
1313 }
1314 
1321 int free_sexp2(int num)
1322 {
1323  int i, count = 0;
1324 
1325  if ((num == -1) || (num == Locked_sexp_true) || (num == Locked_sexp_false)){
1326  return 0;
1327  }
1328 
1329  i = Sexp_nodes[num].rest;
1330  while (i != -1) {
1331  count += free_sexp(i);
1332  i = Sexp_nodes[i].rest;
1333  }
1334 
1335  count += free_sexp(num);
1336  return count;
1337 }
1338 
1342 void flush_sexp_tree(int node)
1343 {
1344  if (node < 0){
1345  return;
1346  }
1347 
1348  Sexp_nodes[node].value = SEXP_UNKNOWN;
1349  flush_sexp_tree(Sexp_nodes[node].first);
1350  flush_sexp_tree(Sexp_nodes[node].rest);
1351 }
1352 
1353 int verify_sexp_tree(int node)
1354 {
1355  if (node == -1){
1356  return 0;
1357  }
1358 
1359  if ((Sexp_nodes[node].type == SEXP_NOT_USED) ||
1360  (Sexp_nodes[node].first == node) ||
1361  (Sexp_nodes[node].rest == node)) {
1362  Error(LOCATION, "Sexp node is corrupt");
1363  return -1;
1364  }
1365 
1366  if (Sexp_nodes[node].first != -1){
1367  verify_sexp_tree(Sexp_nodes[node].first);
1368  }
1369  if (Sexp_nodes[node].rest != -1){
1370  verify_sexp_tree(Sexp_nodes[node].rest);
1371  }
1372 
1373  return 0;
1374 }
1375 
1379 int dup_sexp_chain(int node)
1380 {
1381  int cur, first, rest;
1382 
1383  if (node == -1){
1384  return -1;
1385  }
1386 
1387  // TODO - CASE OF SEXP VARIABLES - ONLY 1 COPY OF VARIABLE
1388  first = dup_sexp_chain(Sexp_nodes[node].first);
1389  rest = dup_sexp_chain(Sexp_nodes[node].rest);
1390  cur = alloc_sexp(Sexp_nodes[node].text, Sexp_nodes[node].type, Sexp_nodes[node].subtype, first, rest);
1391 
1392  if (cur == -1) {
1393  if (first != -1){
1394  free_sexp(first);
1395  }
1396  if (rest != -1){
1397  free_sexp(rest);
1398  }
1399  }
1400 
1401  return cur;
1402 }
1403 
1408 int cmp_sexp_chains(int node1, int node2)
1409 {
1410  if ((node1 == -1) && (node2 == -1)){
1411  return 1;
1412  }
1413 
1414  if ((node1 == -1) || (node2 == -1)){
1415  return 0;
1416  }
1417 
1418  // DA: 1/7/99 Need to check the actual Sexp_node.text, not possible variable, which can be equal
1419  if (stricmp(Sexp_nodes[node1].text, Sexp_nodes[node2].text)){
1420  return 0;
1421  }
1422 
1423  if (!cmp_sexp_chains(Sexp_nodes[node1].first, Sexp_nodes[node2].first)){
1424  return 0;
1425  }
1426 
1427  if (!cmp_sexp_chains(Sexp_nodes[node1].rest, Sexp_nodes[node2].rest)){
1428  return 0;
1429  }
1430 
1431  return 1;
1432 }
1433 
1437 int query_node_in_sexp(int node, int sexp)
1438 {
1439  if (sexp == -1){
1440  return 0;
1441  }
1442  if (node == sexp){
1443  return 1;
1444  }
1445 
1446  if (query_node_in_sexp(node, Sexp_nodes[sexp].first)){
1447  return 1;
1448  }
1449  if (query_node_in_sexp(node, Sexp_nodes[sexp].rest)){
1450  return 1;
1451  }
1452 
1453  return 0;
1454 }
1455 
1460 {
1461  int i;
1462 
1463  for (i = 0; i < Num_sexp_nodes; i++)
1464  {
1465  if (Sexp_nodes[i].first == num)
1466  return i;
1467  }
1468 
1469  // not found
1470  return -1;
1471 }
1472 
1477 {
1478  int i;
1479  Assert((node >= 0) && (node < Num_sexp_nodes));
1480 
1481  if (Sexp_nodes[node].subtype == SEXP_ATOM_OPERATOR)
1482  {
1483  node = find_sexp_list(node);
1484 
1485  // are we already at the top of the list? this will happen for non-standard sexps
1486  // (sexps that fire instantly instead of using a conditional) such as:
1487  // $Formula: ( do-nothing )
1488  if (node < 0)
1489  return -1;
1490  }
1491 
1492  // iterate backwards through the sexps nodes (i.e. do the inverse of CDR)
1493  while (Sexp_nodes[node].subtype != SEXP_ATOM_OPERATOR)
1494  {
1495  for (i = 0; i < Num_sexp_nodes; i++)
1496  {
1497  if (Sexp_nodes[i].rest == node)
1498  break;
1499  }
1500 
1501  if (i == Num_sexp_nodes)
1502  return -1; // not found, probably at top node already.
1503 
1504  node = i;
1505  }
1506 
1507  return node;
1508 }
1509 
1515 int is_sexp_top_level( int node )
1516 {
1517  int i;
1518 
1519  Assert((node >= 0) && (node < Num_sexp_nodes));
1520 
1521  if (Sexp_nodes[node].type == SEXP_NOT_USED)
1522  return 0;
1523 
1524  for (i = 0; i < Num_sexp_nodes; i++)
1525  {
1526  if ((Sexp_nodes[i].type == SEXP_NOT_USED) || (i == node )) // don't check myself or unused nodes
1527  continue;
1528 
1529  if ((Sexp_nodes[i].first == node) || (Sexp_nodes[i].rest == node))
1530  return 0;
1531  }
1532 
1533  return 1;
1534 }
1535 
1539 int find_argnum(int parent, int arg)
1540 {
1541  int n, tally;
1542 
1543  n = CDR(parent);
1544  tally = 0;
1545 
1546  while (CAR(n) != arg)
1547  {
1548  if (n == -1)
1549  return -1;
1550 
1551  tally++;
1552  n = CDR(n);
1553  }
1554 
1555  return tally;
1556 }
1557 
1561 int get_operator_index(const char *token)
1562 {
1563  int i;
1564  Assertion(token != NULL, "get_operator_index(char*) called with a null token; get a coder!\n");
1565 
1566  for (i=0; i<Num_operators; i++){
1567  if (!stricmp(token, Operators[i].text)){
1568  return i;
1569  }
1570  }
1571 
1572  return NOT_A_SEXP_OPERATOR;
1573 }
1574 
1578 int get_operator_index(int node)
1579 {
1580  Assertion(node >= 0 && node < Num_sexp_nodes, "Passed an out-of-range node index (%d) to get_operator_index(int)!", node);
1581 
1582  if (!Fred_running && (Sexp_nodes[node].op_index != NO_OPERATOR_INDEX_DEFINED) ) {
1583  return Sexp_nodes[node].op_index;
1584  }
1585 
1586  int index = get_operator_index(Sexp_nodes[node].text);
1587  Sexp_nodes[node].op_index = index;
1588  return index;
1589 }
1590 
1591 
1595 int get_operator_const(const char *token)
1596 {
1597  int idx = get_operator_index(token);
1598 
1599  if (idx == NOT_A_SEXP_OPERATOR)
1600  return 0;
1601 
1602  return Operators[idx].value;
1603 }
1604 
1605 int get_operator_const(int node)
1606 {
1607  if (!Fred_running && Sexp_nodes[node].op_index >= 0) {
1608  return Operators[Sexp_nodes[node].op_index].value;
1609  }
1610 
1611  int idx = get_operator_index(node);
1612 
1613  if (idx == NOT_A_SEXP_OPERATOR)
1614  return 0;
1615 
1616  return Operators[idx].value;
1617 }
1618 
1619 int query_sexp_args_count(int node, bool only_valid_args = false)
1620 {
1621  int count = 0;
1622  int n = CDR(node);
1623 
1624  for ( ; n != -1; n = CDR(n))
1625  {
1626  if (only_valid_args && !(Sexp_nodes[n].flags & SNF_ARGUMENT_VALID))
1627  continue;
1628 
1629  count++;
1630  }
1631 
1632  return count;
1633 }
1634 
1641 {
1642  if (count < Operators[op].min || count > Operators[op].max)
1643  return 0;
1644 
1645  //send-message-list has arguments as blocks of 4
1646  if (op == OP_SEND_MESSAGE_LIST)
1647  if (count % 4 != 0)
1648  return 0;
1649 
1650  return 1;
1651 }
1652 
1658 int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, int mode)
1659 {
1660  int i = 0, z, t, type, argnum = 0, count, op, type2 = 0, op2;
1661  int op_node;
1662  int var_index = -1;
1663  size_t st;
1664 
1665  Assert(node >= 0 && node < Num_sexp_nodes);
1666  Assert(Sexp_nodes[node].type != SEXP_NOT_USED);
1667  if (Sexp_nodes[node].subtype == SEXP_ATOM_NUMBER && return_type == OPR_BOOL) {
1668  // special case Mark seems to want supported
1669  Assert(Sexp_nodes[node].first == -1); // only lists should have a first pointer
1670  if (Sexp_nodes[node].rest != -1) // anything after the number?
1671  return SEXP_CHECK_NONOP_ARGS; // if so, it's a syntax error
1672 
1673  return 0;
1674  }
1675 
1676  op_node = node; // save the node of the operator since we need to get to other args.
1677  if (bad_node)
1678  *bad_node = op_node;
1679 
1680  if (Sexp_nodes[op_node].subtype != SEXP_ATOM_OPERATOR)
1681  return SEXP_CHECK_OP_EXPECTED; // not an operator, which it should always be
1682 
1683  op = get_operator_index(CTEXT(op_node));
1684  if (op == -1)
1685  return SEXP_CHECK_UNKNOWN_OP; // unrecognized operator
1686 
1687  // check that types match - except that OPR_AMBIGUOUS matches everything
1688  if (return_type != OPR_AMBIGUOUS)
1689  {
1690  // get the return type of the next thing
1692  if (z == OPR_POSITIVE && return_type == OPR_NUMBER)
1693  {
1694  // positive data type can map to number data type just fine
1695  }
1696  // Goober5000's number hack
1697  else if (z == OPR_NUMBER && return_type == OPR_POSITIVE)
1698  {
1699  // this isn't kosher, but we hack it to make it work
1700  }
1701  else if (z != return_type)
1702  {
1703  // anything else is a mismatch
1704  return SEXP_CHECK_TYPE_MISMATCH;
1705  }
1706  }
1707 
1708  count = query_sexp_args_count(op_node);
1709 
1711  return SEXP_CHECK_BAD_ARG_COUNT; // incorrect number of arguments
1712 
1713  // Goober5000 - if this is a list of stuff that has the special argument as
1714  // an item in the list, assume it's valid
1716  return 0;
1717 
1718  node = Sexp_nodes[op_node].rest;
1719  while (node != -1) {
1720  type = query_operator_argument_type(op, argnum);
1721  Assert(Sexp_nodes[node].type != SEXP_NOT_USED);
1722  if (bad_node)
1723  *bad_node = node;
1724 
1725  if (Sexp_nodes[node].subtype == SEXP_ATOM_LIST) {
1726  i = Sexp_nodes[node].first;
1727  if (bad_node)
1728  *bad_node = i;
1729 
1730  // be sure to check to see if this node is a list of stuff and not an actual operator type
1731  // thing. (i.e. in the case of a cond statement, the conditional will fall into this if
1732  // statement. MORE TO DO HERE!!!!
1733  if (Sexp_nodes[i].subtype == SEXP_ATOM_LIST)
1734  return 0;
1735 
1736  op2 = get_operator_index(CTEXT(i));
1737  if (op2 == -1)
1738  return SEXP_CHECK_UNKNOWN_OP;
1739 
1740  type2 = query_operator_return_type(op2);
1741  if (recursive) {
1742  switch (type) {
1743  case OPF_NUMBER:
1744  t = OPR_NUMBER;
1745  break;
1746 
1747  case OPF_POSITIVE:
1748  t = OPR_POSITIVE;
1749  break;
1750 
1751  case OPF_BOOL:
1752  t = OPR_BOOL;
1753  break;
1754 
1755  case OPF_NULL:
1756  t = OPR_NULL;
1757  break;
1758 
1759  // Goober5000
1760  case OPF_FLEXIBLE_ARGUMENT:
1762  break;
1763 
1764  case OPF_AI_GOAL:
1765  t = OPR_AI_GOAL;
1766  break;
1767 
1768  // special case for modify-variable
1769  case OPF_AMBIGUOUS:
1770  t = OPR_AMBIGUOUS;
1771  break;
1772 
1773  default:
1774  return SEXP_CHECK_UNKNOWN_TYPE; // no other return types available
1775  }
1776 
1777  if ((z = check_sexp_syntax(i, t, recursive, bad_node)) != 0) {
1778  return z;
1779  }
1780  }
1781 
1782  } else if (Sexp_nodes[node].subtype == SEXP_ATOM_NUMBER) {
1783  char *ptr;
1784 
1785  type2 = OPR_POSITIVE;
1786  ptr = CTEXT(node);
1787  if (*ptr == '-') {
1788  type2 = OPR_NUMBER;
1789  ptr++;
1790  }
1791 
1792  if (type == OPF_BOOL) // allow numbers to be used where boolean is required.
1793  type2 = OPR_BOOL;
1794 
1795  while (*ptr) {
1796  if (!isdigit(*ptr))
1797  return SEXP_CHECK_INVALID_NUM; // not a valid number
1798 
1799  ptr++;
1800  }
1801 
1802  i = atoi(CTEXT(node));
1803  z = get_operator_const(CTEXT(op_node));
1804  if ( (z == OP_HAS_DOCKED_DELAY) || (z == OP_HAS_UNDOCKED_DELAY) )
1805  if ( (argnum == 2) && (i < 1) )
1807 
1808  // valid color range 0 to 255 - FUBAR
1809  if ((z == OP_CHANGE_IFF_COLOR) && ((argnum >= 2) && (argnum <= 4)))
1810  {
1811  if ( i < 0 || i > 255)
1812  {
1814  }
1815  }
1816 
1817  z = get_operator_index(CTEXT(op_node));
1818  if ( (query_operator_return_type(z) == OPR_AI_GOAL) && (argnum == Operators[op].min - 1) )
1819  if ( (i < 0) || (i > 200) )
1821 
1822  } else if (Sexp_nodes[node].subtype == SEXP_ATOM_STRING) {
1823  type2 = SEXP_ATOM_STRING;
1824 
1825  } else {
1826  Assert(0);
1827  }
1828 
1829  // variables should only be typechecked.
1830  if ((Sexp_nodes[node].type & SEXP_FLAG_VARIABLE) && (type != OPF_VARIABLE_NAME)) {
1831  var_index = get_index_sexp_variable_from_node(node);
1832  Assert(var_index != -1);
1833 
1834  switch (type) {
1835  case OPF_NUMBER:
1836  case OPF_POSITIVE:
1837  if (!(Sexp_variables[var_index].type & SEXP_VARIABLE_NUMBER))
1839  break;
1840 
1841  case OPF_AMBIGUOUS:
1842  break;
1843 
1844  default:
1845  if (!(Sexp_variables[var_index].type & SEXP_VARIABLE_STRING))
1847  }
1848  node = Sexp_nodes[node].rest;
1849  argnum++;
1850  continue;
1851  }
1852 
1853  switch (type) {
1854  case OPF_NAV_POINT:
1855  if (type2 != SEXP_ATOM_STRING){
1856  return SEXP_CHECK_TYPE_MISMATCH;
1857  }
1858  break;
1859 
1860  case OPF_NUMBER:
1861  if ((type2 != OPR_NUMBER) && (type2 != OPR_POSITIVE)){
1862  return SEXP_CHECK_TYPE_MISMATCH;
1863  }
1864 
1865  break;
1866 
1867  case OPF_POSITIVE:
1868  if (type2 == OPR_NUMBER){
1869  // Goober5000's number hack
1870  break;
1871  // return SEXP_CHECK_NEGATIVE_NUM;
1872  }
1873 
1874  if (type2 != OPR_POSITIVE){
1875  return SEXP_CHECK_TYPE_MISMATCH;
1876  }
1877 
1878  break;
1879 
1880  case OPF_SHIP_NOT_PLAYER:
1881  if (type2 != SEXP_ATOM_STRING){
1882  return SEXP_CHECK_TYPE_MISMATCH;
1883  }
1884 
1885  if (ship_name_lookup(CTEXT(node), 0) < 0)
1886  {
1888  {
1889  return SEXP_CHECK_INVALID_SHIP;
1890  }
1891  }
1892 
1893  break;
1894 
1895  case OPF_SHIP_OR_NONE:
1896  if (type2 != SEXP_ATOM_STRING)
1897  {
1898  return SEXP_CHECK_TYPE_MISMATCH;
1899  }
1900 
1901  if (stricmp(CTEXT(node), SEXP_NONE_STRING)) // none is okay
1902  {
1903  if (ship_name_lookup(CTEXT(node), 1) < 0)
1904  {
1906  {
1907  return SEXP_CHECK_INVALID_SHIP;
1908  }
1909  }
1910  }
1911 
1912  break;
1913 
1914  case OPF_SHIP:
1915  case OPF_SHIP_POINT:
1916  if (type2 != SEXP_ATOM_STRING){
1917  return SEXP_CHECK_TYPE_MISMATCH;
1918  }
1919 
1920  if (ship_name_lookup(CTEXT(node), 1) < 0) {
1922  {
1923  if (type == OPF_SHIP)
1924  { // return invalid ship if not also looking for point
1925  return SEXP_CHECK_INVALID_SHIP;
1926  }
1927 
1928  if (find_matching_waypoint(CTEXT(node)) == NULL)
1929  {
1930  if (verify_vector(CTEXT(node))) // verify return non-zero on invalid point
1931  {
1932  return SEXP_CHECK_INVALID_POINT;
1933  }
1934  }
1935  }
1936  }
1937 
1938  break;
1939 
1940  case OPF_WING:
1941  if (type2 != SEXP_ATOM_STRING){
1942  return SEXP_CHECK_TYPE_MISMATCH;
1943  }
1944 
1945  if (wing_name_lookup(CTEXT(node), 1) < 0){
1946  return SEXP_CHECK_INVALID_WING;
1947  }
1948 
1949  break;
1950 
1951  case OPF_SHIP_WING:
1954  case OPF_SHIP_WING_POINT:
1956  case OPF_ORDER_RECIPIENT:
1957  if ( type2 != SEXP_ATOM_STRING ){
1958  return SEXP_CHECK_TYPE_MISMATCH;
1959  }
1960 
1961  if (type == OPF_ORDER_RECIPIENT) {
1962  if (!strcmp ("<all fighters>", CTEXT(node))) {
1963  break;
1964  }
1965  }
1966 
1967  // all of these have ships and wings in common
1968  if (ship_name_lookup(CTEXT(node), 1) >= 0 || wing_name_lookup(CTEXT(node), 1) >= 0) {
1969  break;
1970  }
1971  // also check arrival list if we're running the game
1973  break;
1974  }
1975 
1976  // none is okay for _OR_NONE
1977  if (type == OPF_SHIP_WING_POINT_OR_NONE && !stricmp(CTEXT(node), SEXP_NONE_STRING)) {
1978  break;
1979  }
1980 
1981  // two different ways of checking teams
1982  if ((type == OPF_SHIP_WING_WHOLETEAM) && iff_lookup(CTEXT(node)) >= 0) {
1983  break;
1984  }
1985  if ((type == OPF_SHIP_WING_SHIPONTEAM_POINT) && sexp_determine_team(CTEXT(node)) >= 0) {
1986  break;
1987  }
1988 
1989  // only other possibility is waypoints
1991  if (find_matching_waypoint(CTEXT(node)) == NULL){
1992  if (verify_vector(CTEXT(node))){ // non-zero on verify vector mean invalid!
1993  return SEXP_CHECK_INVALID_POINT;
1994  }
1995  }
1996  break;
1997  }
1998 
1999  // nothing left
2001 
2002  case OPF_AWACS_SUBSYSTEM:
2004  case OPF_SUBSYSTEM:
2005  case OPF_SUBSYSTEM_OR_NONE:
2006  case OPF_SUBSYS_OR_GENERIC:
2007  {
2008  char *shipname;
2009  int shipnum,ship_class;
2010  int ship_index;
2011 
2012  if (type2 != SEXP_ATOM_STRING){
2013  return SEXP_CHECK_TYPE_MISMATCH;
2014  }
2015 
2016  // none is okay for subsys_or_none
2017  if (type == OPF_SUBSYSTEM_OR_NONE && !stricmp(CTEXT(node), SEXP_NONE_STRING))
2018  {
2019  break;
2020  }
2021 
2022  // subsys_or_generic has a few extra options it accepts
2024  break;
2025  }
2026 
2027  // we must get the model of the ship that is part of this sexpression and find a subsystem
2028  // with that name. This code assumes by default that the ship is *always* the first name
2029  // in the sexpression. If this is ever not the case, the code here must be changed to
2030  // get the correct ship name.
2031  switch(get_operator_const(CTEXT(op_node)))
2032  {
2034  case OP_DISTANCE_SUBSYSTEM:
2035  case OP_SET_CARGO:
2036  case OP_IS_CARGO:
2037  case OP_CHANGE_AI_CLASS:
2038  case OP_IS_AI_CLASS:
2039  case OP_MISSILE_LOCKED:
2041  ship_index = CDR(CDR(op_node));
2042  break;
2043 
2044  case OP_BEAM_FIRE:
2045  if(argnum == 1){
2046  ship_index = CDR(op_node);
2047  } else {
2048  ship_index = CDR(CDR(CDR(op_node)));
2049  }
2050  break;
2051 
2052  case OP_BEAM_FLOATING_FIRE:
2053  ship_index = CDDDDDR(CDDR(op_node));
2054  break;
2055 
2056  case OP_QUERY_ORDERS:
2057  ship_index = CDR(CDR(CDR(CDR(op_node))));
2058  break;
2059 
2060  case OP_WEAPON_CREATE:
2061  ship_index = CDDDDDR(CDDDDR(op_node));
2062  break;
2063 
2064  default :
2065  ship_index = CDR(op_node);
2066  break;
2067  }
2068 
2069  shipname = CTEXT(ship_index);
2070  shipnum = ship_name_lookup(shipname, 1);
2071  if (shipnum >= 0)
2072  {
2073  ship_class = Ships[shipnum].ship_info_index;
2074  }
2075  else
2076  {
2077  // must try to find the ship in the arrival list
2078  p_object *p_objp = mission_parse_get_arrival_ship(shipname);
2079 
2080  if (!p_objp)
2081  {
2082  if (type == OPF_SUBSYSTEM_OR_NONE)
2083  break;
2084  else
2085  return SEXP_CHECK_INVALID_SHIP;
2086  }
2087 
2088  ship_class = p_objp->ship_class;
2089  }
2090 
2091  // check for the special "hull" value
2092  if ( (Operators[op].value == OP_SABOTAGE_SUBSYSTEM) || (Operators[op].value == OP_REPAIR_SUBSYSTEM) || (Operators[op].value == OP_SET_SUBSYSTEM_STRNGTH) || (Operators[op].value == OP_SET_ARMOR_TYPE) || (Operators[op].value == OP_BEAM_FIRE)) {
2093  if ( !stricmp( CTEXT(node), SEXP_HULL_STRING) || !stricmp( CTEXT(node), SEXP_SIM_HULL_STRING) ){
2094  break;
2095  }
2096  }
2097  // check for special "shields" value for armor types
2098  if (Operators[op].value == OP_SET_ARMOR_TYPE) {
2099  if ( !stricmp( CTEXT(node), SEXP_SHIELD_STRING) || !stricmp( CTEXT(node), SEXP_SIM_HULL_STRING) ){
2100  break;
2101  }
2102  }
2103 
2104  for (i=0; i<Ship_info[ship_class].n_subsystems; i++)
2105  {
2106  if (!subsystem_stricmp(Ship_info[ship_class].subsystems[i].subobj_name, CTEXT(node)))
2107  {
2108  break;
2109  }
2110  }
2111 
2112  if (i == Ship_info[ship_class].n_subsystems)
2113  {
2115  }
2116 
2117  if(Fred_running)
2118  {
2119  // if we're checking for an AWACS subsystem and this is not an awacs subsystem
2120  if((type == OPF_AWACS_SUBSYSTEM) && !(Ship_info[ship_class].subsystems[i].flags & MSS_FLAG_AWACS))
2121  {
2123  }
2124 
2125  // rotating subsystem, like above - Goober5000
2126  if ((type == OPF_ROTATING_SUBSYSTEM) && !(Ship_info[ship_class].subsystems[i].flags & MSS_FLAG_ROTATES))
2127  {
2129  }
2130  }
2131 
2132  break;
2133  }
2134 
2135  case OPF_SUBSYSTEM_TYPE:
2136  for (i = 0; i < SUBSYSTEM_MAX; i++)
2137  {
2138  if (!stricmp(CTEXT(node), Subsystem_types[i]))
2139  break;
2140  }
2141 
2142  if (i == SUBSYSTEM_MAX)
2144 
2145  break;
2146 
2147  case OPF_POINT:
2148  if (type2 != SEXP_ATOM_STRING)
2149  {
2150  return SEXP_CHECK_TYPE_MISMATCH;
2151  }
2152 
2153  if (find_matching_waypoint(CTEXT(node)) == NULL)
2154  {
2155  if (verify_vector(CTEXT(node)))
2156  {
2157  return SEXP_CHECK_INVALID_POINT;
2158  }
2159  }
2160 
2161  break;
2162 
2163  case OPF_IFF:
2164  if (type2 != SEXP_ATOM_STRING)
2165  {
2166  return SEXP_CHECK_TYPE_MISMATCH;
2167  }
2168 
2169  if (iff_lookup(CTEXT(node)) < 0)
2170  {
2171  return SEXP_CHECK_INVALID_IFF;
2172  }
2173 
2174  break;
2175 
2176  case OPF_AI_CLASS:
2177  if (type2 != SEXP_ATOM_STRING)
2178  {
2179  return SEXP_CHECK_TYPE_MISMATCH;
2180  }
2181 
2182  for (i=0; i<Num_ai_classes; i++)
2183  {
2184  if (!stricmp(Ai_class_names[i], CTEXT(node)))
2185  {
2186  break;
2187  }
2188  }
2189 
2190  if (i == Num_ai_classes)
2191  {
2193  }
2194 
2195  break;
2196 
2197  case OPF_ARRIVAL_LOCATION:
2198  if (type2 != SEXP_ATOM_STRING)
2199  {
2200  return SEXP_CHECK_TYPE_MISMATCH;
2201  }
2202 
2203  for (i=0; i<MAX_ARRIVAL_NAMES; i++)
2204  {
2205  if (!stricmp(Arrival_location_names[i], CTEXT(node)))
2206  {
2207  break;
2208  }
2209  }
2210 
2211  if (i == MAX_ARRIVAL_NAMES)
2212  {
2214  }
2215 
2216  break;
2217 
2219  if (type2 != SEXP_ATOM_STRING)
2220  {
2221  return SEXP_CHECK_TYPE_MISMATCH;
2222  }
2223 
2224  for (i=0; i<MAX_DEPARTURE_NAMES; i++)
2225  {
2226  if (!stricmp(Departure_location_names[i], CTEXT(node)))
2227  {
2228  break;
2229  }
2230  }
2231 
2232  if (i == MAX_DEPARTURE_NAMES)
2233  {
2235  }
2236 
2237  break;
2238 
2240  if (type2 != SEXP_ATOM_STRING)
2241  {
2242  return SEXP_CHECK_TYPE_MISMATCH;
2243  }
2244  else
2245  {
2246  int get_special_anchor(char *name);
2247  int valid = 0;
2248 
2249  // <any friendly>, etc.
2250  if (get_special_anchor(CTEXT(node)) >= 0)
2251  {
2252  valid = 1;
2253  }
2254 
2255  if (ship_name_lookup(CTEXT(node), 1) >= 0)
2256  {
2257  valid = 1;
2258  }
2259 
2261  {
2262  valid = 1;
2263  }
2264 
2265  if (!valid)
2266  {
2268  }
2269  }
2270 
2271  break;
2272 
2273  case OPF_SOUNDTRACK_NAME:
2274  if (type2 != SEXP_ATOM_STRING){
2275  return SEXP_CHECK_TYPE_MISMATCH;
2276  }
2277 
2278  if (!stricmp(CTEXT(node), "<No Music>"))
2279  break;
2280 
2282  break;
2283 
2284  for (i=0; i<Num_soundtracks; i++)
2285  {
2286  if (!stricmp(CTEXT(node), Soundtracks[i].name))
2287  {
2288  break;
2289  }
2290  }
2291 
2292  if (i == Num_soundtracks)
2294 
2295  break;
2296 
2297  case OPF_SHIP_WITH_BAY:
2298  {
2299  char *name = CTEXT(node);
2300  p_object *p_objp;
2301  int shipnum = -1;
2302 
2303  if (type2 != SEXP_ATOM_STRING)
2304  return SEXP_CHECK_TYPE_MISMATCH;
2305 
2306  if (!stricmp(name, "<no anchor>"))
2307  break;
2308 
2309  shipnum = ship_name_lookup(name, 1);
2310  if (shipnum < 0)
2311  {
2312  if (Fred_running)
2313  return SEXP_CHECK_INVALID_SHIP;
2314 
2315  p_objp = mission_parse_get_arrival_ship(name);
2316  if (p_objp == NULL)
2317  return SEXP_CHECK_INVALID_SHIP;
2318 
2319  // Goober5000 - since we can't check POFs for ships which have yet to arrive
2320  // (not without a bit of work anyway), just assume they're okay
2321  break;
2322  }
2323 
2324  // ship exists at this point
2325 
2326  // now determine if this ship has a docking bay
2327  if (!ship_has_dock_bay(shipnum))
2329 
2330  break;
2331  }
2332 
2334  if (type2 != SEXP_ATOM_STRING){
2335  return SEXP_CHECK_TYPE_MISMATCH;
2336  }
2337 
2338  if (!stricmp(CTEXT(node), "<species support ship class>"))
2339  break;
2340 
2341  if (!stricmp(CTEXT(node), "<any support ship class>"))
2342  break;
2343 
2344  i = -1;
2345  for ( auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it ) {
2346  if ( !stricmp(CTEXT(node), it->name) )
2347  {
2348  if (it->flags & SIF_SUPPORT)
2349  {
2350  i = std::distance(Ship_info.cbegin(), it);
2351  break;
2352  }
2353  }
2354  }
2355 
2356  if ( i == -1 )
2358 
2359  break;
2360 
2361  case OPF_BOOL:
2362  if (type2 != OPR_BOOL){
2363  return SEXP_CHECK_TYPE_MISMATCH;
2364  }
2365 
2366  break;
2367 
2368  case OPF_AI_ORDER:
2369  if ( type2 != SEXP_ATOM_STRING ){
2370  return SEXP_CHECK_TYPE_MISMATCH;
2371  }
2372 
2373  break;
2374 
2375  case OPF_NULL:
2376  if (type2 != OPR_NULL){
2377  return SEXP_CHECK_TYPE_MISMATCH;
2378  }
2379 
2380  break;
2381 
2382  case OPF_SSM_CLASS:
2383  if ( type2 != SEXP_ATOM_STRING ) {
2384  return SEXP_CHECK_TYPE_MISMATCH;
2385  }
2386 
2387  if (ssm_info_lookup(CTEXT(node)) < 0) {
2389  }
2390 
2391  break;
2392 
2393  // Goober5000
2394  case OPF_FLEXIBLE_ARGUMENT:
2395  if (type2 != OPR_FLEXIBLE_ARGUMENT) {
2396  return SEXP_CHECK_TYPE_MISMATCH;
2397  }
2398  break;
2399 
2400  // Goober5000
2401  case OPF_ANYTHING:
2402  break;
2403 
2404  case OPF_AI_GOAL:
2405  if (type2 != OPR_AI_GOAL){
2406  return SEXP_CHECK_TYPE_MISMATCH;
2407  }
2408 
2409  if (Fred_running) {
2410  int ship_num, ship2, w = 0;
2411 
2412  // if it's the "goals" operator, this is part of initial orders, so just assume it's okay
2413  if (get_operator_const(Sexp_nodes[op_node].text) == OP_GOALS_ID) {
2414  break;
2415  }
2416 
2417  ship_num = ship_name_lookup(CTEXT(Sexp_nodes[op_node].rest), 1); // Goober5000 - include players
2418  if (ship_num < 0) {
2419  w = wing_name_lookup(CTEXT(Sexp_nodes[op_node].rest));
2420  if (w < 0) {
2421  if (bad_node){
2422  *bad_node = Sexp_nodes[op_node].rest;
2423  }
2424 
2425  return SEXP_CHECK_INVALID_SHIP; // should have already been caught earlier, but just in case..
2426  }
2427  }
2428 
2429  Assert(Sexp_nodes[node].subtype == SEXP_ATOM_LIST);
2430  z = Sexp_nodes[node].first;
2431  Assert(Sexp_nodes[z].subtype != SEXP_ATOM_LIST);
2433  if (ship_num >= 0) {
2434  if (!query_sexp_ai_goal_valid(z, ship_num)){
2436  }
2437 
2438  } else {
2439  for (i=0; i<Wings[w].wave_count; i++){
2440  if (!query_sexp_ai_goal_valid(z, Wings[w].ship_index[i])){
2442  }
2443  }
2444  }
2445 
2446  if ((z == OP_AI_DOCK) && (Sexp_nodes[node].rest >= 0)) {
2447  ship2 = ship_name_lookup(CTEXT(Sexp_nodes[node].rest), 1); // Goober5000 - include players
2448  if ((ship_num < 0) || !ship_docking_valid(ship_num, ship2)){
2450  }
2451  }
2452  }
2453 
2454  // we should check the syntax of the actual goal!!!!
2455  z = Sexp_nodes[node].first;
2456  if ((z = check_sexp_syntax(z, OPR_AI_GOAL, recursive, bad_node)) != 0){
2457  return z;
2458  }
2459 
2460  break;
2461 
2462  case OPF_SHIP_TYPE:
2463  if (type2 != SEXP_ATOM_STRING){
2464  return SEXP_CHECK_TYPE_MISMATCH;
2465  }
2466 
2467  i = ship_type_name_lookup(CTEXT(node));
2468 
2469  if (i < 0){
2471  }
2472 
2473  break;
2474 
2475  case OPF_WAYPOINT_PATH:
2476  if (find_matching_waypoint_list(CTEXT(node)) == NULL) {
2477  return SEXP_CHECK_TYPE_MISMATCH;
2478  }
2479  break;
2480 
2481  case OPF_MESSAGE:
2482  if (type2 != SEXP_ATOM_STRING)
2483  return SEXP_CHECK_TYPE_MISMATCH;
2484 
2485  if (Fred_running) {
2486  for (i=0; i<Num_messages; i++)
2487  if (!stricmp(Messages[i].name, CTEXT(node)))
2488  break;
2489 
2490  if (i == Num_messages)
2492  }
2493 
2494  break;
2495 
2496  case OPF_PRIORITY: {
2497  if (type2 != SEXP_ATOM_STRING)
2498  return SEXP_CHECK_TYPE_MISMATCH;
2499 
2500  if (Fred_running) { // should still check in Fred though..
2501  char *name;
2502 
2503  name = CTEXT(node);
2504  if (!stricmp(name, "low") || !stricmp(name, "normal") || !stricmp(name, "high"))
2505  break;
2506 
2508  }
2509 
2510  break;
2511  }
2512 
2513  case OPF_MISSION_NAME:
2514  if (type2 != SEXP_ATOM_STRING)
2515  return SEXP_CHECK_TYPE_MISMATCH;
2516 
2517  if (Fred_running) {
2518  if (mode == SEXP_MODE_CAMPAIGN) {
2519  for (i=0; i<Campaign.num_missions; i++)
2520  if (!stricmp(CTEXT(node), Campaign.missions[i].name)) {
2522  return SEXP_CHECK_INVALID_LEVEL;
2523 
2524  break;
2525  }
2526 
2527  if (i == Campaign.num_missions)
2529 
2530  } else {
2531  // mwa -- put the following if statement to prevent Fred errors for possibly valid
2532  // conditions. We should do something else here!!!
2533  if ( (Operators[op].value == OP_PREVIOUS_EVENT_TRUE) || (Operators[op].value == OP_PREVIOUS_EVENT_FALSE) || (Operators[op].value == OP_PREVIOUS_EVENT_INCOMPLETE)
2534  || (Operators[op].value == OP_PREVIOUS_GOAL_TRUE) || (Operators[op].value == OP_PREVIOUS_GOAL_FALSE) || (Operators[op].value == OP_PREVIOUS_GOAL_INCOMPLETE) )
2535  break;
2536 
2537  if (!(*Mission_filename) || stricmp(Mission_filename, CTEXT(node)))
2539  }
2540  }
2541 
2542  break;
2543 
2544  case OPF_GOAL_NAME:
2545  if (type2 != SEXP_ATOM_STRING)
2546  return SEXP_CHECK_TYPE_MISMATCH;
2547 
2548  // we only need to check the campaign list if running in Fred and are in campaign mode.
2549  // otherwise, check the set of current goals
2550  if ( Fred_running && (mode == SEXP_MODE_CAMPAIGN) ) {
2551  z = find_parent_operator(node);
2552  Assert(z >= 0);
2553  z = Sexp_nodes[z].rest; // first argument of operator should be mission name
2554  Assert(z >= 0);
2555  for (i=0; i<Campaign.num_missions; i++)
2556  if (!stricmp(CTEXT(z), Campaign.missions[i].name))
2557  break;
2558 
2559  // read the goal/event list from the mission file if both num_goals and num_events
2560  // are < 0
2561  if ((Campaign.missions[i].num_goals <= 0) && (Campaign.missions[i].num_events <= 0) )
2563 
2564  if (i < Campaign.num_missions) {
2565  for (t=0; t<Campaign.missions[i].num_goals; t++)
2566  if (!stricmp(CTEXT(node), Campaign.missions[i].goals[t].name))
2567  break;
2568 
2569  if (t == Campaign.missions[i].num_goals)
2571  }
2572  } else {
2573  // MWA -- short circuit evaluation of these things for now.
2574  if ( (Operators[op].value == OP_PREVIOUS_GOAL_TRUE) || (Operators[op].value == OP_PREVIOUS_GOAL_FALSE) || (Operators[op].value == OP_PREVIOUS_GOAL_INCOMPLETE) )
2575  break;
2576 
2577  for (i=0; i<Num_goals; i++)
2578  if (!stricmp(CTEXT(node), Mission_goals[i].name))
2579  break;
2580 
2581  if (i == Num_goals)
2583  }
2584 
2585  break;
2586 
2587  case OPF_EVENT_NAME:
2588  if ( type2 != SEXP_ATOM_STRING )
2589  return SEXP_CHECK_TYPE_MISMATCH;
2590 
2591  // like above checking for goals, check events in the campaign only if in Fred
2592  // and only if in campaign mode. Otherwise, check the current set of events
2593  if ( Fred_running && (mode == SEXP_MODE_CAMPAIGN) ) {
2594  z = find_parent_operator(node);
2595  Assert(z >= 0);
2596  z = Sexp_nodes[z].rest; // first argument of operator should be mission name
2597  Assert(z >= 0);
2598  for (i=0; i<Campaign.num_missions; i++)
2599  if (!stricmp(CTEXT(z), Campaign.missions[i].name))
2600  break;
2601 
2602  // read the goal/event list from the mission file if both num_goals and num_events
2603  // are < 0
2604  if ((Campaign.missions[i].num_goals <= 0) && (Campaign.missions[i].num_events <= 0) )
2606 
2607  if (i < Campaign.num_missions) {
2608  for (t=0; t<Campaign.missions[i].num_events; t++)
2609  if (!stricmp(CTEXT(node), Campaign.missions[i].events[t].name))
2610  break;
2611 
2612  if (t == Campaign.missions[i].num_events)
2614  }
2615  } else {
2616  // MWA -- short circuit evaluation of these things for now.
2617  if ( (Operators[op].value == OP_PREVIOUS_EVENT_TRUE) || (Operators[op].value == OP_PREVIOUS_EVENT_FALSE) || (Operators[op].value == OP_PREVIOUS_EVENT_INCOMPLETE) )
2618  break;
2619 
2620  for ( i = 0; i < Num_mission_events; i++ ) {
2621  if ( !stricmp(CTEXT(node), Mission_events[i].name) )
2622  break;
2623  }
2624  if ( i == Num_mission_events )
2626  }
2627  break;
2628 
2629  case OPF_DOCKER_POINT:
2630  if (type2 != SEXP_ATOM_STRING)
2631  return SEXP_CHECK_TYPE_MISMATCH;
2632 
2633  // This makes massive assumptions about the structure of the SEXP using it. If you add any
2634  // new SEXPs that use this OPF, you will probably need to edit this section to accommodate them.
2635  if (Fred_running) {
2636  int ship_num, model;
2637 
2638  // Look for the node containing the docker ship as its first argument. For set-docked, we want
2639  // the current SEXP. Otherwise (for ai-dock), we want its parent.
2640  if (get_operator_const(Sexp_nodes[op_node].text) == OP_SET_DOCKED) {
2641  z = op_node;
2642  }
2643  else {
2644  z = find_parent_operator(op_node);
2645 
2646  // if it's the "goals" operator, this is part of initial orders, so just assume it's okay
2647  if (get_operator_const(Sexp_nodes[z].text) == OP_GOALS_ID) {
2648  break;
2649  }
2650  }
2651 
2652  // look for the ship this goal is being assigned to
2653  ship_num = ship_name_lookup(CTEXT(Sexp_nodes[z].rest), 1);
2654  if (ship_num < 0) {
2655  if (bad_node)
2656  *bad_node = Sexp_nodes[z].rest;
2657 
2658  return SEXP_CHECK_INVALID_SHIP; // should have already been caught earlier, but just in case..
2659  }
2660 
2661  model = Ship_info[Ships[ship_num].ship_info_index].model_num;
2662  z = model_get_num_dock_points(model);
2663  for (i=0; i<z; i++)
2664  if (!stricmp(CTEXT(node), model_get_dock_name(model, i)))
2665  break;
2666 
2667  if (i == z)
2669  }
2670 
2671  break;
2672 
2673  case OPF_DOCKEE_POINT:
2674  if (type2 != SEXP_ATOM_STRING)
2675  return SEXP_CHECK_TYPE_MISMATCH;
2676 
2677  // This makes massive assumptions about the structure of the SEXP using it. If you add any
2678  // new SEXPs that use this OPF, you will probably need to edit this section to accommodate them.
2679  if (Fred_running) {
2680  int ship_num, model;
2681 
2682  // If we're using set-docked, we want to look up the ship from the third SEXP argument.
2683  if (get_operator_const(Sexp_nodes[op_node].text) == OP_SET_DOCKED) {
2684  //Navigate to the third argument
2685  z = op_node;
2686  for (i = 0; i < 3; i++)
2687  z = Sexp_nodes[z].rest;
2688 
2689  ship_num = ship_name_lookup(Sexp_nodes[z].text, 1);
2690  }
2691  else {
2692  ship_num = ship_name_lookup(CTEXT(Sexp_nodes[op_node].rest), 1);
2693  }
2694 
2695  if (ship_num < 0) {
2696  if (bad_node)
2697  *bad_node = Sexp_nodes[op_node].rest;
2698 
2699  return SEXP_CHECK_INVALID_SHIP; // should have already been caught earlier, but just in case..
2700  }
2701 
2702  model = Ship_info[Ships[ship_num].ship_info_index].model_num;
2703  z = model_get_num_dock_points(model);
2704  for (i=0; i<z; i++)
2705  if (!stricmp(CTEXT(node), model_get_dock_name(model, i)))
2706  break;
2707 
2708  if (i == z)
2710  }
2711 
2712  break;
2713 
2714  case OPF_WHO_FROM:
2715  if (type2 != SEXP_ATOM_STRING)
2716  return SEXP_CHECK_TYPE_MISMATCH;
2717 
2718  if (*CTEXT(node) != '#') { // not a manual source?
2719  if ( stricmp(CTEXT(node), "<any wingman>"))
2720  if ( stricmp(CTEXT(node), "<none>") ) // not a special token?
2721  if ((ship_name_lookup(CTEXT(node), TRUE) < 0) && (wing_name_lookup(CTEXT(node), 1) < 0)) // is it in the mission?
2724  }
2725 
2726  break;
2727 
2728  //Karajorma
2729  case OPF_PERSONA:
2730  if (type2 != SEXP_ATOM_STRING) {
2731  return SEXP_CHECK_TYPE_MISMATCH;
2732  }
2733 
2734  for (i=0; i < Num_personas ; i++) {
2735  if (!strcmp(CTEXT(node), Personas[i].name)) {
2736  break;
2737  }
2738  }
2739 
2740  if (i == Num_personas) {
2742  }
2743  break;
2744 
2745  case OPF_MISSION_MOOD:
2746  if (type2 != SEXP_ATOM_STRING) {
2747  return SEXP_CHECK_TYPE_MISMATCH;
2748  }
2749 
2750  for (i = 0; i < (int)Builtin_moods.size(); i++) {
2751  if (!strcmp(Builtin_moods[i].c_str(), CTEXT(node))) {
2752  break;
2753  }
2754  }
2755 
2756  if (i == (int)Builtin_moods.size()) {
2758  }
2759 
2760  break;
2761 
2762  case OPF_SHIP_FLAG:
2763  {
2764  bool found = false;
2765  for ( i = 0; i < MAX_OBJECT_FLAG_NAMES; i++) {
2766  if (!stricmp(Object_flag_names[i].flag_name, CTEXT(node))) {
2767  found = true;
2768  break;
2769  }
2770  }
2771 
2772  if (!found) {
2773  for ( i = 0; i < MAX_SHIP_FLAG_NAMES; i++) {
2774  if (!stricmp(Ship_flag_names[i].flag_name, CTEXT(node))) {
2775  found = true;
2776  break;
2777  }
2778  }
2779  }
2780 
2781  if (!found) {
2782  for ( i = 0; i < MAX_AI_FLAG_NAMES; i++) {
2783  if (!stricmp(Ai_flag_names[i].flag_name, CTEXT(node))) {
2784  found = true;
2785  break;
2786  }
2787  }
2788  }
2789 
2790  if (!found) {
2792  }
2793 
2794  break;
2795  }
2796 
2797  case OPF_TEAM_COLOR:
2798  if (type2 != SEXP_ATOM_STRING) {
2799  return SEXP_CHECK_TYPE_MISMATCH;
2800  }
2801 
2802  if (!stricmp(CTEXT(node), "none"))
2803  break;
2804 
2805  if (Team_Colors.find(CTEXT(node)) == Team_Colors.end())
2807 
2808  break;
2809 
2810  case OPF_FONT:
2811  if (type2 != SEXP_ATOM_STRING) {
2812  return SEXP_CHECK_TYPE_MISMATCH;
2813  }
2814 
2815  for (i = 0; i < Num_fonts; i++) {
2816  if (!stricmp(CTEXT(node), Fonts[i].filename)) {
2817  break;
2818  }
2819  }
2820 
2821  if (i == Num_fonts) {
2822  return SEXP_CHECK_INVALID_FONT;
2823  }
2824  break;
2825 
2826  case OPF_SOUND_ENVIRONMENT:
2827  if (type2 != SEXP_ATOM_STRING) {
2828  return SEXP_CHECK_TYPE_MISMATCH;
2829  }
2830 
2831  if (stricmp(CTEXT(node), SEXP_NONE_STRING) && ds_eax_get_preset_id(CTEXT(node)) < 0) {
2833  }
2834  break;
2835 
2837  if (type2 != SEXP_ATOM_STRING) {
2838  return SEXP_CHECK_TYPE_MISMATCH;
2839  }
2840 
2841  if (audio_volume_option_lookup(CTEXT(node)) == -1)
2843  break;
2844 
2845  case OPF_HUD_GAUGE:
2846  if (type2 != SEXP_ATOM_STRING) {
2847  return SEXP_CHECK_TYPE_MISMATCH;
2848  }
2849 
2850  if (hud_gauge_type_lookup(CTEXT(node)) == -1)
2852  break;
2853 
2855  if (type2 != SEXP_ATOM_STRING) {
2856  return SEXP_CHECK_TYPE_MISMATCH;
2857  }
2858 
2861  }
2862  break;
2863 
2864  case OPF_EXPLOSION_OPTION:
2865  if (type2 != SEXP_ATOM_STRING) {
2866  return SEXP_CHECK_TYPE_MISMATCH;
2867  }
2868 
2869  if (sexp_explosion_option_lookup(CTEXT(node)) < 0) {
2871  }
2872  break;
2873 
2874  case OPF_KEYPRESS:
2875  if (type2 != SEXP_ATOM_STRING)
2876  return SEXP_CHECK_TYPE_MISMATCH;
2877 
2878  break;
2879 
2880  case OPF_CARGO:
2881  case OPF_STRING:
2882  case OPF_MESSAGE_OR_STRING:
2883  if (type2 != SEXP_ATOM_STRING)
2884  return SEXP_CHECK_TYPE_MISMATCH;
2885  break;
2886 
2887  case OPF_SKILL_LEVEL:
2888  if ( type2 != SEXP_ATOM_STRING )
2889  return SEXP_CHECK_TYPE_MISMATCH;
2890 
2891  for (i = 0; i < NUM_SKILL_LEVELS; i++) {
2892  if ( !stricmp(CTEXT(node), Skill_level_names(i, 0)) )
2893  break;
2894  }
2895  if ( i == NUM_SKILL_LEVELS )
2897  break;
2898 
2899  case OPF_MEDAL_NAME:
2900  if ( type2 != SEXP_ATOM_STRING)
2901  return SEXP_CHECK_TYPE_MISMATCH;
2902 
2903  for (i = 0; i < Num_medals; i++) {
2904  if ( !stricmp(CTEXT(node), Medals[i].name) )
2905  break;
2906  }
2907 
2908  if ( i == Num_medals )
2910  break;
2911 
2912  case OPF_HUGE_WEAPON:
2913  case OPF_WEAPON_NAME:
2914  if ( type2 != SEXP_ATOM_STRING )
2915  return SEXP_CHECK_TYPE_MISMATCH;
2916 
2917  for (i = 0; i < Num_weapon_types; i++ ) {
2918  if ( !stricmp(CTEXT(node), Weapon_info[i].name) )
2919  break;
2920  }
2921 
2922  if ( i == Num_weapon_types )
2924 
2925  // we need to be sure that for huge weapons, the WIF_HUGE flag is set
2926  if ( type == OPF_HUGE_WEAPON ) {
2927  if ( !(Weapon_info[i].wi_flags & WIF_HUGE) )
2929  }
2930 
2931  break;
2932 
2933  // Goober5000
2934  case OPF_INTEL_NAME:
2935  if ( type2 != SEXP_ATOM_STRING )
2936  return SEXP_CHECK_TYPE_MISMATCH;
2937 
2938  for (i = 0; i < Intel_info_size; i++ ) {
2939  if ( !stricmp(CTEXT(node), Intel_info[i].name) )
2940  break;
2941  }
2942 
2943  if ( i == Intel_info_size )
2945 
2946  break;
2947 
2949  if ( type2 != SEXP_ATOM_STRING )
2950  return SEXP_CHECK_TYPE_MISMATCH;
2951 
2952  for (i = 0; i < NUM_TURRET_ORDER_TYPES; i++ ) {
2953  if ( !stricmp(CTEXT(node), Turret_target_order_names[i]) )
2954  break;
2955  }
2956 
2957  if ( i == NUM_TURRET_ORDER_TYPES )
2959 
2960  break;
2961 
2962  case OPF_ARMOR_TYPE:
2963  if ( type2 != SEXP_ATOM_STRING )
2964  return SEXP_CHECK_TYPE_MISMATCH;
2965 
2966  if (!stricmp(CTEXT(node), SEXP_NONE_STRING))
2967  break;
2968 
2969  for (st = 0; st < Armor_types.size(); st++ ) {
2970  if ( !stricmp(CTEXT(node), Armor_types[st].GetNamePtr()) )
2971  break;
2972  }
2973 
2974  if ( st == Armor_types.size() )
2976 
2977  break;
2978 
2979  case OPF_DAMAGE_TYPE:
2980  if ( type2 != SEXP_ATOM_STRING )
2981  return SEXP_CHECK_TYPE_MISMATCH;
2982 
2983  if (!stricmp(CTEXT(node), SEXP_NONE_STRING))
2984  break;
2985 
2986  for (st = 0; st < Damage_types.size(); st++ ) {
2987  if ( !stricmp(CTEXT(node), Damage_types[st].name) )
2988  break;
2989  }
2990 
2991  if ( st == Damage_types.size() )
2993 
2994  break;
2995 
2996  case OPF_ANIMATION_TYPE:
2997  if ( type2 != SEXP_ATOM_STRING )
2998  return SEXP_CHECK_TYPE_MISMATCH;
2999 
3000  i = model_anim_match_type(CTEXT(node));
3001  if ( i == TRIGGER_TYPE_NONE )
3003 
3004  break;
3005 
3006  case OPF_TARGET_PRIORITIES:
3007  if ( type2 != SEXP_ATOM_STRING )
3008  return SEXP_CHECK_TYPE_MISMATCH;
3009 
3010  for(st = 0; st < Ai_tp_list.size(); st++) {
3011  if ( !stricmp(CTEXT(node), Ai_tp_list[st].name) )
3012  break;
3013  }
3014 
3015  if ( st == Ai_tp_list.size() )
3017 
3018  break;
3019 
3020  case OPF_SHIP_CLASS_NAME:
3021  if ( type2 != SEXP_ATOM_STRING )
3022  return SEXP_CHECK_TYPE_MISMATCH;
3023 
3024  if (ship_info_lookup(CTEXT(node)) < 0)
3026 
3027  break;
3028 
3029  case OPF_HUD_GAUGE_NAME:
3030  if ( type2 != SEXP_ATOM_STRING )
3031  return SEXP_CHECK_TYPE_MISMATCH;
3032 
3033  for ( i = 0; i < NUM_HUD_GAUGES; i++ ) {
3034  if ( !stricmp(CTEXT(node), HUD_gauge_text[i]) )
3035  break;
3036  }
3037 
3038  // if we reached the end of the list, then the name is invalid
3039  if ( i == NUM_HUD_GAUGES )
3041 
3042  break;
3043 
3044  case OPF_SKYBOX_MODEL_NAME:
3045  if ( type2 != SEXP_ATOM_STRING )
3046  return SEXP_CHECK_TYPE_MISMATCH;
3047 
3048  if ( stricmp(CTEXT(node), NOX("default")) && !strstr(CTEXT(node), NOX(".pof")) )
3050 
3051  break;
3052 
3053  case OPF_SKYBOX_FLAGS:
3054  if ( type2 != SEXP_ATOM_STRING )
3055  return SEXP_CHECK_TYPE_MISMATCH;
3056 
3057  for ( i = 0; i < Num_skybox_flags; ++i ) {
3058  if ( !stricmp( CTEXT(node), Skybox_flags[i]) )
3059  break;
3060  }
3061 
3062  // if we reached the end of the list, then the flag is invalid
3063  if ( i == Num_skybox_flags )
3065 
3066  break;
3067 
3068  case OPF_JUMP_NODE_NAME:
3069  if ( type2 != SEXP_ATOM_STRING )
3070  return SEXP_CHECK_TYPE_MISMATCH;
3071 
3072  if (jumpnode_get_by_name(CTEXT(node)) == NULL)
3074 
3075  break;
3076 
3077 
3078  case OPF_VARIABLE_NAME:
3079  var_index = get_index_sexp_variable_from_node(node);
3080  if ( var_index == -1) {
3082  }
3083 
3084  switch (Operators[op].value)
3085  {
3086  // some SEXPs demand a number variable
3088  case OP_ADD_SUN_BITMAP:
3089  if (!(Sexp_variables[var_index].type & SEXP_VARIABLE_NUMBER))
3091  break;
3092 
3093  // some demand a string variable
3094  case OP_STRING_CONCATENATE:
3095  case OP_INT_TO_STRING:
3098  case OP_SCRIPT_EVAL_STRING:
3099  if (!(Sexp_variables[var_index].type & SEXP_VARIABLE_STRING))
3101  break;
3102 
3103  default:
3104  break;
3105  }
3106 
3107  // otherwise anything goes
3108  break;
3109 
3110  case OPF_AMBIGUOUS:
3111  // type checking for modify-variable
3112  // string or number -- anything goes
3113  break;
3114 
3115  case OPF_BACKGROUND_BITMAP:
3116  case OPF_SUN_BITMAP:
3117  case OPF_NEBULA_STORM_TYPE:
3118  case OPF_NEBULA_POOF:
3119  case OPF_NEBULA_PATTERN:
3120  case OPF_POST_EFFECT:
3121  if (type2 != SEXP_ATOM_STRING) {
3122  return SEXP_CHECK_TYPE_MISMATCH;
3123  }
3124  break;
3125 
3126  case OPF_HUD_ELEMENT:
3127  if (type2 != SEXP_ATOM_STRING) {
3128  return SEXP_CHECK_TYPE_MISMATCH;
3129  } else {
3130  char *gauge = CTEXT(node);
3131  if ( strcmp(SEXP_HUD_GAUGE_WARPOUT, gauge) == 0 ) {
3132  break;
3133  }
3134  }
3136 
3138  if (type2 != SEXP_ATOM_STRING) {
3139  return SEXP_CHECK_TYPE_MISMATCH;
3140  }
3141 
3142  if (!stricmp(CTEXT(node), SEXP_ALL_BANKS_STRING)) {
3143  break;
3144  }
3145 
3146  // if we haven't specified all banks we need to check the number of the bank is legal
3147  else {
3148  int num_banks = atoi(CTEXT(node));
3149  if ((num_banks >= MAX_SHIP_PRIMARY_BANKS) && (num_banks >= MAX_SHIP_SECONDARY_BANKS)) {
3151  }
3152  }
3153  break;
3154 
3155  case OPF_SHIP_EFFECT:
3156  if (type2 != SEXP_ATOM_STRING) {
3157  return SEXP_CHECK_TYPE_MISMATCH;
3158  }
3159 
3160  if (get_effect_from_name(CTEXT(node)) == -1 ) {
3162  }
3163  break;
3164 
3165  case OPF_GAME_SND:
3166  if (type2 == SEXP_ATOM_NUMBER)
3167  {
3168  if (gamesnd_get_by_tbl_index(atoi(CTEXT(node))) < 0)
3169  {
3171  }
3172  }
3173  else if (type2 == SEXP_ATOM_STRING)
3174  {
3175  if (stricmp(CTEXT(node), SEXP_NONE_STRING) && gamesnd_get_by_name(CTEXT(node)) < 0)
3176  {
3178  }
3179  }
3180  break;
3181 
3182  default:
3183  Error(LOCATION, "Unhandled argument format");
3184  }
3185 
3186  node = Sexp_nodes[node].rest;
3187  argnum++;
3188  }
3189 
3190  return 0;
3191 }
3192 
3193 // Goober5000
3194 void get_unformatted_sexp_variable_name(char *unformatted, char *formatted_pre)
3195 {
3196  int end_index;
3197  char *formatted;
3198 
3199  // Goober5000 - trim @ if needed
3200  if (formatted_pre[0] == SEXP_VARIABLE_CHAR)
3201  formatted = formatted_pre+1;
3202  else
3203  formatted = formatted_pre;
3204 
3205  // get variable name (up to '['
3206  end_index = strcspn(formatted, "[");
3207  Assert( (end_index != 0) && (end_index < TOKEN_LENGTH-1) );
3208  strncpy(unformatted, formatted, end_index);
3209  unformatted[end_index] = '\0';
3210 }
3211 
3218 void get_sexp_text_for_variable(char *text, char *token)
3219 {
3220  int sexp_var_index;
3221 
3223 
3224  if ( !Fred_running ) {
3225  // freespace - get index into Sexp_variables array
3226  sexp_var_index = get_index_sexp_variable_name(text);
3227  Assert(sexp_var_index != -1);
3228  sprintf(text, "%d", sexp_var_index);
3229  }
3230 }
3231 
3232 // Goober5000
3233 void do_preload_for_arguments(void (*preloader)(char *), int arg_node, int arg_handler_node)
3234 {
3235  // we have a special argument
3236  if (!strcmp(Sexp_nodes[arg_node].text, SEXP_ARGUMENT_STRING))
3237  {
3238  int n;
3239 
3240  // we might not be handling it, either because this is not a *_of operator
3241  // or because we've disabled preloading for special arguments
3242  if (arg_handler_node < 0)
3243  return;
3244 
3245  // preload for each argument
3246  for (n = CDR(arg_handler_node); n != -1; n = CDR(n))
3247  {
3248  preloader(CTEXT(n));
3249  }
3250  }
3251  // we don't
3252  else
3253  {
3254  // preload for just the one argument
3255  preloader(CTEXT(arg_node));
3256  }
3257 }
3258 
3259 // Goober5000
3261 {
3262  int idx;
3263  ship_info *sip;
3264 
3265  idx = ship_info_lookup(text);
3266  if (idx < 0)
3267  return;
3268 
3269  // preload the model, just in case there is no other ship of this class in the mission
3270  // (this eliminates the slight pause during a mission when changing to a previously unloaded model)
3271  sip = &Ship_info[idx];
3272  sip->model_num = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
3273 
3274  if (sip->model_num >= 0)
3275  model_page_in_textures(sip->model_num, idx);
3276 }
3277 
3278 // Goober5000
3280 {
3281  int idx;
3282 
3283  idx = weapon_info_lookup(text);
3284  if (idx < 0)
3285  return;
3286 
3287  weapon_mark_as_used(idx);
3288 }
3289 
3296 {
3297  int start, node, last, op, count;
3298  char token[TOKEN_LENGTH];
3299  char variable_text[TOKEN_LENGTH];
3300 
3301  Assert(*(Mp-1) == '(');
3302 
3303  // start - the node allocated in first instance of function
3304  // node - the node allocated in current instance of function
3305  // count - number of nodes allocated this instance of function [do we set last.rest or .first]
3306  // variable - whether string or number is a variable referencing Sexp_variables
3307 
3308  // initialization
3309  start = last = -1;
3310  count = 0;
3311 
3313  while (*Mp != ')') {
3314  // end of string or end of file
3315  if (*Mp == '\0' || *Mp == EOF_CHAR) {
3316  Error(LOCATION, "Unexpected end of sexp!");
3317  return -1;
3318  }
3319 
3320  // Sexp list
3321  if (*Mp == '(') {
3322  Mp++;
3323  node = alloc_sexp("", SEXP_LIST, SEXP_ATOM_LIST, get_sexp(), -1);
3324  }
3325 
3326  // Sexp string
3327  else if (*Mp == '\"') {
3328  int len = strcspn(Mp + 1, "\"");
3329  // was closing quote not found?
3330  if (*(Mp + 1 + len) != '\"') {
3331  Error(LOCATION, "Unexpected end of quoted string embedded in sexp!");
3332  return -1;
3333  }
3334 
3335  // check if string variable
3336  if ( *(Mp + 1) == SEXP_VARIABLE_CHAR ) {
3337  char variable_token[2*TOKEN_LENGTH+2]; // variable_token[contents_token]
3338 
3339  // reduce length by 1 for end \"
3340  int length = len - 1;
3341  if (length >= 2*TOKEN_LENGTH+2) {
3342  Error(LOCATION, "Variable token %s is too long. Needs to be %d characters or shorter.", Mp, 2*TOKEN_LENGTH+2 - 1);
3343  return -1;
3344  }
3345 
3346  // start copying after skipping 1st char (i.e. variable char)
3347  strncpy(variable_token, Mp + 2, length);
3348  variable_token[length] = 0;
3349 
3350  get_sexp_text_for_variable(variable_text, variable_token);
3351  node = alloc_sexp(variable_text, (SEXP_ATOM | SEXP_FLAG_VARIABLE), SEXP_ATOM_STRING, -1, -1);
3352  } else {
3353  // token is too long?
3354  if (len >= TOKEN_LENGTH) {
3355  Error(LOCATION, "Token %s is too long. Needs to be %d characters or shorter.", Mp, TOKEN_LENGTH - 1);
3356  return -1;
3357  }
3358 
3359  strncpy(token, Mp + 1, len);
3360  token[len] = 0;
3361  node = alloc_sexp(token, SEXP_ATOM, SEXP_ATOM_STRING, -1, -1);
3362  }
3363 
3364  // bump past closing \" by 1 char
3365  Mp += (len + 2);
3366 
3367  }
3368 
3369  // Sexp operator or number
3370  else {
3371  int len = 0;
3372  bool variable = false;
3373  while (*Mp != ')' && !is_white_space(*Mp)) {
3374  // numeric variable?
3375  if ( (len == 0) && (*Mp == SEXP_VARIABLE_CHAR) ) {
3376  variable = true;
3377  Mp++;
3378  continue;
3379  }
3380 
3381  // end of string or end of file?
3382  if (*Mp == '\0' || *Mp == EOF_CHAR) {
3383  Error(LOCATION, "Unexpected end of sexp!");
3384  return -1;
3385  }
3386 
3387  // token is too long?
3388  if (len >= TOKEN_LENGTH - 1) {
3389  token[TOKEN_LENGTH - 1] = '\0';
3390  Error(LOCATION, "Token %s is too long. Needs to be %d characters or shorter.", token, TOKEN_LENGTH - 1);
3391  return -1;
3392  }
3393 
3394  // build the token
3395  token[len++] = *Mp++;
3396  }
3397  token[len] = 0;
3398 
3399  // maybe replace deprecated names
3400  if (!stricmp(token, "set-ship-position"))
3401  strcpy_s(token, "set-object-position");
3402  else if (!stricmp(token, "set-ship-facing"))
3403  strcpy_s(token, "set-object-facing");
3404  else if (!stricmp(token, "set-ship-facing-object"))
3405  strcpy_s(token, "set-object-facing-object");
3406  else if (!stricmp(token, "ai-chase-any-except"))
3407  strcpy_s(token, "ai-chase-any");
3408  else if (!stricmp(token, "change-ship-model"))
3409  strcpy_s(token, "change-ship-class");
3410  else if (!stricmp(token, "radar-set-max-range"))
3411  strcpy_s(token, "hud-set-max-targeting-range");
3412  else if (!stricmp(token, "ship-subsys-vanished"))
3413  strcpy_s(token, "ship-subsys-vanish");
3414  else if (!stricmp(token, "directive-is-variable"))
3415  strcpy_s(token, "directive-value");
3416  else if (!stricmp(token, "variable-array-get"))
3417  strcpy_s(token, "get-variable-by-index");
3418  else if (!stricmp(token, "variable-array-set"))
3419  strcpy_s(token, "set-variable-by-index");
3420 
3421  op = get_operator_index(token);
3422  if (op >= 0) {
3423  node = alloc_sexp(token, SEXP_ATOM, SEXP_ATOM_OPERATOR, -1, -1);
3424  } else {
3425  if ( variable ) {
3426  // convert token text for variable
3427  get_sexp_text_for_variable(variable_text, token);
3428 
3429  node = alloc_sexp(variable_text, (SEXP_ATOM | SEXP_FLAG_VARIABLE), SEXP_ATOM_NUMBER, -1, -1);
3430  } else {
3431  node = alloc_sexp(token, SEXP_ATOM, SEXP_ATOM_NUMBER, -1, -1);
3432  }
3433  }
3434  }
3435 
3436  // update links
3437  if (count++) {
3438  Assert(last != -1);
3439  Sexp_nodes[last].rest = node;
3440  } else {
3441  start = node;
3442  }
3443 
3444  Assert(node != -1); // ran out of nodes. Time to raise the MAX!
3445  last = node;
3447  }
3448 
3449  Mp++; // skip past the ')'
3450 
3451 
3452  // Goober5000 - backwards compatibility for removed ai-chase-any-except
3453  if (get_operator_const(CTEXT(start)) == OP_AI_CHASE_ANY)
3454  {
3455  // if there is more than one argument, free the extras
3456  int n = CDR(CDR(start));
3457  if (n >= 0)
3458  {
3459  // free the entire rest of the argument list
3460  free_sexp2(n);
3461  }
3462  }
3463 
3464  // Goober5000 - preload stuff for certain sexps
3465  if (!Fred_running)
3466  {
3467  int n, parent, arg_handler = -1;
3468 
3469  // see if we're using special arguments
3470  parent = find_parent_operator(start);
3471  if (parent >= 0 && is_blank_argument_op(get_operator_const(CTEXT(parent))))
3472  {
3473  // get the first op of the parent, which should be a *_of operator
3474  arg_handler = CADR(parent);
3475  if (arg_handler >= 0 && !is_blank_of_op(get_operator_const(CTEXT(arg_handler))))
3476  arg_handler = -1;
3477  }
3478 
3479  // DISABLE ARGUMENT PRELOADING FOR NOW
3480  // see Mantis #925 for discussion
3481  // Also, the preloader will have to be moved to a different function (after the parsing is finished)
3482  // in order to work properly with special arguments. The current node is an orphan until get_sexp
3483  // completes, at which time it will be linked into the sexp node list; this means that it is
3484  // impossible to get the parent node.
3485  arg_handler = -1;
3486 
3487  // preload according to sexp
3488  op = get_operator_const(CTEXT(start));
3489  switch (op)
3490  {
3491  case OP_CHANGE_SHIP_CLASS:
3492  // ship class is argument #1
3493  n = CDR(start);
3495  break;
3496 
3497  case OP_SHIP_CREATE:
3498  // ship class is argument #2
3499  n = CDDR(start);
3500  // page in ship classes of dynamically created ships
3501  // preload_change_ship_class doesn't require a class change, so we can use that here -zookeeper
3503  break;
3504 
3506  // set flag for taylor
3508  break;
3509 
3510  case OP_MISSION_SET_NEBULA:
3511  // set flag for WMC
3512  Nebula_sexp_used = true;
3513  Dynamic_environment = true;
3514  break;
3515 
3517  Dynamic_environment = true;
3518  break;
3519 
3520  case OP_WARP_EFFECT:
3521  // type of warp is argument #11
3522  n = CDDDDDR(start);
3523  n = CDDDDDR(n);
3524  n = CDR(n);
3525 
3526  // set flag for taylor
3527  if (CAR(n) != -1 || !strcmp(Sexp_nodes[n].text, SEXP_ARGUMENT_STRING)) // if it's evaluating a sexp or a special argument
3528  Knossos_warp_ani_used = 1; // set flag just in case
3529  else if (atoi(CTEXT(n)) == 1) // if it's the Knossos type
3530  Knossos_warp_ani_used = 1; // set flag for sure
3531  break;
3532 
3533  case OP_SET_SKYBOX_MODEL:
3534  // model is argument #1
3535  n = CDR(start);
3537  Dynamic_environment = true;
3538  break;
3539 
3541  // weapon to change to is arg #3
3542  n = CDDDR(start);
3544  break;
3545 
3546  case OP_ADD_SUN_BITMAP:
3547  n = CDR(start);
3549  Dynamic_environment = true;
3550  break;
3551 
3553  n = CDR(start);
3555  Dynamic_environment = true;
3556  break;
3557 
3559  // do XSTR translation for each entry in the list
3560  // we don't use the do_preload function because the preloader needs to access two nodes at a time
3561  // also we're not using CTEXT or eval_num here because XSTR should really be constant, and
3562  // also because we can't really run sexp stuff in a preloader
3563  n = CDR(start);
3564  while (n >= 0)
3565  {
3566  if (CDR(n) < 0)
3567  break;
3568 
3569  int id = atoi(Sexp_nodes[CDR(n)].text);
3570  Assert(id < 10000000);
3571  char xstr[NAME_LENGTH + 20];
3572  sprintf(xstr, "XSTR(\"%s\", %d)", Sexp_nodes[n].text, id);
3573 
3574  memset(Sexp_nodes[n].text, 0, NAME_LENGTH*sizeof(char));
3575  lcl_ext_localize(xstr, Sexp_nodes[n].text, NAME_LENGTH - 1);
3576 
3577  n = CDDR(n);
3578  }
3579  break;
3580  }
3581  }
3582 
3583  return start;
3584 }
3585 
3586 
3591 {
3592  int count;
3593  char var_name[TOKEN_LENGTH];
3594  char default_value[TOKEN_LENGTH];
3595  char str_type[TOKEN_LENGTH];
3596  char persistent[TOKEN_LENGTH];
3597  char network[TOKEN_LENGTH];
3598  int index;
3599  int type;
3600 
3601  count = 0;
3602  required_string("$Variables:");
3604 
3605  // check for start of list
3606  if (*Mp != '(') {
3607  error_display(1, "Reading sexp variable list. Found [%c]. Expecting '('.\n", *Mp);
3608  throw parse::ParseException("Syntax error");
3609  }
3610 
3611  Mp++;
3613 
3614  while (*Mp != ')') {
3615  Assert(count < MAX_SEXP_VARIABLES);
3616 
3617  // get index - for debug
3618  stuff_int(&index);
3620 
3621  // get var_name
3622  get_string(var_name);
3624 
3625  // get default_value;
3626  get_string(default_value);
3628 
3629  // get type
3630  get_string(str_type);
3632 
3633  // determine type
3634  if (!stricmp(str_type, "number")) {
3635  type = SEXP_VARIABLE_NUMBER;
3636  } else if (!stricmp(str_type, "string")) {
3637  type = SEXP_VARIABLE_STRING;
3638  } else if (!stricmp(str_type, "block")) {
3639  // Goober5000 - This looks dangerous... these flags are needed for certain things, but it
3640  // looks like BLOCK_*_SIZE is the only thing that keeps a block from running off the end
3641  // of its boundary.
3642  type = SEXP_VARIABLE_BLOCK;
3643  } else {
3644  type = SEXP_VARIABLE_UNKNOWN;
3645  Error(LOCATION, "SEXP variable '%s' is an unknown type!", var_name);
3646  }
3647 
3648  // possibly get network-variable
3649  if (check_for_string("\"network-variable\"")) {
3650  // eat it
3651  get_string(network);
3653 
3654  // set type
3655  type |= SEXP_VARIABLE_NETWORK;
3656  }
3657 
3658  // possibly get player-persistent
3659  if (check_for_string("\"player-persistent\"")) {
3660  // eat it
3661  get_string(persistent);
3663 
3664  // set type
3666  // possibly get campaign-persistent
3667  } else if (check_for_string("\"campaign-persistent\"")) {
3668  // eat it
3669  get_string(persistent);
3671 
3672  // set type
3674  // trap error
3675  } else if (check_for_string("\"")) {
3676  // eat garbage
3677  get_string(persistent);
3679 
3680  // notify of error
3681  Error(LOCATION, "Error parsing sexp variables - unknown persistence type encountered. You can continue from here without trouble.");
3682  }
3683 
3684  // check if variable name already exists
3685  if ( (type & SEXP_VARIABLE_NUMBER) || (type & SEXP_VARIABLE_STRING) ) {
3686  Assert(get_index_sexp_variable_name(var_name) == -1);
3687  }
3688 
3689  if ( type & SEXP_VARIABLE_BLOCK ) {
3690  add_block_variable(default_value, var_name, type, index);
3691  }
3692  else {
3693  count++;
3694  sexp_add_variable(default_value, var_name, type, index);
3695  }
3696  }
3697 
3698  Mp++;
3699 
3700  return count;
3701 }
3702 
3704 {
3705  int current_index;
3706 
3707  for ( current_index = (MAX_SEXP_VARIABLES - BLOCK_EXP_SIZE) ; current_index >= (MAX_SEXP_VARIABLES - (BLOCK_EXP_SIZE * Num_special_expl_blocks)) ; current_index = (current_index - BLOCK_EXP_SIZE) ) {
3708  if (
3709  (atoi(Block_variables[current_index+INNER_RAD].text) == shipp->special_exp_inner) &&
3710  (atoi(Block_variables[current_index+OUTER_RAD].text) == shipp->special_exp_outer) &&
3711  (atoi(Block_variables[current_index+DAMAGE].text) == shipp->special_exp_damage) &&
3712  (atoi(Block_variables[current_index+BLAST].text) == shipp->special_exp_blast) &&
3713  (atoi(Block_variables[current_index+PROPAGATE].text) == (shipp->use_shockwave ? 1:0) ) &&
3714  (atoi(Block_variables[current_index+SHOCK_SPEED].text) == shipp->special_exp_shockwave_speed)
3715  ) {
3716  *index = current_index;
3717  return true;
3718  }
3719  }
3720 
3721  // if we got here, this ship's special explosions aren't represented in the Block_variables array
3722  *index = current_index;
3723  return false;
3724 }
3725 
3727 {
3728  ship *shipp;
3729  ship_obj *sop;
3730  int current_index;
3731  bool already_added = false;
3732  int num_sexp_variables;
3733  int i;
3734 
3735  // since we're (re)generating the block variable index, we don't start off with any block variables
3736  Num_special_expl_blocks = 0;
3737 
3738  // get the number of sexp_variables we currently have. We must not try to add a block variable with an index below this.
3739  num_sexp_variables = sexp_variable_count();
3740 
3741  for ( sop = GET_FIRST(&Ship_obj_list); sop != END_OF_LIST(&Ship_obj_list); sop = GET_NEXT(sop) ) {
3742  shipp=&Ships[Objects[sop->objnum].instance];
3743 
3744  if (!(shipp->use_special_explosion)) {
3745  continue;
3746  }
3747 
3748  already_added = has_special_explosion_block_index(shipp, &current_index);
3749 
3750  // if we can't add an index for this add this ship to the list of those which failed
3751  if (current_index < num_sexp_variables) {
3752  // fail list code goes here
3753  continue;
3754  }
3755 
3756  //if we haven't added this entry already, do so
3757  if (!already_added) {
3758  sprintf(Block_variables[current_index+INNER_RAD].text, "%d", shipp->special_exp_inner);
3759  sprintf(Block_variables[current_index+OUTER_RAD].text, "%d", shipp->special_exp_outer);
3760  sprintf(Block_variables[current_index+DAMAGE].text, "%d", shipp->special_exp_damage);
3761  sprintf(Block_variables[current_index+BLAST].text, "%d", shipp->special_exp_blast);
3762  sprintf(Block_variables[current_index+PROPAGATE].text, "%d", (shipp->use_shockwave ? 1:0) );
3763  sprintf(Block_variables[current_index+SHOCK_SPEED].text, "%d", shipp->special_exp_shockwave_speed);
3764 
3765  // add the names
3766  for (i = current_index; i < (current_index + BLOCK_EXP_SIZE); i++ ) {
3767  sprintf(Block_variables[i].variable_name, "%s", shipp->ship_name);
3768  }
3769 
3770  Num_special_expl_blocks++;
3771  }
3772  }
3773 
3774  return true;
3775 }
3776 
3778 {
3779  return Num_special_expl_blocks * BLOCK_EXP_SIZE;
3780 }
3781 
3785 void stuff_sexp_text_string(SCP_string &dest, int node, int mode)
3786 {
3787  Assert( (node >= 0) && (node < Num_sexp_nodes) );
3788 
3789  if (Sexp_nodes[node].type & SEXP_FLAG_VARIABLE) {
3790 
3791  int sexp_variables_index = get_index_sexp_variable_name(Sexp_nodes[node].text);
3792  Assertion(sexp_variables_index != -1, "Couldn't find variable: %s\n", Sexp_nodes[node].text);
3793  Assert( (Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_NUMBER) || (Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_STRING) );
3794 
3795  // number
3796  if (Sexp_nodes[node].subtype == SEXP_ATOM_NUMBER) {
3797  Assert(Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_NUMBER);
3798 
3799  // Error check - can be Fred or FreeSpace
3800  if (mode == SEXP_ERROR_CHECK_MODE) {
3801  if ( Fred_running ) {
3802  sprintf(dest, "%s[%s] ", Sexp_nodes[node].text, Sexp_variables[sexp_variables_index].text);
3803  } else {
3804  sprintf(dest, "%s[%s] ", Sexp_variables[sexp_variables_index].variable_name, Sexp_variables[sexp_variables_index].text);
3805  }
3806  } else {
3807  // Save as string - only Fred
3808  Assert(mode == SEXP_SAVE_MODE);
3809  sprintf(dest, "@%s[%s] ", Sexp_nodes[node].text, Sexp_variables[sexp_variables_index].text);
3810  }
3811  } else {
3812  // string
3813  Assert(Sexp_nodes[node].subtype == SEXP_ATOM_STRING);
3814  Assert(Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_STRING);
3815 
3816  // Error check - can be Fred or FreeSpace
3817  if (mode == SEXP_ERROR_CHECK_MODE) {
3818  if ( Fred_running ) {
3819  sprintf(dest, "%s[%s] ", Sexp_variables[sexp_variables_index].variable_name, Sexp_variables[sexp_variables_index].text);
3820  } else {
3821  sprintf(dest, "%s[%s] ", Sexp_nodes[node].text, Sexp_variables[sexp_variables_index].text);
3822  }
3823  } else {
3824  // Save as string - only Fred
3825  Assert(mode == SEXP_SAVE_MODE);
3826  sprintf(dest, "\"@%s[%s]\" ", Sexp_nodes[node].text, Sexp_variables[sexp_variables_index].text);
3827  }
3828  }
3829  } else {
3830  // not a variable
3831  if (Sexp_nodes[node].subtype == SEXP_ATOM_STRING) {
3832  sprintf(dest, "\"%s\" ", CTEXT(node));
3833  } else {
3834  sprintf(dest, "%s ", CTEXT(node));
3835  }
3836  }
3837 }
3838 
3839 int build_sexp_string(SCP_string &accumulator, int cur_node, int level, int mode)
3840 {
3841  SCP_string buf;
3842  int node, old_length = accumulator.length();
3843 
3844  accumulator += "( ";
3845  node = cur_node;
3846  while (node != -1) {
3847  Assert(node >= 0 && node < Num_sexp_nodes);
3848  if (Sexp_nodes[node].first == -1) {
3849  // build text to string
3850  stuff_sexp_text_string(buf, node, mode);
3851  accumulator += buf;
3852 
3853  } else {
3854  build_sexp_string(accumulator, Sexp_nodes[node].first, level + 1, mode);
3855  }
3856 
3857  node = Sexp_nodes[node].rest;
3858  }
3859 
3860  accumulator += ") ";
3861  if ((accumulator.length() - old_length) > 40) {
3862  accumulator.resize(old_length);
3863  build_extended_sexp_string(accumulator, cur_node, level, mode);
3864  return 1;
3865  }
3866 
3867  return 0;
3868 }
3869 
3870 void build_extended_sexp_string(SCP_string &accumulator, int cur_node, int level, int mode)
3871 {
3872  SCP_string buf;
3873  int i, flag = 0, node;
3874 
3875  accumulator += "( ";
3876  node = cur_node;
3877  while (node != -1) {
3878  // not the first line?
3879  if (flag) {
3880  for (i=0; i<level + 1; i++)
3881  accumulator += " ";
3882  }
3883 
3884  flag = 1;
3885  Assert(node >= 0 && node < Num_sexp_nodes);
3886  if (Sexp_nodes[node].first == -1) {
3887  stuff_sexp_text_string(buf, node, mode);
3888  accumulator += buf;
3889 
3890  } else {
3891  build_sexp_string(accumulator, Sexp_nodes[node].first, level + 1, mode);
3892  }
3893 
3894  accumulator += "\n";
3895  node = Sexp_nodes[node].rest;
3896  }
3897 
3898  for (i=0; i<level; i++)
3899  accumulator += " ";
3900 
3901  accumulator += ")";
3902 }
3903 
3904 void convert_sexp_to_string(SCP_string &dest, int cur_node, int mode)
3905 {
3906  if (cur_node >= 0) {
3907  dest = "";
3908  build_sexp_string(dest, cur_node, 0, mode);
3909  } else {
3910  dest = "( )";
3911  }
3912 }
3913 
3914 
3915 // -----------------------------------------------------------------------------------
3916 // Helper methods for getting data from nodes. Cause it's stupid to keep re-rolling this stuff for every single SEXP
3917 // -----------------------------------------------------------------------------------
3918 
3922 player * get_player_from_ship_node(int node, bool test_respawns)
3923 {
3924  int sindex, np_index = -1;
3925  p_object *p_objp;
3926 
3927  Assert (node != -1);
3928 
3929  sindex = ship_name_lookup(CTEXT(node));
3930 
3931  // singleplayer
3932  if (!(Game_mode & GM_MULTIPLAYER)){
3933  if(sindex >= 0){
3934  if(Player_obj == &Objects[Ships[sindex].objnum]){
3935  return Player;
3936  }
3937  }
3938  return NULL;
3939  }
3940  // multiplayer
3941  else {
3942  if(sindex >= 0){
3943  if(Ships[sindex].objnum >= 0) {
3944  // try and find the player
3945  np_index = multi_find_player_by_object(&Objects[Ships[sindex].objnum]);
3946  }
3947  }
3948  if (test_respawns && np_index < 0) {
3949  // Respawning ships don't have an objnum so we need to take a different approach
3950  p_objp = mission_parse_get_arrival_ship(CTEXT(node));
3951  if (p_objp != NULL) {
3952  np_index = multi_find_player_by_parse_object(p_objp);
3953  }
3954  }
3955 
3956  if((np_index >= 0) && (np_index < MAX_PLAYERS)){
3957  return Net_players[np_index].m_player;
3958  }
3959 
3960  return NULL;
3961  }
3962 }
3963 
3968 {
3969  int sindex;
3970  ship *shipp = NULL;
3971 
3972  sindex = ship_name_lookup( CTEXT(node) );
3973 
3974  if (sindex < 0) {
3975  return shipp;
3976  }
3977 
3978  if (Ships[sindex].objnum < 0) {
3979  return shipp;
3980  }
3981 
3982  shipp = &Ships[sindex];
3983  return shipp;
3984 }
3985 
3990 {
3991  int i;
3992 
3993  if (ship_query_state(name) < 0)
3994  return 1;
3995 
3996  i = wing_name_lookup(name, 1);
3997 
3998  // has not arrived yet
3999  if ((i >= 0) && (Wings[i].num_waves >= 0) && !Wings[i].total_arrived_count){
4000  return 1;
4001  }
4002 
4003  return 0;
4004 }
4005 
4006 // arithmetic functions
4007 int add_sexps(int n)
4008 {
4009  int sum = 0, val;
4010 
4011  if (n != -1) {
4012  if ( CAR(n) != -1) {
4013  sum = eval_sexp( CAR(n) );
4014  // be sure to check for the NAN value when doing arithmetic -- this value should
4015  // get propagated to the next highest function.
4016  if ( Sexp_nodes[CAR(n)].value == SEXP_NAN )
4017  return SEXP_NAN;
4018  else if ( Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
4019  return SEXP_NAN_FOREVER;
4020  }
4021  else
4022  sum = atoi( CTEXT(n) );
4023 
4024  while (CDR(n) != -1) {
4025  val = eval_sexp( CDR(n) );
4026  // be sure to check for the NAN value when doing arithmetic -- this value should
4027  // get propagated to the next highest function.
4028  if ( Sexp_nodes[CDR(n)].value == SEXP_NAN )
4029  return SEXP_NAN;
4030  else if ( Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
4031  return SEXP_NAN_FOREVER;
4032  sum += val;
4033  n = CDR(n);
4034  }
4035  }
4036 
4037  return sum;
4038 }
4039 
4040 int sub_sexps(int n)
4041 {
4042  int sum = 0;
4043 
4044  if (n != -1) {
4045  if (Sexp_nodes[n].first != -1)
4046  sum = eval_sexp(CAR(n));
4047  else
4048  sum = atoi(CTEXT(n));
4049 
4050  while (CDR(n) != -1) {
4051  sum -= eval_sexp(CDR(n));
4052  n = CDR(n);
4053  }
4054  }
4055 
4056  return sum;
4057 }
4058 
4059 int mul_sexps(int n)
4060 {
4061  int sum = 0;
4062 
4063  if (n != -1) {
4064  if (Sexp_nodes[n].first != -1)
4065  sum = eval_sexp(Sexp_nodes[n].first);
4066  else
4067  sum = atoi(CTEXT(n));
4068 
4069  while (Sexp_nodes[n].rest != -1) {
4070  sum *= eval_sexp(Sexp_nodes[n].rest);
4071  n = Sexp_nodes[n].rest;
4072  }
4073  }
4074 
4075  return sum;
4076 }
4077 
4078 int div_sexps(int n)
4079 {
4080  int sum = 0;
4081 
4082  if (n != -1) {
4083  if (Sexp_nodes[n].first != -1)
4084  sum = eval_sexp(Sexp_nodes[n].first);
4085  else
4086  sum = atoi(CTEXT(n));
4087 
4088  while (Sexp_nodes[n].rest != -1) {
4089  int div = eval_sexp(Sexp_nodes[n].rest);
4090  n = Sexp_nodes[n].rest;
4091  if (div == 0) {
4092  Warning(LOCATION, "Division by zero in sexp. Please check all uses of the / operator for possible causes.\n");
4093  Int3();
4094  continue;
4095  }
4096  sum /= div;
4097  }
4098  }
4099 
4100  return sum;
4101 }
4102 
4103 int mod_sexps(int n)
4104 {
4105  int sum = 0;
4106 
4107  if (n != -1) {
4108  if (Sexp_nodes[n].first != -1)
4109  sum = eval_sexp(Sexp_nodes[n].first);
4110  else
4111  sum = atoi(CTEXT(n));
4112 
4113  while (Sexp_nodes[n].rest != -1) {
4114  sum = sum % eval_sexp(Sexp_nodes[n].rest);
4115  n = Sexp_nodes[n].rest;
4116  }
4117  }
4118 
4119  return sum;
4120 }
4121 
4122 int rand_internal(int low, int high, int seed = 0)
4123 {
4124  int diff;
4125 
4126  // maybe seed it
4127  if (seed > 0)
4128  srand(seed);
4129 
4130  // get diff - don't allow negative or zero
4131  diff = high - low;
4132  if (diff < 0)
4133  diff = 0;
4134 
4135  return (low + rand32() % (diff + 1));
4136 }
4137 
4138 // Goober5000
4139 int abs_sexp(int n)
4140 {
4141  return abs(eval_num(n));
4142 }
4143 
4144 // Goober5000
4145 int min_sexp(int n)
4146 {
4147  int temp, min_val = INT_MAX;
4148 
4149  while (n != -1)
4150  {
4151  temp = eval_num(n);
4152 
4153  if (temp < min_val)
4154  min_val = temp;
4155 
4156  n = CDR(n);
4157  }
4158 
4159  return min_val;
4160 }
4161 
4162 // Goober5000
4163 int max_sexp(int n)
4164 {
4165  int temp, max_val = INT_MIN;
4166 
4167  while (n != -1)
4168  {
4169  temp = eval_num(n);
4170 
4171  if (temp > max_val)
4172  max_val = temp;
4173 
4174  n = CDR(n);
4175  }
4176 
4177  return max_val;
4178 }
4179 
4180 // Goober5000
4181 int avg_sexp(int n)
4182 {
4183  int num = 0, avg_val = 0;
4184 
4185  while (n != -1)
4186  {
4187  avg_val += eval_num(n);
4188  num++;
4189 
4190  n = CDR(n);
4191  }
4192 
4193  return (int) floor(((double) avg_val / num) + 0.5);
4194 }
4195 
4196 // Goober5000
4197 int pow_sexp(int node)
4198 {
4199  int num_1 = eval_num(node);
4200  int num_2 = eval_num(CDR(node));
4201 
4202  // this is disallowed in FRED, but can still happen through careless arithmetic
4203  if (num_2 < 0)
4204  {
4205  Warning(LOCATION, "Power function pow(%d, %d) attempted to raise to a negative power!", num_1, num_2);
4206  return 0;
4207  }
4208 
4209  double pow_result = pow(static_cast<double>(num_1), num_2);
4210 
4211  if (pow_result > static_cast<double>(INT_MAX))
4212  {
4213  nprintf(("SEXP", "Power function pow(%d, %d) is greater than INT_MAX! Returning INT_MAX.", num_1, num_2));
4214  return INT_MAX;
4215  }
4216  else if (pow_result < static_cast<double>(INT_MIN))
4217  {
4218  nprintf(("SEXP", "Power function pow(%d, %d) is less than INT_MIN! Returning INT_MIN.", num_1, num_2));
4219  return INT_MIN;
4220  }
4221 
4222  return static_cast<int>(pow_result);
4223 }
4224 
4225 // Goober5000
4226 int signum_sexp(int node)
4227 {
4228  int num = eval_num(node);
4229 
4230  if (num == 0)
4231  return 0;
4232 
4233  if (num < 0)
4234  return -1;
4235 
4236  // hurr durr math
4237  Assert(num > 0);
4238  return 1;
4239 }
4240 
4241 // Goober5000
4242 int sexp_set_bit(int node, bool set_it)
4243 {
4244  int val = eval_num(node);
4245  int bit_index = eval_num(CDR(node));
4246 
4247  if (bit_index < 0 || bit_index > 31)
4248  {
4249  Warning(LOCATION, "Bit index %d out of range! Must be between 0 and 31.", bit_index);
4250  return SEXP_NAN;
4251  }
4252 
4253  if (set_it)
4254  return val | (1<<bit_index);
4255  else
4256  return val & ~(1<<bit_index);
4257 }
4258 
4259 // Goober5000
4260 int sexp_is_bit_set(int node)
4261 {
4262  int val = eval_num(node);
4263  int bit_index = eval_num(CDR(node));
4264 
4265  if (bit_index < 0 || bit_index > 31)
4266  {
4267  Warning(LOCATION, "Bit index %d out of range! Must be between 0 and 31.", bit_index);
4268  return SEXP_NAN;
4269  }
4270 
4271  if (val & (1<<bit_index))
4272  return SEXP_TRUE;
4273  else
4274  return SEXP_FALSE;
4275 }
4276 
4277 // Goober5000
4278 int sexp_bitwise_and(int node)
4279 {
4280  int val = eval_num(node);
4281 
4282  for (int n = CDR(node); n != -1; n = CDR(n))
4283  val &= eval_num(n);
4284 
4285  return val;
4286 }
4287 
4288 // Goober5000
4289 int sexp_bitwise_or(int node)
4290 {
4291  int val = eval_num(node);
4292 
4293  for (int n = CDR(node); n != -1; n = CDR(n))
4294  val |= eval_num(n);
4295 
4296  return val;
4297 }
4298 
4299 // Goober5000
4300 int sexp_bitwise_not(int node)
4301 {
4302  int result = ~(eval_num(node));
4303 
4304  // clear the sign bit
4305  return result & INT_MAX;
4306 }
4307 
4308 // Goober5000
4309 int sexp_bitwise_xor(int node)
4310 {
4311  return eval_num(node) ^ eval_num(CDR(node));
4312 }
4313 
4314 // seeding added by Karajorma and Goober5000
4315 int rand_sexp(int n, bool multiple)
4316 {
4317  int low, high, rand_num, seed;
4318 
4319  if (n < 0)
4320  {
4321  Int3();
4322  return 0;
4323  }
4324 
4325  // when getting a saved value
4326  if (Sexp_nodes[n].value == SEXP_NUM_EVAL)
4327  {
4328  // don't regenerate new random number
4329  return atoi(CTEXT(n));
4330  }
4331 
4332  low = eval_num(n);
4333 
4334  // get high
4335  high = eval_num(CDR(n));
4336 
4337  // is there a seed provided?
4338  if (CDDR(n) != -1)
4339  seed = eval_num(CDDR(n));
4340  else
4341  seed = 0;
4342 
4343  // get the random number
4344  rand_num = rand_internal(low, high, seed);
4345 
4346  // when saving the value
4347  if (!multiple)
4348  {
4349  // set .value and .text so random number is generated only once.
4350  Sexp_nodes[n].value = SEXP_NUM_EVAL;
4351  sprintf(Sexp_nodes[n].text, "%d", rand_num);
4352  }
4353  // if this is multiple with a nonzero seed provided
4354  else if (seed > 0)
4355  {
4356  // Set the seed to a new seeded random value. This will ensure that the next time the method
4357  // is called it will return a predictable but different number from the previous time.
4358  sprintf(Sexp_nodes[CDDR(n)].text, "%d", rand_internal(1, INT_MAX, seed));
4359  }
4360 
4361  return rand_num;
4362 }
4363 
4364 // boolean evaluation functions. Evaluate all sexpressions in the 'or' operator. Needed to mark
4365 // entries in the mission log as essential so when pruning the log, we know which entries we might
4366 // need to keep.
4367 int sexp_or(int n)
4368 {
4369  int all_false, result;
4370 
4371  all_false = 1;
4372  result = 0;
4373  if (n != -1)
4374  {
4375  if (CAR(n) != -1)
4376  {
4377  result |= is_sexp_true(CAR(n));
4378  if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_TRUE )
4379  return SEXP_KNOWN_TRUE; // if one of the OR clauses is TRUE, whole clause is true
4380  if ( Sexp_nodes[CAR(n)].value != SEXP_KNOWN_FALSE ) // if the value is still unknown, they all can't be false
4381  all_false = 0;
4382  }
4383  else
4384  result |= atoi(CTEXT(n));
4385 
4386  while (CDR(n) != -1)
4387  {
4388  result |= is_sexp_true(CDR(n));
4389  if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_TRUE )
4390  return SEXP_KNOWN_TRUE; // if one of the OR clauses is TRUE, whole clause is true
4391  if ( Sexp_nodes[CDR(n)].value != SEXP_KNOWN_FALSE ) // if the value is still unknown, they all can't be false
4392  all_false = 0;
4393 
4394  n = CDR(n);
4395  }
4396  }
4397 
4398  if (all_false)
4399  return SEXP_KNOWN_FALSE;
4400 
4401  return result;
4402 }
4403 
4404 // this function does the 'and' operator. It will short circuit evaluation *but* it will still
4405 // evaluate other members of the and construct. I do this because I need events in the mission log
4406 // to get marked as essential for goal purposes, and evaluation is pretty much the only way
4407 int sexp_and(int n)
4408 {
4409  int all_true, result;
4410 
4411  result = -1;
4412  all_true = 1;
4413  if (n != -1)
4414  {
4415  if (CAR(n) != -1)
4416  {
4417  result &= is_sexp_true(CAR(n));
4418  if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
4419  return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
4420  if ( Sexp_nodes[CAR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be true
4421  all_true = 0;
4422  }
4423  else
4424  result &= atoi(CTEXT(n));
4425 
4426  while (CDR(n) != -1)
4427  {
4428  int new_result;
4429 
4430  new_result = is_sexp_true(CDR(n));
4431  result &= new_result;
4432  if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
4433  return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
4434  if ( Sexp_nodes[CDR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be true
4435  all_true = 0;
4436 
4437  n = CDR(n);
4438  }
4439  }
4440 
4441  if (all_true)
4442  return SEXP_KNOWN_TRUE;
4443 
4444  return result;
4445 }
4446 
4447 // this version of the 'and' operator determines whether or not it's arguments become true
4448 // in the order in which they are specified in the when statement. Should be a simple matter of
4449 // seeing if anything evaluates to true later than something that evalueated to false
4451 {
4452  int result = -1;
4453  int all_true;
4454 
4455  all_true = 1; // represents whether or not all nodes we have seen so far are true
4456  if (n != -1)
4457  {
4458  if (CAR(n) != -1)
4459  {
4460  result &= is_sexp_true(CAR(n));
4461  if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
4462  return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
4463  if ( Sexp_nodes[CAR(n)].value != SEXP_KNOWN_TRUE ) // if value is true, mark our all_true variable for later checking
4464  all_true = 0;
4465  }
4466  else
4467  result &= atoi(CTEXT(n));
4468 
4469  // a little test -- if the previous sexpressions was true, then mark the node itself as always
4470  // true. I did this because of the distance function. It might become true, then when waiting for
4471  // the second evalation, it might become false, rendering this function false. So, when one becomes
4472  // true -- mark it true forever.
4473  if ( result )
4474  Sexp_nodes[CAR(n)].value = SEXP_KNOWN_TRUE;
4475 
4476  while (CDR(n) != -1)
4477  {
4478  int next_result;
4479 
4480  next_result = is_sexp_true(CDR(n));
4481  if ( next_result && !result ) // if current result is true, and our running result is false, thngs didn't become true in order
4482  return SEXP_KNOWN_FALSE;
4483  result &= next_result;
4484  if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
4485  return SEXP_KNOWN_FALSE; // if one of the OR clauses is TRUE, whole clause is true
4486  if ( Sexp_nodes[CDR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be false
4487  all_true = 0;
4488 
4489  // see comment above for explanation of next lines
4490  if ( result )
4491  Sexp_nodes[CDR(n)].value = SEXP_KNOWN_TRUE;
4492 
4493  n = CDR(n);
4494  }
4495  }
4496 
4497  if ( all_true )
4498  return SEXP_KNOWN_TRUE;
4499 
4500  return result;
4501 }
4502 
4503 // for these four basic boolean operations (not, <, >, and =), we have special cases that we must deal
4504 // with. We have sexpressions operators that might return a NAN type return value (such as the distance
4505 // between two ships when one of the ships is destroyed or departed). These operations need to check for
4506 // this special NAN value and adjust their return types accordingly. NAN values represent false return values
4507 int sexp_not(int n)
4508 {
4509  int result = 0;
4510 
4511  if (n != -1)
4512  {
4513  if (CAR(n) != -1)
4514  {
4515  result = is_sexp_true(CAR(n));
4516  if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
4517  return SEXP_KNOWN_TRUE; // not KNOWN_FALSE == KNOWN_TRUE;
4518  else if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_TRUE ) // not KNOWN_TRUE == KNOWN_FALSE
4519  return SEXP_KNOWN_FALSE;
4520  else if ( Sexp_nodes[CAR(n)].value == SEXP_NAN ) // not NAN == TRUE (I think)
4521  return SEXP_TRUE;
4522  }
4523  else
4524  result = atoi(CTEXT(n));
4525  }
4526 
4527  return !result;
4528 }
4529 
4530 int sexp_xor(int node)
4531 {
4532  int num_true = 0;
4533 
4534  for (int n = node; n != -1; n = CDR(n))
4535  {
4536  if (is_sexp_true(n))
4537  num_true++;
4538  }
4539 
4540  return (num_true == 1);
4541 }
4542 
4543 // Goober5000
4544 int sexp_number_compare(int n, int op)
4545 {
4546  int first_node = n;
4547  int current_node;
4548  int first_number = eval_sexp(first_node);
4549  int current_number;
4550 
4551  // bail on NANs
4552  if (CAR(first_node) != -1)
4553  {
4554  if (Sexp_nodes[CAR(first_node)].value == SEXP_NAN) return SEXP_FALSE;
4555  if (Sexp_nodes[CAR(first_node)].value == SEXP_NAN_FOREVER) return SEXP_KNOWN_FALSE;
4556  }
4557  if (CDR(first_node) != -1)
4558  {
4559  if (Sexp_nodes[CDR(first_node)].value == SEXP_NAN) return SEXP_FALSE;
4560  if (Sexp_nodes[CDR(first_node)].value == SEXP_NAN_FOREVER) return SEXP_KNOWN_FALSE;
4561  }
4562 
4563  // compare first node with each of the others
4564  for (current_node = CDR(first_node); current_node != -1; current_node = CDR(current_node))
4565  {
4566  // bail on NANs
4567  if (CAR(current_node) != -1)
4568  {
4569  if (Sexp_nodes[CAR(current_node)].value == SEXP_NAN) return SEXP_FALSE;
4570  if (Sexp_nodes[CAR(current_node)].value == SEXP_NAN_FOREVER) return SEXP_KNOWN_FALSE;
4571  }
4572  if (CDR(current_node) != -1)
4573  {
4574  if (Sexp_nodes[CDR(current_node)].value == SEXP_NAN) return SEXP_FALSE;
4575  if (Sexp_nodes[CDR(current_node)].value == SEXP_NAN_FOREVER) return SEXP_KNOWN_FALSE;
4576  }
4577 
4578  current_number = eval_sexp(current_node);
4579 
4580  // must satisfy our particular operator
4581  switch(op)
4582  {
4583  case OP_EQUALS:
4584  if (first_number != current_number) return SEXP_FALSE;
4585  break;
4586 
4587  case OP_NOT_EQUAL:
4588  if (first_number == current_number) return SEXP_FALSE;
4589  break;
4590 
4591  case OP_GREATER_THAN:
4592  if (first_number <= current_number) return SEXP_FALSE;
4593  break;
4594 
4595  case OP_GREATER_OR_EQUAL:
4596  if (first_number < current_number) return SEXP_FALSE;
4597  break;
4598 
4599  case OP_LESS_THAN:
4600  if (first_number >= current_number) return SEXP_FALSE;
4601  break;
4602 
4603  case OP_LESS_OR_EQUAL:
4604  if (first_number > current_number) return SEXP_FALSE;
4605  break;
4606 
4607  default:
4608  Warning(LOCATION, "Unhandled comparison case! Operator = %d", op);
4609  break;
4610  }
4611  }
4612 
4613  // it satisfies the operator for all the arguments
4614  return SEXP_TRUE;
4615 }
4616 
4617 // Goober5000
4618 int sexp_string_compare(int n, int op)
4619 {
4620  int first_node = n;
4621  int current_node;
4622  int val;
4623  char *first_string = CTEXT(first_node);
4624 
4625  // compare first node with each of the others
4626  for (current_node = CDR(first_node); current_node != -1; current_node = CDR(current_node))
4627  {
4628  val = strcmp(first_string, CTEXT(current_node));
4629 
4630  // must satisfy our particular operator
4631  switch(op)
4632  {
4633  case OP_STRING_EQUALS:
4634  if (val != 0) return SEXP_FALSE;
4635  break;
4636 
4638  if (val <= 0) return SEXP_FALSE;
4639  break;
4640 
4641  case OP_STRING_LESS_THAN:
4642  if (val >= 0) return SEXP_FALSE;
4643  break;
4644  }
4645  }
4646 
4647  // it satisfies the operator for all the arguments
4648  return SEXP_TRUE;
4649 }
4650 
4651 #define OSWPT_TYPE_NONE 0
4652 #define OSWPT_TYPE_SHIP 1
4653 #define OSWPT_TYPE_WING 2
4654 #define OSWPT_TYPE_WAYPOINT 3
4655 #define OSWPT_TYPE_SHIP_ON_TEAM 4 // e.g. <any friendly>
4656 #define OSWPT_TYPE_WHOLE_TEAM 5 // e.g. Friendly
4657 #define OSWPT_TYPE_PARSE_OBJECT 6 // a "ship" that hasn't arrived yet
4658 #define OSWPT_TYPE_EXITED 7
4659 #define OSWPT_TYPE_WING_NOT_PRESENT 8 // a wing that hasn't arrived yet or is between waves
4660 
4661 // Goober5000
4663 {
4665  int type;
4666 
4668  object *objp;
4672  int team;
4673 
4674  void clear();
4675 }
4677 
4679 {
4680  object_name = NULL;
4682 
4683  p_objp = NULL;
4684  objp = NULL;
4685  shipp = NULL;
4686  waypointp = NULL;
4687  wingp = NULL;
4688  team = -1;
4689 }
4690 
4691 void sexp_object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship *shipp, bool set_parse_flag_too = false);
4692 void sexp_object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship_obj *so, bool set_parse_flag_too = false);
4693 void sexp_get_object_ship_wing_point_team(object_ship_wing_point_team *oswpt, char *object_name, bool set_parse_flag_too = false);
4694 
4696 {
4697  oswpt->clear();
4698 
4699  oswpt->shipp = shipp;
4700  oswpt->object_name = oswpt->shipp->ship_name;
4701  oswpt->objp = &Objects[shipp->objnum];
4702  oswpt->type = OSWPT_TYPE_SHIP;
4703 
4704  if (set_parse_flag_too) {
4706  }
4707 }
4708 
4709 
4711 {
4712  object_ship_wing_point_team_set_ship(oswpt, &Ships[Objects[so->objnum].instance], set_parse_flag_too);
4713 }
4714 
4715 
4716 // Goober5000
4718 {
4719  int team, ship_num, wing_num;
4720  waypoint *wpt;
4721  p_object *p_objp;
4722 
4723  Assert(oswpt != NULL);
4724  Assert(object_name != NULL);
4725 
4726  oswpt->clear();
4727  oswpt->object_name = object_name;
4728 
4729  if(!stricmp(object_name, SEXP_NONE_STRING))
4730  {
4731  oswpt->type = OSWPT_TYPE_NONE;
4732  return;
4733  }
4734 
4735  // check to see if ship destroyed or departed. In either case, do nothing.
4736  if (mission_log_get_time(LOG_SHIP_DEPARTED, object_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, object_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, object_name, NULL, NULL))
4737  {
4738  oswpt->type = OSWPT_TYPE_EXITED;
4739  return;
4740  }
4741 
4742  // the object might be the name of a wing. Check to see if the wing is destroyed or departed.
4743  if (mission_log_get_time(LOG_WING_DESTROYED, object_name, NULL, NULL) || mission_log_get_time(LOG_WING_DEPARTED, object_name, NULL, NULL))
4744  {
4745  oswpt->type = OSWPT_TYPE_EXITED;
4746  return;
4747  }
4748 
4749 
4750  // check if we have a ship for a target
4751  ship_num = ship_name_lookup(object_name);
4752  if (ship_num >= 0)
4753  {
4754  oswpt->type = OSWPT_TYPE_SHIP;
4755 
4756  oswpt->shipp = &Ships[ship_num];
4757  oswpt->objp = &Objects[oswpt->shipp->objnum];
4758 
4759  if (!set_parse_flag_too) {
4760  return;
4761  }
4762  }
4763 
4764 
4765  // check to see if we have a parse object instead
4766  p_objp = mission_parse_get_arrival_ship(object_name);
4767  if (p_objp != NULL)
4768  {
4769  if (oswpt->type != OSWPT_TYPE_SHIP) {
4770  oswpt->type = OSWPT_TYPE_PARSE_OBJECT;
4771  }
4772 
4773  oswpt->p_objp = p_objp;
4774 
4775  return;
4776  }
4777 
4778 
4779  // check if we have a wing for a target
4780  wing_num = wing_name_lookup(object_name, 1);
4781  if (wing_num >= 0)
4782  {
4783  wing *wingp = &Wings[wing_num];
4784 
4785  // make sure that at least one ship exists
4786  if (wingp->current_count > 0)
4787  {
4788  oswpt->type = OSWPT_TYPE_WING;
4789  oswpt->wingp = wingp;
4790 
4791  // point to wing leader if he is valid
4792  if ((wingp->special_ship >= 0) && (wingp->ship_index[wingp->special_ship] >= 0))
4793  {
4794  oswpt->shipp = &Ships[wingp->ship_index[wingp->special_ship]];
4795  oswpt->objp = &Objects[oswpt->shipp->objnum];
4796  }
4797  // boo... well, just point to ship at index 0
4798  else
4799  {
4800  oswpt->shipp = &Ships[wingp->ship_index[0]];
4801  oswpt->objp = &Objects[oswpt->shipp->objnum];
4802  Warning(LOCATION, "Substituting ship '%s' at index 0 for nonexistent wing leader at index %d!", oswpt->shipp->ship_name, oswpt->wingp->special_ship);
4803  }
4804  }
4805  // it's still a valid wing even if nobody is here
4806  else
4807  {
4809  oswpt->wingp = wingp;
4810  }
4811 
4812  return;
4813  }
4814 
4815 
4816  // check if we have a point for a target
4817  wpt = find_matching_waypoint(object_name);
4818  if ((wpt != NULL) && (wpt->get_objnum() >= 0))
4819  {
4820  oswpt->type = OSWPT_TYPE_WAYPOINT;
4821 
4822  oswpt->waypointp = wpt;
4823  oswpt->objp = &Objects[wpt->get_objnum()];
4824 
4825  return;
4826  }
4827 
4828 
4829  // check if we have an "<any team>" type
4830  team = sexp_determine_team(object_name);
4831  if (team >= 0)
4832  {
4833  oswpt->type = OSWPT_TYPE_SHIP_ON_TEAM;
4834  oswpt->team = team;
4835  }
4836 
4837 
4838  // check if we have a whole-team type
4839  team = iff_lookup(object_name);
4840  if (team >= 0)
4841  {
4842  oswpt->type = OSWPT_TYPE_WHOLE_TEAM;
4843  oswpt->team = team;
4844  }
4845 
4846 
4847  // we apparently don't have anything legal
4848  return;
4849 }
4850 
4855 {
4856  int count=0;
4857  ship_obj *so;
4858  ship *shipp;
4860  if ( n == -1) {
4861  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
4862  shipp=&Ships[Objects[so->objnum].instance];
4863  count++;
4864  }
4865 
4866  return count;
4867  }
4868 
4869  while (n != -1) {
4871 
4872  switch (oswpt1.type){
4873  case OSWPT_TYPE_WHOLE_TEAM:
4874  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
4875  shipp=&Ships[Objects[so->objnum].instance];
4876  if (shipp->team == oswpt1.team) {
4877  count++;
4878  }
4879  }
4880  break;
4881 
4882  case OSWPT_TYPE_SHIP:
4883  count++;
4884  break;
4885 
4886  case OSWPT_TYPE_WING:
4887  count += oswpt1.wingp->current_count;
4888  break;
4889  }
4890 
4891  n = CDR(n);
4892  }
4893 
4894  return count;
4895 }
4896 
4901 {
4902  char *name;
4903  int num_ships = 0 ;
4904 
4905  // A wing name must be provided, Assert that there is one.
4906  Assert ( n != -1 );
4907 
4908  //Cycle through the list of ships given
4909  while (n != -1)
4910  {
4911  // Get the name of the wing
4912  name = CTEXT(n);
4913 
4914  int wingnum;
4915  wingnum = wing_name_lookup( name, 0 );
4916 
4917  //If the wing exists add the number of ships in it to the total
4918  if (wingnum > -1)
4919  {
4920  num_ships += Wings[wingnum].current_count ;
4921  }
4922 
4923  //get the next node
4924  n = CDR (n) ;
4925  }
4926 
4927  return num_ships ;
4928 }
4929 
4934 {
4935  return fl2i(dock_calc_docked_speed(obj));
4936 }
4937 
4944 {
4947 
4948  switch (oswpt.type)
4949  {
4950  case OSWPT_TYPE_EXITED:
4951  return SEXP_NAN;
4952 
4953  case OSWPT_TYPE_SHIP:
4954  case OSWPT_TYPE_WING:
4955  return sexp_get_real_speed(oswpt.objp);
4956  }
4957 
4958  return 0;
4959 }
4960 
4965 int sexp_is_destroyed(int n, fix *latest_time)
4966 {
4967  char *name;
4968  int count, num_destroyed, wing_index;
4969  fix time;
4970 
4971  Assert ( n != -1 );
4972 
4973  count = 0;
4974  num_destroyed = 0;
4975  wing_index = -1;
4976  while (n != -1) {
4977  count++;
4978  name = CTEXT(n);
4979 
4980  if (sexp_query_has_yet_to_arrive(name))
4981  return SEXP_CANT_EVAL;
4982 
4983  // check to see if this ship/wing has departed. If so, then function is known false
4984  if ( mission_log_get_time (LOG_SHIP_DEPARTED, name, NULL, NULL) || mission_log_get_time (LOG_WING_DEPARTED, name, NULL, NULL) )
4985  return SEXP_KNOWN_FALSE;
4986 
4987  // check the mission log. If ship/wing not destroyed, immediately return SEXP_FALSE.
4988  if ( mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, &time) || mission_log_get_time(LOG_WING_DESTROYED, name, NULL, &time) || mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, &time)) {
4989  num_destroyed++;
4990  if ( latest_time && (time > *latest_time) )
4991  *latest_time = time;
4992  } else {
4993  // ship or wing isn't destroyed -- add to directive count
4994  if ( (wing_index = wing_name_lookup( name, 1 )) >= 0 ) {
4995  Directive_count += Wings[wing_index].current_count;
4996  } else
4997  Directive_count++;
4998  }
4999 
5000  // move to next ship/wing in list
5001  n = CDR(n);
5002  }
5003 
5004  // special case to mark a directive for destroy wing objectives true after a short amount
5005  // of time when there are more waves for this wing.
5006  if ( (count == 1) && (wing_index >= 0) && (Directive_count == 0) ) {
5007  if ( Wings[wing_index].current_wave < Wings[wing_index].num_waves )
5009  }
5010 
5011  if ( count == num_destroyed )
5012  return SEXP_KNOWN_TRUE;
5013  else
5014  return SEXP_FALSE;
5015 }
5016 
5021 {
5022  char *ship_name, *subsys_name;
5023 
5024  Assert( n != -1 );
5025 
5026  ship_name = CTEXT(n);
5027  subsys_name = CTEXT(CDR(n));
5028 
5029  if (sexp_query_has_yet_to_arrive(ship_name))
5030  return SEXP_CANT_EVAL;
5031 
5032  // if the ship has departed, no way to destroy it's subsystem.
5033  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL ))
5034  return SEXP_KNOWN_FALSE;
5035 
5036  if ( mission_log_get_time(LOG_SHIP_SUBSYS_DESTROYED, ship_name, subsys_name, NULL) )
5037  return SEXP_KNOWN_TRUE;
5038 
5039  return SEXP_FALSE;
5040 
5041 }
5042 
5046 int sexp_has_arrived(int n, fix *latest_time)
5047 {
5048  char *name;
5049  int count, num_arrived;
5050  fix time;
5051 
5052  count = 0;
5053  num_arrived = 0;
5054  while ( n != -1 ) {
5055  count++;
5056  name = CTEXT(n);
5057  // if there is no log entry for this ship/wing for arrival, sexpression is false
5058  if ( mission_log_get_time(LOG_SHIP_ARRIVED, name, NULL, &time) || mission_log_get_time(LOG_WING_ARRIVED, name, NULL, &time) ) {
5059  num_arrived++;
5060  if ( latest_time && (time > *latest_time) )
5061  *latest_time = time;
5062  }
5063  n = CDR(n);
5064  }
5065 
5066  if ( count == num_arrived )
5067  return SEXP_KNOWN_TRUE;
5068  else
5069  return SEXP_FALSE;
5070 }
5071 
5075 int sexp_has_departed(int n, fix *latest_time)
5076 {
5077  char *name;
5078  int count, num_departed;
5079  fix time;
5080 
5081  count = 0;
5082  num_departed = 0;
5083  while ( n != -1 ) {
5084  count++;
5085  name = CTEXT(n);
5086 
5087  if (sexp_query_has_yet_to_arrive(name))
5088  return SEXP_CANT_EVAL;
5089 
5090  // if ship/wing destroyed, sexpression is known false. Also, if there is no departure log entry, then
5091  // the sexpression is not true.
5092  if ( mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, NULL) || mission_log_get_time(LOG_WING_DESTROYED, name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, NULL))
5093  return SEXP_KNOWN_FALSE;
5094  else if ( mission_log_get_time(LOG_SHIP_DEPARTED, name, NULL, &time) || mission_log_get_time(LOG_WING_DEPARTED, name, NULL, &time) ) {
5095  num_departed++;
5096  if ( latest_time && (time > *latest_time) )
5097  *latest_time = time;
5098  }
5099  n = CDR(n);
5100  }
5101 
5102  if ( count == num_departed )
5103  return SEXP_KNOWN_TRUE;
5104  else
5105  return SEXP_FALSE;
5106 }
5107 
5111 int sexp_is_disabled( int n, fix *latest_time )
5112 {
5113  char *name;
5114  int count, num_disabled;
5115  fix time;
5116 
5117  count = 0;
5118  num_disabled = 0;
5119  while ( n != -1 ) {
5120  count++;
5121  name = CTEXT(n);
5122 
5123  if (sexp_query_has_yet_to_arrive(name))
5124  return SEXP_CANT_EVAL;
5125 
5126  // if ship/wing destroyed, sexpression is known false. Also, if there is no disable log entry, then
5127  // the sexpression is not true.
5128  if ( mission_log_get_time(LOG_SHIP_DEPARTED, name, NULL, &time) || mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, &time) || mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, &time) )
5129  return SEXP_KNOWN_FALSE;
5130  else if ( mission_log_get_time(LOG_SHIP_DISABLED, name, NULL, &time) ) {
5131  num_disabled++;
5132  if ( latest_time && (time > *latest_time) )
5133  *latest_time = time;
5134  }
5135  n = CDR(n);
5136  }
5137 
5138  if ( count == num_disabled )
5139  return SEXP_KNOWN_TRUE;
5140  else
5141  return SEXP_FALSE;
5142 }
5143 
5148 {
5149  char *ship_name, *waypoint_name;
5150 
5151  ship_name = CTEXT(n);
5152  waypoint_name = CTEXT(CDR(n));
5153 
5154  if (sexp_query_has_yet_to_arrive(ship_name))
5155  return SEXP_CANT_EVAL;
5156 
5157  // a destroyed or departed ship will never reach their goal -- return known false
5158  if ( mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
5159  return SEXP_KNOWN_FALSE;
5160  else if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) )
5161  return SEXP_KNOWN_FALSE;
5162 
5163  // now check the log for the waypoints done entry
5164  if ( mission_log_get_time(LOG_WAYPOINTS_DONE, ship_name, waypoint_name, NULL) )
5165  return SEXP_KNOWN_TRUE;
5166 
5167  return SEXP_FALSE;
5168 }
5169 
5170 
5174 int sexp_is_disarmed( int n, fix *latest_time )
5175 {
5176  char *name;
5177  int count, num_disarmed;
5178  fix time;
5179 
5180  count = 0;
5181  num_disarmed = 0;
5182  while ( n != -1 ) {
5183  count++;
5184  name = CTEXT(n);
5185 
5186  if (sexp_query_has_yet_to_arrive(name))
5187  return SEXP_CANT_EVAL;
5188 
5189  // if ship/wing destroyed, sexpression is known false. Also, if there is no disarm log entry, then
5190  // the sexpression is not true.
5191  if ( mission_log_get_time(LOG_SHIP_DEPARTED, name, NULL, &time) || mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, &time) || mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, &time) )
5192  return SEXP_KNOWN_FALSE;
5193  else if ( mission_log_get_time(LOG_SHIP_DISARMED, name, NULL, &time) ) {
5194  num_disarmed++;
5195  if ( latest_time && (time > *latest_time) )
5196  *latest_time = time;
5197  }
5198  n = CDR(n);
5199  }
5200 
5201  if ( count == num_disarmed )
5202  return SEXP_KNOWN_TRUE;
5203  else
5204  return SEXP_FALSE;
5205 }
5206 
5207 // the following functions are similar to the above objective functions but return true/false
5208 // if N seconds have elasped after the corresponding function is true.
5210 {
5211  fix delay, time;
5212  int val;
5213 
5214  Assert ( n >= 0 );
5215 
5216  time = 0;
5217 
5218  delay = i2f(eval_num(n));
5219 
5220  // check value of is_destroyed function. KNOWN_FALSE should be returned immediately
5221  val = sexp_is_destroyed( CDR(n), &time );
5222  if ( val == SEXP_KNOWN_FALSE )
5223  return val;
5224 
5225  if ( val == SEXP_CANT_EVAL )
5226  return SEXP_CANT_EVAL;
5227 
5228  if ( val ) {
5229 
5230  if ( (Missiontime - time) >= delay )
5231  return SEXP_KNOWN_TRUE;
5232  }
5233 
5234  return SEXP_FALSE;
5235 }
5236 
5237 
5238 // First ship is the destroyer, rest of the arguments are the destroyed ships.
5239 int sexp_was_destroyed_by(int n, fix* latest_time)
5240 {
5241  char* destroyer_ship_name;
5242  char* destroyed_ship_name;
5243  int count = 0, num_destroyed;
5244  fix time;
5245 
5246  Assert(n != -1);
5247 
5248  destroyer_ship_name = CTEXT(n);
5249 
5250  num_destroyed = 0;
5251 
5252  for (n = CDR(n); n != -1; n = CDR(n))
5253  {
5254  count++;
5255  destroyed_ship_name = CTEXT(n);
5256 
5257  if (sexp_query_has_yet_to_arrive(destroyed_ship_name))
5258  return SEXP_CANT_EVAL;
5259 
5260  // check to see if this ship/wing has departed. If so, then function is known false
5261  if (mission_log_get_time(LOG_SHIP_DEPARTED, destroyed_ship_name, NULL, NULL))
5262  return SEXP_KNOWN_FALSE;
5263 
5264  // check the mission log. If ship/wing not destroyed, immediately return SEXP_FALSE.
5265  if (mission_log_get_time(LOG_SHIP_DESTROYED, destroyed_ship_name, destroyer_ship_name, &time))
5266  {
5267  num_destroyed++;
5268  if (latest_time && (time > *latest_time))
5269  *latest_time = time;
5270  }
5271  }
5272 
5273  if (count == num_destroyed)
5274  return SEXP_KNOWN_TRUE;
5275  else
5276  return SEXP_FALSE;
5277 }
5278 
5280 {
5281  fix delay, time;
5282  int val;
5283 
5284  Assert(n >= 0);
5285 
5286  time = 0;
5287 
5288  delay = i2f(eval_num(n));
5289 
5290  // check value of is_destroyed function. KNOWN_FALSE should be returned immediately
5291  val = sexp_was_destroyed_by(CDR(n), &time);
5292  if (val == SEXP_KNOWN_FALSE)
5293  return val;
5294 
5295  if (val == SEXP_CANT_EVAL)
5296  return SEXP_CANT_EVAL;
5297 
5298  if (val)
5299  {
5300 
5301  if ((Missiontime - time) >= delay)
5302  return SEXP_KNOWN_TRUE;
5303  }
5304 
5305  return SEXP_FALSE;
5306 }
5307 
5309 {
5310  char *ship_name, *subsys_name;
5311  fix delay, time;
5312 
5313  Assert( n != -1 );
5314 
5315  ship_name = CTEXT(n);
5316  subsys_name = CTEXT(CDR(n));
5317  delay = i2f(eval_num(CDR(CDR(n))));
5318 
5319  if (sexp_query_has_yet_to_arrive(ship_name))
5320  return SEXP_CANT_EVAL;
5321 
5322  // if the ship has departed, no way to destroy it's subsystem.
5323  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL ))
5324  return SEXP_KNOWN_FALSE;
5325 
5326  if ( mission_log_get_time(LOG_SHIP_SUBSYS_DESTROYED, ship_name, subsys_name, &time) ) {
5327  if ( (Missiontime - time) >= delay )
5328  return SEXP_KNOWN_TRUE;
5329  }
5330 
5331  return SEXP_FALSE;
5332 }
5333 
5335 {
5336  fix delay, time;
5337  int val;
5338 
5339  Assert ( n >= 0 );
5340 
5341  time = 0;
5342  delay = i2f(eval_num(n));
5343 
5344  // check value of is_disable for known false and return immediately if it is.
5345  val = sexp_is_disabled( CDR(n), &time );
5346  if ( val == SEXP_KNOWN_FALSE )
5347  return val;
5348 
5349  if ( val == SEXP_CANT_EVAL )
5350  return SEXP_CANT_EVAL;
5351 
5352  if ( val ) {
5353  if ( (Missiontime - time) >= delay )
5354  return SEXP_KNOWN_TRUE;
5355  }
5356 
5357  return SEXP_FALSE;
5358 }
5359 
5361 {
5362  fix delay, time;
5363  int val;
5364 
5365  Assert ( n >= 0 );
5366 
5367  time = 0;
5368  delay = i2f(eval_num(n));
5369 
5370  // check value of is_disarmed for a known false value and return that immediately if it is
5371  val = sexp_is_disarmed( CDR(n), &time );
5372  if ( val == SEXP_KNOWN_FALSE )
5373  return val;
5374 
5375  if ( val == SEXP_CANT_EVAL )
5376  return SEXP_CANT_EVAL;
5377 
5378  if ( val ) {
5379  if ( (Missiontime - time) >= delay )
5380  return SEXP_KNOWN_TRUE;
5381  }
5382 
5383  return SEXP_FALSE;
5384 }
5385 
5387 {
5388  Assert(op_num == OP_HAS_DOCKED || op_num == OP_HAS_UNDOCKED || op_num == OP_HAS_DOCKED_DELAY || op_num == OP_HAS_UNDOCKED_DELAY);
5389 
5390  char *docker = CTEXT(n);
5391  char *dockee = CTEXT(CDR(n));
5392  int count = eval_num(CDR(CDR(n))); // count of times that we should look for
5393 
5394  if (count <= 0)
5395  {
5396  Warning(LOCATION, "Has-%sdocked%s count should be at least 1! This has been automatically adjusted.", (op_num == OP_HAS_UNDOCKED || op_num == OP_HAS_UNDOCKED_DELAY ? "un" : ""), (op_num == OP_HAS_DOCKED_DELAY || op_num == OP_HAS_UNDOCKED_DELAY ? "-delay" : ""));
5397  count = 1;
5398  }
5399 
5400  if (sexp_query_has_yet_to_arrive(docker))
5401  return SEXP_CANT_EVAL;
5402 
5403  if (sexp_query_has_yet_to_arrive(dockee))
5404  return SEXP_CANT_EVAL;
5405 
5406  if (op_num == OP_HAS_DOCKED_DELAY || op_num == OP_HAS_UNDOCKED_DELAY)
5407  {
5408  fix delay = i2f(eval_num(CDR(CDR(CDR(n)))));
5409  fix time;
5410 
5411  if ( mission_log_get_time_indexed(op_num == OP_HAS_DOCKED_DELAY ? LOG_SHIP_DOCKED : LOG_SHIP_UNDOCKED, docker, dockee, count, &time) )
5412  {
5413  if ( (Missiontime - time) >= delay )
5414  return SEXP_KNOWN_TRUE;
5415 }
5416  }
5417  else
5418  {
5419  if ( mission_log_get_time_indexed(op_num == OP_HAS_DOCKED ? LOG_SHIP_DOCKED : LOG_SHIP_UNDOCKED, docker, dockee, count, NULL) )
5420  return SEXP_KNOWN_TRUE;
5421  }
5422 
5423  if ( mission_log_get_time(LOG_SHIP_DESTROYED, docker, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, dockee, NULL, NULL) )
5424  return SEXP_KNOWN_FALSE;
5425 
5426  if ( mission_log_get_time(LOG_SELF_DESTRUCTED, docker, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, dockee, NULL, NULL) )
5427  return SEXP_KNOWN_FALSE;
5428 
5429  return SEXP_FALSE;
5430  }
5431 
5433 {
5434  fix delay, time;
5435  int val;
5436 
5437  Assert ( n >= 0 );
5438 
5439  time = 0;
5440  delay = i2f(eval_num(n));
5441 
5442  // check return value from arrived function. if can never arrive, then return that value here as well
5443  val = sexp_has_arrived( CDR(n), &time );
5444  if ( val == SEXP_KNOWN_FALSE )
5445  return val;
5446 
5447  if ( val == SEXP_CANT_EVAL )
5448  return SEXP_CANT_EVAL;
5449 
5450  if ( val ) {
5451  if ( (Missiontime - time) >= delay )
5452  return SEXP_KNOWN_TRUE;
5453  }
5454 
5455  return SEXP_FALSE;
5456 }
5457 
5459 {
5460  fix delay, time;
5461  int val;
5462 
5463  Assert ( n >= 0 );
5464 
5465  time = 0;
5466  delay = i2f(eval_num(n));
5467 
5468  // must first check to see if the departed function could ever be true/false or is true or false.
5469  // if it can never be true, return that value
5470  val = sexp_has_departed( CDR(n), &time);
5471  if ( val == SEXP_KNOWN_FALSE )
5472  return val;
5473 
5474  if ( val == SEXP_CANT_EVAL )
5475  return SEXP_CANT_EVAL;
5476 
5477  if ( val ) {
5478  if ( (Missiontime - time) >= delay )
5479  return SEXP_KNOWN_TRUE;
5480  }
5481 
5482  return SEXP_FALSE;
5483 }
5484 
5489 {
5490  char *ship_name, *waypoint_name;
5491  int count, n = node;
5492  fix time, delay;
5493 
5494  ship_name = CTEXT(n);
5495  n = CDR(n);
5496  waypoint_name = CTEXT(n);
5497  n = CDR(n);
5498  delay = i2f(eval_num(n));
5499  n = CDR(n);
5500  count = (n >= 0) ? eval_num(n) : 1;
5501  if (count <= 0)
5502  {
5503  Warning(LOCATION, "Are-waypoints-done-delay count should be at least 1! This has been automatically adjusted.");
5504  count = 1;
5505  }
5506 
5507  if (sexp_query_has_yet_to_arrive(ship_name))
5508  return SEXP_CANT_EVAL;
5509 
5510  // a destroyed or departed ship will never reach their goal -- return known false
5511  //
5512  // Not checking the entries below. Ships which warp out after reaching their goal (or getting
5513  // destroyed after their goal), but after reaching their waypoints, may have this goal incorrectly
5514  // marked false!!!!
5515 
5516  // now check the log for the waypoints done entry
5517  if ( mission_log_get_time_indexed(LOG_WAYPOINTS_DONE, ship_name, waypoint_name, count, &time) ) {
5518  if ( (Missiontime - time) >= delay )
5519  return SEXP_KNOWN_TRUE;
5520  } else {
5521  if ( mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
5522  return SEXP_KNOWN_FALSE;
5523  else if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) )
5524  return SEXP_KNOWN_FALSE;
5525  }
5526 
5527  return SEXP_FALSE;
5528 }
5529 
5534 {
5535  int percent;
5536  int type;
5537  char *shiptype;
5538 
5539  percent = eval_num(n);
5540  shiptype = CTEXT(CDR(n));
5541 
5542  type = ship_type_name_lookup(shiptype);
5543 
5544  // bogus if we reach the end of this array!!!!
5545  if ( type < 0 ) {
5546  Warning(LOCATION, "Invalid shiptype passed to ship-type-destroyed");
5547  return SEXP_FALSE;
5548  }
5549 
5550  if ( type >= (int)Ship_type_counts.size() || Ship_type_counts[type].total == 0 )
5551  return SEXP_FALSE;
5552 
5553  //We are safe from array indexing probs b/c of previous if.
5554  // determine if the percentage of killed/total is >= percentage given in the expression
5555  if ( (Ship_type_counts[type].killed * 100 / Ship_type_counts[type].total) >= percent)
5556  return SEXP_KNOWN_TRUE;
5557 
5558  return SEXP_FALSE;
5559 }
5560 
5561 
5562 // following are time based functions
5564 {
5565  int time = eval_num(n);
5566 
5567  if ( f2i(Missiontime) >= time )
5568  return SEXP_KNOWN_TRUE;
5569 
5570  return SEXP_FALSE;
5571 }
5572 
5577 {
5578  return f2i(Missiontime);
5579 }
5580 
5585 {
5586  // multiplying by 1000 can go over the limit for LONG_MAX so cast to long long int first
5587  return f2i((longlong)Missiontime * 1000);
5588 }
5589 
5594 {
5595  char *ship_name;
5596  int shipnum;
5597 
5598  // get shipname
5599  ship_name = CTEXT(n);
5600 
5601  // check to see if either ship was destroyed or departed. If so, then make this node known false
5602  if ( mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) ) {
5603  return SEXP_NAN_FOREVER;
5604  }
5605 
5606  // get ship name
5607  shipnum = ship_name_lookup(ship_name);
5608  if (shipnum < 0) {
5609  return SEXP_NAN;
5610  }
5611 
5612  // check that ship has warpout_objnum
5613  if (Ships[shipnum].special_warpout_objnum < 0) {
5614  return SEXP_NAN;
5615  }
5616 
5617  Assert( (Ships[shipnum].special_warpout_objnum >= 0) && (Ships[shipnum].special_warpout_objnum < MAX_OBJECTS));
5618  if ( (Ships[shipnum].special_warpout_objnum < 0) && (Ships[shipnum].special_warpout_objnum >= MAX_OBJECTS) ) {
5619  return SEXP_NAN;
5620  }
5621 
5622  // check the special warpout device is valid
5623  int valid = FALSE;
5624  object *ship_objp = &Objects[Ships[shipnum].objnum];
5625  object *warp_objp = &Objects[Ships[shipnum].special_warpout_objnum];
5626  if (warp_objp->type == OBJ_SHIP) {
5627  if (Ship_info[Ships[warp_objp->instance].ship_info_index].flags & SIF_KNOSSOS_DEVICE) {
5628  valid = TRUE;
5629  }
5630  }
5631 
5632  if (!valid) {
5633  return SEXP_NAN;
5634  }
5635 
5636  // check if within 45 degree half-angle cone of facing
5637  float dot = fl_abs(vm_vec_dot(&warp_objp->orient.vec.fvec, &ship_objp->orient.vec.fvec));
5638  if (dot < 0.707f) {
5639  return SEXP_NAN;
5640  }
5641 
5642  // get distance
5643  vec3d hit_pt;
5644  float dist = fvi_ray_plane(&hit_pt, &warp_objp->pos, &warp_objp->orient.vec.fvec, &ship_objp->pos, &ship_objp->orient.vec.fvec, 0.0f);
5645  polymodel *pm = model_get(Ship_info[Ships[shipnum].ship_info_index].model_num);
5646  dist += pm->mins.xyz.z;
5647 
5648  // return as a percent of length
5649  return (int) (100.0f * dist / ship_class_get_length(&Ship_info[Ships[shipnum].ship_info_index]));
5650 }
5651 
5652 
5654 {
5655  fix time;
5656 
5657  if ( !mission_log_get_time( LOG_SHIP_DESTROYED, CTEXT(n), NULL, &time)
5658  && !mission_log_get_time( LOG_SELF_DESTRUCTED, CTEXT(n), NULL, &time) ) { // returns 0 when not found
5659  return SEXP_NAN;
5660  }
5661 
5662  return f2i(time);
5663 }
5664 
5666 {
5667  fix time;
5668 
5669  if ( !mission_log_get_time( LOG_WING_DESTROYED, CTEXT(n), NULL, &time) ){
5670  return SEXP_NAN;
5671  }
5672 
5673  return f2i(time);
5674 }
5675 
5677 {
5678  fix time;
5679  char *docker = CTEXT(n);
5680  char *dockee = CTEXT(CDR(n));
5681  int count = eval_num(CDR(CDR(n)));
5682 
5683  Assert ( count > 0 );
5684  if ( !mission_log_get_time_indexed(LOG_SHIP_DOCKED, docker, dockee, count, &time) ){
5685  return SEXP_NAN;
5686  }
5687 
5688  return f2i(time);
5689 }
5690 
5692 {
5693  fix time;
5694  char *docker = CTEXT(n);
5695  char *dockee = CTEXT(CDR(n));
5696  int count = eval_num(CDR(CDR(n)));
5697 
5698  Assert ( count > 0 );
5699  if ( !mission_log_get_time_indexed(LOG_SHIP_UNDOCKED, docker, dockee, count, &time) ){
5700  return SEXP_NAN;
5701  }
5702 
5703  return f2i(time);
5704 }
5705 
5707 {
5708  fix time;
5709 
5710  Assert( n != -1 );
5711  if ( !mission_log_get_time( LOG_SHIP_ARRIVED, CTEXT(n), NULL, &time ) ){
5712  return SEXP_NAN;
5713  }
5714 
5715  return f2i(time);
5716 }
5717 
5719 {
5720  fix time;
5721 
5722  Assert( n != -1 );
5723  if ( !mission_log_get_time( LOG_WING_ARRIVED, CTEXT(n), NULL, &time ) ){
5724  return SEXP_NAN;
5725  }
5726 
5727  return f2i(time);
5728 }
5729 
5731 {
5732  fix time;
5733 
5734  Assert( n != -1 );
5735  if ( !mission_log_get_time( LOG_SHIP_DEPARTED, CTEXT(n), NULL, &time ) ){
5736  return SEXP_NAN;
5737  }
5738 
5739  return f2i(time);
5740 }
5741 
5743 {
5744  fix time;
5745 
5746  Assert( n != -1 );
5747  if ( !mission_log_get_time(LOG_WING_DEPARTED, CTEXT(n), NULL, &time ) ){
5748  return SEXP_NAN;
5749  }
5750 
5751  return f2i(time);
5752 }
5753 
5754 void sexp_set_energy_pct (int node, int op_num)
5755 {
5756  int sindex;
5757  float new_pct;
5758  char *shipname;
5759  ship * shipp;
5760  ship_info * sip;
5761 
5762  Assert (node > -1);
5763  new_pct = eval_num(node) / 100.0f;
5764 
5765  // deal with ridiculous percentages
5766  CLAMP(new_pct, 0.0f, 1.0f);
5767 
5768  // only need to send a packet for afterburners because shields and weapon energy are sent from server to clients
5769  if (MULTIPLAYER_MASTER && (op_num == OP_SET_AFTERBURNER_ENERGY)) {
5771  multi_send_float(new_pct);
5772  }
5773 
5774  node = CDR(node);
5775 
5776  while (node > -1) {
5777  // get the ship
5778  shipname = CTEXT(node);
5779 
5780  sindex = ship_name_lookup( shipname );
5781  if ( sindex == -1 ){ // hmm.. if true, must not have arrived yet
5782  node = CDR(node);
5783  continue;
5784  }
5785 
5786  shipp = &Ships[sindex];
5787  sip = &Ship_info[Ships[sindex].ship_info_index];
5788 
5789  switch (op_num) {
5791  shipp->afterburner_fuel = sip->afterburner_fuel_capacity * new_pct;
5792  break;
5793 
5794  case OP_SET_WEAPON_ENERGY:
5795  if (!(ship_has_energy_weapons(shipp)) ) {
5796  node = CDR(node);
5797  continue;
5798  }
5799 
5800  shipp->weapon_energy = sip->max_weapon_reserve * new_pct;
5801  break;
5802 
5803  case OP_SET_SHIELD_ENERGY:
5804  if (shipp->ship_max_shield_strength == 0.0f) {
5805  node = CDR(node);
5806  continue;
5807  }
5808 
5809  shield_set_strength(&Objects[shipp->objnum], (shipp->ship_max_shield_strength * new_pct));
5810  break;
5811  }
5812 
5813  if (MULTIPLAYER_MASTER && (op_num == OP_SET_AFTERBURNER_ENERGY)) {
5814  multi_send_ship(shipp);
5815  }
5816 
5817  node = CDR(node);
5818  }
5819 
5820  if (MULTIPLAYER_MASTER && (op_num == OP_SET_AFTERBURNER_ENERGY)) {
5821  multi_end_callback();
5822  }
5823 }
5824 
5826 {
5827  ship *shipp;
5828  float new_pct;
5829  ship_info * sip;
5830 
5832 
5833  multi_get_float(new_pct);
5834  while (multi_get_ship(shipp)) {
5835  sip = &Ship_info[shipp->ship_info_index];
5836 
5837  switch (op_num) {
5839  shipp->afterburner_fuel = sip->afterburner_fuel_capacity * new_pct;
5840  break;
5841 
5842  case OP_SET_WEAPON_ENERGY:
5843  shipp->weapon_energy = sip->max_weapon_reserve * new_pct;
5844  break;
5845 
5846  case OP_SET_SHIELD_ENERGY:
5847  shield_set_strength(&Objects[shipp->objnum], (shipp->ship_max_shield_strength * new_pct));
5848  break;
5849  }
5850  }
5851 }
5852 
5853 
5854 int sexp_get_energy_pct (int node, int op_num)
5855 {
5856  int sindex;
5857  float maximum = 0.0f, current = 0.0f;
5858  ship * shipp;
5859  ship_info * sip;
5860  char *shipname;
5861 
5862  // get the ship
5863  shipname = CTEXT(node);
5864 
5865  sindex = ship_name_lookup( shipname );
5866  if ( sindex == -1 ){ // has either not arrived yet or has departed
5867  return SEXP_NAN;
5868  }
5869 
5870  shipp = &Ships[sindex];
5871  sip = &Ship_info[Ships[sindex].ship_info_index];
5872 
5873  switch (op_num) {
5874  case OP_AFTERBURNER_LEFT:
5875  maximum = sip->afterburner_fuel_capacity;
5876  current = shipp->afterburner_fuel;
5877  break;
5878  case OP_WEAPON_ENERGY_LEFT:
5879  if (ship_has_energy_weapons(shipp)) {
5880  maximum = sip->max_weapon_reserve;
5881  current = shipp->weapon_energy;
5882  }
5883  break;
5884  }
5885  if (maximum < WEAPON_RESERVE_THRESHOLD || current < WEAPON_RESERVE_THRESHOLD) {
5886  return 0;
5887  }
5888 
5889  return (int)(100 * (current/maximum));
5890 }
5891 
5896 {
5897  int shipnum, percent;
5898  char *shipname;
5899 
5900  shipname = CTEXT(n);
5901 
5902  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
5903  if ( mission_log_get_time(LOG_SHIP_DESTROYED, shipname, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, shipname, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, shipname, NULL, NULL) ) {
5904  return SEXP_NAN_FOREVER;
5905  }
5906 
5907  shipnum = ship_name_lookup( shipname );
5908  if ( shipnum == -1 ){ // hmm.. if true, must not have arrived yet
5909  return SEXP_NAN;
5910  }
5911 
5912  // Goober5000: in case ship has no shields
5913  if (Ships[shipnum].ship_max_shield_strength == 0.0f)
5914  {
5915  return 0;
5916  }
5917 
5918  // now return the amount of shields left as a percentage of the whole.
5919  percent = fl2i((get_shield_pct(&Objects[Ships[shipnum].objnum]) * 100.0f) + 0.5f);
5920  return percent;
5921 }
5922 
5929 {
5930  int shipnum, percent;
5931  char *shipname;
5932 
5933  shipname = CTEXT(n);
5934 
5935  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
5936  if ( mission_log_get_time(LOG_SHIP_DESTROYED, shipname, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, shipname, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, shipname, NULL, NULL) ) {
5937  return SEXP_NAN_FOREVER;
5938  }
5939 
5940  shipnum = ship_name_lookup( shipname );
5941  if ( shipnum == -1 ){ // hmm.. if true, must not have arrived yet
5942  return SEXP_NAN;
5943  }
5944 
5945  // now return the amount of hits left as a percentage of the whole. Subtract the percentage from 100
5946  // since we are working with total hit points taken, not total remaining.
5947  ship *shipp = &Ships[shipnum];
5948  object *objp = &Objects[shipp->objnum];
5949  percent = fl2i((100.0f * get_hull_pct(objp)) + 0.5f);
5950  return percent;
5951 }
5952 
5954 {
5955  int shipnum, percent;
5956  char *shipname;
5957 
5958  shipname = CTEXT(n);
5959 
5960  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
5961  if ( mission_log_get_time(LOG_SHIP_DESTROYED, shipname, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, shipname, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, shipname, NULL, NULL) ) {
5962  return SEXP_NAN_FOREVER;
5963  }
5964 
5965  shipnum = ship_name_lookup( shipname );
5966  if ( shipnum == -1 ){ // hmm.. if true, must not have arrived yet
5967  return SEXP_NAN;
5968  }
5969 
5970  // now return the amount of hits left as a percentage of the whole. Subtract the percentage from 100
5971  // since we are working with total hit points taken, not total remaining.
5972  ship *shipp = &Ships[shipnum];
5973  object *objp = &Objects[shipp->objnum];
5974  percent = fl2i((100.0f * get_sim_hull_pct(objp)) + 0.5f);
5975  return percent;
5976 }
5977 
5986 {
5987  char *shipname;
5988  int shipnum;
5989  int ship_is_visible = 0;
5990 
5991  // if multiplayer, bail
5992  if (Game_mode & GM_MULTIPLAYER) {
5993  return SEXP_NAN_FOREVER;
5994  }
5995 
5996  shipname = CTEXT(n);
5997 
5998  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
5999  if ( mission_log_get_time(LOG_SHIP_DESTROYED, shipname, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, shipname, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, shipname, NULL, NULL) ) {
6000  return SEXP_NAN_FOREVER;
6001  }
6002 
6003  shipnum = ship_name_lookup( shipname );
6004  if ( shipnum == -1 ){ // hmm.. if true, must not have arrived yet
6005  return SEXP_NAN;
6006  }
6007 
6008  // get ship's *radar* visiblity
6009  if (Player_ship != NULL)
6010  {
6011  if (ship_is_visible_by_team(&Objects[Ships[shipnum].objnum], Player_ship))
6012  {
6013  ship_is_visible = 2;
6014  }
6015  }
6016 
6017  // only check awacs level if ship is not visible by team
6018  if (Player_ship != NULL && !ship_is_visible) {
6019  float awacs_level = awacs_get_level(&Objects[Ships[shipnum].objnum], Player_ship);
6020  if (awacs_level >= 1.0f) {
6021  ship_is_visible = 2;
6022  } else if (awacs_level > 0) {
6023  ship_is_visible = 1;
6024  }
6025  }
6026 
6027  return ship_is_visible;
6028 }
6029 
6034 {
6035  char *shipname;
6036  int shipnum;
6037 
6038  shipname = CTEXT(n);
6039 
6040  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
6041  if ( mission_log_get_time(LOG_SHIP_DESTROYED, shipname, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, shipname, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, shipname, NULL, NULL) ) {
6042  return SEXP_NAN_FOREVER;
6043  }
6044 
6045  shipnum = ship_name_lookup( shipname );
6046  if ( shipnum == -1 ) { // hmm.. if true, must not have arrived yet
6047  return SEXP_NAN;
6048  }
6049 
6050  if (Ships[shipnum].flags2 & SF2_STEALTH)
6051  return SEXP_TRUE;
6052  else
6053  return SEXP_FALSE;
6054 }
6055 
6060 {
6061  char *shipname;
6062  int shipnum;
6063 
6064  shipname = CTEXT(n);
6065 
6066  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
6067  if ( mission_log_get_time(LOG_SHIP_DESTROYED, shipname, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, shipname, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, shipname, NULL, NULL) ) {
6068  return SEXP_NAN_FOREVER;
6069  }
6070 
6071  shipnum = ship_name_lookup( shipname );
6072  if ( shipnum == -1 ) { // hmm.. if true, must not have arrived yet
6073  return SEXP_NAN;
6074  }
6075 
6076  if (Ships[shipnum].flags2 & SF2_FRIENDLY_STEALTH_INVIS)
6077  return SEXP_FALSE;
6078  else
6079  return SEXP_TRUE;
6080 }
6081 
6082 // get multi team v team score
6083 // if not multi team v team return 0
6084 // if invalid team return 0
6085 int sexp_team_score(int node)
6086 {
6087  // if multi t vs t
6088  if (Game_mode & GM_MULTIPLAYER) {
6090 
6091  int team = eval_num(node);
6092 
6093  // Teams can only be 1 or 2 at the moment but we should use Num_teams in case more become possible in the future
6094  if (team <= 0 || team > Num_teams)
6095  {
6096  // invalid team index
6097  Warning(LOCATION, "sexp-team-score: team %d is not a valid team #", team);
6098  return 0;
6099  }
6100 
6101  return Multi_team_score[team - 1];
6102  }
6103  }
6104 
6105  return 0;
6106 }
6107 
6108 
6115 {
6116  int shipnum, percent, type, single_subsystem = 0;
6117  char *shipname;
6118  char *subsys_name;
6119 
6120  shipname = CTEXT(n);
6121 
6122  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
6123  if ( mission_log_get_time(LOG_SHIP_DESTROYED, shipname, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, shipname, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, shipname, NULL, NULL) ) {
6124  return SEXP_NAN_FOREVER;
6125  }
6126 
6127  shipnum = ship_name_lookup( shipname );
6128  if ( shipnum == -1 ){ // hmm.. if true, must not have arrived yet
6129  return SEXP_NAN;
6130  }
6131 
6132  subsys_name = CTEXT(CDR(n));
6133  ship_subsys *ss = ship_get_subsys(&Ships[shipnum], subsys_name);
6134  if (ss != NULL)
6135  type = ss->system_info->type;
6136  else
6137  type = SUBSYSTEM_NONE;
6138 
6139  if ( (type >= 0) && (type < SUBSYSTEM_MAX) ) {
6140  // check for the optional argument
6141  n = CDDR(n);
6142  if (n >= 0) {
6143  single_subsystem = is_sexp_true(n);
6144  }
6145 
6146  // if the third option is present or if this is an unknown subsystem type we only want to find the percentage of the
6147  // named subsystem
6148  if (single_subsystem || (type == SUBSYSTEM_UNKNOWN)) {
6149  if (ss != NULL) {
6150  percent = fl2i((ss->current_hits / ss->max_hits * 100.0f) + 0.5f);
6151  return percent;
6152  }
6153 
6154  // we reached end of ship subsys list without finding subsys_name
6155  if (ship_class_unchanged(shipnum)) {
6156  Error(LOCATION, "Invalid subsystem '%s' passed to hits-left-subsystem", subsys_name);
6157  }
6158  return SEXP_NAN;
6159 
6160  // by default we return as a percentage the hits remaining on the subsystem as a whole (i.e. for 3 engines,
6161  // we are returning the sum of the hits on the 3 engines)
6162  } else {
6163  percent = fl2i((ship_get_subsystem_strength(&Ships[shipnum],type) * 100.0f) + 0.5f);
6164  return percent;
6165  }
6166  }
6167  return SEXP_NAN; // if for some strange reason, the type field of the subsystem is bogus
6168 }
6169 
6170 // Goober5000
6172 {
6173  int i, ship_num, subsys_type;
6174  char *ship_name, *subsys_type_name;
6175 
6176  ship_name = CTEXT(node);
6177  subsys_type_name = CTEXT(CDR(node));
6178 
6179  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
6180  if (mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL)) {
6181  return SEXP_NAN_FOREVER;
6182  }
6183 
6184  ship_num = ship_name_lookup(ship_name);
6185  if (ship_num < 0) {
6186  return SEXP_NAN;
6187  }
6188 
6189  // find subsystem type
6190  subsys_type = -1;
6191  for (i = 0; i < SUBSYSTEM_MAX; i++)
6192  {
6193  if (!stricmp(subsys_type_name, Subsystem_types[i]))
6194  subsys_type = i;
6195  }
6196 
6197  // error checking
6198  if (subsys_type < 0) {
6199  Warning(LOCATION, "Subsystem type '%s' not recognized in hits-left-subsystem-generic!", subsys_type_name);
6200  return SEXP_NAN_FOREVER;
6201  } else if (subsys_type == SUBSYSTEM_NONE) {
6202  // as you wish...?
6203  return 0;
6204  } else if (subsys_type == SUBSYSTEM_UNKNOWN) {
6205  Warning(LOCATION, "Cannot use SUBSYSTEM_UNKNOWN in hits-left-subsystem-generic!");
6206  return SEXP_NAN_FOREVER;
6207  }
6208 
6209  // return as a percentage the hits remaining on the subsystem as a whole (i.e. for 3 engines,
6210  // we are returning the sum of the hits on the 3 engines)
6211  return fl2i((ship_get_subsystem_strength(&Ships[ship_num], subsys_type) * 100.0f) + 0.5f);
6212 }
6213 
6214 // Goober5000
6216 {
6217  int ship_num;
6218  char *ship_name, *subsys_name;
6219  ship_subsys *ss;
6220 
6221  ship_name = CTEXT(node);
6222  subsys_name = CTEXT(CDR(node));
6223 
6224  // if ship is gone or departed, cannot ever evaluate properly. Return NAN_FOREVER
6225  if (mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL)) {
6226  return SEXP_NAN_FOREVER;
6227  }
6228 
6229  ship_num = ship_name_lookup(ship_name);
6230  if (ship_num < 0) {
6231  return SEXP_NAN;
6232  }
6233 
6234  // find subsystem
6235  ss = ship_get_subsys(&Ships[ship_num], subsys_name);
6236  if (ss != NULL) {
6237  // return as a percentage the hits remaining on this subsystem only
6238  return fl2i((ss->current_hits / ss->max_hits * 100.0f) + 0.5f);
6239  }
6240 
6241  // we reached end of ship subsys list without finding subsys_name
6242  if (ship_class_unchanged(ship_num)) {
6243  Error(LOCATION, "Invalid subsystem '%s' passed to hits-left-subsystem", subsys_name);
6244  }
6245  return SEXP_NAN;
6246 }
6247 
6249 {
6250  int replace_current_value = SEXP_TRUE;
6251  int directive_value;
6252 
6253  Assert(n >= 0);
6254 
6255  directive_value = eval_num(n);
6256 
6257  if ((directive_value == SEXP_NAN) || (directive_value == SEXP_NAN_FOREVER)) {
6258  directive_value = 0;
6259  }
6260 
6261  n = CDR(n);
6262  if (n > -1) {
6263  replace_current_value = eval_sexp(n);
6264  }
6265 
6266  if (replace_current_value == SEXP_FALSE) { // note: any SEXP_KNOWN_FALSE result will return SEXP_FALSE
6267  Directive_count += directive_value;
6268  }
6269  else {
6270  Directive_count = directive_value;
6271  }
6272 
6273 
6274  return SEXP_TRUE;
6275 }
6276 
6277 int sexp_determine_team(char *subj)
6278 {
6279  int len;
6280  char team_name[NAME_LENGTH];
6281 
6282  // quick check
6283  if (strnicmp(subj, "<any ", 5))
6284  return -1;
6285 
6286  // grab IFF (rest of string except for closing angle bracket)
6287  len = strlen(subj + 5) - 1;
6288  strncpy(team_name, subj + 5, len);
6289  team_name[len] = '\0';
6290 
6291  // find it
6292  return iff_lookup(team_name);
6293 }
6294 
6298 int sexp_distance3(object *objp1, object *objp2)
6299 {
6300  // if either object isn't present in the mission now
6301  if (objp1 == NULL || objp2 == NULL)
6302  return SEXP_NAN;
6303 
6304  if ((objp1->type == OBJ_SHIP) && (objp2->type == OBJ_SHIP))
6305  {
6306  if (Player_obj == objp1)
6307  return (int) hud_find_target_distance(objp2, objp1);
6308  else
6309  return (int) hud_find_target_distance(objp1, objp2);
6310  }
6311  else
6312  {
6313  return (int) vm_vec_dist_quick(&objp1->pos, &objp2->pos);
6314  }
6315 }
6316 
6320 int sexp_distance2(object *objp1, object_ship_wing_point_team *oswpt2)
6321 {
6322  int dist, dist_min = 0, inited = 0;
6323 
6324  switch (oswpt2->type)
6325  {
6326  // we have a ship-on-team type, so check all ships of that type
6328  {
6329  for (ship_obj *so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
6330  {
6331  if (Ships[Objects[so->objnum].instance].team == oswpt2->team)
6332  {
6333  dist = sexp_distance3(objp1, &Objects[so->objnum]);
6334  if (dist != SEXP_NAN)
6335  {
6336  if (!inited || (dist < dist_min))
6337  {
6338  dist_min = dist;
6339  inited = 1;
6340  }
6341  }
6342  }
6343  }
6344 
6345  // no objects were checked
6346  if (!inited)
6347  return SEXP_NAN;
6348 
6349  return dist_min;
6350  }
6351 
6352  // check ships and points
6353  case OSWPT_TYPE_SHIP:
6354  case OSWPT_TYPE_WAYPOINT:
6355  {
6356  return sexp_distance3(objp1, oswpt2->objp);
6357  }
6358 
6359  // check wings
6360  case OSWPT_TYPE_WING:
6361  {
6362  for (int i = 0; i < oswpt2->wingp->current_count; i++)
6363  {
6364  dist = sexp_distance3(objp1, &Objects[Ships[oswpt2->wingp->ship_index[i]].objnum]);
6365  if (dist != SEXP_NAN)
6366  {
6367  if (!inited || (dist < dist_min))
6368  {
6369  dist_min = dist;
6370  inited = 1;
6371  }
6372  }
6373  }
6374 
6375  // no objects were checked
6376  if (!inited)
6377  return SEXP_NAN;
6378 
6379  return dist_min;
6380  }
6381  }
6382 
6383  return SEXP_NAN;
6384 }
6385 
6392 {
6393  int dist, dist_min = 0, inited = 0;
6394  object_ship_wing_point_team oswpt1, oswpt2;
6395 
6398 
6399  // check to see if either object was destroyed or departed
6400  if (oswpt1.type == OSWPT_TYPE_EXITED || oswpt2.type == OSWPT_TYPE_EXITED)
6401  return SEXP_NAN_FOREVER;
6402 
6403  switch (oswpt1.type)
6404  {
6405  // we have a ship-on-team type, so check all ships of that type
6407  {
6408  for (ship_obj *so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
6409  {
6410  if (Ships[Objects[so->objnum].instance].team == oswpt1.team)
6411  {
6412  dist = sexp_distance2(&Objects[so->objnum], &oswpt2);
6413  if (dist != SEXP_NAN)
6414  {
6415  if (!inited || (dist < dist_min))
6416  {
6417  dist_min = dist;
6418  inited = 1;
6419  }
6420  }
6421  }
6422  }
6423 
6424  // no objects were checked
6425  if (!inited)
6426  return SEXP_NAN;
6427 
6428  return dist_min;
6429  }
6430 
6431  // check ships and points
6432  case OSWPT_TYPE_SHIP:
6433  case OSWPT_TYPE_WAYPOINT:
6434  {
6435  return sexp_distance2(oswpt1.objp, &oswpt2);
6436  }
6437 
6438  // check wings
6439  case OSWPT_TYPE_WING:
6440  {
6441  for (int i = 0; i < oswpt1.wingp->current_count; i++)
6442  {
6443  dist = sexp_distance2(&Objects[Ships[oswpt1.wingp->ship_index[i]].objnum], &oswpt2);
6444  if (dist != SEXP_NAN)
6445  {
6446  if (!inited || (dist < dist_min))
6447  {
6448  dist_min = dist;
6449  inited = 1;
6450  }
6451  }
6452  }
6453 
6454  // no objects were checked
6455  if (!inited)
6456  return SEXP_NAN;
6457 
6458  return dist_min;
6459  }
6460  }
6461 
6462  return SEXP_NAN;
6463 }
6464 
6470 bool sexp_get_subsystem_world_pos(vec3d *subsys_world_pos, int shipnum, char *subsys_name)
6471 {
6472  Assert(subsys_name);
6473  Assert(subsys_world_pos);
6474 
6475  if(shipnum < 0)
6476  {
6477  Error(LOCATION, "Error - nonexistent ship.\n");
6478  }
6479 
6480  // find the ship subsystem
6481  ship_subsys *ss = ship_get_subsys(&Ships[shipnum], subsys_name);
6482  if (ss != NULL)
6483  {
6484  // find world position of subsystem on this object (the ship)
6485  get_subsystem_world_pos(&Objects[Ships[shipnum].objnum], ss, subsys_world_pos);
6486  return true;
6487  }
6488 
6489  // we reached end of ship subsys list without finding subsys_name
6490  if (ship_class_unchanged(shipnum)) {
6491  // this ship should have had the subsystem named as it shouldn't have changed class
6492  Error(LOCATION, "sexp_get_subsystem_world_pos could not find subsystem '%s'", subsys_name);
6493  }
6494  return false;
6495 }
6496 
6503 {
6504  int ship_with_subsys_num, dist, dist_min = 0, inited = 0;
6505  char *ship_with_subsys_name, *subsys_name;
6506  vec3d subsys_pos;
6508 
6510  ship_with_subsys_name = CTEXT(CDR(n));
6511  subsys_name = CTEXT(CDR(CDR(n)));
6512 
6513  // for the ship with the subsystem - see if it was destroyed or departed
6514  if (mission_log_get_time(LOG_SHIP_DESTROYED, ship_with_subsys_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DEPARTED, ship_with_subsys_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_with_subsys_name, NULL, NULL))
6515  return SEXP_NAN_FOREVER;
6516 
6517  // check the other ship too
6518  if (oswpt.type == OSWPT_TYPE_EXITED)
6519  return SEXP_NAN_FOREVER;
6520 
6521  // for the ship with the subsystem - get its index
6522  ship_with_subsys_num = ship_name_lookup(ship_with_subsys_name);
6523  if (ship_with_subsys_num < 0)
6524  return SEXP_NAN;
6525 
6526  // get the subsystem's coordinates or bail if we can't
6527  if (!sexp_get_subsystem_world_pos(&subsys_pos, ship_with_subsys_num, subsys_name))
6528  return SEXP_NAN;
6529 
6530  switch (oswpt.type)
6531  {
6532  // we have a ship-on-team type, so check all ships of that type
6534  {
6535  for (ship_obj *so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
6536  {
6537  if (Ships[Objects[so->objnum].instance].team == oswpt.team)
6538  {
6539  dist = (int) vm_vec_dist_quick(&Objects[so->objnum].pos, &subsys_pos);
6540 
6541  if (!inited || (dist < dist_min))
6542  {
6543  dist_min = dist;
6544  inited = 1;
6545  }
6546  }
6547  }
6548 
6549  // no objects were checked
6550  if (!inited)
6551  return SEXP_NAN;
6552 
6553  return dist_min;
6554  }
6555 
6556  // check ships and points
6557  case OSWPT_TYPE_SHIP:
6558  case OSWPT_TYPE_WAYPOINT:
6559  {
6560  return (int) vm_vec_dist_quick(&oswpt.objp->pos, &subsys_pos);
6561  }
6562 
6563  // check wings
6564  case OSWPT_TYPE_WING:
6565  {
6566  for (int i = 0; i < oswpt.wingp->current_count; i++)
6567  {
6568  dist = (int) vm_vec_dist_quick(&Objects[Ships[oswpt.wingp->ship_index[i]].objnum].pos, &subsys_pos);
6569 
6570  if (!inited || (dist < dist_min))
6571  {
6572  dist_min = dist;
6573  inited = 1;
6574  }
6575  }
6576 
6577  // no objects were checked
6578  if (!inited)
6579  return SEXP_NAN;
6580 
6581  return dist_min;
6582  }
6583  }
6584 
6585  return SEXP_NAN;
6586 }
6587 
6588 bool sexp_helper_is_within_box(float *box_vals, vec3d *pos)
6589 {
6590  int i;
6591  for(i = 0; i < 3; i++)
6592  {
6593  if(pos->a1d[i] < (box_vals[i] - box_vals[i+3])
6594  || pos->a1d[i] > (box_vals[i] + box_vals[i+3]))
6595  {
6596  return false;
6597  }
6598  }
6599 
6600  return true;
6601 }
6602 
6604 {
6605  float box_vals[6];//x,y,z,width,height,depth
6606  char *ship_wing;
6607  int i, idx;
6608  int retval = 0;
6609 
6610  for(i = 0; i < 6; i++)
6611  {
6612  box_vals[i] = i2fl(eval_num(n));
6613  n = CDR(n);
6614  }
6615 
6616 
6617  for(;n != -1; n = CDR(n))
6618  {
6619  ship_wing = CTEXT(n);
6620 
6621  idx = ship_name_lookup(ship_wing);
6622  if(idx > -1)
6623  {
6624  if(sexp_helper_is_within_box(box_vals, &Objects[Ships[idx].objnum].pos))
6625  retval++;
6626  }
6627  else
6628  {
6629  idx = wing_name_lookup(ship_wing);
6630  if(idx > -1)
6631  {
6632  bool wing_check = true;
6633  for(i = 0; i < Wings[idx].current_count; i++)
6634  {
6635  if(!sexp_helper_is_within_box(box_vals, &Objects[Ships[Wings[idx].ship_index[i]].objnum].pos))
6636  {
6637  wing_check = false;
6638  break;
6639  }
6640  }
6641 
6642  if(wing_check)
6643  retval++;
6644  }
6645  }
6646  }
6647 
6648  return retval;
6649 }
6650 
6651 // Goober5000
6652 void sexp_set_object_speed(object *objp, int speed, int axis, int subjective)
6653 {
6654  Assert(axis >= 0 && axis <= 2);
6655 
6656  if (subjective)
6657  {
6658  vec3d subjective_vel;
6659 
6660  // translate objective into subjective velocity
6661  vm_vec_rotate(&subjective_vel, &objp->phys_info.vel, &objp->orient);
6662 
6663  // set it
6664  subjective_vel.a1d[axis] = i2fl(speed);
6665 
6666  // translate it back to objective
6667  vm_vec_unrotate(&objp->phys_info.vel, &subjective_vel, &objp->orient);
6668  }
6669  else
6670  {
6671  objp->phys_info.vel.a1d[axis] = i2fl(speed);
6672  }
6673 }
6674 
6675 // Goober5000
6676 void sexp_set_object_speed(int n, int axis)
6677 {
6678  Assert(n >= 0);
6679 
6680  int speed, subjective = 0;
6682 
6684  n = CDR(n);
6685 
6686  speed = eval_num(n);
6687  n = CDR(n);
6688 
6689  if (n >= 0)
6690  {
6691  subjective = is_sexp_true(n);
6692  n = CDR(n);
6693  }
6694 
6695  switch (oswpt.type)
6696  {
6697  case OSWPT_TYPE_SHIP:
6698  case OSWPT_TYPE_WING:
6699  {
6700  sexp_set_object_speed(oswpt.objp, speed, axis, subjective);
6701 
6702  //CommanderDJ - we put the multiplayer callback stuff in here to prevent doing unnecessary checks clientside
6704  multi_send_object(oswpt.objp);
6705  multi_send_int(speed);
6706  multi_send_int(axis);
6707  multi_send_int(subjective);
6709 
6710  break;
6711  }
6712  }
6713 }
6714 
6715 //CommanderDJ
6717 {
6718  object *objp;
6719  int speed = 0, axis = 0, subjective = 0;
6720 
6721  multi_get_object(objp);
6722  multi_get_int(speed);
6723  multi_get_int(axis);
6724  multi_get_int(subjective);
6725 
6726  sexp_set_object_speed(objp, speed, axis, subjective);
6727 }
6728 
6729 int sexp_get_object_speed(object *objp, int axis, int subjective)
6730 {
6731  Assertion(((axis >= 0) && (axis <= 2)), "Axis is out of range (%d)", axis);
6732  int speed;
6733 
6734  if (subjective)
6735  {
6736  // return the speed based on the orentation of the object
6737  vec3d subjective_vel;
6738  vm_vec_rotate(&subjective_vel, &objp->phys_info.vel, &objp->orient);
6739  speed = fl2i(subjective_vel.a1d[axis]);
6740  vm_vec_unrotate(&objp->phys_info.vel, &subjective_vel, &objp->orient);
6741  }
6742  else
6743  {
6744  // return the speed according to the grid
6745  speed = fl2i(objp->phys_info.vel.a1d[axis]);
6746  }
6747  return speed;
6748 }
6749 
6750 int sexp_get_object_speed(int n, int axis)
6751 {
6752  Assert(n >= 0);
6753 
6754  int speed, subjective = 0;
6756 
6758  n = CDR(n);
6759 
6760  if (n >= 0)
6761  {
6762  subjective = is_sexp_true(n);
6763  n = CDR(n);
6764  }
6765 
6766  switch (oswpt.type)
6767  {
6768  case OSWPT_TYPE_EXITED:
6769  return SEXP_NAN_FOREVER;
6770 
6771  case OSWPT_TYPE_SHIP:
6772  case OSWPT_TYPE_WING:
6773  speed = sexp_get_object_speed(oswpt.objp, axis, subjective);
6774  break;
6775 
6776  default:
6777  return SEXP_NAN;
6778  }
6779  return speed;
6780 }
6781 
6782 // Goober5000
6783 int sexp_calculate_coordinate(vec3d *origin, matrix *orient, vec3d *relative_location, int axis)
6784 {
6785  Assert(origin != NULL);
6786  Assert(orient != NULL);
6787  Assert(axis >= 0 && axis <= 2);
6788 
6789  if (relative_location == NULL)
6790  {
6791  return fl2i(origin->a1d[axis]);
6792  }
6793  else
6794  {
6795  vec3d new_world_pos;
6796 
6797  vm_vec_unrotate(&new_world_pos, relative_location, orient);
6798  vm_vec_add2(&new_world_pos, origin);
6799 
6800  return fl2i(new_world_pos.a1d[axis]);
6801  }
6802 }
6803 
6804 // Goober5000
6806 {
6807  Assert(orient != NULL);
6808  Assert(axis >= 0 && axis <= 2);
6809 
6810  angles a;
6812 
6813  // blugh
6814  float rad;
6815  switch (axis)
6816  {
6817  case 0: rad = a.p; break;
6818  case 1: rad = a.b; break;
6819  case 2: rad = a.h; break;
6820  default: rad = 0.0f; break;
6821  }
6822 
6823  float deg = fl_degrees(rad);
6824 
6825  int deg2 = static_cast<int>(deg < 0.0f ? deg - 0.5f : deg + 0.5f);
6826  if (deg2 < 0)
6827  deg2 += 360;
6828 
6829  return deg2;
6830 }
6831 
6832 // Goober5000
6833 int sexp_get_object_coordinate(int n, int axis)
6834 {
6835  Assert(n >= 0);
6836 
6837  char *subsystem_name = NULL;
6838  vec3d *pos = NULL, *relative_location = NULL, relative_location_buf, subsys_pos_buf;
6840 
6842  n = CDR(n);
6843 
6844  if (n >= 0)
6845  {
6846  subsystem_name = CTEXT(n);
6847  n = CDR(n);
6848 
6849  if (n >= 0)
6850  {
6851  relative_location = &relative_location_buf;
6852 
6853  relative_location->xyz.x = (float) eval_num(n);
6854  n = CDR(n);
6855  if (n >= 0) {
6856  relative_location->xyz.y = (float) eval_num(n);
6857  n = CDR(n);
6858  if (n >= 0) {
6859  relative_location->xyz.z = (float) eval_num(n);
6860  n = CDR(n);
6861  }
6862  }
6863  }
6864  }
6865 
6866  switch (oswpt.type)
6867  {
6868  case OSWPT_TYPE_EXITED:
6869  return SEXP_NAN_FOREVER;
6870 
6871  case OSWPT_TYPE_SHIP:
6872  case OSWPT_TYPE_WING:
6873  case OSWPT_TYPE_WAYPOINT:
6874  pos = &oswpt.objp->pos;
6875  break;
6876 
6877  default:
6878  return SEXP_NAN;
6879  }
6880 
6881  // see if we have a subsys
6882  if (oswpt.objp->type == OBJ_SHIP)
6883  {
6884  if ((subsystem_name != NULL) && stricmp(subsystem_name, SEXP_NONE_STRING) && stricmp(subsystem_name, SEXP_HULL_STRING))
6885  {
6886  pos = &subsys_pos_buf;
6887  // get the world pos but bail if we can't get one
6888  if (!sexp_get_subsystem_world_pos(pos, oswpt.objp->instance, subsystem_name))
6889  return SEXP_NAN;
6890  }
6891  }
6892 
6893  return sexp_calculate_coordinate(pos, &oswpt.objp->orient, relative_location, axis);
6894 }
6895 
6896 // Goober5000
6897 int sexp_get_object_angle(int n, int axis)
6898 {
6899  Assert(n >= 0);
6900 
6903 
6904  switch (oswpt.type)
6905  {
6906  case OSWPT_TYPE_EXITED:
6907  return SEXP_NAN_FOREVER;
6908 
6909  case OSWPT_TYPE_SHIP:
6910  case OSWPT_TYPE_WING:
6911  return sexp_calculate_angle(&oswpt.objp->orient, axis);
6912 
6913  default:
6914  return SEXP_NAN;
6915  }
6916 }
6917 
6919 {
6920  if (!(Game_mode & GM_MULTIPLAYER)) {
6921  return;
6922  }
6923 
6924  // Tell the player (if this is a client) that they've moved.
6925  if ((objp->flags & OF_PLAYER_SHIP) && (objp != Player_obj) ){
6927  }
6928 }
6929 
6931 {
6932  vec3d target_vec, orig_leader_vec;
6934 
6936  n = CDR(n);
6937 
6938  target_vec.xyz.x = i2fl(eval_num(n));
6939  n = CDR(n);
6940  target_vec.xyz.y = i2fl(eval_num(n));
6941  n = CDR(n);
6942  target_vec.xyz.z = i2fl(eval_num(n));
6943  n = CDR(n);
6944 
6945  // retime all collision checks so they're performed
6946  // Goober5000 - only if we have a valid object (don't do this for departed ships, waypoints, etc.)
6947  if (oswpt.type == OSWPT_TYPE_SHIP || oswpt.type == OSWPT_TYPE_WING)
6948  {
6949  if ( Cmdline_old_collision_sys ) {
6951  } else {
6953  }
6954  }
6955 
6956  // if this is a nebula mission and a player is being moved far enough,
6957  // regenerate the nebula
6958  extern neb2_detail *Nd;
6959 
6960  if ( (oswpt.objp == Player_obj)
6962  && (vm_vec_dist(&oswpt.objp->pos, &target_vec) >= Nd->cube_inner) )
6963  {
6964  neb2_eye_changed();
6965  }
6966 
6967  switch (oswpt.type)
6968  {
6969  case OSWPT_TYPE_SHIP:
6970  {
6971  oswpt.objp->pos = target_vec;
6973  return;
6974  }
6975 
6976  case OSWPT_TYPE_WAYPOINT:
6977  {
6978  oswpt.objp->pos = target_vec;
6979  oswpt.waypointp->set_pos(&target_vec);
6982  multi_send_float(target_vec.xyz.x);
6983  multi_send_float(target_vec.xyz.y);
6984  multi_send_float(target_vec.xyz.z);
6985  multi_end_callback();
6986  return;
6987  }
6988 
6989  case OSWPT_TYPE_WING:
6990  {
6991  // move the wing leader first
6992  orig_leader_vec = oswpt.objp->pos;
6993  oswpt.objp->pos = target_vec;
6995 
6996  // move everything in the wing
6997  for (int i = 0; i < oswpt.wingp->current_count; i++)
6998  {
6999  object *objp = &Objects[Ships[oswpt.wingp->ship_index[i]].objnum];
7000 
7001  if (objp != oswpt.objp)
7002  {
7003  vm_vec_sub2(&objp->pos, &orig_leader_vec);
7004  vm_vec_add2(&objp->pos, &target_vec);
7005  set_object_for_clients(objp);
7006  }
7007  }
7008 
7009  return;
7010  }
7011  }
7012 }
7013 
7014 // only for waypoints cause they don't get transferred the normal way
7016 {
7017  object *objp;
7018  vec3d wp_vec;
7019  ushort obj_sig;
7020  multi_get_ushort(obj_sig);
7021  multi_get_float(wp_vec.xyz.x);
7022  multi_get_float(wp_vec.xyz.y);
7023  multi_get_float(wp_vec.xyz.z);
7024  objp = multi_get_network_object(obj_sig);
7025  if (objp->type == OBJ_WAYPOINT) {
7026  objp->pos = wp_vec;
7028  wpt->set_pos(&wp_vec);
7029  }
7030 }
7031 
7032 // Goober5000
7034 {
7035  angles a;
7036  matrix target_orient;
7038 
7040  n = CDR(n);
7041 
7042  a.p = fl_radians(eval_num(n) % 360);
7043  n = CDR(n);
7044  a.b = fl_radians(eval_num(n) % 360);
7045  n = CDR(n);
7046  a.h = fl_radians(eval_num(n) % 360);
7047  n = CDR(n);
7048 
7049  vm_angles_2_matrix(&target_orient, &a);
7050 
7051  // retime all collision checks so they're performed
7052  // Goober5000 - only if we have a valid object (don't do this for departed ships, waypoints, etc.)
7053  if (oswpt.type == OSWPT_TYPE_SHIP || oswpt.type == OSWPT_TYPE_WING)
7054  {
7055  if ( Cmdline_old_collision_sys ) {
7057  } else {
7059  }
7060  }
7061 
7062  switch (oswpt.type)
7063  {
7064  case OSWPT_TYPE_SHIP:
7065  {
7066  oswpt.objp->orient = target_orient;
7068  return;
7069  }
7070 
7071  case OSWPT_TYPE_WING:
7072  {
7073  // move everything in the wing
7074  for (int i = 0; i < oswpt.wingp->current_count; i++)
7075  {
7076  object *objp = &Objects[Ships[oswpt.wingp->ship_index[i]].objnum];
7077  objp->orient = target_orient;
7078  set_object_for_clients(objp);
7079  }
7080 
7081  return;
7082  }
7083  }
7084 }
7085 
7086 // Goober5000
7087 // this is different from sexp_set_object_orientation
7088 void sexp_set_object_orient_sub(object *objp, vec3d *location, int turn_time, int bank)
7089 {
7090  Assert(objp && location);
7091 
7092  vec3d v_orient;
7093  matrix m_orient;
7094 
7095 
7096  // are we doing this via ai? -------------------
7097  if (turn_time)
7098  {
7099  // set flag
7100  int bankflag = 0;
7101  if (!bank)
7102  {
7103  bankflag = AITTV_IGNORE_BANK;
7104  }
7105 
7106  // turn
7107  ai_turn_towards_vector(location, objp, flFrametime, float(turn_time)/(1000.0f), NULL, NULL, 0.0f, 0, NULL, (AITTV_VIA_SEXP | bankflag));
7108 
7109  // return
7110  return;
7111  }
7112 
7113 
7114  // calculate orientation matrix ----------------
7115 
7116  vm_vec_sub(&v_orient, location, &objp->pos);
7117 
7118  if (IS_VEC_NULL_SQ_SAFE(&v_orient))
7119  {
7120  Warning(LOCATION, "error in sexp setting ship orientation: can't point to self; quitting...\n");
7121  return;
7122  }
7123 
7124  vm_vector_2_matrix(&m_orient, &v_orient, NULL, NULL);
7125 
7126 
7127  // set orientation -----------------------------
7128  objp->orient = m_orient;
7129  // Tell the player (assuming it's a client) that they've moved.
7130  set_object_for_clients(objp);
7131 }
7132 
7133 // Goober5000
7134 void sexp_set_oswpt_facing(object_ship_wing_point_team *oswpt, vec3d *location, int turn_time = 0, int bank = 0)
7135 {
7136  Assert(oswpt && location);
7137 
7138  switch (oswpt->type)
7139  {
7140  case OSWPT_TYPE_SHIP:
7141  sexp_set_object_orient_sub(oswpt->objp, location, turn_time, bank);
7142  break;
7143 
7144  case OSWPT_TYPE_WING:
7145  {
7146  for (int i = 0; i < oswpt->wingp->current_count; i++)
7147  {
7148  object *objp = &Objects[Ships[oswpt->wingp->ship_index[i]].objnum];
7149 
7150  sexp_set_object_orient_sub(objp, location, turn_time, bank);
7151  }
7152 
7153  break;
7154  }
7155  }
7156 }
7157 
7158 // Goober5000
7159 void sexp_set_object_facing(int n, bool facing_object)
7160 {
7161  vec3d *location, location_buf;
7162  int turn_time, bank;
7163  object_ship_wing_point_team oswpt1, oswpt2;
7164 
7166  n = CDR(n);
7167 
7168  // ensure it's valid
7169  if (oswpt1.objp == NULL)
7170  return;
7171 
7172  // get location
7173  if (facing_object)
7174  {
7176  n = CDR(n);
7177 
7178  // ensure it's valid
7179  if (oswpt2.objp == NULL)
7180  return;
7181 
7182  location = &oswpt2.objp->pos;
7183  }
7184  else
7185  {
7186  location = &location_buf;
7187 
7188  location->xyz.x = (float) eval_num(n);
7189  n = CDR(n);
7190  location->xyz.y = (float) eval_num(n);
7191  n = CDR(n);
7192  location->xyz.z = (float) eval_num(n);
7193  n = CDR(n);
7194  }
7195 
7196  // get optional turn time and bank
7197  turn_time = bank = 0;
7198  if (n != -1)
7199  {
7200  turn_time = eval_num(n);
7201  n = CDR(n);
7202  }
7203  if (n != -1)
7204  {
7205  bank = eval_num(n);
7206  }
7207 
7208  sexp_set_oswpt_facing(&oswpt1, location, turn_time, bank);
7209 }
7210 
7211 void sexp_set_ship_man(object *objp, int duration, int heading, int pitch, int bank, bool apply_all_rotate, int up, int sideways, int forward, bool apply_all_lat)
7212 {
7213  if (objp->type != OBJ_SHIP)
7214  return;
7215 
7216  ship *shipp = &Ships[objp->instance];
7217  ai_info *aip = &Ai_info[shipp->ai_index];
7218 
7219  aip->ai_override_timestamp = timestamp(duration);
7220  aip->ai_override_flags = 0;
7221 
7222  if (apply_all_rotate) {
7223  aip->ai_override_flags |= AIORF_FULL;
7224  aip->ai_override_ci.bank = bank / 100.0f;
7225  aip->ai_override_ci.pitch = pitch / 100.0f;
7226  aip->ai_override_ci.heading = heading / 100.0f;
7227  } else {
7228  if (bank != 0) {
7229  aip->ai_override_flags |= AIORF_ROLL;
7230  aip->ai_override_ci.bank = bank / 100.0f;
7231  }
7232  if (pitch != 0) {
7234  aip->ai_override_ci.pitch = pitch / 100.0f;
7235  }
7236  if (heading != 0) {
7238  aip->ai_override_ci.heading = heading / 100.0f;
7239  }
7240  }
7241  if (apply_all_lat) {
7243  aip->ai_override_ci.vertical = up / 100.0f;
7244  aip->ai_override_ci.sideways = sideways / 100.0f;
7245  aip->ai_override_ci.forward = forward / 100.0f;
7246  } else {
7247  if (up != 0) {
7248  aip->ai_override_flags |= AIORF_UP;
7249  aip->ai_override_ci.vertical = up / 100.0f;
7250  }
7251  if (sideways != 0) {
7253  aip->ai_override_ci.sideways = sideways / 100.0f;
7254  }
7255  if (forward != 0) {
7257  aip->ai_override_ci.forward = forward / 100.0f;
7258  }
7259  }
7260 }
7261 
7262 void sexp_set_oswpt_maneuver(object_ship_wing_point_team *oswpt, int duration, int heading, int pitch, int bank, bool apply_all_rotate, int up, int sideways, int forward, bool apply_all_lat)
7263 {
7264  Assert(oswpt);
7265 
7266  switch (oswpt->type)
7267  {
7268  case OSWPT_TYPE_SHIP:
7269  sexp_set_ship_man(oswpt->objp, duration, heading, pitch, bank, apply_all_rotate, up, sideways, forward, apply_all_lat);
7270  break;
7271 
7272  case OSWPT_TYPE_WING:
7273  {
7274  for (int i = 0; i < oswpt->wingp->current_count; i++)
7275  {
7276  object *objp = &Objects[Ships[oswpt->wingp->ship_index[i]].objnum];
7277 
7278  sexp_set_ship_man(objp, duration, heading, pitch, bank, apply_all_rotate, up, sideways, forward, apply_all_lat);
7279  }
7280 
7281  break;
7282  }
7283  }
7284 }
7285 
7287 {
7288  int bank = 0, heading = 0, pitch = 0;
7289  int up = 0, sideways = 0, forward = 0;
7290  int duration, i, temp;
7291  bool apply_all_rotate = false, apply_all_lat = false;
7293 
7295 
7296  n = CDR(n);
7297  duration = eval_num(n);
7298  if (duration < 2)
7299  return;
7300 
7301  if (op_num == OP_SHIP_ROT_MANEUVER || op_num == OP_SHIP_MANEUVER) {
7302  for(i=0;i<3;i++) {
7303  n = CDR(n);
7304 
7305  temp = eval_num(n);
7306  if (temp > 100) temp = 100;
7307  if (temp < -100) temp = -100;
7308 
7309  if (i == 0)
7310  heading = temp;
7311  else if (i == 1)
7312  pitch = temp;
7313  else
7314  bank = temp;
7315  }
7316 
7317  n = CDR(n);
7318  apply_all_rotate = (is_sexp_true(n) != 0);
7319  }
7320 
7321  if (op_num == OP_SHIP_LAT_MANEUVER || op_num == OP_SHIP_MANEUVER) {
7322  for(i=0;i<3;i++) {
7323  n = CDR(n);
7324 
7325  temp = eval_num(n);
7326  if (temp > 100) temp = 100;
7327  if (temp < -100) temp = -100;
7328 
7329  if (i == 0)
7330  up = temp;
7331  else if (i == 1)
7332  sideways = temp;
7333  else
7334  forward = temp;
7335  }
7336 
7337  n = CDR(n);
7338  apply_all_lat = (is_sexp_true(n) != 0);
7339  }
7340 
7341  if ((bank == 0) && (pitch == 0) && (heading == 0) && !apply_all_rotate && (up == 0) && (sideways == 0) && (forward == 0) && !apply_all_lat)
7342  return;
7343 
7344  sexp_set_oswpt_maneuver(&oswpt, duration, heading, pitch, bank, apply_all_rotate, up, sideways, forward, apply_all_lat);
7345 }
7346 
7353 {
7354  int instance, i;
7355  fix time;
7356  char *name;
7357  ai_goal *aigp;
7358 
7359  time = i2f(eval_num(n));
7360  Assert ( time >= 0 );
7361 
7362  n = CDR(n);
7363  while ( n != -1 ) {
7364  name = CTEXT(n);
7365  instance = ship_name_lookup(name);
7366  if ( instance != -1 ) {
7367  aigp = Ai_info[Ships[instance].ai_index].goals;
7368  } else {
7369  instance = wing_name_lookup(name);
7370  if ( instance == -1 ) // if we cannot find ship or wing, return SEXP_FALSE
7371  return SEXP_FALSE;
7372  aigp = Wings[instance].ai_goals;
7373  }
7374 
7375  // with the ship, check the ai_goals structure for this ship and determine if there are any
7376  // orders which are < time seconds since current mission time
7377  for ( i = 0; i < MAX_AI_GOALS; i++ ) {
7378  int mode;
7379 
7380  mode = aigp->ai_mode;
7381  if ( (mode != AI_GOAL_NONE) && (mode != AI_GOAL_WARP) )
7382  if ( (aigp->time + time) > Missiontime )
7383  break;
7384  aigp++;
7385  }
7386  if ( i == MAX_AI_GOALS )
7387  return SEXP_TRUE;
7388 
7389  n = CDR(n);
7390  }
7391 
7392  return SEXP_FALSE;
7393 }
7394 
7399 {
7400  int count;
7401  object *objp;
7402 
7403  count = 0;
7404  for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
7405  if ( (objp->type == OBJ_SHIP) && (objp->flags & OF_PLAYER_SHIP) )
7406  count++;
7407  }
7408 
7409  return count;
7410 }
7411 
7416 {
7417  int i;
7418  char *level_name;
7419 
7420  level_name = CTEXT(n);
7421 
7422  if (level_name == NULL)
7423  return SEXP_FALSE;
7424 
7425  for (i = 0; i < NUM_SKILL_LEVELS; i++ ) {
7426  if ( !stricmp(level_name, Skill_level_names(i, 0)) ) {
7427  if ( Game_skill_level >= i ){
7428  return SEXP_TRUE;
7429  } else {
7430  return SEXP_FALSE;
7431  }
7432  }
7433  }
7434 
7435  // return SEXP_FALSE if not found!!!
7436  return SEXP_FALSE;
7437 }
7438 
7440 {
7442  return SEXP_TRUE;
7443 
7444  return SEXP_FALSE;
7445 }
7446 
7448 {
7449  int i;
7450  char *medal_name;
7451 
7452  if (n < 0) {
7453  if (Player->stats.m_medal_earned >= 0)
7454  return SEXP_TRUE;
7455 
7456  return SEXP_FALSE;
7457  }
7458 
7459  medal_name = CTEXT(n);
7460 
7461  if (medal_name == NULL)
7462  return SEXP_FALSE;
7463 
7464  for (i=0; i<Num_medals; i++) {
7465  if (!stricmp(medal_name, Medals[i].name))
7466  break;
7467  }
7468 
7469  if ( (i < Num_medals) && (Player->stats.m_medal_earned == i) )
7470  return SEXP_TRUE;
7471 
7472  return SEXP_FALSE;
7473 }
7474 
7478 float get_damage_caused(int damaged_ship, int attacker )
7479 {
7480  int sindex, idx;
7481  float damage_total = 0.0f;
7482 
7483 
7484  // is the ship that took damage in the mission still?
7485  sindex = ship_get_by_signature(damaged_ship);
7486 
7487  if (sindex >= 0 ) {
7488  for(idx=0; idx<MAX_DAMAGE_SLOTS; idx++){
7489  if (Ships[sindex].damage_ship_id[idx] == attacker) {
7490  damage_total += Ships[sindex].damage_ship[idx];
7491  break;
7492  }
7493  }
7494  }
7495  else {
7496  //TO DO - Add code to check the damage ships which have exited have taken
7497 
7498  sindex = ship_find_exited_ship_by_signature(damaged_ship);
7499  for(idx=0; idx<MAX_DAMAGE_SLOTS; idx++){
7500  if (Ships_exited[sindex].damage_ship_id[idx] == attacker) {
7501  damage_total += Ships_exited[sindex].damage_ship[idx];
7502  break;
7503  }
7504  }
7505 
7506 
7507  }
7508  return damage_total;
7509 }
7510 
7511 // Karajorma
7513 {
7514  int sindex, damaged_sig, attacker_sig;
7515  float damage_caused = 0.0f;
7516  char *name;
7517  int ship_class;
7518 
7519  name = CTEXT(node);
7520  sindex = ship_name_lookup(name);
7521  if (sindex < 0) {
7522  // this ship may have exited already.
7523  sindex = ship_find_exited_ship_by_name(CTEXT(node));
7524  if (sindex < 0) {
7525  // this is probably a ship which hasn't arrived and thus can't have taken any damage yet
7526  return fl2i(damage_caused);
7527  }
7528  else {
7529  damaged_sig = Ships_exited[sindex].obj_signature;
7530  ship_class = Ships_exited[sindex].ship_class;
7531  }
7532  }
7533  else {
7534  damaged_sig = Objects[Ships[sindex].objnum].signature ;
7535  ship_class = Ships[sindex].ship_info_index;
7536  }
7537 
7538 
7539  node = CDR(node);
7540  Assert (node != -1);
7541 
7542  // go through the list of ships who we think may have attacked the ship
7543  for ( ; node != -1; node = CDR(node) ) {
7544  name = CTEXT(node);
7545  sindex = ship_name_lookup(name);
7546  if (sindex < 0) {
7547  sindex = ship_find_exited_ship_by_name(name);
7548  if (sindex < 0) {
7549  continue;
7550  } else {
7551  attacker_sig = Ships_exited[sindex].obj_signature;
7552  }
7553  }
7554  else {
7555  attacker_sig = Objects[Ships[sindex].objnum].signature ;
7556  }
7557 
7558  if (attacker_sig < 0) {
7559  continue;
7560  }
7561 
7562  damage_caused += get_damage_caused (damaged_sig, attacker_sig);
7563  }
7564 
7565  Assertion((ship_class > -1) && (ship_class < static_cast<int>(Ship_info.size())), "Invalid ship class '%d' passed to sexp_get_damage_caused() (should be >= 0 and < %d); get a coder!\n", ship_class, static_cast<int>(Ship_info.size()));
7566  return (int) ((damage_caused/Ship_info[ship_class].max_hull_strength) * 100.0f);
7567 }
7568 
7576 {
7577  int percent;
7578  int total, count;
7579  char *name;
7580 
7581  percent = eval_num(n);
7582 
7583  total = 0;
7584  count = 0;
7585  // iterate through the rest of the ships/wings in the list and tally the departures and the
7586  // total
7587  for ( n = CDR(n); n != -1; n = CDR(n) ) {
7588  int wingnum;
7589 
7590  name = CTEXT(n);
7591 
7592  wingnum = wing_name_lookup( name, 1 );
7593  if ( wingnum != -1 ) {
7594  // for wings, we can increment the total by the total number of ships that we expect for
7595  // this wing, and the departures by the number of departures stored for this wing
7596  total += (Wings[wingnum].wave_count * Wings[wingnum].num_waves);
7597  if ( what == OP_PERCENT_SHIPS_DEPARTED )
7598  count += Wings[wingnum].total_departed;
7599  else if ( what == OP_PERCENT_SHIPS_DESTROYED )
7600  count += Wings[wingnum].total_destroyed;
7601  else if ( what == OP_PERCENT_SHIPS_ARRIVED )
7602  count += Wings[wingnum].total_arrived_count;
7603  else
7604  Error(LOCATION, "Invalid status check '%d' for wing '%s' in sexp_percent_ships_arrive_depart_destroy_disarm_disable", what, name);
7605  } else {
7606  // must be a ship, so increment the total by 1, then determine if this ship has departed
7607  total++;
7608  if ( what == OP_PERCENT_SHIPS_DEPARTED ) {
7609  if ( mission_log_get_time(LOG_SHIP_DEPARTED, name, NULL, NULL) )
7610  count++;
7611  } else if ( what == OP_PERCENT_SHIPS_DESTROYED ) {
7612  if ( mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, NULL) )
7613  count++;
7614  } else if ( what == OP_PERCENT_SHIPS_DISABLED ) {
7615  if ( mission_log_get_time(LOG_SHIP_DISABLED, name, NULL, NULL) )
7616  count++;
7617  } else if ( what == OP_PERCENT_SHIPS_DISARMED ) {
7618  if ( mission_log_get_time(LOG_SHIP_DISARMED, name, NULL, NULL) )
7619  count++;
7620  } else if ( what == OP_PERCENT_SHIPS_ARRIVED ) {
7621  if ( mission_log_get_time(LOG_SHIP_ARRIVED, name, NULL, NULL) )
7622  count++;
7623  } else
7624  Error(LOCATION, "Invalid status check '%d' for ship '%s' in sexp_percent_ships_depart_destroy_disarm_disable", what, name);
7625 
7626  }
7627  }
7628 
7629  // now, look at the percentage
7630  if ( ((count * 100) / total) >= percent )
7631  return SEXP_KNOWN_TRUE;
7632  else
7633  return SEXP_FALSE;
7634 }
7635 
7641 {
7642  int delay, count, num_departed;
7643  char *jump_node_name, *name;
7644  fix latest_time, this_time;
7645 
7646  Assert( n >= 0 );
7647 
7648  delay = eval_num(n);
7649  n = CDR(n);
7650  jump_node_name = CTEXT(n);
7651 
7652  // iterate through the list of ships
7653  n = CDR(n);
7654  latest_time = 0;
7655  count = 0;
7656  num_departed = 0;
7657  while ( n != -1 ) {
7658  count++;
7659  name = CTEXT(n);
7660 
7661  if (sexp_query_has_yet_to_arrive(name))
7662  return SEXP_CANT_EVAL;
7663 
7664  // if ship/wing destroyed, sexpression is known false. Also, if there is no departure log entry, then
7665  // the sexpression is not true.
7666  if ( mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, NULL) )
7667  return SEXP_KNOWN_FALSE;
7668  else if ( mission_log_get_time(LOG_SHIP_DEPARTED, name, jump_node_name, &this_time) ) {
7669  num_departed++;
7670  if ( this_time > latest_time )
7671  latest_time = this_time;
7672  }
7673  n = CDR(n);
7674  }
7675 
7676  if ( (count == num_departed) && ((Missiontime - latest_time) >= delay) )
7677  return SEXP_KNOWN_TRUE;
7678  else
7679  return SEXP_FALSE;
7680 }
7681 
7686 {
7687  int count, total;
7688  fix delay, latest_time;
7689  char *name;
7690 
7691  Assert( n >= 0 );
7692 
7693  // get the delay
7694  delay = i2f(eval_num(n));
7695  n = CDR(n);
7696 
7697  count = 0; // number destroyed or departed
7698  total = 0; // total number of ships/wings to check
7699  latest_time = 0;
7700  while ( n != -1 ) {
7701  int wingnum;
7702  fix time_gone = 0;
7703 
7704  total++;
7705  name = CTEXT(n);
7706 
7707  // for wings, check the WF_GONE flag to see if there are no more ships in this wing to arrive.
7708  wingnum = wing_name_lookup(name, 1);
7709  if ( wingnum != -1 ) {
7710  if ( Wings[wingnum].flags & WF_WING_GONE ) {
7711  // be sure to get the latest time of one of these
7712  if ( Wings[wingnum].time_gone > latest_time ){
7713  time_gone = Wings[wingnum].time_gone;
7714  }
7715  count++;
7716  }
7717  } else if ( mission_log_get_time(LOG_SHIP_DEPARTED, name, NULL, &time_gone) ) {
7718  count++;
7719  } else if ( mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, &time_gone) ) {
7720  count++;
7721  } else if ( mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, &time_gone) ) {
7722  count++;
7723  }
7724 
7725  // check our latest time
7726  if ( time_gone > latest_time ){
7727  latest_time = time_gone;
7728  }
7729 
7730  n = CDR(n);
7731  }
7732 
7733  if ( (count == total) && (Missiontime > (latest_time + delay)) )
7734  return SEXP_KNOWN_TRUE;
7735  else
7736  return SEXP_FALSE;
7737 }
7738 
7740 {
7741  int shipnum, knossos_shipnum;
7742  char *ship_name, *knossos;
7743 
7744  ship_name = CTEXT(node);
7745  knossos = CTEXT(CDR(node));
7746 
7747  // check to see if either ship was destroyed or departed. If so, then make this node known false
7748  if ( mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time( LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) ||
7749  mission_log_get_time(LOG_SHIP_DESTROYED, knossos, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, knossos, NULL, NULL) || mission_log_get_time( LOG_SELF_DESTRUCTED, knossos, NULL, NULL) )
7750  return SEXP_NAN_FOREVER;
7751 
7752  // get ship name
7753  shipnum = ship_name_lookup(ship_name);
7754  if (shipnum < 0) {
7755  return SEXP_NAN;
7756  }
7757 
7758  // get knossos ship
7759  knossos_shipnum = ship_name_lookup(knossos);
7760  if (knossos_shipnum < 0) {
7761  return SEXP_NAN;
7762  }
7763 
7764  // set special warpout objnum
7765  Ships[shipnum].special_warpout_objnum = Ships[knossos_shipnum].objnum;
7766  return SEXP_FALSE;
7767 }
7768 
7776 int sexp_is_cargo_known( int n, int check_delay )
7777 {
7778  int count, ship_num, num_known, delay;
7779 
7780  char *name;
7781 
7782  Assert ( n >= 0 );
7783 
7784  count = 0;
7785  num_known = 0;
7786 
7787  // get the delay value (if there is one)
7788  delay = 0;
7789  if ( check_delay )
7790  {
7791  delay = eval_num(n);
7792  n = CDR(n);
7793  }
7794 
7795  while ( n != -1 )
7796  {
7797  fix time_known;
7798  int is_known;
7799 
7800  is_known = 0;
7801 
7802  count++;
7803 
7804  // see if we have already checked this entry
7805  if ( Sexp_nodes[n].value == SEXP_KNOWN_TRUE )
7806  {
7807  num_known++;
7808  }
7809  else
7810  {
7811  name = CTEXT(n);
7812 
7813  // find the index in the ship array (will be -1 if not in mission)
7814  ship_num = ship_name_lookup(name);
7815 
7816  // see if the ship has already exited the mission (either through departure or destruction)
7817  int exited_index = ship_find_exited_ship_by_name(name);
7818  if (exited_index != -1)
7819  {
7820  // if not known, the whole thing is known false
7821  if ( !(Ships_exited[exited_index].flags & SEF_CARGO_KNOWN) )
7822  return SEXP_KNOWN_FALSE;
7823 
7824  // check the delay of when we found out
7825  time_known = Missiontime - Ships_exited[exited_index].time_cargo_revealed;
7826  if ( f2i(time_known) >= delay )
7827  {
7828  is_known = 1;
7829 
7830  // here is the only place in the new sexp that this can be known true
7831  Sexp_nodes[n].value = SEXP_KNOWN_TRUE;
7832  }
7833  }
7834  // ship either in mission or not arrived yet
7835  else
7836  {
7837  // if ship_name_lookup returns -1, then ship is either exited or yet to arrive,
7838  // and we've already checked exited
7839  if ( ship_num != -1 )
7840  {
7841  if ( Ships[ship_num].flags & SF_CARGO_REVEALED )
7842  {
7843  time_known = Missiontime - Ships[ship_num].time_cargo_revealed;
7844  if ( f2i(time_known) >= delay )
7845  {
7846  is_known = 1;
7847  }
7848  }
7849  }
7850  }
7851  }
7852 
7853  // if cargo is known, mark our variable, but not the sexp, because it may change later
7854  if ( is_known )
7855  {
7856  num_known++;
7857  }
7858 
7859  n = CDR(n);
7860  }
7861 
7862  Directive_count += count - num_known;
7863  if ( count == num_known )
7864  return SEXP_TRUE;
7865  else
7866  return SEXP_FALSE;
7867 }
7868 
7869 void get_cap_subsys_cargo_flags(int shipnum, char *subsys_name, int *known, fix *time_revealed)
7870 {
7871  // find the ship subsystem
7872  ship_subsys *ss = ship_get_subsys(&Ships[shipnum], subsys_name);
7873  if (ss != NULL)
7874  {
7875  // set the flags
7876  *known = (ss->flags & SSF_CARGO_REVEALED);
7877  *time_revealed = ss->time_subsys_cargo_revealed;
7878  }
7879  // if we didn't find the subsystem, the ship hasn't arrived yet
7880  else
7881  {
7882  *known = -1;
7883  *time_revealed = 0;
7884  }
7885 }
7886 
7887 // reworked by Goober5000 to allow for set-scanned and set-unscanned to be used more than once
7889 {
7890  int delay, count, num_known, ship_num;
7891  char *ship_name, *subsys_name;
7892 
7893  num_known = 0;
7894  count = 0;
7895 
7896  Assert( n >= 0 );
7897 
7898  // get delay
7899  delay = eval_num(n);
7900  n = CDR(n);
7901 
7902  // get ship name
7903  ship_name = CTEXT(n);
7904  n = CDR(n);
7905 
7906  // find the index in the ship array
7907  ship_num = ship_name_lookup(ship_name);
7908 
7909  while ( n != -1 )
7910  {
7911  fix time_known;
7912  int is_known;
7913 
7914  is_known = 0;
7915  count++;
7916 
7917  // see if we have already checked this entry
7918  if ( Sexp_nodes[n].value == SEXP_KNOWN_TRUE )
7919  {
7920  num_known++;
7921  }
7922  else
7923  {
7924  // get subsys name
7925  subsys_name = CTEXT(n);
7926 
7927  // see if the ship has already exited the mission (either through departure or destruction)
7928  if (ship_find_exited_ship_by_name(ship_name) != -1)
7929  {
7930  // check the delay of when we found out...
7931  // Since there is no way to keep track of subsystem status once a ship has departed
7932  // or has been destroyed, check the mission log. This will work in 99.9999999% of
7933  // all cases; however, if the mission designer repeatedly sets and resets the scanned
7934  // status of the subsystem, the mission log will only return the first occurrence of the
7935  // subsystem cargo being revealed (regardless of whether it was first hidden using
7936  // set-unscanned). Normally, ships keep track of cargo data in the subsystem struct,
7937  // but once/ the ship has left the mission, the subsystem linked list is purged,
7938  // causing the loss of this information. I judged the significant rework of the
7939  // subsystem code not worth the rare instance that this sexp may be required to work
7940  // in this way, especially since this problem only occurs after the ship departs. If
7941  // the mission designer really needs this functionality, he or she can achieve the
7942  // same result with creative combinations of event chaining and is-event-true.
7943  if (!mission_log_get_time(LOG_CAP_SUBSYS_CARGO_REVEALED, ship_name, subsys_name, &time_known))
7944  {
7945  // if not known, the whole thing is known false
7946  return SEXP_KNOWN_FALSE;
7947  }
7948 
7949  if (f2i(Missiontime - time_known) >= delay)
7950  {
7951  is_known = 1;
7952 
7953  // here is the only place in the new sexp that this can be known true
7954  Sexp_nodes[n].value = SEXP_KNOWN_TRUE;
7955  }
7956  }
7957  // ship either in mission or not arrived yet
7958  else
7959  {
7960  // if ship_name_lookup returns -1, then ship is either exited or yet to arrive,
7961  // and we've already checked exited
7962  if ( ship_num != -1 )
7963  {
7964  int cargo_revealed(0);
7965  fix time_revealed(0);
7966 
7967  // get flags
7968  get_cap_subsys_cargo_flags(ship_num, subsys_name, &cargo_revealed, &time_revealed);
7969 
7970  if (cargo_revealed)
7971  {
7972  time_known = Missiontime - time_revealed;
7973  if ( f2i(time_known) >= delay )
7974  {
7975  is_known = 1;
7976  }
7977  }
7978  }
7979  }
7980  }
7981 
7982  // if cargo is known, mark our variable, but not the sexp, because it may change later
7983  if (is_known)
7984  {
7985  num_known++;
7986  }
7987 
7988  n = CDR(n);
7989  }
7990 
7991  Directive_count += count - num_known;
7992  if ( count == num_known )
7993  return SEXP_TRUE;
7994  else
7995  return SEXP_FALSE;
7996 }
7997 
7998 // Goober5000
7999 void sexp_set_scanned_unscanned(int n, int flag)
8000 {
8001  char *ship_name, *subsys_name;
8002  int shipnum;
8003  ship_subsys *ss;
8004 
8005  // get ship name
8006  ship_name = CTEXT(n);
8007 
8008  // check to see the ship was destroyed or departed - if so, do nothing
8009  if ( mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time( LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
8010  {
8011  return;
8012  }
8013 
8014  // get ship number
8015  shipnum = ship_name_lookup(ship_name);
8016 
8017  // if the ship isn't in the mission, do nothing
8018  if (shipnum == -1)
8019  {
8020  return;
8021  }
8022 
8023  // check for possible next optional argument: subsystem
8024  n = CDR(n);
8025 
8026  // if no subsystem specified, just do it for the ship and exit
8027  if (n == -1)
8028  {
8029  if (flag)
8030  ship_do_cargo_revealed(&Ships[shipnum]);
8031  else
8032  ship_do_cargo_hidden(&Ships[shipnum]);
8033 
8034  return;
8035  }
8036 
8037  // iterate through all subsystems
8038  while (n != -1)
8039  {
8040  subsys_name = CTEXT(n);
8041 
8042  // find the ship subsystem
8043  ss = ship_get_subsys(&Ships[shipnum], subsys_name);
8044  if (ss != NULL)
8045  {
8046  // do it for the subsystem
8047  if (flag)
8049  else
8050  ship_do_cap_subsys_cargo_hidden(&Ships[shipnum], ss);
8051  }
8052 
8053  // if we didn't find the subsystem -- bad
8054  if (ss == NULL && ship_class_unchanged(shipnum)) {
8055  Error(LOCATION, "Couldn't find subsystem '%s' on ship '%s' in sexp_set_scanned_unscanned", subsys_name, ship_name);
8056  }
8057 
8058  // but if it did, loop again
8059  n = CDR(n);
8060  }
8061 }
8062 
8064 {
8065  int count, shipnum, num_known, delay;
8066  char *name;
8067 
8068  Assert ( n >= 0 );
8069 
8070  count = 0;
8071  num_known = 0;
8072 
8073  // get the delay value
8074  delay = eval_num(n);
8075 
8076  n = CDR(n);
8077 
8078  while ( n != -1 ) {
8079  fix time_known;
8080  int is_known;
8081 
8082  is_known = 0;
8083 
8084  count++;
8085 
8086  // see if we have already checked this entry
8087  if ( Sexp_nodes[n].value == SEXP_KNOWN_TRUE ) {
8088  num_known++;
8089  } else {
8090  int exited_index;
8091 
8092  name = CTEXT(n);
8093 
8094  // see if the ship has already exited the mission (either through departure or destruction). If so,
8095  // grab the status of whether the cargo is known from this list
8096  exited_index = ship_find_exited_ship_by_name( name );
8097  if (exited_index != -1 ) {
8098  if ( !(Ships_exited[exited_index].flags & SEF_BEEN_TAGGED) )
8099  return SEXP_KNOWN_FALSE;
8100 
8101  // check the delay of when we found out. We use the ship died time which isn't entirely accurate
8102  // but won't cause huge delays.
8103  time_known = Missiontime - Ships_exited[exited_index].time;
8104  if ( f2i(time_known) >= delay )
8105  is_known = 1;
8106  } else {
8107 
8108  // otherwise, ship should still be in the mission. If ship_name_lookup returns -1, then ship
8109  // is yet to arrive.
8110  shipnum = ship_name_lookup( name );
8111  if ( shipnum != -1 ) {
8112  if ( Ships[shipnum].time_first_tagged != 0 ) {
8113  time_known = Missiontime - Ships[shipnum].time_first_tagged;
8114  if ( f2i(time_known) >= delay )
8115  is_known = 1;
8116  }
8117  }
8118  }
8119  }
8120 
8121  // if cargo is known, mark our variable and this sexpression.
8122  if ( is_known ) {
8123  num_known++;
8124  Sexp_nodes[n].value = SEXP_KNOWN_TRUE;
8125  }
8126 
8127  n = CDR(n);
8128  }
8129 
8130  Directive_count += count - num_known;
8131  if ( count == num_known )
8132  return SEXP_KNOWN_TRUE;
8133  else
8134  return SEXP_FALSE;
8135 }
8136 
8137 // Karajorma
8139 {
8140  arg_item *ptr;
8141 
8142  // loop through all the supplied arguments
8143  ptr = Sexp_applicable_argument_list.get_next();
8144  while (ptr != NULL)
8145  {
8146  // acquire argument to be used
8147  Sexp_replacement_arguments.push_back(ptr->text);
8148 
8149  Sexp_current_argument_nesting_level++;
8150  Sexp_applicable_argument_list.add_data(ptr->text);
8151 
8152  // execute sexp... CTEXT will insert the argument as necessary
8153  eval_sexp(cur_node);
8154 
8155  // clean up any special sexp stuff
8156  Sexp_applicable_argument_list.clear_nesting_level();
8157  Sexp_current_argument_nesting_level--;
8158 
8159  // remove the argument
8160  Sexp_replacement_arguments.pop_back();
8161 
8162  // continue along argument list
8163  ptr = ptr->get_next();
8164  }
8165 }
8166 
8167 
8168 // Goober5000
8170 {
8171  arg_item *ptr;
8172 
8173  // loop through all the supplied arguments
8174  ptr = Sexp_applicable_argument_list.get_next();
8175  while (ptr != NULL)
8176  {
8177  // acquire argument to be used
8178  Sexp_replacement_arguments.push_back(ptr->text);
8179 
8180  // execute sexp... CTEXT will insert the argument as necessary
8181  // (since these are all actions, they don't return any meaningful values)
8182  eval_sexp(cur_node);
8183 
8184  // remove the argument
8185  Sexp_replacement_arguments.pop_back();
8186  // continue along argument list
8187  ptr = ptr->get_next();
8188  }
8189 }
8190 
8191 // Goober5000
8193 {
8194  // empty tree
8195  if (node < 0)
8196  return 0;
8197 
8198  // special argument?
8199  if (!strcmp(Sexp_nodes[node].text, SEXP_ARGUMENT_STRING))
8200  return 1;
8201 
8202  // we don't want to include special arguments if they are nested in a new argument SEXP
8203  if (Sexp_nodes[node].type == SEXP_ATOM && Sexp_nodes[node].subtype == SEXP_ATOM_OPERATOR) {
8205  return 0;
8206  }
8207  }
8208 
8211 }
8212 
8213 // Goober5000
8215 {
8216  // look through list
8217  while (node != -1)
8218  {
8219  // special argument?
8220  if (!strcmp(Sexp_nodes[node].text, SEXP_ARGUMENT_STRING))
8221  return 1;
8222 
8223  node = CDR(node);
8224  }
8225 
8226  return 0;
8227 }
8228 
8229 // conditional sexpressions follow
8230 
8231 // Goober5000
8233 {
8234  arg_item *ptr;
8235  int do_node;
8236 
8237  switch (get_operator_const(CTEXT(exp)))
8238  {
8239  // if the op is a conditional then we just evaluate it
8240  case OP_WHEN:
8241  case OP_EVERY_TIME:
8242  case OP_IF_THEN_ELSE:
8243  // need to account for the possibility this call uses <arguments>
8245  ptr = Sexp_applicable_argument_list.get_next();
8246  if (ptr != NULL) {
8248  }
8249  else {
8250  eval_sexp(exp);
8251  }
8252  }
8253  else {
8254  eval_sexp(exp);
8255  }
8256  break;
8257 
8260  Warning(LOCATION, "<Argument> used within Do-for-valid-arguments SEXP. Skipping entire SEXP");
8261  break;
8262  }
8263 
8264  do_node = CDR(exp);
8265  while (do_node != -1) {
8267  do_node = CDR(do_node);
8268  }
8269  break;
8270 
8271  case OP_WHEN_ARGUMENT:
8273  eval_sexp(exp);
8274  break;
8275 
8276  // otherwise we need to check if arguments are used
8277  default:
8278  // if we're using the special argument in this action
8280  {
8281  do_action_for_each_special_argument(exp); // these sexps eval'd only for side effects
8282  }
8283  // if not, just evaluate it once as-is
8284  else
8285  {
8286  // Goober5000 - possible bug? (see when val is used below)
8287  /*val = */eval_sexp(exp); // these sexps eval'd only for side effects
8288  }
8289  }
8290 }
8291 
8292 
8293 // Karajorma
8294 void eval_when_do_all_exp(int all_actions, int when_op_num)
8295 {
8296  arg_item *ptr;
8297  int exp;
8298  int actions;
8299  int op_num;
8300 
8301  bool first_loop = true;
8302 
8303  // loop through all the supplied arguments
8304  ptr = Sexp_applicable_argument_list.get_next();
8305 
8306  while (ptr != NULL)
8307  {
8308  // acquire argument to be used
8309  Sexp_replacement_arguments.push_back(ptr->text);
8310  actions = all_actions;
8311 
8312  while (actions != -1)
8313  {
8314  exp = CAR(actions);
8315 
8316  op_num = get_operator_const(CTEXT(exp));
8317 
8318  if (op_num == OP_DO_FOR_VALID_ARGUMENTS) {
8319  int do_node = CDR(exp);
8320  while (do_node != -1) {
8321  eval_sexp(do_node);
8322  do_node = CDR(do_node);
8323  }
8324  }
8325  else if ( first_loop || special_argument_appears_in_sexp_tree(exp) ) {
8326  switch (op_num)
8327  {
8328  // if the op is a conditional we have to make sure that it can access arguments
8329  case OP_WHEN:
8330  case OP_EVERY_TIME:
8331  case OP_IF_THEN_ELSE:
8332  Sexp_current_argument_nesting_level++;
8333  Sexp_applicable_argument_list.add_data(ptr->text);
8334  eval_sexp(exp);
8335  Sexp_applicable_argument_list.clear_nesting_level();
8336  Sexp_current_argument_nesting_level--;
8337  break;
8338 
8339  default:
8340  eval_sexp(exp);
8341  }
8342  }
8343 
8344  // iterate
8345  actions = CDR(actions);
8346 
8347  // if-then-else only has one "if" action
8348  if (when_op_num == OP_IF_THEN_ELSE)
8349  break;
8350  }
8351 
8352  first_loop = false;
8353 
8354  // remove the argument
8355  Sexp_replacement_arguments.pop_back();
8356  // continue along argument list
8357  ptr = ptr->get_next();
8358  }
8359 }
8360 
8366 {
8367  int cond, val, actions;
8368  Assert( n >= 0 );
8369 
8370  cond = CAR(n);
8371  actions = CDR(n);
8372 
8373  // evaluate the conditional to see what value we eventually return
8374  val = eval_sexp(cond);
8375 
8376  // perform all the actions in the rest of the sexp
8377  // (Since we are technically inside a condition already, no special argument handling is needed. The special argument, if any,
8378  // will have been provided by a higher level of nesting.)
8379  while (actions != -1)
8380  {
8381  // get the operator
8382  int exp = CAR(actions);
8383  if (exp != -1)
8384  eval_sexp(exp);
8385 
8386  // iterate
8387  actions = CDR(actions);
8388  }
8389 
8390  // return whatever val was, but don't return known-*
8391  // note: SEXP_KNOWN_TRUE/SEXP_KNOWN_FALSE are never returned from eval_sexp
8392  return val;
8393 }
8394 
8401 int eval_when(int n, int when_op_num)
8402 {
8403  int arg_handler = -1, cond, val, actions;
8404  Assert( n >= 0 );
8405  arg_item *ptr;
8406 
8407  // get the parts of the sexp and evaluate the conditional
8408  if (is_blank_argument_op(when_op_num))
8409  {
8410  arg_handler = CAR(n);
8411  cond = CADR(n);
8412  actions = CDDR(n);
8413 
8414  Sexp_current_argument_nesting_level++;
8415  // evaluate for custom arguments
8416  val = eval_sexp(arg_handler, cond);
8417  }
8418  // normal evaluation
8419  else
8420  {
8421  cond = CAR(n);
8422  actions = CDR(n);
8423 
8424  // evaluate just as-is
8425  val = eval_sexp(cond);
8426  }
8427 
8428 
8429  // if value is true, perform the actions in the 'then' part
8430  if (val == SEXP_TRUE) // note: SEXP_KNOWN_TRUE is never returned from eval_sexp
8431  {
8432  // get the operator
8433  int exp = CAR(actions);
8434 
8435  // if the mod.tbl setting is in effect we want to each evaluate all the SEXPs for
8436  // each argument
8438  if (exp != -1) {
8439  eval_when_do_all_exp(actions, when_op_num);
8440  }
8441  }
8442  // without the mod.tbl setting (or if there are no arguments in this SEXP) we loop
8443  // through every action performing them for all arguments
8444  else {
8445  while (actions != -1)
8446  {
8447  // get the operator
8448  exp = CAR(actions);
8449  if (exp != -1)
8450  eval_when_do_one_exp(exp);
8451 
8452  // iterate
8453  actions = CDR(actions);
8454 
8455  // if-then-else only has one "if" action
8456  if (when_op_num == OP_IF_THEN_ELSE)
8457  break;
8458  }
8459  }
8460  }
8461  // if-then-else has actions to perform under "else"
8462  else if (val == SEXP_FALSE && when_op_num == OP_IF_THEN_ELSE) // note: SEXP_KNOWN_FALSE is never returned from eval_sexp
8463  {
8464  // skip past the "if" action
8465  actions = CDR(actions);
8466 
8467  // loop through every action
8468  while (actions != -1)
8469  {
8470  // get the operator
8471  int exp = CAR(actions);
8472  if (exp != -1)
8473  eval_when_do_one_exp(exp);
8474 
8475  // iterate
8476  actions = CDR(actions);
8477  }
8478 
8479  // invert val so that we behave like a when with opposite results
8480  // note: SEXP_KNOWN_FALSE is never returned from eval_sexp
8481  val = SEXP_TRUE;
8482  }
8483 
8484  if (is_blank_argument_op(when_op_num))
8485  {
8486  if (Log_event) {
8487  ptr = Sexp_applicable_argument_list.get_next();
8488  while(ptr != NULL) {
8489  // See if we have an argument.
8490  Current_event_log_argument_buffer->push_back(ptr->text);
8491  ptr = ptr->get_next();
8492  }
8493  }
8494 
8495  // clean up any special sexp stuff
8496  Sexp_applicable_argument_list.clear_nesting_level();
8497  Sexp_current_argument_nesting_level--;
8498  }
8499 
8500  // thanks to MageKing17 for noticing that we need to short-circuit on the correct node!
8501  int short_circuit_node = (arg_handler >= 0) ? arg_handler : cond;
8502 
8503  if (Sexp_nodes[short_circuit_node].value == SEXP_KNOWN_FALSE || Sexp_nodes[short_circuit_node].value == SEXP_NAN_FOREVER)
8504  return SEXP_KNOWN_FALSE; // no need to waste time on this anymore
8505 
8506  // note: val can't be SEXP_KNOWN_FALSE at this point
8507 
8508  return val;
8509 }
8510 
8514 int eval_cond(int n)
8515 {
8516  int cond = 0, node, val = SEXP_FALSE;
8517 
8518  Assert (n >= 0);
8519  while (n >= 0)
8520  {
8521  node = CAR(n);
8522  cond = CAR(node);
8523  val = eval_sexp(cond);
8524 
8525  // if the conditional evaluated to true, then we must evaluate the rest of the expression returning
8526  // the value of this evaluation
8527  if (val == SEXP_TRUE) // note: any SEXP_KNOWN_TRUE result is returned as SEXP_TRUE
8528  {
8529  int actions, exp;
8530 
8531  val = SEXP_FALSE;
8532  actions = CDR(node);
8533  while (actions >= 0)
8534  {
8535  exp = CAR(actions);
8536  if (exp >= -1)
8537  val = eval_sexp(exp); // these sexp evaled only for side effects
8538 
8539  actions = CDR(actions);
8540  }
8541 
8542  break;
8543  }
8544 
8545  // move onto the next cond clause
8546  n = CDR(n);
8547  }
8548 
8549  return val;
8550 }
8551 
8552 // Goober5000
8553 // NOTE: if you change this function, check to see if the following function should also be changed!
8554 int test_argument_nodes_for_condition(int n, int condition_node, int *num_true, int *num_false, int *num_known_true, int *num_known_false)
8555 {
8556  int val, num_valid_arguments;
8557  Assert(n != -1 && condition_node != -1);
8558  Assert((num_true != NULL) && (num_false != NULL) && (num_known_true != NULL) && (num_known_false != NULL));
8559 
8560  // ensure special argument list is empty
8561  Sexp_applicable_argument_list.clear_nesting_level();
8562  Applicable_arguments_temp.clear();
8563 
8564  // ditto for counters
8565  num_valid_arguments = 0;
8566  *num_true = 0;
8567  *num_false = 0;
8568  *num_known_true = 0;
8569  *num_known_false = 0;
8570 
8571  // loop through all arguments
8572  while (n != -1)
8573  {
8574  // only eval this argument if it's valid
8575  if (Sexp_nodes[n].flags & SNF_ARGUMENT_VALID)
8576  {
8577  // flush conditional to avoid short-circuiting
8578  flush_sexp_tree(condition_node);
8579 
8580  // evaluate conditional for current argument
8581  Sexp_replacement_arguments.push_back(Sexp_nodes[n].text);
8582  val = eval_sexp(condition_node);
8583  if ( Sexp_nodes[condition_node].value == SEXP_KNOWN_TRUE ||
8584  Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) {
8585  val = Sexp_nodes[condition_node].value;
8586  } else if ( Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER ) {
8587  // In accordance with SEXP_NAN/SEXP_NAN_FOREVER becoming SEXP_FALSE in eval_sexp()
8588  val = SEXP_KNOWN_FALSE;
8589  }
8590 
8591  switch (val)
8592  {
8593  case SEXP_TRUE:
8594  (*num_true)++;
8595  Applicable_arguments_temp.push_back(Sexp_nodes[n].text);
8596  break;
8597 
8598  case SEXP_FALSE:
8599  (*num_false)++;
8600  break;
8601 
8602  case SEXP_KNOWN_TRUE:
8603  (*num_known_true)++;
8604  Applicable_arguments_temp.push_back(Sexp_nodes[n].text);
8605  break;
8606 
8607  case SEXP_KNOWN_FALSE:
8608  (*num_known_false)++;
8609  break;
8610  }
8611 
8612  // clear argument, but not list, as we'll need it later
8613  Sexp_replacement_arguments.pop_back();
8614 
8615  // increment
8616  num_valid_arguments++;
8617  }
8618 
8619  // continue along argument list
8620  n = CDR(n);
8621  }
8622 
8623  // now we write from the temporary store into the real one, reversing the order. We do this because
8624  // Sexp_applicable_argument_list is a stack and we want the first argument in the list to be the first one out
8625  while (!Applicable_arguments_temp.empty())
8626  {
8627  Sexp_applicable_argument_list.add_data(Applicable_arguments_temp.back());
8628  Applicable_arguments_temp.pop_back();
8629  }
8630 
8631  return num_valid_arguments;
8632 }
8633 
8634 // Goober5000
8635 // NOTE: if you change this function, check to see if the previous function should also be changed!
8636 int test_argument_vector_for_condition(SCP_vector<char*> argument_vector, bool already_dupped, int condition_node, int *num_true, int *num_false, int *num_known_true, int *num_known_false)
8637 {
8638  int val, num_valid_arguments;
8639  Assert(condition_node != -1);
8640  Assert((num_true != NULL) && (num_false != NULL) && (num_known_true != NULL) && (num_known_false != NULL));
8641 
8642  // ensure special argument list is empty
8643  Sexp_applicable_argument_list.clear_nesting_level();
8644  Applicable_arguments_temp.clear();
8645 
8646  // ditto for counters
8647  num_valid_arguments = 0;
8648  *num_true = 0;
8649  *num_false = 0;
8650  *num_known_true = 0;
8651  *num_known_false = 0;
8652 
8653  // loop through all arguments
8654  for (size_t i = 0; i < argument_vector.size(); i++)
8655  {
8656  // since we can't see or modify the validity, assume all are valid
8657  {
8658  // flush conditional to avoid short-circuiting
8659  flush_sexp_tree(condition_node);
8660 
8661  // evaluate conditional for current argument
8662  Sexp_replacement_arguments.push_back(argument_vector[i]);
8663  val = eval_sexp(condition_node);
8664  if ( Sexp_nodes[condition_node].value == SEXP_KNOWN_TRUE ||
8665  Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) {
8666  val = Sexp_nodes[condition_node].value;
8667  } else if ( Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER ) {
8668  // In accordance with SEXP_NAN/SEXP_NAN_FOREVER becoming SEXP_FALSE in eval_sexp()
8669  val = SEXP_KNOWN_FALSE;
8670  }
8671 
8672  switch (val)
8673  {
8674  case SEXP_TRUE:
8675  (*num_true)++;
8676  Applicable_arguments_temp.push_back(argument_vector[i]);
8677  break;
8678 
8679  case SEXP_FALSE:
8680  (*num_false)++;
8681  break;
8682 
8683  case SEXP_KNOWN_TRUE:
8684  (*num_known_true)++;
8685  Applicable_arguments_temp.push_back(argument_vector[i]);
8686  break;
8687 
8688  case SEXP_KNOWN_FALSE:
8689  (*num_known_false)++;
8690  break;
8691  }
8692 
8693  // if the argument was already dup'd, but not added as an applicable argument,
8694  // we need to free it here before we cause a memory leak
8695  if ((val == SEXP_FALSE || val == SEXP_KNOWN_FALSE) && already_dupped)
8696  vm_free(argument_vector[i]);
8697 
8698  // clear argument, but not list, as we'll need it later
8699  Sexp_replacement_arguments.pop_back();
8700 
8701  // increment
8702  num_valid_arguments++;
8703  }
8704  }
8705 
8706  // now we write from the temporary store into the real one, reversing the order. We do this because
8707  // Sexp_applicable_argument_list is a stack and we want the first argument in the list to be the first one out
8708  while (!Applicable_arguments_temp.empty())
8709  {
8710  // we need to dup the strings regardless, since we're not using Sexp_nodes[n].text as a string buffer,
8711  // but we need to know whether the calling function dup'd them, or whether we should dup them here
8712  if (already_dupped)
8713  Sexp_applicable_argument_list.add_data_set_dup(Applicable_arguments_temp.back());
8714  else
8715  Sexp_applicable_argument_list.add_data_dup(Applicable_arguments_temp.back());
8716 
8717  Applicable_arguments_temp.pop_back();
8718  }
8719 
8720  return num_valid_arguments;
8721 }
8722 
8723 // Goober5000
8724 int eval_any_of(int arg_handler_node, int condition_node)
8725 {
8726  int n, num_valid_arguments, num_true, num_false, num_known_true, num_known_false;
8727  Assert(arg_handler_node != -1 && condition_node != -1);
8728 
8729  // the arguments should just be data, not operators, so we can skip the CAR
8730  n = CDR(arg_handler_node);
8731 
8732  // test the whole argument list
8733  num_valid_arguments = test_argument_nodes_for_condition(n, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
8734 
8735  // use the sexp_or algorithm
8736  if (num_known_true || num_true)
8737  return SEXP_TRUE;
8738  else if (num_known_false == num_valid_arguments)
8739  return SEXP_KNOWN_FALSE;
8740  else
8741  return SEXP_FALSE;
8742 }
8743 
8744 // Goober5000
8745 int eval_every_of(int arg_handler_node, int condition_node)
8746 {
8747  int n, num_valid_arguments, num_true, num_false, num_known_true, num_known_false;
8748  Assert(arg_handler_node != -1 && condition_node != -1);
8749 
8750  // the arguments should just be data, not operators, so we can skip the CAR
8751  n = CDR(arg_handler_node);
8752 
8753  // test the whole argument list
8754  num_valid_arguments = test_argument_nodes_for_condition(n, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
8755 
8756  // use the sexp_and algorithm
8757  if ((!num_valid_arguments) || num_known_false)
8758  return SEXP_KNOWN_FALSE;
8759  else if (num_false)
8760  return SEXP_FALSE;
8761  else
8762  return SEXP_TRUE;
8763 }
8764 
8765 // Goober5000
8766 int eval_number_of(int arg_handler_node, int condition_node)
8767 {
8768  int n, num_valid_arguments, num_true, num_false, num_known_true, num_known_false, threshold;
8769  Assert(arg_handler_node != -1 && condition_node != -1);
8770 
8771  // the arguments should just be data, not operators, so we can skip the CAR
8772  n = CDR(arg_handler_node);
8773 
8774  // the first argument is the number threshold
8775  threshold = eval_num(n);
8776  n = CDR(n);
8777 
8778  // test the whole argument list
8779  num_valid_arguments = test_argument_nodes_for_condition(n, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
8780 
8781  // use the sexp_or algorithm, modified
8782  // (true if at least threshold arguments are true)
8783  if (num_true + num_known_true >= threshold)
8784  return SEXP_TRUE;
8785  else if (num_valid_arguments - num_known_false < threshold)
8786  return SEXP_KNOWN_FALSE;
8787  else
8788  return SEXP_FALSE;
8789 }
8790 
8791 // Goober5000
8792 // this works a little differently... we randomly pick one argument to use
8793 // for our condition, but this argument must be saved among sexp calls...
8794 // so we select an argument and set its flag
8795 // addendum: hook karajorma's random-multiple-of into the same sexp
8796 int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
8797 {
8798  int n = -1, i, val, num_valid_args, random_argument, num_known_false = 0;
8799  Assert(arg_handler_node != -1 && condition_node != -1);
8800 
8801  // get the number of valid arguments
8802  num_valid_args = query_sexp_args_count(arg_handler_node, true);
8803 
8804  if (num_valid_args == 0)
8805  {
8806  return SEXP_KNOWN_FALSE; // Not much point in trying to evaluate it again.
8807  }
8808 
8809  // find which argument we picked, if we picked one
8810  if (!multiple)
8811  {
8812  n = CDR(arg_handler_node);
8813 
8814  // iterate to the argument we previously selected
8815  for ( ; n != -1; n = CDR(n))
8816  {
8817  if (Sexp_nodes[n].flags & SNF_ARGUMENT_SELECT)
8818  break;
8819  }
8820  }
8821 
8822  // if argument not found (or never specified in the first place), we have to pick one
8823  if (n == -1)
8824  {
8825  n = CDR(arg_handler_node);
8826  int temp_node = n;
8827 
8828  // pick an argument and iterate to it
8829  random_argument = rand_internal(1, num_valid_args);
8830  i = 0;
8831  for (int j = 0; j < num_valid_args; temp_node = CDR(temp_node))
8832  {
8833  Assert(n >= 0);
8834 
8835  // count only valid arguments
8836  if (Sexp_nodes[temp_node].flags & SNF_ARGUMENT_VALID) {
8837  j++;
8838  if (i < random_argument && (++i == random_argument)) {
8839  // Found the node we want, store it for use
8840  n = temp_node;
8841  }
8842 
8843  if ((Sexp_nodes[temp_node].value == SEXP_KNOWN_FALSE) || (Sexp_nodes[temp_node].value == SEXP_NAN_FOREVER))
8844  num_known_false++;
8845  }
8846  }
8847 
8848  if (num_known_false == num_valid_args) {
8849  return SEXP_KNOWN_FALSE; // We're going nowhere fast.
8850  }
8851 
8852  // save it, if we're saving
8853  if (!multiple)
8854  {
8855  Sexp_nodes[n].flags |= SNF_ARGUMENT_SELECT;
8856  }
8857  }
8858 
8859  // only eval this argument if it's valid
8860  val = SEXP_FALSE;
8861  if (Sexp_nodes[n].flags & SNF_ARGUMENT_VALID)
8862  {
8863  // flush stuff
8864  Sexp_applicable_argument_list.clear_nesting_level();
8865  flush_sexp_tree(condition_node);
8866 
8867  // evaluate conditional for current argument
8868  Sexp_replacement_arguments.push_back(Sexp_nodes[n].text);
8869  val = eval_sexp(condition_node);
8870 
8871  // true?
8872  if (val == SEXP_TRUE)
8873  {
8874  Sexp_applicable_argument_list.add_data(Sexp_nodes[n].text);
8875  } else if ((!multiple || num_valid_args == 1) && (Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE || Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER)) {
8876  val = SEXP_KNOWN_FALSE; // If we can't randomly pick another one and this one is guaranteed never to be true, then give up now.
8877  }
8878 
8879  // clear argument, but not list, as we'll need it later
8880  Sexp_replacement_arguments.pop_back();
8881  }
8882 
8883  // true if our selected argument is true
8884  return val;
8885 }
8886 
8887 // Karajorma - this conditional returns the first valid option on its list.
8888 int eval_in_sequence(int arg_handler_node, int condition_node)
8889 {
8890  int val = SEXP_FALSE;
8891  int n = -1 ;
8892 
8893  Assert(arg_handler_node != -1 && condition_node != -1);
8894 
8895  // get the first argument
8896  n = CDR(arg_handler_node);
8897  Assert (n != -1);
8898 
8899  // loop through the nodes until we find one that is holds a valid argument or run out of nodes
8900  for (int i=1 ; i<query_sexp_args_count(arg_handler_node) ; i++)
8901  {
8902  if (!(Sexp_nodes[n].flags & SNF_ARGUMENT_VALID)) {
8903  n = CDR(n) ;
8904  }
8905  // if we've found a valid node there is no need to continue
8906  else {
8907  break;
8908  }
8909  }
8910 
8911  // Only execute if the argument is valid (if all nodes were invalid we would still reach this point)
8912  if (Sexp_nodes[n].flags & SNF_ARGUMENT_VALID)
8913  {
8914  // flush stuff
8915  Sexp_applicable_argument_list.clear_nesting_level();
8916  flush_sexp_tree(condition_node);
8917 
8918  // evaluate conditional for current argument
8919  Sexp_replacement_arguments.push_back(Sexp_nodes[n].text);
8920  val = eval_sexp(condition_node);
8921 
8922  // true?
8923  if (val == SEXP_TRUE)
8924  {
8925  Sexp_applicable_argument_list.add_data(Sexp_nodes[n].text);
8926  } else if ((Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) || (Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER)) {
8927  val = SEXP_KNOWN_FALSE; // If we're wasting our time evaluating this ever again, just go ahead and short-circuit.
8928  }
8929 
8930  // clear argument, but not list, as we'll need it later
8931  Sexp_replacement_arguments.pop_back();
8932  }
8933 
8934  // return the value of the conditional
8935  return val;
8936 }
8937 
8938 // is there a better place to put this? seems useful...
8939 // credit to http://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
8940 template <typename T>
8941 T sign(T t)
8942 {
8943  if (t == 0)
8944  return T(0);
8945  else
8946  return (t < 0) ? T(-1) : T(1);
8947 }
8948 
8949 // Goober5000
8950 int eval_for_counter(int arg_handler_node, int condition_node)
8951 {
8952  int n, num_valid_arguments, num_true, num_false, num_known_true, num_known_false;
8953  int i, counter_start, counter_stop, counter_step;
8954  char buf[NAME_LENGTH];
8955  Assert(arg_handler_node != -1 && condition_node != -1);
8956 
8957  // determine the counter parameters
8958  n = CDR(arg_handler_node);
8959  counter_start = eval_num(n);
8960  n = CDR(n);
8961  counter_stop = eval_num(n);
8962  n = CDR(n);
8963  counter_step = (n >= 0) ? eval_num(n) : 1;
8964 
8965  // a bunch of error checking
8966  if (counter_step == 0)
8967  {
8968  Warning(LOCATION, "A counter increment of 0 is illegal! (start=%d, stop=%d, increment=%d)", counter_start, counter_stop, counter_step);
8969  return SEXP_KNOWN_FALSE;
8970  }
8971  else if (counter_start == counter_stop)
8972  {
8973  Warning(LOCATION, "The counter start and stop values are identical! (start=%d, stop=%d, increment=%d)", counter_start, counter_stop, counter_step);
8974  return SEXP_KNOWN_FALSE;
8975  }
8976  else if (sign(counter_stop - counter_start) != sign(counter_step))
8977  {
8978  Warning(LOCATION, "The counter cannot complete with the given values! (start=%d, stop=%d, increment=%d)", counter_start, counter_stop, counter_step);
8979  return SEXP_KNOWN_FALSE;
8980  }
8981 
8982  // build a vector of counter values
8983  SCP_vector<char*> argument_vector;
8984  for (i = counter_start; ((counter_step > 0) ? i <= counter_stop : i >= counter_stop); i += counter_step)
8985  {
8986  sprintf(buf, "%d", i);
8987  argument_vector.push_back(vm_strdup(buf));
8988  // Note: we do not call vm_free() on the contents of argument_vector, and we don't for the very good
8989  // reason that those pointers are then passed along by test_argument_vector_for_condition(), below.
8990  // The strings will then be freed by arg_item::expunge() or arg_item::clear_nesting_level(), or even
8991  // inside test_argument_vector_for_condition() (if the argument doesn't satisfy the condition). So
8992  // under no circumstances try to free these strings inside this function! It will cause a double-free
8993  // situation, resulting in a crash at best. -MageKing17
8994  }
8995 
8996  // test the whole argument vector
8997  num_valid_arguments = test_argument_vector_for_condition(argument_vector, true, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
8998 
8999  // use the sexp_or algorithm
9000  if (num_known_true || num_true)
9001  return SEXP_TRUE;
9002  else if (num_known_false == num_valid_arguments)
9003  return SEXP_KNOWN_FALSE;
9004  else
9005  return SEXP_FALSE;
9006 }
9007 
9008 void sexp_change_all_argument_validity(int n, bool invalidate)
9009 {
9010  int arg_handler, arg_n;
9011 
9012  arg_handler = get_handler_for_x_of_operator(n);
9013 
9014  // thanks to woutersmits for finding this loophole
9015  if (arg_handler < 0)
9016  return;
9017 
9018  // can't change validity of for-counter
9019  if (get_operator_const(CTEXT(arg_handler)) == OP_FOR_COUNTER)
9020  return;
9021 
9022  while (n != -1)
9023  {
9024  arg_n = CDR(arg_handler);
9025  while (arg_n != -1) {
9026  if (invalidate) {
9027  Sexp_nodes[arg_n].flags &= ~SNF_ARGUMENT_VALID;
9028  }
9029  else {
9030  Sexp_nodes[arg_n].flags |= SNF_ARGUMENT_VALID;
9031  }
9032  // iterate
9033  arg_n = CDR(arg_n);
9034  }
9035 
9036  // iterate
9037  n = CDR(n);
9038  }
9039 }
9040 
9042 {
9043  int arg_handler, arg_n;
9044  int matches = 0;
9045 
9046  arg_handler = get_handler_for_x_of_operator(n);
9047 
9048  // loop through arguments
9049  arg_n = CDR(arg_handler);
9050  while (arg_n != -1) {
9051  if (Sexp_nodes[arg_n].flags & SNF_ARGUMENT_VALID) {
9052  matches++;
9053  }
9054 
9055 
9056  // iterate
9057  arg_n = CDR(arg_n);
9058  }
9059 
9060  return matches;
9061 }
9062 
9063 // Goober5000
9064 void sexp_change_argument_validity(int n, bool invalidate)
9065 {
9066  int arg_handler, arg_n;
9067  bool toggled;
9068 
9069  arg_handler = get_handler_for_x_of_operator(n);
9070 
9071  // thanks to woutersmits for finding this loophole
9072  if (arg_handler < 0)
9073  return;
9074 
9075  // can't change validity of for-counter
9076  if (get_operator_const(CTEXT(arg_handler)) == OP_FOR_COUNTER)
9077  return;
9078 
9079  // loop through arguments
9080  while (n != -1)
9081  {
9082  toggled = false;
9083 
9084  // first we must check if the arg_handler marks a selection. At the moment random-of is the only one that does this
9085  arg_n = CDR(arg_handler);
9086  while (invalidate && (arg_n != -1)) {
9087  if (Sexp_nodes[arg_n].flags & SNF_ARGUMENT_SELECT) {
9088  // now check if the selected argument matches the one we want to invalidate
9089  if (!strcmp(CTEXT(n), CTEXT(arg_n))) {
9090  // set it as invalid
9091  Sexp_nodes[arg_n].flags &= ~SNF_ARGUMENT_VALID;
9092  toggled = true;
9093  }
9094  }
9095 
9096  // iterate
9097  arg_n = CDR(arg_n);
9098  }
9099 
9100  if (!toggled) {
9101  // search for argument in arg_handler list
9102  arg_n = CDR(arg_handler);
9103  while (arg_n != -1)
9104  {
9105  // match?
9106  if (!strcmp(CTEXT(n), CTEXT(arg_n)))
9107  {
9108  if (invalidate) {
9109  // we need to check if the argument is already invalid as some argument lists may contain duplicates
9110  if (Sexp_nodes[arg_n].flags & SNF_ARGUMENT_VALID) {
9111  // set it as invalid
9112  Sexp_nodes[arg_n].flags &= ~SNF_ARGUMENT_VALID;
9113 
9114  // exit inner loop
9115  break;
9116  }
9117  }
9118  else {
9119  if (!(Sexp_nodes[arg_n].flags & SNF_ARGUMENT_VALID)) {
9120  // set it as valid
9121  Sexp_nodes[arg_n].flags |= SNF_ARGUMENT_VALID;
9122 
9123  // exit inner loop
9124  break;
9125  }
9126  }
9127  }
9128 
9129  // iterate
9130  arg_n = CDR(arg_n);
9131  }
9132  }
9133 
9134  // iterate
9135  n = CDR(n);
9136  }
9137 }
9138 
9140 {
9141  int conditional, arg_handler;
9142 
9143  if (n < 0) {
9144  return -1;
9145  }
9146 
9147  conditional = n;
9148  do {
9149  // find the conditional sexp
9150  conditional = find_parent_operator(conditional);
9151  if (conditional == -1) {
9152  return -1;
9153  }
9154  }
9155  while (!is_blank_argument_op(get_operator_const(CTEXT(conditional))));
9156 
9157  // get the first op of the parent, which should be a *_of operator
9158  arg_handler = CADR(conditional);
9159  if (arg_handler < 0 || !is_blank_of_op(get_operator_const(CTEXT(arg_handler)))) {
9160  return -1;
9161  }
9162 
9163  return arg_handler;
9164 }
9165 
9166 // Goober5000
9167 bool is_blank_argument_op(int op_const)
9168 {
9169  switch (op_const)
9170  {
9171  case OP_WHEN_ARGUMENT:
9173  return true;
9174 
9175  default:
9176  return false;
9177  }
9178 }
9179 
9180 // Goober5000
9181 bool is_blank_of_op(int op_const)
9182 {
9183  switch (op_const)
9184  {
9185  case OP_ANY_OF:
9186  case OP_EVERY_OF:
9187  case OP_NUMBER_OF:
9188  case OP_RANDOM_OF:
9189  case OP_RANDOM_MULTIPLE_OF:
9190  case OP_IN_SEQUENCE:
9191  case OP_FOR_COUNTER:
9192  return true;
9193 
9194  default:
9195  return false;
9196  }
9197 }
9198 
9199 // Goober5000 - added wing capability
9200 int sexp_is_iff(int n)
9201 {
9202  int i, team;
9203 
9204  // iff value is the first parameter, second is a list of one or more ships/wings to check to see if the
9205  // iff value matches
9206  team = iff_lookup(CTEXT(n));
9207 
9208  n = CDR(n);
9209  for ( ; n != -1; n = CDR(n) )
9210  {
9213 
9214  switch (oswpt.type)
9215  {
9216  case OSWPT_TYPE_SHIP:
9217  {
9218  // if the team doesn't match the team specified, return false immediately
9219  if (oswpt.shipp->team != team)
9220  return SEXP_FALSE;
9221 
9222  break;
9223  }
9224 
9226  {
9227  // if the team doesn't match the team specified, return false immediately
9228  if (oswpt.p_objp->team != team)
9229  return SEXP_FALSE;
9230 
9231  break;
9232  }
9233 
9234  case OSWPT_TYPE_WING:
9236  {
9237  for (i = 0; i < oswpt.wingp->current_count; i++)
9238  {
9239  // if the team doesn't match the team specified, return false immediately
9240  if (Ships[oswpt.wingp->ship_index[i]].team != team)
9241  return SEXP_FALSE;
9242  }
9243 
9244  break;
9245  }
9246 
9247  case OSWPT_TYPE_EXITED:
9248  {
9249  // see if we can find information about the exited ship (if it is a ship)
9250  int exited_index = ship_find_exited_ship_by_name(CTEXT(n));
9251  if (exited_index >= 0)
9252  {
9253  // if the team doesn't match the team specified, return false immediately
9254  if (Ships_exited[exited_index].team != team)
9255  return SEXP_KNOWN_FALSE;
9256  }
9257  else
9258  {
9259  // it's probably an exited wing, which we don't store information about
9260  return SEXP_NAN_FOREVER;
9261  }
9262  }
9263 
9264  // we don't handle the other cases
9265  default:
9266  return SEXP_NAN;
9267  }
9268 
9269  }
9270 
9271  // got this far: we must be okay for all ships/wings
9272  return SEXP_TRUE;
9273 }
9274 
9275 // Goober5000
9277 {
9278  Assert(shipp != NULL);
9279 
9280  shipp->team = new_team;
9281 
9282  // send a network packet if we need to
9283  if( MULTIPLAYER_MASTER && (Net_player != NULL) && (shipp->objnum >= 0))
9285 }
9286 
9287 // Goober5000
9288 void sexp_parse_ship_change_iff(p_object *parse_obj, int new_team)
9289 {
9290  Assert(parse_obj);
9291 
9292  parse_obj->team = new_team;
9293 }
9294 
9295 // Goober5000 - added wing capability
9297 {
9298  int new_team;
9299 
9300  new_team = iff_lookup(CTEXT(n));
9301  n = CDR(n);
9302 
9303  for ( ; n != -1; n = CDR(n) )
9304  {
9307 
9308  switch (oswpt.type)
9309  {
9310  // change ingame ship
9311  case OSWPT_TYPE_SHIP:
9312  {
9313  sexp_ingame_ship_change_iff(oswpt.shipp, new_team);
9314 
9315  break;
9316  }
9317 
9318  // change ship yet to arrive
9320  {
9321  sexp_parse_ship_change_iff(oswpt.p_objp, new_team);
9322 
9323  break;
9324  }
9325 
9326  // change wing (we must set the flags for all ships present as well as all ships yet to arrive)
9327  case OSWPT_TYPE_WING:
9329  {
9330  // current ships
9331  for (int i = 0; i < oswpt.wingp->current_count; i++)
9332  sexp_ingame_ship_change_iff(&Ships[oswpt.wingp->ship_index[i]], new_team);
9333 
9334  // ships yet to arrive
9335  for (p_object *p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
9336  {
9337  if (p_objp->wingnum == WING_INDEX(oswpt.wingp))
9338  sexp_parse_ship_change_iff(p_objp, new_team);
9339  }
9340 
9341  break;
9342  }
9343  }
9344  }
9345 }
9346 
9347 void sexp_ingame_ship_change_iff_color(ship *shipp, int observer_team, int observed_team, int alternate_iff_color)
9348 {
9349  Assert(shipp != NULL);
9350 
9351  shipp->ship_iff_color[observer_team][observed_team] = alternate_iff_color;
9352 
9353  // Like the rest of the change_iff_color functions copied with minor alterations from earlier change_iff functions.
9354  if( MULTIPLAYER_MASTER && (Net_player != NULL) && (shipp->objnum >= 0))
9355  send_change_iff_color_packet(Objects[shipp->objnum].net_signature, observer_team, observed_team, alternate_iff_color);
9356 }
9357 
9358 void sexp_parse_ship_change_iff_color(p_object *parse_obj, int observer_team, int observed_team, int alternate_iff_color)
9359 {
9360  Assert(parse_obj);
9361 
9362  parse_obj->alt_iff_color[observer_team][observed_team] = alternate_iff_color;
9363 }
9364 
9365  // Wanderer
9367 {
9368  int observer_team, observed_team, alternate_iff_color;
9369  int i;
9370  int rgb[3];
9371 
9372  // First node
9373  if(n == -1){
9374  Warning(LOCATION, "Detected missing observer team parameter in sexp-change_iff_color");
9375  return;
9376  }
9377  observer_team = iff_lookup(CTEXT(n));
9378 
9379  // Second node
9380  n = CDR(n);
9381  if(n == -1){
9382  Warning(LOCATION, "Detected missing observed team parameter in sexp-change_iff_color");
9383  return;
9384  }
9385  observed_team = iff_lookup(CTEXT(n));
9386 
9387  // Three following nodes
9388  for (i=0;i<3;i++)
9389  {
9390  n = CDR(n);
9391  if(n == -1){
9392  Warning(LOCATION, "Detected incomplete color parameter list in sexp-change_iff_color\n");
9393  return;
9394  }
9395  rgb[i] = eval_num(n);
9396  if (rgb[i] > 255) {
9397  Warning(LOCATION, "Invalid argument for iff color in sexp-change-iff-color. Valid range is 0 to 255.\n");
9398  rgb[i] = 255;
9399  }
9400  }
9401  alternate_iff_color = iff_init_color(rgb[0],rgb[1],rgb[2]);
9402 
9403  // Rest of the nodes
9404  n = CDR(n);
9405  for ( ; n != -1; n = CDR(n) )
9406  {
9409 
9410  switch (oswpt.type)
9411  {
9412  // change ingame ship
9413  case OSWPT_TYPE_SHIP:
9414  {
9415  sexp_ingame_ship_change_iff_color(oswpt.shipp, observer_team, observed_team, alternate_iff_color);
9416 
9417  break;
9418  }
9419 
9420  // change ship yet to arrive
9422  {
9423  sexp_parse_ship_change_iff_color(oswpt.p_objp, observer_team, observed_team, alternate_iff_color);
9424 
9425  break;
9426  }
9427 
9428  // change wing (we must set the flags for all ships present as well as all ships yet to arrive)
9429  case OSWPT_TYPE_WING:
9431  {
9432  // current ships
9433  for (i = 0; i < oswpt.wingp->current_count; i++)
9434  sexp_ingame_ship_change_iff_color(&Ships[oswpt.wingp->ship_index[i]], observer_team, observed_team, alternate_iff_color);
9435 
9436  // ships yet to arrive
9437  for (p_object *p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
9438  {
9439  if (p_objp->wingnum == WING_INDEX(oswpt.wingp))
9440  sexp_parse_ship_change_iff_color(p_objp, observer_team, observed_team, alternate_iff_color);
9441  }
9442 
9443  break;
9444  }
9445  }
9446  }
9447 }
9448 
9449 // Goober5000
9451 {
9452  int ship_num, ship_class_num;
9453 
9454  Assert( n >= 0 );
9455 
9456  // get class
9457  ship_class_num = ship_info_lookup(CTEXT(n));
9458  n = CDR(n);
9459 
9460  // eval ships
9461  while (n != -1)
9462  {
9463  // get ship
9464  ship_num = ship_name_lookup(CTEXT(n));
9465 
9466  // we can't do anything with ships that aren't present
9467  if (ship_num < 0)
9468  return SEXP_CANT_EVAL;
9469 
9470  // if it doesn't match, return false
9471  if (Ships[ship_num].ship_info_index != ship_class_num)
9472  return SEXP_FALSE;
9473 
9474  // increment
9475  n = CDR(n);
9476  }
9477 
9478  // we're this far; it must be true
9479  return SEXP_TRUE;
9480 }
9481 
9482 // Goober5000
9484 {
9485  int ship_num, ship_type_num;
9486 
9487  Assert( n >= 0 );
9488 
9489  // get type
9490  ship_type_num = ship_type_name_lookup(CTEXT(n));
9491  n = CDR(n);
9492 
9493  // eval ships
9494  while (n != -1)
9495  {
9496  // get ship
9497  ship_num = ship_name_lookup(CTEXT(n));
9498 
9499  // we can't do anything with ships that aren't present
9500  if (ship_num < 0)
9501  return SEXP_CANT_EVAL;
9502 
9503  // if it doesn't match, return false
9504  if(ship_class_query_general_type(Ships[ship_num].ship_info_index) != ship_type_num)
9505  return SEXP_FALSE;
9506 
9507  // increment
9508  n = CDR(n);
9509  }
9510 
9511  // we're this far; it must be true
9512  return SEXP_TRUE;
9513 }
9514 
9515 // Goober5000
9516 // ai class value is the first parameter, second is a ship, rest are subsystems to check
9518 {
9519  char *ship_name, *subsystem;
9520  int i, ship_num, ai_class_to_check;
9521 
9522  Assert ( n >= 0 );
9523 
9524  // find ai class
9525  ai_class_to_check = -1;
9526  for (i=0; i<Num_ai_classes; i++)
9527  {
9528  if (!stricmp(Ai_class_names[i], CTEXT(n)))
9529  ai_class_to_check = i;
9530  }
9531 
9532  Assert(ai_class_to_check >= 0);
9533 
9534  n = CDR(n);
9535  ship_name = CTEXT(n);
9536  n = CDR(n);
9537 
9538  // find ship
9539  ship_num = ship_name_lookup(ship_name);
9540 
9541  // we can't do anything with ships that aren't present
9542  if (ship_num < 0)
9543  return SEXP_CANT_EVAL;
9544 
9545  // subsys?
9546  if (n != -1)
9547  {
9548  ship_subsys *ss;
9549 
9550  // loopity-loop
9551  for ( ; n != -1; n = CDR(n) )
9552  {
9553  subsystem = CTEXT(n);
9554 
9555  // find the ship subsystem
9556  // if it doesn't match, or subsys isn't found, return false immediately
9557  ss = ship_get_subsys(&Ships[ship_num], subsystem);
9558  if (ss != NULL)
9559  {
9560  if (ss->weapons.ai_class != ai_class_to_check)
9561  return SEXP_FALSE;
9562  }
9563  else
9564  return SEXP_FALSE;
9565  }
9566 
9567  // we've come this far; it must all be true
9568  return SEXP_TRUE;
9569  }
9570  // just the ship
9571  else
9572  {
9573  if (Ai_info[Ships[ship_num].ai_index].ai_class == ai_class_to_check)
9574  return SEXP_TRUE;
9575  else
9576  return SEXP_FALSE;
9577  }
9578 }
9579 
9580 // Goober5000
9582 {
9583  int i, ship_num, new_ai_class;
9584 
9585  Assert ( n >= 0 );
9586 
9587  // find ai class
9588  new_ai_class = -1;
9589  for (i=0; i<Num_ai_classes; i++)
9590  {
9591  if (!stricmp(Ai_class_names[i], CTEXT(n)))
9592  new_ai_class = i;
9593  }
9594 
9595  Assert(new_ai_class >= 0);
9596 
9597  // find ship
9598  n = CDR(n);
9599  ship_num = ship_name_lookup(CTEXT(n));
9600  n = CDR(n);
9601 
9602  // we can't do anything with ships that aren't present
9603  if (ship_num < 0)
9604  return;
9605 
9606  // subsys?
9607  if (n != -1)
9608  {
9609  // loopity-loop
9610  for ( ; n != -1; n = CDR(n) )
9611  {
9612  ship_subsystem_set_new_ai_class(ship_num, CTEXT(n), new_ai_class);
9613 
9614  // send a network packet if we need to
9615  if( MULTIPLAYER_MASTER && (Net_player != NULL) && (Ships[ship_num].objnum >= 0))
9616  {
9617  send_change_ai_class_packet(Objects[Ships[ship_num].objnum].net_signature, CTEXT(n), new_ai_class);
9618  }
9619  }
9620  }
9621  // just the one ship
9622  else
9623  {
9624  ship_set_new_ai_class(ship_num, new_ai_class);
9625 
9626  // send a network packet if we need to
9627  if( MULTIPLAYER_MASTER && (Net_player != NULL) && (Ships[ship_num].objnum >= 0))
9628  {
9629  send_change_ai_class_packet(Objects[Ships[ship_num].objnum].net_signature, NULL, new_ai_class);
9630  }
9631  }
9632 }
9633 
9634 // following routine adds an ai goal to a ship structure. The sexpression index
9635 // passed in should be an ai-goal of the proper form. The code in MissionGoal should
9636 // check the syntax.
9637 
9639 {
9640  int num, sindex;
9641  char *ship_name;
9642 
9643  Assert ( n >= 0 );
9644  ship_name = CTEXT(n);
9645  num = ship_name_lookup(ship_name, 1); // Goober5000 - including player
9646  if ( num < 0 ) // ship not around anymore???? then forget it!
9647  return;
9648 
9649  sindex = CDR(n);
9650  ai_add_ship_goal_sexp( sindex, AIG_TYPE_EVENT_SHIP, &(Ai_info[Ships[num].ai_index]) );
9651 }
9652 
9653 // identical to above, except add a wing
9655 {
9656  int num, sindex;
9657  char *wing_name;
9658 
9659  Assert ( n >= 0 );
9660  wing_name = CTEXT(n);
9661  num = wing_name_lookup(wing_name);
9662  if ( num < 0 ) // ship not around anymore???? then forget it!
9663  return;
9664 
9665  sindex = CDR(n);
9667 }
9668 
9672 void sexp_add_goal(int n)
9673 {
9674  int num, sindex;
9675  char *name;
9676 
9677  Assert ( n >= 0 );
9678  name = CTEXT(n);
9679  sindex = CDR(n);
9680 
9681  // first, look for ship name -- if found, then add ship goal. else look for wing name -- if
9682  // found, add wing goal
9683  if ( (num = ship_name_lookup(name, 1)) != -1 ) // Goober5000 - include players
9684  ai_add_ship_goal_sexp( sindex, AIG_TYPE_EVENT_SHIP, &(Ai_info[Ships[num].ai_index]) );
9685  else if ( (num = wing_name_lookup(name)) != -1 )
9687 }
9688 
9689 // Goober5000
9691 {
9692  Assert( n >= 0 );
9693  /* Grab the information that we need about this goal removal action */
9694  int num, sindex;
9695  int goalindex;
9696  char *name;
9697 
9698  name = CTEXT(n);
9699  sindex = CDR(n);
9700 
9701  // first, look for ship name -- if found, then add ship goal. else look for wing name -- if
9702  // found, add wing goal
9703  if ( (num = ship_name_lookup(name, 1)) != -1 )
9704  {
9705  goalindex = ai_remove_goal_sexp_sub( sindex, Ai_info[Ships[num].ai_index].goals );
9706  if ( goalindex >= 0 )
9707  {
9708  if ( Ai_info[Ships[num].ai_index].active_goal == goalindex )
9710  }
9711  }
9712  else if ( (num = wing_name_lookup(name)) != -1 )
9713  {
9714  ai_remove_wing_goal_sexp( sindex, num );
9715  }
9716 
9717 }
9718 
9723 {
9724  int num;
9725  char *ship_name;
9726 
9727  Assert ( n >= 0 );
9728  ship_name = CTEXT(n);
9729  if ( (num = ship_name_lookup(ship_name, 1)) != -1) // Goober5000 - include players
9730  {
9731  ai_clear_ship_goals( &(Ai_info[Ships[num].ai_index]) );
9732  }
9733 }
9734 
9739 {
9740  int num;
9741  char *wing_name;
9742 
9743  Assert ( n >= 0 );
9744  wing_name = CTEXT(n);
9745  num = wing_name_lookup(wing_name);
9746  if ( num < 0 )
9747  return;
9748  ai_clear_wing_goals( num );
9749 }
9750 
9755 {
9756  int num;
9757  char *name;
9758 
9759  Assert ( n >= 0 );
9760  while ( n != -1 ) {
9761  name = CTEXT(n);
9762  if ( (num = ship_name_lookup(name, 1)) != -1 ) // Goober5000 - include players
9763  ai_clear_ship_goals( &(Ai_info[Ships[num].ai_index]) );
9764  else if ( (num = wing_name_lookup(name)) != -1 )
9765  ai_clear_wing_goals( num );
9766 
9767  n = CDR(n);
9768  }
9769 }
9770 
9771 // Goober5000
9773 {
9774  int disable_hud = eval_num(n);
9775  hud_set_draw(!disable_hud);
9776 
9778  multi_send_int(disable_hud);
9780 }
9781 
9783 {
9784  int disable_hud;
9785 
9786  if (multi_get_int(disable_hud)) {
9787  hud_set_draw(!disable_hud);
9788  }
9789 }
9790 
9791 // Goober5000
9793 {
9794  int disable_hud = eval_num(n);
9795  hud_disable_except_messages(disable_hud);
9796 
9798  multi_send_int(disable_hud);
9800 }
9801 
9803 {
9804  int disable_hud;
9805 
9806  if (multi_get_int(disable_hud)) {
9807  hud_disable_except_messages(disable_hud);
9808  }
9809 }
9810 
9812 {
9813  char* gaugename = CTEXT(n);
9814  char tmp[16] = "";
9815 
9816  HudGauge* cg = hud_get_gauge(gaugename);
9817  if(cg) {
9818  sprintf( tmp, "%d", eval_num(CDR(n)) );
9819  cg->updateCustomGaugeText(tmp);
9820  }
9821 }
9822 
9824 {
9825  char* gaugename = CTEXT(n);
9826  char* text = CTEXT(CDR(n));
9827 
9828  HudGauge* cg = hud_get_gauge(gaugename);
9829  if(cg) {
9830  cg->updateCustomGaugeText(text);
9831  }
9832 }
9833 
9835 {
9836  char* gaugename = CTEXT(n);
9837  char* text = CTEXT(CDR(n));
9839 
9840  for (int i = 0; i < Num_messages; i++) {
9841  if ( !stricmp(text, Messages[i].name) ) {
9842  message = Messages[i].message;
9843 
9845 
9846  HudGauge* cg = hud_get_gauge(gaugename);
9847  if(cg) {
9848  cg->updateCustomGaugeText(message);
9849  } else {
9850  WarningEx(LOCATION, "Could not find a hud gauge named %s\n", gaugename);
9851  }
9852  return;
9853  }
9854  }
9855 
9856  WarningEx(LOCATION, "sexp_hud_set_message couldn't find a message by the name of %s in the mission\n", text);
9857 }
9858 
9860 {
9861  char* gaugename = CTEXT(n);
9862  char* text = CTEXT(CDR(n));
9863  char message[MESSAGE_LENGTH];
9864 
9865  message_translate_tokens(message, text);
9866 
9867  if (strlen(message) > MESSAGE_LENGTH) {
9868  WarningEx(LOCATION, "Message %s is too long for use in a HUD gauge. Please shorten it to %d characters or less.", message, MESSAGE_LENGTH);
9869  return;
9870  }
9871 
9872  HudGauge* cg = hud_get_gauge(gaugename);
9873  if(cg) {
9874  cg->updateCustomGaugeText(message);
9875  } else {
9876  WarningEx(LOCATION, "Could not find a hud gauge named %s\n", gaugename);
9877  }
9878 }
9879 
9881 {
9882  if(Ship_info[Player_ship->ship_info_index].hud_gauges.size() > 0) {
9883  size_t num_gauges = Ship_info[Player_ship->ship_info_index].hud_gauges.size();
9884 
9885  for(size_t i = 0; i < num_gauges; i++) {
9886  if (Ship_info[Player_ship->ship_info_index].hud_gauges[i]->getObjectType() == HUD_OBJECT_MESSAGES) {
9887  HudGaugeMessages* gauge = static_cast<HudGaugeMessages*>(Ship_info[Player_ship->ship_info_index].hud_gauges[i]);
9888  gauge->clearMessages();
9889  }
9890  }
9891  } else {
9892  size_t num_gauges = default_hud_gauges.size();
9893 
9894  for(size_t i = 0; i < num_gauges; i++) {
9895  if (default_hud_gauges[i]->getObjectType() == HUD_OBJECT_MESSAGES) {
9896  HudGaugeMessages* gauge = static_cast<HudGaugeMessages*>(default_hud_gauges[i]);
9897  gauge->clearMessages();
9898  }
9899  }
9900  }
9901 }
9902 
9904 {
9905  char* gaugename = CTEXT(n);
9906  int coord_x = eval_num(CDR(n));
9907  int coord_y = eval_num(CDR(CDR(n)));
9908 
9909  HudGauge* cg = hud_get_gauge(gaugename);
9910  if(cg) {
9911  cg->updateCustomGaugeCoords(coord_x, coord_y);
9912  }
9913 }
9914 
9916 {
9917  char* gaugename = CTEXT(n);
9918  int frame_num = eval_num(CDR(n));
9919 
9920  HudGauge* cg = hud_get_gauge(gaugename);
9921  if(cg) {
9922  cg->updateCustomGaugeFrame(frame_num);
9923  }
9924 }
9925 
9927 {
9928  char* gaugename = CTEXT(n);
9929  ubyte red = (ubyte) eval_num(CDR(n));
9930  ubyte green = (ubyte) eval_num(CDR(CDR(n)));
9931  ubyte blue = (ubyte) eval_num(CDR(CDR(CDR(n))));
9932 
9933  HudGauge* cg = hud_get_gauge(gaugename);
9934  if(cg) {
9935  cg->sexpLockConfigColor(false);
9936  cg->updateColor(red, green, blue, (HUD_color_alpha+1)*16);
9937  cg->sexpLockConfigColor(true);
9938  }
9939 }
9940 
9941 
9942 // Goober5000
9944 {
9946 
9947  if (Hud_max_targeting_range < 0) {
9949 }
9950 
9954 
9955 }
9956 
9958 {
9960 }
9961 
9962 /* Make sure that the Sexp_hud_display_* get added to the game_state
9963 transitions in freespace.cpp (game_enter_state()). */
9965 
9967  int show_for = eval_num(n);
9968  char* gauge = CTEXT(CDR(n));
9969 
9970  if ( stricmp(SEXP_HUD_GAUGE_WARPOUT, gauge) == 0 ) {
9971  Sexp_hud_display_warpout = (show_for > 1)? timestamp(show_for) : (show_for);
9972  }
9973 }
9974 
9976  HudGauge* hg;
9977  char* name = CTEXT(n);
9978  bool active = (is_sexp_true(CDR(n)) != 0);
9979 
9980  hg = hud_get_gauge(name);
9981 
9982  if (hg != NULL) {
9983  hg->updateActive(active);
9984  }
9985 }
9986 
9988  HudGauge* hg;
9989  bool activate = (is_sexp_true(node) > 0);
9990  node = CDR(node);
9991  for(; node >= 0; node = CDR(node)) {
9992 
9993  char* name = CTEXT(node);
9994  hg = hud_get_gauge(name);
9995 
9996  if (hg != NULL) {
9997  hg->updateActive(activate);
9998  }
9999 
10000  }
10001 
10002 }
10003 
10005  for(int i = 0; i < Num_hud_gauge_types; i++) {
10006  if(!stricmp(name, Hud_gauge_types[i].name))
10007  return Hud_gauge_types[i].def;
10008  }
10009  return -1;
10010 }
10011 
10013  int config_type = hud_gauge_type_lookup(CTEXT(n));
10014  bool active = (is_sexp_true(CDR(n)) != 0);
10015 
10016  if (config_type != -1) {
10017  if(Ship_info[Player_ship->ship_info_index].hud_gauges.size() > 0) {
10018  size_t num_gauges = Ship_info[Player_ship->ship_info_index].hud_gauges.size();
10019 
10020  for(size_t i = 0; i < num_gauges; i++) {
10021  if (Ship_info[Player_ship->ship_info_index].hud_gauges[i]->getObjectType() == config_type)
10022  Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateSexpOverride(!active);
10023  }
10024  } else {
10025  size_t num_gauges = default_hud_gauges.size();
10026 
10027  for(size_t i = 0; i < num_gauges; i++) {
10028  if (default_hud_gauges[i]->getObjectType() == config_type)
10029  default_hud_gauges[i]->updateSexpOverride(!active);
10030  }
10031  }
10032  }
10033 }
10034 
10036 
10037  bool activate = (is_sexp_true(node) > 0);
10038  node = CDR(node);
10039 
10040  for(; node >= 0; node = CDR(node)) {
10041 
10042  int config_type = hud_gauge_type_lookup(CTEXT(node));
10043 
10044  if (config_type != -1) {
10045  if(Ship_info[Player_ship->ship_info_index].hud_gauges.size() > 0) {
10046  size_t num_gauges = Ship_info[Player_ship->ship_info_index].hud_gauges.size();
10047 
10048  for(size_t i = 0; i < num_gauges; i++) {
10049  if (Ship_info[Player_ship->ship_info_index].hud_gauges[i]->getObjectType() == config_type)
10050  Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateSexpOverride(!activate);
10051  }
10052  } else {
10053  size_t num_gauges = default_hud_gauges.size();
10054 
10055  for(size_t i = 0; i < num_gauges; i++) {
10056  if (default_hud_gauges[i]->getObjectType() == config_type)
10057  default_hud_gauges[i]->updateSexpOverride(!activate);
10058  }
10059  }
10060  }
10061 
10062  }
10063 
10064 }
10065 
10067 {
10068  int show_for;
10069 
10070  if (multi_get_int(show_for)) {
10071  Sexp_hud_display_warpout = (show_for > 1)? timestamp(show_for) : (show_for);
10072  }
10073 }
10074 
10075 // Goober5000
10079 void sexp_player_use_ai(int flag)
10080 {
10081  Player_use_ai = flag ? 1 : 0;
10082 }
10083 
10084 // Karajorma
10086 {
10087  n = CDR(n);
10088  if (n != -1) {
10089  if ( is_sexp_true(n) ) {
10091  }
10092  else {
10094  }
10095  }
10096 }
10097 
10099 {
10100  ship *shipp;
10101  int i;
10102  int allow_order;
10103  int orders = 0;
10104  int default_orders;
10105 
10106  shipp = sexp_get_ship_from_node(n);
10107 
10108  if (shipp == NULL) {
10109  return;
10110  }
10111 
10112  // we need to know which orders this ship class can accept.
10113  default_orders = ship_get_default_orders_accepted(&Ship_info[shipp->ship_info_index]);
10114  n = CDR(n);
10115  allow_order = is_sexp_true(n);
10116  n = CDR(n);
10117  do {
10118  for (i = 0 ; i < NUM_COMM_ORDER_ITEMS ; i++) {
10119  // since it's the cheaper test, test first if the ship will even accept this order first
10120  if (default_orders & Sexp_comm_orders[i].item) {
10121  if (!stricmp(CTEXT(n), Sexp_comm_orders[i].name)) {
10122  orders |= Sexp_comm_orders[i].item;
10123  break;
10124  }
10125  }
10126  }
10127 
10128  n = CDR(n);
10129  }while (n >= 0);
10130 
10131  // set or unset the orders
10132  if (allow_order) {
10133  shipp->orders_accepted |= orders;
10134  }
10135  else {
10136  shipp->orders_accepted &= ~orders;
10137  }
10138 }
10139 
10140 // Goober5000
10142 {
10144 
10145  if (MULTIPLAYER_MASTER) {
10148  multi_end_callback();
10149  }
10150 }
10151 
10153 {
10154  char new_track[NAME_LENGTH];
10155 
10156  if (multi_get_string(new_track)) {
10157  event_sexp_change_soundtrack(new_track);
10158  }
10159 }
10160 
10161 // Goober5000
10163 {
10164  if ( Sexp_music_handle != -1 ) {
10165  if ( pause && !audiostream_is_paused(Sexp_music_handle) ) {
10166  audiostream_pause(Sexp_music_handle, true);
10167  } else if ( !pause && audiostream_is_paused(Sexp_music_handle) ) {
10168  audiostream_unpause(Sexp_music_handle, true);
10169  }
10170  }
10171 }
10172 
10173 // Goober5000
10174 void sexp_stop_music(int fade)
10175 {
10176  if ( Sexp_music_handle != -1 ) {
10177  audiostream_close_file(Sexp_music_handle, fade);
10178  Sexp_music_handle = -1;
10179  }
10180 }
10181 
10182 // Goober5000
10184 {
10186  return;
10187  }
10188 
10189  sexp_stop_music();
10190 }
10191 
10192 // Goober5000
10193 void sexp_load_music(char* fname, int type = -1)
10194 {
10196  return;
10197  }
10198 
10199  if ( Sexp_music_handle != -1 )
10200  {
10201  sexp_stop_music();
10202  }
10203 
10204  if ( type < 0 )
10205  {
10206  type = ASF_MENUMUSIC;
10207  }
10208 
10209  if ( fname )
10210  {
10211  Sexp_music_handle = audiostream_open( fname, type );
10212  }
10213 }
10214 
10215 // Goober5000
10216 void sexp_start_music(int loop)
10217 {
10218  if ( Sexp_music_handle != -1 ) {
10219  if ( !audiostream_is_playing(Sexp_music_handle) )
10220  audiostream_play(Sexp_music_handle, (Master_event_music_volume * aav_music_volume), loop);
10221  }
10222  else {
10223  nprintf(("Warning", "Can not play music. sexp_start_music called when no music file is set for Sexp_music_handle!\n"));
10224  }
10225 }
10226 
10228 {
10229  Assert(node >= 0);
10230  int sound_index = -1;
10231 
10232  // this node is another SEXP operator or a plain number
10233  if (CAR(node) != -1 || Sexp_nodes[node].subtype == SEXP_ATOM_NUMBER)
10234  {
10235  sound_index = gamesnd_get_by_tbl_index(eval_num(node));
10236  }
10237  // it's gotta be a name
10238  else
10239  {
10240  const char *sound_name = CTEXT(node);
10241 
10242  // if it's not <none>, try looking it up
10243  if (stricmp(sound_name, SEXP_NONE_STRING))
10244  {
10245  sound_index = gamesnd_get_by_name(sound_name);
10246 
10247  if (sound_index < 0)
10248  Warning(LOCATION, "unrecognized sound name \"%s\"!", sound_name);
10249  }
10250  }
10251 
10252  return sound_index;
10253 }
10254 
10255 // Goober5000
10257 {
10258  vec3d origin;
10259  int sound_index;
10260 
10261  Assert( n >= 0 );
10262 
10263  // read in data --------------------------------
10264  origin.xyz.x = (float)eval_num(n);
10265  n = CDR(n);
10266  origin.xyz.y = (float)eval_num(n);
10267  n = CDR(n);
10268  origin.xyz.z = (float)eval_num(n);
10269  n = CDR(n);
10270  sound_index = sexp_get_sound_index(n);
10271 
10272 
10273  // play sound effect ---------------------------
10274  if (sound_index >= 0) {
10275  game_snd *snd = &Snds[sound_index];
10276  if (snd->min == 0 && snd->max == 0) {
10277  // if sound doesn't specify 3d range, don't play in 3d
10278  snd_play( snd, 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY );
10279  } else {
10280  snd_play_3d( snd, &origin, &View_position, 0.0f, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY );
10281  }
10282  }
10283 
10284  if (MULTIPLAYER_MASTER) {
10286  multi_send_float(origin.xyz.x);
10287  multi_send_float(origin.xyz.y);
10288  multi_send_float(origin.xyz.z);
10289  multi_send_int(sound_index);
10291  }
10292 }
10293 
10295 {
10296  vec3d origin;
10297  int sound_index = -1;
10298 
10299  multi_get_float(origin.xyz.x);
10300  multi_get_float(origin.xyz.y);
10301  multi_get_float(origin.xyz.z);
10302  multi_get_int(sound_index);
10303 
10304 
10305  // play sound effect ---------------------------
10306  if (sound_index >= 0) {
10307  game_snd *snd = &Snds[sound_index];
10308  if (snd->min == 0 && snd->max == 0) {
10309  // if sound doesn't specify 3d range, don't play in 3d
10310  snd_play( snd, 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY );
10311  } else {
10312  snd_play_3d( snd, &origin, &View_position, 0.0f, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY );
10313  }
10314  }
10315 }
10316 
10317 // Goober5000
10319 {
10320  int fade = is_sexp_true(n);
10321  sexp_stop_music(fade);
10322 
10323  if (MULTIPLAYER_MASTER) {
10325  multi_send_bool(fade ? true : false);
10327  }
10328 }
10329 
10331 {
10332  bool fade;
10333  if (multi_get_bool(fade)) {
10334  sexp_stop_music(fade);
10335  }
10336 }
10337 
10338 // Goober5000
10340 {
10341  int loop = 0;
10342  int soundfx = 0;
10343  int type = ASF_MENUMUSIC;
10344 
10345  // third option, but needed when loading music -
10346  soundfx = CDDR(n);
10347 
10348  if (soundfx >= 0) {
10349  soundfx = eval_sexp(soundfx);
10350 
10351  if (soundfx > 0) {
10352  type = ASF_SOUNDFX;
10353  }
10354  }
10355 
10356  // load sound file -----------------------------
10357  sexp_load_music(CTEXT(n), type);
10358 
10359  if (MULTIPLAYER_MASTER) {
10362  }
10363 
10364  n = CDR(n);
10365  if (n >= 0) {
10366  loop = eval_sexp(n);
10367  }
10368 
10369  // play sound file -----------------------------
10370  sexp_start_music(loop);
10371 
10372  if (MULTIPLAYER_MASTER) {
10373  multi_send_bool(loop ? true : false);
10375  }
10376 }
10377 
10379 {
10380  char filename[NAME_LENGTH];
10381  bool (loop);
10382  if (!multi_get_string(filename)) {
10383  return;
10384  }
10385  sexp_load_music(filename);
10386 
10387  multi_get_bool(loop);
10388  sexp_start_music(loop);
10389 }
10390 
10391 // Goober5000
10393 {
10394  bool pause = (is_sexp_true(node) != 0);
10395 
10396  if (MULTIPLAYER_MASTER) {
10397  multi_send_bool(pause);
10399  }
10400 
10401  sexp_pause_unpause_music(pause);
10402 }
10403 
10405 {
10406  bool pause;
10407  if (multi_get_bool(pause)) {
10408  sexp_pause_unpause_music(pause);
10409  }
10410 }
10411 
10413 {
10414  int i;
10415 
10416  Assert(text != NULL);
10417  if (text == NULL) {
10418  return -1;
10419  }
10420 
10421  for (i = 0; i < Num_sound_environment_options; i++) {
10422  if (!strcmp(text, Sound_environment_option[i])) {
10423  return i;
10424  }
10425  }
10426 
10427  return -1;
10428 }
10429 
10430 // Taylor
10432 {
10433  int n = node;
10434  sound_env env;
10435  int preset_id = -1;
10436 
10437  char *preset = CTEXT(n);
10438  n = CDR(n);
10439 
10440  if ( preset && !stricmp(preset, SEXP_NONE_STRING) ) {
10442  return;
10443  }
10444 
10445  preset_id = ds_eax_get_preset_id( preset );
10446  if (preset_id < 0) {
10447  return;
10448  }
10449 
10450  // fill in defaults for this preset, in case we don't set everything
10451  if ( sound_env_get(&env, preset_id) ) {
10452  return;
10453  }
10454 
10455  while (n >= 0) {
10457  n = CDR(n);
10458 
10459  // watch out for bogus options
10460  if (n < 0) {
10461  break;
10462  }
10463 
10464  float val = (float)eval_num(n) / 1000.0f;
10465  n = CDR(n);
10466 
10467  if ( option == SEO_VOLUME ) {
10468  env.volume = val;
10469  } else if ( option == SEO_DECAY_TIME ) {
10470  env.decay = val;
10471  } else if ( option == SEO_DAMPING ) {
10472  env.damping = val;
10473  }
10474  }
10475 
10476  sound_env_set(&env);
10477 }
10478 
10479 // Taylor
10481 {
10482  int n = node;
10483 
10484  while (n >= 0) {
10486  n = CDR(n);
10487 
10488  // watch out for bogus options
10489  if (n < 0) {
10490  break;
10491  }
10492 
10493  float val = (float)eval_num(n) / 1000.0f;
10494  n = CDR(n);
10495 
10496  if ( option == SEO_VOLUME ) {
10497  ds_eax_set_volume(val);
10498  } else if ( option == SEO_DECAY_TIME ) {
10499  ds_eax_set_decay_time(val);
10500  } else if ( option == SEO_DAMPING ) {
10501  ds_eax_set_damping(val);
10502  }
10503  }
10504 }
10505 
10506 //The E
10507  //From sexp help:
10508  //{ OP_ADJUST_AUDIO_VOLUME, "adjust-audio-volume\r\n"
10509  // "Adjusts the relative volume of one sound type. Takes 2 or 3 arguments....\r\n"
10510  // "\t1:\tSound Type to adjust, either Music, Voice or Effects\r\n"
10511  // "\t2:\tPercentage of the users' settings to adjust to, 0 will be silence, 100 means the maximum volume as set by the user\r\n"
10512  // "\t3:\tFade time (optional), time in milliseconds to adjust the volume"},
10513 
10515 {
10516  int i;
10517 
10518  Assert(text != NULL);
10519  if (text == NULL) {
10520  return -1;
10521  }
10522 
10523  for (i = 0; i < Num_adjust_audio_options; i++) {
10524  if (!strcmp(text, Adjust_audio_options[i])) {
10525  return i;
10526  }
10527  }
10528 
10529  return -1;
10530 }
10531 
10533 {
10534  int n = node;
10535 
10536  if (n > 0) {
10538  if (option >= 0) {
10539  n = CDR(n);
10540 
10541  float target_volume = 1.0f;
10542  if (n >= 0) {
10543  target_volume = (float)eval_num(n) / 100;
10544  CLAMP(target_volume, 0.0f, 1.0f);
10545  n = CDR(n);
10546  }
10547 
10548  int time = 0;
10549  if (n >= 0)
10550  time = eval_num(n);
10551 
10552  snd_adjust_audio_volume(option, target_volume, time);
10553  }
10554  }
10555 }
10556 
10558 {
10559  int i;
10560 
10561  Assert(text != NULL);
10562  if (text == NULL) {
10563  return -1;
10564  }
10565 
10566  for (i = 0; i < Num_explosion_options; i++) {
10567  if (!strcmp(text, Explosion_option[i])) {
10568  return i;
10569  }
10570  }
10571 
10572  return -1;
10573 }
10574 
10575 // Goober5000
10577 {
10578  int n = node, ship_num;
10579  ship *shipp;
10580  ship_info *sip;
10581  shockwave_create_info *sci;
10582 
10583  // get ship
10584  ship_num = ship_name_lookup(CTEXT(n));
10585  if (ship_num < 0)
10586  return;
10587 
10588  shipp = &Ships[ship_num];
10589  sip = &Ship_info[shipp->ship_info_index];
10590  sci = &sip->shockwave;
10591 
10592  n = CDR(n);
10593 
10594  // if we haven't changed anything yet, create a new special-exp with the same values as a standard exp
10595  if (!shipp->use_special_explosion)
10596  {
10597  shipp->special_exp_damage = fl2i(sci->damage);
10598  shipp->special_exp_blast = fl2i(sci->blast);
10599  shipp->special_exp_inner = fl2i(sci->inner_rad);
10600  shipp->special_exp_outer = fl2i(sci->outer_rad);
10601  shipp->special_exp_shockwave_speed = fl2i(sci->speed);
10602  shipp->special_exp_deathroll_time = 0;
10603 
10604  shipp->use_special_explosion = true;
10605  shipp->use_shockwave = (sci->speed > 0);
10606  }
10607 
10608  // process all options
10609  while (n >= 0)
10610  {
10612  n = CDR(n);
10613 
10614  // watch out for bogus options
10615  if (n < 0)
10616  break;
10617 
10618  int val = eval_num(n);
10619  Assert(val >= 0); // should be true due to OPF_POSITIVE
10620  n = CDR(n);
10621 
10622  if (option == EO_DAMAGE) {
10623  shipp->special_exp_damage = val;
10624  } else if (option == EO_BLAST) {
10625  shipp->special_exp_blast = val;
10626  } else if (option == EO_INNER_RADIUS) {
10627  shipp->special_exp_inner = val;
10628  } else if (option == EO_OUTER_RADIUS) {
10629  shipp->special_exp_outer = val;
10630  } else if (option == EO_SHOCKWAVE_SPEED) {
10632  shipp->use_shockwave = (val > 0);
10633  } else if (option == EO_DEATH_ROLL_TIME) {
10635 
10636  // hmm, it would be cool to modify the explosion in progress
10637  if (shipp->flags & SF_DYING && val >= 2) {
10638  shipp->final_death_time = timestamp(val);
10639  }
10640  }
10641  }
10642 
10643  // if all our values are the same as a standard exp, turn off the special exp
10644  if ((shipp->special_exp_damage == sci->damage) && (shipp->special_exp_blast == sci->blast) && (shipp->special_exp_inner == sci->inner_rad)
10645  && (shipp->special_exp_outer == sci->outer_rad) && (shipp->special_exp_shockwave_speed == sci->speed) && (shipp->special_exp_deathroll_time == 0))
10646  {
10647  shipp->use_special_explosion = false;
10648  shipp->use_shockwave = false;
10649 
10650  shipp->special_exp_damage = -1;
10651  shipp->special_exp_blast = -1;
10652  shipp->special_exp_inner = -1;
10653  shipp->special_exp_outer = -1;
10654  shipp->special_exp_shockwave_speed = -1;
10655  shipp->special_exp_deathroll_time = 0;
10656  }
10657 }
10658 
10659 // Goober5000
10661 /* From the SEXP help...
10662  { OP_EXPLOSION_EFFECT, "explosion-effect\r\n"
10663  "\tCauses an explosion at a given origin, with the given parameters. "
10664  "Takes 11 or 13 arguments...\r\n"
10665  "\t1: Origin X\r\n"
10666  "\t2: Origin Y\r\n"
10667  "\t3: Origin Z\r\n"
10668  "\t4: Damage\r\n"
10669  "\t5: Blast force\r\n"
10670  "\t6: Size of explosion (if 0, explosion will not be visible)\r\n"
10671  "\t7: Inner radius to apply damage (if 0, explosion will not be visible)\r\n"
10672  "\t8: Outer radius to apply damage (if 0, explosion will not be visible)\r\n"
10673  "\t9: Shockwave speed (if 0, there will be no shockwave)\r\n"
10674  "\t10: Type (0 = medium, 1 = large1, 2 = large2)\r\n" (otherwise use the index in fireball.tbl - FUBAR)
10675  "\t11: Sound (index into sounds.tbl)\r\n"
10676  "\t12: EMP intensity (optional)\r\n"
10677  "\t13: EMP duration in seconds (optional)" },
10678 */
10679 // Basically, this function pretends that there's a ship at the origin that's blowing up, and
10680 // it does stuff accordingly. In some places, it has to tiptoe around a little because the
10681 // code often expects a parent object when in fact there is none. <.< >.>
10682 {
10683  vec3d origin;
10684  int max_damage, max_blast, explosion_size, inner_radius, outer_radius, shockwave_speed, fireball_type, sound_index;
10685  int emp_intensity, emp_duration;
10686 
10687  Assert( n >= 0 );
10688 
10689  // read in data --------------------------------
10690  origin.xyz.x = (float)eval_num(n);
10691  n = CDR(n);
10692  origin.xyz.y = (float)eval_num(n);
10693  n = CDR(n);
10694  origin.xyz.z = (float)eval_num(n);
10695  n = CDR(n);
10696 
10697  max_damage = eval_num(n);
10698  n = CDR(n);
10699  max_blast = eval_num(n);
10700  n = CDR(n);
10701 
10702  explosion_size = eval_num(n);
10703  n = CDR(n);
10704  inner_radius = eval_num(n);
10705  n = CDR(n);
10706  outer_radius = eval_num(n);
10707  n = CDR(n);
10708 
10709  shockwave_speed = eval_num(n);
10710  n = CDR(n);
10711 
10712  // fireball type
10713  if (eval_num(n) == 0)
10714  {
10715  fireball_type = FIREBALL_EXPLOSION_MEDIUM;
10716  }
10717  else if (eval_num(n) == 1)
10718  {
10719  fireball_type = FIREBALL_EXPLOSION_LARGE1;
10720  }
10721  else if (eval_num(n) == 2)
10722  {
10723  fireball_type = FIREBALL_EXPLOSION_LARGE2;
10724  }
10725  else if (eval_num(n) >= Num_fireball_types) {
10726  Warning(LOCATION, "explosion-effect type is out of range; quitting the explosion...\n");
10727  return;
10728  }
10729  else {
10730  fireball_type = eval_num(n);
10731  }
10732  n = CDR(n);
10733 
10734  sound_index = sexp_get_sound_index(n);
10735 
10736  n = CDR(n);
10737 
10738  // optional EMP
10739  emp_intensity = 0;
10740  emp_duration = 0;
10741  if (n != -1)
10742  {
10743  emp_intensity = eval_num(n);
10744  n = CDR(n);
10745  }
10746  if (n != -1)
10747  {
10748  emp_duration = eval_num(n);
10749  n = CDR(n);
10750  }
10751 
10752 
10753  // play sound effect ---------------------------
10754  if (sound_index >= 0)
10755  {
10756  snd_play_3d( &Snds[sound_index], &origin, &View_position, 0.0f, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY );
10757  }
10758 
10759 
10760  // create the fireball -------------------------
10761  if (explosion_size && inner_radius && outer_radius)
10762  {
10763  if(fireball_type == FIREBALL_EXPLOSION_MEDIUM)
10764  fireball_create( &origin, fireball_type, FIREBALL_MEDIUM_EXPLOSION, -1, (float)explosion_size );
10765  else
10766  fireball_create( &origin, fireball_type, FIREBALL_LARGE_EXPLOSION, -1, (float)explosion_size );
10767  }
10768 
10769  // apply area affect damage --------------------
10770  if (max_damage || max_blast)
10771  {
10772  if ( shockwave_speed > 0 )
10773  {
10776 
10777  sci.inner_rad = (float)inner_radius;
10778  sci.outer_rad = (float)outer_radius;
10779  sci.blast = (float)max_blast;
10780  sci.damage = (float)max_damage;
10781  sci.speed = (float)shockwave_speed;
10782  sci.rot_angles.p = frand_range(0.0f, 1.99f*PI);
10783  sci.rot_angles.b = frand_range(0.0f, 1.99f*PI);
10784  sci.rot_angles.h = frand_range(0.0f, 1.99f*PI);
10785  shockwave_create(-1, &origin, &sci, SW_SHIP_DEATH);
10786  }
10787  else
10788  {
10789  object *objp;
10790  float t_blast = 0.0f;
10791  float t_damage = 0.0f;
10792  for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) )
10793  {
10794  if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) )
10795  {
10796  continue;
10797  }
10798 
10799  // don't blast navbuoys
10800  if ( objp->type == OBJ_SHIP )
10801  {
10802  if ( ship_get_SIF(objp->instance) & SIF_NAVBUOY )
10803  {
10804  continue;
10805  }
10806  }
10807 
10808  if ( ship_explode_area_calc_damage( &origin, &objp->pos, (float)inner_radius, (float)outer_radius, (float)max_damage, (float)max_blast, &t_damage, &t_blast ) == -1 )
10809  {
10810  continue;
10811  }
10812 
10813  switch ( objp->type )
10814  {
10815  case OBJ_SHIP:
10816  ship_apply_global_damage( objp, NULL, &origin, t_damage );
10817  vec3d force, vec_ship_to_impact;
10818  vm_vec_sub( &vec_ship_to_impact, &objp->pos, &origin );
10819  if (!IS_VEC_NULL_SQ_SAFE( &vec_ship_to_impact )) {
10820  vm_vec_copy_normalize( &force, &vec_ship_to_impact );
10821  vm_vec_scale( &force, (float)max_blast );
10822  ship_apply_whack( &force, &vec_ship_to_impact, objp );
10823  }
10824  break;
10825 
10826  case OBJ_ASTEROID:
10827  asteroid_hit(objp, NULL, NULL, t_damage);
10828  break;
10829 
10830  default:
10831  Int3();
10832  break;
10833  }
10834  } // end for
10835  }
10836  }
10837 
10838 
10839  // apply emp damage if applicable --------------
10840  if (emp_intensity && emp_duration)
10841  {
10842  emp_apply(&origin, (float)inner_radius, (float)outer_radius, (float)emp_intensity, (float)emp_duration);
10843  }
10844 }
10845 
10846 // Goober5000
10848 /* From the SEXP help...
10849  { OP_WARP_EFFECT, "warp-effect\r\n"
10850  "\tCauses a subspace warp effect at a given origin, facing toward a given location, with the given parameters. "
10851  "Takes 12 arguments...\r\n"
10852  "\t1: Origin X\r\n"
10853  "\t2: Origin Y\r\n"
10854  "\t3: Origin Z\r\n"
10855  "\t4: Location X\r\n"
10856  "\t5: Location Y\r\n"
10857  "\t6: Location Z\r\n"
10858  "\t7: Radius\r\n"
10859  "\t8: Duration in seconds\r\n"
10860  "\t9: Warp opening sound (index into sounds.tbl)\r\n"
10861  "\t10: Warp closing sound (index into sounds.tbl)\r\n"
10862  "\t11: Type (0 for standard blue [default], 1 for Knossos green)\r\n"
10863  "\t12: Shape (0 for 2-D [default], 1 for 3-D)" },
10864 */
10865 {
10866  vec3d origin, location, v_orient;
10867  matrix m_orient;
10868  int radius, duration, warp_open_sound_index, warp_close_sound_index, fireball_type, extra_flags;
10869  extra_flags = FBF_WARP_VIA_SEXP;
10870 
10871  // read in data --------------------------------
10872  origin.xyz.x = (float)eval_num(n);
10873  n = CDR(n);
10874  origin.xyz.y = (float)eval_num(n);
10875  n = CDR(n);
10876  origin.xyz.z = (float)eval_num(n);
10877  n = CDR(n);
10878 
10879  location.xyz.x = (float)eval_num(n);
10880  n = CDR(n);
10881  location.xyz.y = (float)eval_num(n);
10882  n = CDR(n);
10883  location.xyz.z = (float)eval_num(n);
10884  n = CDR(n);
10885 
10886  radius = eval_num(n);
10887  n = CDR(n);
10888  duration = eval_num(n);
10889  if (duration < 4) duration = 4;
10890  n = CDR(n);
10891 
10892  warp_open_sound_index = sexp_get_sound_index(n);
10893  n = CDR(n);
10894  warp_close_sound_index = sexp_get_sound_index(n);
10895  n = CDR(n);
10896 
10897  // fireball type
10898  if (eval_num(n) == 0)
10899  {
10900  fireball_type = FIREBALL_WARP;
10901  }
10902  else if (eval_num(n) == 1)
10903  {
10904  fireball_type = FIREBALL_KNOSSOS;
10905  }
10906  else
10907  {
10908  Warning(LOCATION, "warp-effect type is out of range; quitting the warp...\n");
10909  return;
10910  }
10911  n = CDR(n);
10912 
10913  // shape
10914  if (eval_num(n) == 0)
10915  {
10916  // do nothing; this is standard
10917  }
10918  else if (eval_num(n) == 1)
10919  {
10920  extra_flags |= FBF_WARP_3D;
10921  }
10922  else
10923  {
10924  Warning(LOCATION, "warp-effect shape is out of range; quitting the warp...\n");
10925  return;
10926  }
10927 
10928 
10929  // calculate orientation matrix ----------------
10930 
10931  vm_vec_sub(&v_orient, &location, &origin);
10932 
10933  if (IS_VEC_NULL_SQ_SAFE(&v_orient))
10934  {
10935  Warning(LOCATION, "error in warp-effect: warp can't point to itself; quitting the warp...\n");
10936  return;
10937  }
10938 
10939  vm_vector_2_matrix(&m_orient, &v_orient, NULL, NULL);
10940 
10941  // create fireball -----------------------------
10942 
10943  fireball_create(&origin, fireball_type, FIREBALL_WARP_EFFECT, -1, (float)radius, 0, NULL, (float)duration, -1, &m_orient, 0, extra_flags, warp_open_sound_index, warp_close_sound_index);
10944 }
10945 
10946 // this function get called by send-message or send-message random with the name of the message, sender,
10947 // and priority.
10948 void sexp_send_one_message( char *name, char *who_from, char *priority, int group, int delay )
10949 {
10950  int ipriority, num, ship_index, source;
10951  ship *shipp;
10952 
10953  if(physics_paused){
10954  return;
10955  }
10956 
10957  Assert( (name != NULL) && (who_from != NULL) && (priority != NULL) );
10958 
10959  // determine the priority of the message
10960  if ( !stricmp(priority, "low") )
10961  ipriority = MESSAGE_PRIORITY_LOW;
10962  else if ( !stricmp(priority, "normal") )
10963  ipriority = MESSAGE_PRIORITY_NORMAL;
10964  else if ( !stricmp(priority, "high") )
10965  ipriority = MESSAGE_PRIORITY_HIGH;
10966  else {
10967  Int3();
10968  ipriority = MESSAGE_PRIORITY_NORMAL;
10969  }
10970 
10971  // check to see if the 'who_from' string is a ship that had been destroyed or departed. If so,
10972  // then don't send the message. We must look at 'who_from' to determine what to look for. who_from
10973  // may be any allied person, any wingman, a wingman from a specific wing, or a specific ship
10974  ship_index = -1;
10975  shipp = NULL;
10976  source = MESSAGE_SOURCE_COMMAND;
10977  if ( who_from[0] == '#' ) {
10978  message_send_unique_to_player( name, &(who_from[1]), MESSAGE_SOURCE_SPECIAL, ipriority, group, delay );
10979  return;
10980  } else if (!stricmp(who_from, "<any allied>")) {
10981  return;
10982  } else if ( (num = wing_name_lookup(who_from)) != -1 ) {
10983  // message from a wing
10984  // choose wing leader to speak for wing (hence "1" at end of ship_get_random_ship_in_wing)
10985  ship_index = ship_get_random_ship_in_wing( num, SHIP_GET_UNSILENCED, 1 );
10986  if ( ship_index == -1 ) {
10987  if ( ipriority != MESSAGE_PRIORITY_HIGH )
10988  return;
10989  }
10990 
10991  } else if ( mission_log_get_time(LOG_SHIP_DESTROYED, who_from, NULL, NULL) || mission_log_get_time(LOG_SHIP_DEPARTED, who_from, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, who_from, NULL, NULL)
10992  || mission_log_get_time(LOG_WING_DESTROYED, who_from, NULL, NULL) || mission_log_get_time(LOG_WING_DEPARTED, who_from, NULL, NULL) ) {
10993  // getting into this if statement means that the ship or wing (sender) is no longer in the mission
10994  // if message is high priority, make it come from Terran Command
10995  if ( ipriority != MESSAGE_PRIORITY_HIGH )
10996  return;
10997 
10998  source = MESSAGE_SOURCE_COMMAND;
10999 
11000  } else if ( !stricmp(who_from, "<any wingman>") || (wing_name_lookup(who_from) != -1) ) {
11001  source = MESSAGE_SOURCE_WINGMAN;
11002  } else if ( !stricmp(who_from, "<none>") ) {
11003  source = MESSAGE_SOURCE_NONE;
11004  } else {
11005  // Message from a apecific ship
11006  source = MESSAGE_SOURCE_SHIP;
11007  ship_index = ship_name_lookup(who_from);
11008  if ( ship_index == -1 ) {
11009  // bail if not high priority, otherwise reroute to command
11010  if ( ipriority != MESSAGE_PRIORITY_HIGH )
11011  return;
11012  source = MESSAGE_SOURCE_COMMAND;
11013  }
11014  }
11015 
11016  if ( ship_index == -1 ){
11017  shipp = NULL;
11018  } else {
11019  shipp = &Ships[ship_index];
11020  }
11021 
11022  message_send_unique_to_player( name, shipp, source, ipriority, group, delay );
11023 }
11024 
11026 {
11027  char *name, *who_from, *priority, *tmp;
11028 
11029  if(physics_paused){
11030  return;
11031  }
11032 
11033  Assert ( n != -1 );
11034  who_from = CTEXT(n);
11035  priority = CTEXT(CDR(n));
11036  name = CTEXT(CDR(CDR(n)));
11037 
11038  // a temporary check to see if the name field matched a priority since I am in the process
11039  // of reordering the arguments
11040  if ( !stricmp(name, "low") || !stricmp(name, "normal") || !stricmp(name, "high") ) {
11041  tmp = name;
11042  name = priority;
11043  priority = tmp;
11044  }
11045 
11046  sexp_send_one_message( name, who_from, priority, 0, 0 );
11047 }
11048 
11050 {
11051  char *name, *who_from, *priority;
11052  int delay;
11053 
11054  if(physics_paused){
11055  return;
11056  }
11057 
11058  // send a bunch of messages
11059  delay = 0;
11060  while(n != -1){
11061  who_from = CTEXT(n);
11062 
11063  // next node
11064  n = CDR(n);
11065  if(n == -1){
11066  Warning(LOCATION, "Detected incomplete parameter list in sexp-send-message-list");
11067  return;
11068  }
11069  priority = CTEXT(n);
11070 
11071  // next node
11072  n = CDR(n);
11073  if(n == -1){
11074  Warning(LOCATION, "Detected incomplete parameter list in sexp-send-message-list");
11075  return;
11076  }
11077  name = CTEXT(n);
11078 
11079  // next node
11080  n = CDR(n);
11081  if(n == -1){
11082  Warning(LOCATION, "Detected incomplete parameter list in sexp-send-message-list");
11083  return;
11084  }
11085  delay += eval_num(n);
11086 
11087  // send the message
11088  sexp_send_one_message(name, who_from, priority, 1, delay);
11089 
11090  // next node
11091  n = CDR(n);
11092  }
11093 }
11094 
11096 {
11097  char *name, *who_from, *priority;
11098  int temp, num_messages, message_num;
11099 
11100  Assert ( n != -1 );
11101  who_from = CTEXT(n);
11102  priority = CTEXT(CDR(n));
11103 
11104  if(physics_paused){
11105  return;
11106  }
11107 
11108  // count the number of messages that we have
11109  n = CDR(CDR(n));
11110  temp = n;
11111  num_messages = 0;
11112  while ( n != -1 ) {
11113  n = CDR(n);
11114  num_messages++;
11115  }
11116  Assert ( num_messages >= 1 );
11117 
11118  // get a random message, and pass the parameters to send_one_message
11119  message_num = myrand() % num_messages;
11120  n = temp;
11121  while ( n != -1 ) {
11122  if ( message_num == 0 )
11123  break;
11124  message_num--;
11125  n = CDR(n);
11126  }
11127  Assert (n != -1); // should have found the message!!!
11128  name = CTEXT(n);
11129 
11130  sexp_send_one_message( name, who_from, priority, 0, 0 );
11131 }
11132 
11133 void sexp_self_destruct(int node)
11134 {
11135  int n, ship_num;
11136 
11137  for (n = node; n != -1; n = CDR(n)) {
11138  // get the ship
11139  ship_num = ship_name_lookup(CTEXT(n));
11140 
11141  // if it still exists, destroy it
11142  if (ship_num >= 0) {
11143  ship_self_destruct(&Objects[Ships[ship_num].objnum]);
11144  }
11145  }
11146 }
11147 
11149 {
11150  char *mission_name;
11151  int i;
11152 
11153  mission_name = CTEXT(n);
11154 
11155  if (mission_name == NULL) {
11156  Error( LOCATION, "Mission name is NULL in campaign file for next-mission command!");
11157  }
11158 
11159  for (i = 0; i < Campaign.num_missions; i++) {
11160  if ( !stricmp(Campaign.missions[i].name, mission_name) ) {
11162  return;
11163  }
11164  }
11165  Error(LOCATION, "Mission name %s not found in campaign file for next-mission command", mission_name);
11166 }
11167 
11172 {
11173  // this is really a do-nothing sexpression. It is pretty much a placeholder to allow
11174  // campaigns to have repeat-mission branches at the end of the campaign. By not setting
11175  // anything in this function, the higher level campaign code will see this as end-of-campaign
11176  // since next_mission isn't set to anything. (To be safe, we'll set to -1).
11177  Campaign.next_mission = -1;
11178 }
11179 
11180 // sexpression to end everything. One parameter is the movie to play when this is over.
11181 // Goober5000 - edited to only to the FS2-specific code when actually ending the FS2 main
11182 // campaign, and otherwise to do the conventional code
11184 {
11185  int ignore_player_mortality = 1;
11186 
11187  if (!(Game_mode & GM_CAMPAIGN_MODE)) {
11188  return;
11189  }
11190 
11191  if (n != -1) {
11192  ignore_player_mortality = is_sexp_true(n);
11193  }
11194 
11195  // if the player is dead we may want to let the death screen handle things
11196  if (!ignore_player_mortality && (Player_ship->flags & SF_DYING)) {
11197  return;
11198  }
11199 
11200  // in FS2 our ending is a bit wacky. we'll just flag the mission as having ended the campaign
11201  //
11202  // changed this to check for an active supernova rather than a special campaign since the supernova
11203  // code needs special time to execute and will post GS_EVENT_END_CAMPAIGN with Game_mode check
11204  // or show death-popup when it's done - taylor
11205  if (supernova_active() /*&& !stricmp(Campaign.filename, "freespace2")*/) {
11207  } else {
11208  // post and event to move us to the end-of-campaign state
11210  }
11211 }
11212 
11219 {
11220  char *shipname, *subsystem;
11221  int percentage, shipnum, index, generic_type;
11222  float sabotage_hits;
11223  ship *shipp;
11224  ship_subsys *ss = NULL, *ss_start;
11225  bool do_loop = true;
11226 
11227  shipname = CTEXT(n);
11228  subsystem = CTEXT(CDR(n));
11229  percentage = eval_num(CDR(CDR(n)));
11230 
11231  shipnum = ship_name_lookup(shipname);
11232 
11233  // if no ship, then return immediately.
11234  if ( shipnum == -1 )
11235  return;
11236  shipp = &Ships[shipnum];
11237 
11238  // see if we are dealing with the HULL
11239  if ( !stricmp( subsystem, SEXP_HULL_STRING) ) {
11240  float ihs;
11241  object *objp;
11242 
11243  ihs = shipp->ship_max_hull_strength;
11244  sabotage_hits = ihs * ((float)percentage / 100.0f);
11245  objp = &Objects[shipp->objnum];
11246  objp->hull_strength -= sabotage_hits;
11247 
11248  // self destruct the ship if <= 0.
11249  if ( objp->hull_strength <= 0.0f )
11250  ship_self_destruct( objp );
11251  return;
11252  }
11253 
11254  // see if we are dealing with the Simulated HULL
11255  if ( !stricmp( subsystem, SEXP_SIM_HULL_STRING) ) {
11256  float ihs;
11257  object *objp;
11258 
11259  ihs = shipp->ship_max_hull_strength;
11260  sabotage_hits = ihs * ((float)percentage / 100.0f);
11261  objp = &Objects[shipp->objnum];
11262  objp->sim_hull_strength -= sabotage_hits;
11263 
11264  return;
11265  }
11266 
11267  // now find the given subsystem on the ship. This could be a generic type like <All Engines>
11268  generic_type = get_generic_subsys(subsystem);
11269  ss_start = GET_FIRST(&shipp->subsys_list);
11270 
11271  while (do_loop) {
11272  if (generic_type) {
11273  // loop until we find a subsystem of that type
11274  for ( ; ss_start != END_OF_LIST(&Ships[shipnum].subsys_list); ss_start = GET_NEXT(ss_start)) {
11275  ss = NULL;
11276  if (generic_type == ss_start->system_info->type) {
11277  ss = ss_start;
11278  ss_start = GET_NEXT(ss_start);
11279  break;
11280  }
11281  }
11282 
11283  // reached the end of the subsystem list
11284  if (ss_start == END_OF_LIST(&Ships[shipnum].subsys_list)) {
11285  // If the last subsystem wasn't of interest we don't need to go any further
11286  if (ss == NULL) {
11287  return;
11288  }
11289  do_loop = false;
11290  }
11291  }
11292  else {
11293  do_loop = false;
11294  index = ship_get_subsys_index(shipp, subsystem, 1); // Bypass any error since we supply one here
11295  if ( index == -1 ) {
11296  nprintf(("Warning", "Couldn't find subsystem %s on ship %s for sabotage subsystem\n", subsystem, shipp->ship_name));
11297  return;
11298  }
11299  // get the pointer to the subsystem. Check it's current hits against it's max hits, and
11300  // set the strength to the given percentage if current strength is > given percentage
11301  ss = ship_get_indexed_subsys( shipp, index );
11302  if (ss == NULL) {
11303  nprintf(("Warning", "Nonexistent subsystem for index %d on ship %s for sabotage subsystem\n", index, shipp->ship_name));
11304  return;
11305  }
11306  }
11307 
11308  sabotage_hits = ss->max_hits * ((float)percentage / 100.0f);
11309  ss->current_hits -= sabotage_hits;
11310  if ( ss->current_hits < 0.0f )
11311  ss->current_hits = 0.0f;
11312 
11313  // maybe blow up subsys
11314  if (ss->current_hits <= 0) {
11315  do_subobj_destroyed_stuff(shipp, ss, NULL);
11316  }
11317 
11318  ship_recalc_subsys_strength( shipp );
11319  }
11320 }
11321 
11328 {
11329  char *shipname, *subsystem;
11330  int percentage, shipnum, index, do_submodel_repair, generic_type;
11331  float repair_hits;
11332  ship *shipp;
11333  ship_subsys *ss = NULL, *ss_start;
11334  bool do_loop = true;
11335 
11336  shipname = CTEXT(n);
11337  subsystem = CTEXT(CDR(n));
11338  shipnum = ship_name_lookup(shipname);
11339 
11340  do_submodel_repair = is_sexp_true(CDDDR(n));
11341 
11342  // if no ship, then return immediately.
11343  if ( shipnum == -1 ) {
11344  return;
11345  }
11346  shipp = &Ships[shipnum];
11347 
11348  // get percentage
11349  percentage = eval_num(CDR(CDR(n)));
11350 
11351  // see if we are dealing with the HULL
11352  if ( !stricmp( subsystem, SEXP_HULL_STRING) ) {
11353  float ihs;
11354  object *objp;
11355 
11356  ihs = shipp->ship_max_hull_strength;
11357  repair_hits = ihs * ((float)percentage / 100.0f);
11358  objp = &Objects[shipp->objnum];
11359  objp->hull_strength += repair_hits;
11360  if ( objp->hull_strength > ihs )
11361  objp->hull_strength = ihs;
11362  return;
11363  }
11364 
11365  // see if we are dealing with the Simulated HULL
11366  if ( !stricmp( subsystem, SEXP_SIM_HULL_STRING) ) {
11367  float ihs;
11368  object *objp;
11369 
11370  ihs = shipp->ship_max_hull_strength;
11371  repair_hits = ihs * ((float)percentage / 100.0f);
11372  objp = &Objects[shipp->objnum];
11373  objp->hull_strength += repair_hits;
11374  if ( objp->sim_hull_strength > ihs )
11375  objp->sim_hull_strength = ihs;
11376  return;
11377  }
11378 
11379  // now find the given subsystem on the ship.This could be a generic type like <All Engines>
11380  generic_type = get_generic_subsys(subsystem);
11381  ss_start = GET_FIRST(&shipp->subsys_list);
11382 
11383  while (do_loop) {
11384  if (generic_type) {
11385  // loop until we find a subsystem of that type
11386  for ( ; ss_start != END_OF_LIST(&Ships[shipnum].subsys_list); ss_start = GET_NEXT(ss_start)) {
11387  ss = NULL;
11388  if (generic_type == ss_start->system_info->type) {
11389  ss = ss_start;
11390  ss_start = GET_NEXT(ss_start);
11391  break;
11392  }
11393  }
11394 
11395  // reached the end of the subsystem list
11396  if (ss_start == END_OF_LIST(&Ships[shipnum].subsys_list)) {
11397  // If the last subsystem wasn't of interest we don't need to go any further
11398  if (ss == NULL) {
11399  return;
11400  }
11401  do_loop = false;
11402  }
11403  }
11404  else {
11405  do_loop = false;
11406  index = ship_get_subsys_index(shipp, subsystem, 1); // Bypass any error since we supply one here
11407  if ( index == -1 ) {
11408  nprintf(("Warning", "Couldn't find subsystem %s on ship %s for repair subsystem\n", subsystem, shipp->ship_name));
11409  return;
11410  }
11411  // get the pointer to the subsystem. Check it's current hits against it's max hits, and
11412  // set the strength to the given percentage if current strength is < given percentage
11413  ss = ship_get_indexed_subsys( shipp, index );
11414  if (ss == NULL) {
11415  nprintf(("Warning", "Nonexistent subsystem for index %d on ship %s for repair subsystem\n", index, shipp->ship_name));
11416  return;
11417  }
11418  }
11419 
11420  repair_hits = ss->max_hits * ((float)percentage / 100.0f);
11421  ss->current_hits += repair_hits;
11422  if ( ss->current_hits > ss->max_hits )
11423  ss->current_hits = ss->max_hits;
11424 
11425  if ((ss->current_hits > 0) && (do_submodel_repair))
11426  {
11427  ss->submodel_info_1.blown_off = 0;
11428  ss->submodel_info_2.blown_off = 0;
11429  }
11430 
11431  ship_recalc_subsys_strength( shipp );
11432  }
11433 }
11434 
11439 {
11440  char *shipname, *subsystem;
11441  int percentage, shipnum, index, do_submodel_repair, generic_type;
11442  ship *shipp;
11443  ship_subsys *ss = NULL, *ss_start;
11444  bool do_loop = true;
11445 
11446  shipname = CTEXT(n);
11447  subsystem = CTEXT(CDR(n));
11448  percentage = eval_num(CDR(CDR(n)));
11449 
11450  do_submodel_repair = is_sexp_true(CDDDR(n));
11451 
11452  shipnum = ship_name_lookup(shipname);
11453 
11454  // if no ship, then return immediately.
11455  if ( shipnum == -1 )
11456  return;
11457  shipp = &Ships[shipnum];
11458 
11459  if ( percentage > 100 ) {
11460  mprintf(("Percentage for set_subsystem_strength > 100 on ship %s for subsystem '%s'-- setting to 100\n", shipname, subsystem));
11461  percentage = 100;
11462  } else if ( percentage < 0 ) {
11463  mprintf(("Percantage for set_subsystem_strength < 0 on ship %s for subsystem '%s' -- setting to 0\n", shipname, subsystem));
11464  percentage = 0;
11465  }
11466 
11467  // see if we are dealing with the HULL
11468  if ( !stricmp( subsystem, SEXP_HULL_STRING) ) {
11469  float ihs;
11470  object *objp;
11471 
11472  objp = &Objects[shipp->objnum];
11473 
11474  // destroy the ship if percentage is 0
11475  if ( percentage == 0 ) {
11476  ship_self_destruct( objp );
11477  } else {
11478  ihs = shipp->ship_max_hull_strength;
11479  objp->hull_strength = ihs * ((float)percentage / 100.0f);
11480  }
11481 
11482  return;
11483  }
11484 
11485  // see if we are dealing with the Simulated HULL
11486  if ( !stricmp( subsystem, SEXP_SIM_HULL_STRING) ) {
11487  float ihs;
11488  object *objp;
11489 
11490  objp = &Objects[shipp->objnum];
11491  ihs = shipp->ship_max_hull_strength;
11492  objp->sim_hull_strength = ihs * ((float)percentage / 100.0f);
11493 
11494  return;
11495  }
11496 
11497  // now find the given subsystem on the ship.This could be a generic type like <All Engines>
11498  generic_type = get_generic_subsys(subsystem);
11499  ss_start = GET_FIRST(&shipp->subsys_list);
11500 
11501  while (do_loop) {
11502  if (generic_type) {
11503  // loop until we find a subsystem of that type
11504  for ( ; ss_start != END_OF_LIST(&Ships[shipnum].subsys_list); ss_start = GET_NEXT(ss_start)) {
11505  ss = NULL;
11506  if (generic_type == ss_start->system_info->type) {
11507  ss = ss_start;
11508  ss_start = GET_NEXT(ss_start);
11509  break;
11510  }
11511  }
11512 
11513  // reached the end of the subsystem list
11514  if (ss_start == END_OF_LIST(&Ships[shipnum].subsys_list)) {
11515  // If the last subsystem wasn't of interest we don't need to go any further
11516  if (ss == NULL) {
11517  return;
11518  }
11519  do_loop = false;
11520  }
11521  }
11522  else {
11523  do_loop = false;
11524  index = ship_get_subsys_index(shipp, subsystem, 1); // Bypass any error since we supply one here
11525  if ( index == -1 ) {
11526  nprintf(("Warning", "Couldn't find subsystem %s on ship %s for set subsystem strength\n", subsystem, shipp->ship_name));
11527  return;
11528  }
11529 
11530  // get the pointer to the subsystem. Check it's current hits against it's max hits, and
11531  // set the strength to the given percentage
11532  ss = ship_get_indexed_subsys( shipp, index );
11533  if (ss == NULL) {
11534  nprintf(("Warning", "Nonexistent subsystem for index %d on ship %s for set subsystem strength\n", index, shipp->ship_name));
11535  return;
11536  }
11537  }
11538 
11539  // maybe blow up subsys
11540  if (ss->current_hits > 0) {
11541  if (percentage < 1) {
11542  do_subobj_destroyed_stuff(shipp, ss, NULL);
11543  }
11544  }
11545 
11546  // set hit points
11547  ss->current_hits = ss->max_hits * ((float)percentage / 100.0f);
11548 
11549  if ((ss->current_hits > 0) && (do_submodel_repair))
11550  {
11551  ss->submodel_info_1.blown_off = 0;
11552  ss->submodel_info_2.blown_off = 0;
11553  }
11554 
11555  ship_recalc_subsys_strength( shipp );
11556  }
11557 }
11558 
11559 // destroys a subsystem without explosions
11561 {
11562  char *subsystem;
11563  int shipnum, index, generic_type;
11564  ship *shipp;
11565  ship_subsys *ss = NULL;
11566 
11567  // if MULTIPLAYER bail
11568  if (Game_mode & GM_MULTIPLAYER) {
11569  return;
11570  }
11571 
11572  shipnum = ship_name_lookup(CTEXT(n));
11573  // if no ship, then return immediately.
11574  if ( shipnum == -1 ){
11575  return;
11576  }
11577 
11578  shipp = &Ships[shipnum];
11579  n = CDR(n);
11580 
11581  //Process subsystems
11582  while(n != -1)
11583  {
11584  subsystem = CTEXT(n);
11585  if ( !stricmp( subsystem, SEXP_HULL_STRING) || !stricmp( subsystem, SEXP_SIM_HULL_STRING)){
11586  n = CDR(n);
11587  continue;
11588  }
11589  // deal with generic subsystems
11590  generic_type = get_generic_subsys(subsystem);
11591  if (generic_type) {
11592  for (ss = GET_FIRST(&shipp->subsys_list); ss != END_OF_LIST(&shipp->subsys_list); ss = GET_NEXT(ss)) {
11593  if (generic_type == ss->system_info->type) {
11594  // do destruction stuff
11595  ss->current_hits = 0;
11597  do_subobj_destroyed_stuff(shipp, ss, NULL, true);
11598  }
11599  }
11600  }
11601  else
11602  {
11603  // normal subsystems
11604  ss = ship_get_subsys(shipp, subsystem);
11605  index = ship_get_subsys_index(shipp, subsystem, 1);
11606  if ( index == -1 ) {
11607  nprintf(("Warning", "Couldn't find subsystem %s on ship %s for destroy-subsys-instantly\n", subsystem, shipp->ship_name));
11608  n = CDR(n);
11609  continue;
11610  }
11611  if(ss == NULL) {
11612  nprintf(("Warning", "Nonexistent subsystem for index %d on ship %s for destroy-subsys-instantly\n", index, shipp->ship_name));
11613  n = CDR(n);
11614  continue;
11615  }
11616  // do destruction stuff
11617  ss->current_hits = 0;
11619  do_subobj_destroyed_stuff(shipp, ss, NULL, true);
11620  }
11621  // next
11622  n = CDR(n);
11623  }
11624 }
11625 
11631 void sexp_change_goal_validity( int n, int flag )
11632 {
11633  char *name;
11634 
11635  while ( n != -1 ) {
11636  name = CTEXT(n);
11637  if ( flag )
11638  mission_goal_mark_valid( name );
11639  else
11640  mission_goal_mark_invalid( name );
11641 
11642  n = CDR(n);
11643  }
11644 }
11645 
11646 // Goober5000
11647 // yeesh - be careful of the cargo-no-deplete flag :p
11649 {
11650  char *cargo, *ship_name, *subsystem;
11651  int ship_num, cargo_index;
11652 
11653  cargo = CTEXT(n);
11654  ship_name = CTEXT(CDR(n));
11655  if (CDR(CDR(n)) != -1)
11656  subsystem = CTEXT(CDR(CDR(n)));
11657  else
11658  subsystem = NULL;
11659 
11660  cargo_index = -1;
11661 
11662  // find ship
11663  ship_num = ship_name_lookup(ship_name);
11664 
11665  // in-mission?
11666  if (ship_num != -1)
11667  {
11668  if (subsystem)
11669  {
11670  // find the ship subsystem
11671  ship_subsys *ss = ship_get_subsys(&Ships[ship_num], subsystem);
11672  if (ss != NULL)
11673  {
11674  // set cargo
11675  cargo_index = ss->subsys_cargo_name;
11676  }
11677  }
11678  else
11679  {
11680  cargo_index = Ships[ship_num].cargo1;
11681  }
11682  }
11683  else
11684  {
11685  // can't check subsys of ships not in mission
11686  if (subsystem)
11687  {
11688  return SEXP_CANT_EVAL;
11689  }
11690 
11691  // departed?
11692  int exited_index = ship_find_exited_ship_by_name(ship_name);
11693  if (exited_index != -1)
11694  {
11695  cargo_index = Ships_exited[exited_index].cargo1;
11696  }
11697  // not arrived yet
11698  else
11699  {
11700  p_object *p_objp;
11701 
11702  // find cargo for the parse object
11703  p_objp = mission_parse_get_arrival_ship(ship_name);
11704  Assert (p_objp);
11705  cargo_index = (int) p_objp->cargo1;
11706  }
11707  }
11708 
11709  // did we get any cargo
11710  if (cargo_index < 0)
11711  return SEXP_FALSE;
11712 
11713  // check cargo
11714  if (!stricmp(Cargo_names[cargo_index & CARGO_INDEX_MASK], cargo))
11715  return SEXP_TRUE;
11716  else
11717  return SEXP_FALSE;
11718 }
11719 
11720 // Goober5000
11721 // yeesh - be careful of the cargo-no-deplete flag :p
11723 {
11724  char *cargo, *ship_name, *subsystem;
11725  int ship_num, i, cargo_index;
11726 
11727  cargo = CTEXT(n);
11728  ship_name = CTEXT(CDR(n));
11729  if (CDR(CDR(n)) != -1)
11730  subsystem = CTEXT(CDR(CDR(n)));
11731  else
11732  subsystem = NULL;
11733 
11734  // check to see if ship destroyed or departed. In either case, do nothing.
11735  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
11736  return;
11737 
11738  cargo_index = -1;
11739  // find this cargo in the cargo list
11740  for (i = 0; i < Num_cargo; i++)
11741  {
11742  // found it?
11743  if (!stricmp(cargo, Cargo_names[i]))
11744  {
11745  cargo_index = i;
11746  break;
11747  }
11748  }
11749 
11750  // not found
11751  if (cargo_index == -1)
11752  {
11753  // make new entry if possible
11754  if (Num_cargo + 1 >= MAX_CARGO)
11755  {
11756  Warning(LOCATION, "set-cargo: Maximum number of cargo names (%d) reached. Ignoring new name.\n", MAX_CARGO);
11757  return;
11758  }
11759 
11760  Assert(strlen(cargo) <= NAME_LENGTH - 1);
11761 
11762  cargo_index = Num_cargo;
11763  Num_cargo++;
11764 
11765  strcpy(Cargo_names[cargo_index], cargo);
11766  }
11767 
11768  // get the ship
11769  ship_num = ship_name_lookup(ship_name);
11770 
11771  // we can only set subsystems if the ship is in the mission
11772  if (ship_num != -1)
11773  {
11774  if (subsystem)
11775  {
11776  ship_subsys *ss = ship_get_subsys(&Ships[ship_num], subsystem);
11777  if (ss == NULL) {
11778  Assert (!ship_class_unchanged(ship_num));
11779  return;
11780  }
11781 
11782  // set cargo
11783  ss->subsys_cargo_name = cargo_index | (ss->subsys_cargo_name & CARGO_NO_DEPLETE);
11784  }
11785  else
11786  {
11787  // simply set the ship cargo
11788  Ships[ship_num].cargo1 = char(cargo_index | (Ships[ship_num].cargo1 & CARGO_NO_DEPLETE));
11789  }
11790  }
11791  else
11792  {
11793  if (!subsystem)
11794  {
11795  p_object *p_objp;
11796 
11797  // set cargo for the parse object
11798  p_objp = mission_parse_get_arrival_ship(ship_name);
11799  Assert (p_objp);
11800  p_objp->cargo1 = char(cargo_index | (p_objp->cargo1 & CARGO_NO_DEPLETE));
11801  }
11802  }
11803 }
11804 
11809 {
11810  char *shipname1, *shipname2;
11811  int shipnum1, shipnum2, i;
11812 
11813  shipname1 = CTEXT(n);
11814  shipname2 = CTEXT(CDR(n));
11815 
11816  // find the ships -- if neither in the mission, the abort
11817  shipnum1 = ship_name_lookup(shipname1);
11818  shipnum2 = ship_name_lookup(shipname2);
11819  if ( (shipnum1 == -1) || (shipnum2 == -1) )
11820  return;
11821 
11822  // we must be sure that these two objects are indeed docked
11823  if (!dock_check_find_direct_docked_object(&Objects[Ships[shipnum1].objnum], &Objects[Ships[shipnum2].objnum]))
11824  {
11825  return;
11826  }
11827 
11828  if ( !stricmp(Cargo_names[Ships[shipnum1].cargo1 & CARGO_INDEX_MASK], "nothing") ) {
11829  return;
11830  }
11831 
11832  // transfer cargo from ship1 to ship2
11833 #ifndef NDEBUG
11834  // Don't give warning for large ships (cruiser on up)
11835  if (! (Ship_info[Ships[shipnum2].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
11836  if ( stricmp(Cargo_names[Ships[shipnum2].cargo1 & CARGO_INDEX_MASK], "nothing") ) {
11837  Warning(LOCATION, "Transferring cargo to %s which already\nhas cargo %s.\nCargo will be replaced", Ships[shipnum2].ship_name, Cargo_names[Ships[shipnum2].cargo1 & CARGO_INDEX_MASK] );
11838  }
11839  }
11840 #endif
11841  Ships[shipnum2].cargo1 = char((Ships[shipnum1].cargo1 & CARGO_INDEX_MASK) | (Ships[shipnum2].cargo1 & CARGO_NO_DEPLETE));
11842 
11843  if ( !(Ships[shipnum1].cargo1 & CARGO_NO_DEPLETE) ) {
11844  // need to set ship1's cargo to nothing. scan the cargo_names array looking for the string nothing.
11845  // add it if not found
11846  for (i = 0; i < Num_cargo; i++ ) {
11847  if ( !stricmp(Cargo_names[i], "nothing") ) {
11848  Ships[shipnum1].cargo1 = char(i);
11849  return;
11850  }
11851  }
11852  strcpy(Cargo_names[i], "Nothing");
11853  Num_cargo++;
11854  }
11855 }
11856 
11861 {
11862  char *shipname1, *shipname2;
11863  int shipnum1, shipnum2, temp;
11864 
11865  shipname1 = CTEXT(n);
11866  shipname2 = CTEXT(CDR(n));
11867 
11868  // find the ships -- if neither in the mission, abort
11869  shipnum1 = ship_name_lookup(shipname1);
11870  shipnum2 = ship_name_lookup(shipname2);
11871  if ( (shipnum1 == -1) || (shipnum2 == -1) )
11872  return;
11873 
11874  // we must be sure that these two objects are indeed docked
11875  if (!dock_check_find_direct_docked_object(&Objects[Ships[shipnum1].objnum], &Objects[Ships[shipnum2].objnum]))
11876  {
11877  Int3(); // you are trying to transfer cargo between two ships not docked
11878  return;
11879  }
11880 
11881  temp = (Ships[shipnum1].cargo1 & CARGO_INDEX_MASK);
11882  Ships[shipnum1].cargo1 = char(Ships[shipnum2].cargo1 & CARGO_INDEX_MASK);
11883  Ships[shipnum2].cargo1 = char(temp);
11884 }
11885 
11887 {
11888  char *shipname;
11889  int shipnum;
11890  int speed;
11891 
11892  shipname = CTEXT(n);
11893  speed = eval_num(CDR(n));
11894 
11895  shipnum = ship_name_lookup(shipname);
11896 
11897  if (shipnum == -1) {
11898  // trying to set waypoint speed of ship not already in game
11899  return;
11900  }
11901 
11902  // cap speed to range (-1, 32767) to store within int
11903  if (speed < 0) {
11904  speed = -1;
11905  }
11906 
11907  if (speed > 32767) {
11908  speed = 32767;
11909  }
11910 
11911  Ai_info[Ships[shipnum].ai_index].waypoint_speed_cap = speed;
11912 }
11913 
11919 {
11920  char *shipname;
11921  int ship_index;
11922 
11923  // get some data
11924  shipname = CTEXT(n);
11925 
11926  // lookup the ship
11927  ship_index = ship_name_lookup(shipname);
11928  if(ship_index < 0)
11929  return;
11930  object *parent_objp = &Objects[Ships[ship_index].objnum];
11931 
11932  // note: skipping over the unimplemented "jettison delay"
11933  n = CDDR(n);
11934 
11935  // no arguments - jettison all docked objects
11936  if (n == -1)
11937  {
11938  // Goober5000 - as with ai_deathroll_start, we can't simply iterate through the dock list while we're
11939  // undocking things. So just repeatedly jettison the first object.
11940  while (object_is_docked(parent_objp))
11941  {
11942  object_jettison_cargo(parent_objp, dock_get_first_docked_object(parent_objp));
11943  }
11944  }
11945  // arguments - jettison only those objects
11946  else
11947  {
11948  for (; n != -1; n = CDR(n))
11949  {
11950  // make sure ship exists
11951  ship_index = ship_name_lookup(CTEXT(n));
11952  if (ship_index < 0)
11953  continue;
11954 
11955  // make sure we are docked to it
11956  if (!dock_check_find_direct_docked_object(parent_objp, &Objects[Ships[ship_index].objnum]))
11957  continue;
11958 
11959  object_jettison_cargo(parent_objp, &Objects[Ships[ship_index].objnum]);
11960  }
11961  }
11962 }
11963 
11965 {
11966  // get some data
11967  char* docker_ship_name = CTEXT(n);
11968  n = CDR(n);
11969  char* docker_point_name = CTEXT(n);
11970  n = CDR(n);
11971  char* dockee_ship_name = CTEXT(n);
11972  n = CDR(n);
11973  char* dockee_point_name = CTEXT(n);
11974  n = CDR(n);
11975 
11976  // lookup the ships
11977  int docker_ship_index = ship_name_lookup(docker_ship_name);
11978  int dockee_ship_index = ship_name_lookup(dockee_ship_name);
11979  if(docker_ship_index < 0 || dockee_ship_index < 0)
11980  return;
11981 
11982  ship* docker_ship = &Ships[docker_ship_index];
11983  ship* dockee_ship = &Ships[dockee_ship_index];
11984  object* docker_objp = &Objects[docker_ship->objnum];
11985  object* dockee_objp = &Objects[dockee_ship->objnum];
11986 
11987  //Get dockpoints by name
11988  int docker_point_index = model_find_dock_name_index(Ship_info[docker_ship->ship_info_index].model_num, docker_point_name);
11989  int dockee_point_index = model_find_dock_name_index(Ship_info[dockee_ship->ship_info_index].model_num, dockee_point_name);
11990 
11991  Assertion(docker_point_index >= 0, "Docker point '%s' not found on docker ship '%s'", docker_point_name, docker_ship_name);
11992  Assertion(dockee_point_index >= 0, "Dockee point '%s' not found on dockee ship '%s'", dockee_point_name, dockee_ship_name);
11993 
11994  //Make sure that the specified dockpoints are all free (if not, do nothing)
11995  if (dock_find_object_at_dockpoint(docker_objp, docker_point_index) != NULL ||
11996  dock_find_object_at_dockpoint(dockee_objp, dockee_point_index) != NULL)
11997  {
11998  return;
11999  }
12000 
12001  //Set docked
12002  dock_orient_and_approach(docker_objp, docker_point_index, dockee_objp, dockee_point_index, DOA_DOCK_STAY);
12003  ai_do_objects_docked_stuff(docker_objp, docker_point_index, dockee_objp, dockee_point_index, true);
12004 }
12005 
12007 {
12008  char *shipname;
12009  int ship_index, no_deplete = 1;
12010 
12011  // get some data
12012  shipname = CTEXT(n);
12013 
12014  // lookup the ship
12015  ship_index = ship_name_lookup(shipname);
12016  if(ship_index < 0){
12017  return;
12018  }
12019 
12020  if ( !(Ship_info[Ships[ship_index].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
12021  Warning(LOCATION, "Trying to make non BIG or HUGE ship %s with non-depletable cargo.\n", Ships[ship_index].ship_name);
12022  return;
12023  }
12024 
12025  if (CDR(n) != -1) {
12026  no_deplete = eval_num(CDR(n));
12027  Assert((no_deplete == 0) || (no_deplete == 1));
12028  if ( (no_deplete != 0) && (no_deplete != 1) ) {
12029  no_deplete = 1;
12030  }
12031  }
12032 
12033  if (no_deplete) {
12034  Ships[ship_index].cargo1 |= CARGO_NO_DEPLETE;
12035  } else {
12036  Ships[ship_index].cargo1 &= (~CARGO_NO_DEPLETE);
12037  }
12038 
12039 }
12040 
12041 // Goober5000
12043 {
12044  // Shouldn't be gliding now....
12047 
12048  if (Game_mode & GM_MULTIPLAYER) {
12050  }
12051  else {
12052  // forced warp, taken from training failure code
12053  gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START_FORCED ); // Force player to warp out.
12054  }
12055 
12056 }
12057 
12059 {
12060  stars_set_nebula(eval_num(n) > 0);
12061 }
12062 
12063 /* freespace.cpp does not have these availiable externally, and we must call
12064 them so that the main simulation loop does not have to constantly check for
12065 Game_subspace_effect so that it could turn on the subspace sounds.
12066 
12067 Because these are in freespace.cpp there are also stubs of these functions
12068 in fred.cpp as it does not deal with the game loop (obviously) but still
12069 links against code.lib. */
12070 extern void game_start_subspace_ambient_sound();
12071 extern void game_stop_subspace_ambient_sound();
12072 
12074 {
12075  if (eval_num(n) > 0) {
12079  } else {
12083  }
12084 }
12085 
12087 {
12088  int sexp_var;
12089  int new_number;
12090  char number_as_str[TOKEN_LENGTH];
12092 
12093  // filename
12094  strcpy_s(sle.filename, CTEXT(n));
12095  n = CDR(n);
12096 
12097  // sanity checking
12098  if (stars_find_bitmap(sle.filename) < 0)
12099  {
12100  Warning(LOCATION, "sexp-add-background-bitmap: Background bitmap %s not found!", sle.filename);
12101  return;
12102  }
12103 
12104  // angles
12105  sle.ang.p = fl_radians(eval_num(n) % 360);
12106  n = CDR(n);
12107  sle.ang.b = fl_radians(eval_num(n) % 360);
12108  n = CDR(n);
12109  sle.ang.h = fl_radians(eval_num(n) % 360);
12110  n = CDR(n);
12111 
12112  // scale
12113  sle.scale_x = eval_num(n) / 100.0f;
12114  n = CDR(n);
12115  sle.scale_y = eval_num(n) / 100.0f;
12116  n = CDR(n);
12117 
12118  // div
12119  sle.div_x = eval_num(n);
12120  n = CDR(n);
12121  sle.div_y = eval_num(n);
12122  n = CDR(n);
12123 
12124  // restrict parameters
12125  if (sle.scale_x > 18) sle.scale_x = 18;
12126  if (sle.scale_x < 0.1f) sle.scale_x = 0.1f;
12127  if (sle.scale_y > 18) sle.scale_y = 18;
12128  if (sle.scale_y < 0.1f) sle.scale_y = 0.1f;
12129  if (sle.div_x > 5) sle.div_x = 5;
12130  if (sle.div_x < 1) sle.div_x = 1;
12131  if (sle.div_y > 5) sle.div_y = 5;
12132  if (sle.div_y < 1) sle.div_y = 1;
12133 
12134  if (n == -1) {
12135  stars_add_bitmap_entry(&sle);
12136  } else {
12137  Assert((n >= 0) && (n < Num_sexp_nodes));
12138 
12139  // ripped from sexp_modify_variable()
12140  // get sexp_variable index
12141  Assert(Sexp_nodes[n].first == -1);
12142  sexp_var = atoi(Sexp_nodes[n].text);
12143 
12144  // verify variable set
12145  Assert(Sexp_variables[sexp_var].type & SEXP_VARIABLE_SET);
12146 
12147  if (Sexp_variables[sexp_var].type & SEXP_VARIABLE_NUMBER)
12148  {
12149  new_number = stars_add_bitmap_entry(&sle);
12150  if (new_number < 0)
12151  {
12152  Warning(LOCATION, "Unable to add starfield bitmap: '%s'!", sle.filename);
12153  new_number = 0;
12154  }
12155 
12156  sprintf(number_as_str, "%d", new_number);
12157 
12158  // assign to variable
12159  sexp_modify_variable(number_as_str, sexp_var);
12160  }
12161  else
12162  {
12163  Error(LOCATION, "sexp-add-background-bitmap: Variable %s must be a number variable!", Sexp_variables[sexp_var].variable_name);
12164  return;
12165  }
12166  }
12167 }
12168 
12170 {
12171  int slot = eval_num(n);
12172 
12173  if (slot >= 0) {
12174  int instances = stars_get_num_bitmaps();
12175  if ( instances > slot ) {
12176  stars_mark_bitmap_unused( slot );
12177  } else {
12178  Warning(LOCATION, "remove-background-bitmap: slot %d does not exist. Slot must be less than %d.",
12179  slot, instances);
12180  }
12181  }
12182 }
12183 
12185 {
12186  int sexp_var;
12187  int new_number;
12188  char number_as_str[TOKEN_LENGTH];
12190 
12191  // filename
12192  strcpy_s(sle.filename, CTEXT(n));
12193  n = CDR(n);
12194 
12195  // sanity checking
12196  if (stars_find_sun(sle.filename) < 0)
12197  {
12198  Warning(LOCATION, "sexp-add-sun-bitmap: Sun %s not found!", sle.filename);
12199  return;
12200  }
12201 
12202  // angles
12203  sle.ang.p = fl_radians(eval_num(n) % 360);
12204  n = CDR(n);
12205  sle.ang.b = fl_radians(eval_num(n) % 360);
12206  n = CDR(n);
12207  sle.ang.h = fl_radians(eval_num(n) % 360);
12208  n = CDR(n);
12209 
12210  // scale
12211  sle.scale_x = eval_num(n) / 100.0f;
12212  n = CDR(n);
12213  sle.scale_y = sle.scale_x;
12214 
12215  // div
12216  sle.div_x = 1;
12217  sle.div_y = 1;
12218 
12219  // restrict parameters
12220  if (sle.scale_x > 50) sle.scale_x = 50;
12221  if (sle.scale_x < 0.1f) sle.scale_x = 0.1f;
12222  if (sle.scale_y > 50) sle.scale_y = 50;
12223  if (sle.scale_y < 0.1f) sle.scale_y = 0.1f;
12224 
12225  if (n == -1) {
12226  stars_add_sun_entry(&sle);
12227  } else {
12228  Assert((n >= 0) && (n < Num_sexp_nodes));
12229 
12230  // ripped from sexp_modify_variable()
12231  // get sexp_variable index
12232  Assert(Sexp_nodes[n].first == -1);
12233  sexp_var = atoi(Sexp_nodes[n].text);
12234 
12235  // verify variable set
12236  Assert(Sexp_variables[sexp_var].type & SEXP_VARIABLE_SET);
12237 
12238  if (Sexp_variables[sexp_var].type & SEXP_VARIABLE_NUMBER)
12239  {
12240  // get new numerical value
12241  new_number = stars_add_sun_entry(&sle);
12242 
12243  if (new_number < 0)
12244  {
12245  Warning(LOCATION, "Unable to add sun: '%s'!", sle.filename);
12246  new_number = 0;
12247  }
12248 
12249  sprintf(number_as_str, "%d", new_number);
12250 
12251  // assign to variable
12252  sexp_modify_variable(number_as_str, sexp_var);
12253  }
12254  else
12255  {
12256  Error(LOCATION, "sexp-add-sun-bitmap: Variable %s must be a number variable!", Sexp_variables[sexp_var].variable_name);
12257  return;
12258  }
12259  }
12260 }
12261 
12263 {
12264  int slot = eval_num(n);
12265 
12266  if (slot >= 0) {
12267  int instances = stars_get_num_suns();
12268  if ( instances > slot ) {
12269  stars_mark_sun_unused( slot );
12270  } else {
12271  Warning(LOCATION, "remove-sun-bitmap: slot %d does not exist. Slot must be less than %d.",
12272  slot, instances);
12273  }
12274  }
12275 }
12276 
12278 {
12279  if (!(The_mission.flags & MISSION_FLAG_FULLNEB)) return;
12280 
12281  nebl_set_storm(CTEXT(n));
12282 }
12283 
12285 {
12286  char *name = CTEXT(n);
12287  int result = is_sexp_true(CDR(n));
12288  int i;
12289 
12290  if (name == NULL) return;
12291 
12292  for (i = 0; i < MAX_NEB2_POOFS; i++)
12293  {
12294  if (!stricmp(name,Neb2_poof_filenames[i])) break;
12295  }
12296 
12297  //coulnd't find the poof
12298  if (i == MAX_NEB2_POOFS) return;
12299 
12300  if (result) Neb2_poof_flags |= (1 << i);
12301  else Neb2_poof_flags &= ~(1 << i);
12302 
12303  neb2_eye_changed();
12304 }
12305 
12307 {
12308  if (!(The_mission.flags & MISSION_FLAG_FULLNEB)) return;
12309 
12311 
12313 }
12314 
12321 {
12322  int ignore_player_mortality = 1;
12323  int boot_to_main_hall = 0;
12324  int from_debrief_to_main_hall = 0;
12325 
12326  if (n != -1) {
12327  ignore_player_mortality = is_sexp_true(n);
12328  n = CDR(n);
12329  }
12330  if (n != -1) {
12331  boot_to_main_hall = is_sexp_true(n);
12332  n = CDR(n);
12333  }
12334  if (n != -1) {
12335  from_debrief_to_main_hall = is_sexp_true(n);
12336  n = CDR(n);
12337  }
12338 
12339  // if the player is dead we may want to let the death screen handle things
12340  if (!ignore_player_mortality && (Player_ship->flags & SF_DYING)) {
12341  return;
12342  }
12343 
12344  // ending via debrief and then going to mainhall could maybe work with multiplayer?
12345  if (from_debrief_to_main_hall) {
12347  } else {
12349  }
12350 
12351  // if we go straight to the main hall we have to clean up the mission without entering the debriefing
12352  if (boot_to_main_hall && !(Game_mode & GM_MULTIPLAYER)) {
12354  } else {
12356  }
12357 
12358  // Karajorma - callback all the clients here.
12359  if (MULTIPLAYER_MASTER)
12360  {
12363  }
12364 }
12365 
12366 // Goober5000
12368 {
12369  if (is_sexp_true(node))
12371  else
12373 }
12374 
12381 {
12382  int team, time;
12383 
12384  team = iff_lookup(CTEXT(n));
12385  time = eval_num(CDR(n)); // this is the time for how long a good rearm is active -- in seconds
12386 
12387  ai_set_rearm_status(team, time);
12388 }
12389 
12394 {
12395  // short circuit multiplayer for now until we figure out what to do.
12396  if ( Game_mode & GM_MULTIPLAYER )
12397  return;
12398 
12399  // set a bit to tell player should get promoted at the end of the mission. I suppose the other
12400  // thing that we could do would be to set the players score to at least the amount of
12401  // points for the next level, but this way is better I think.
12402  if ( Game_mode & GM_CAMPAIGN_MODE ) {
12404  }
12405 }
12406 
12411 {
12412  int i;
12413  char *medal_name;
12414 
12415  // don't give medals in normal gameplay when not in campaign mode
12416  if ( (Game_mode & GM_NORMAL) && !(Game_mode & GM_CAMPAIGN_MODE) )
12417  return;
12418 
12419  medal_name = CTEXT(n);
12420  if (medal_name == NULL)
12421  return;
12422 
12423  if (Player->stats.m_medal_earned >= 0) {
12424  Warning(LOCATION, "Cannot grant more than one medal per mission! New medal '%s' will replace old medal '%s'!", medal_name, Medals[Player->stats.m_medal_earned].name);
12425  }
12426 
12427  for (i = 0; i < Num_medals; i++ ) {
12428  if ( !stricmp(medal_name, Medals[i].name) )
12429  break;
12430  }
12431 
12432  if ( i < Num_medals ) {
12434 
12435  if ( Game_mode & GM_MULTIPLAYER ) {
12436  for ( int j = 0; j < MAX_PLAYERS; j++ ) {
12437  if ( MULTI_CONNECTED(Net_players[j]) ) {
12439  }
12440  }
12441  }
12442  }
12443 }
12444 
12446 {
12447  int sindex;
12448  int score;
12449  int plr_index;
12450 
12451  score = eval_num(node);
12452  node = CDR(node);
12453 
12454  if(!(Game_mode & GM_MULTIPLAYER)){
12455  if ( (sindex = ship_name_lookup(CTEXT(node))) == -1) {
12456  Warning(LOCATION, "Invalid shipname '%s' passed to sexp_change_player_score!", CTEXT(node));
12457  return;
12458  }
12459 
12460  if (Player_ship != &Ships[sindex]) {
12461  Warning(LOCATION, "Can not award points to '%s'. Ship is not a player!", CTEXT(node));
12462  return;
12463  }
12464  Player->stats.m_score += score;
12465  if (Player->stats.m_score < 0) {
12466  Player->stats.m_score = 0;
12467  }
12468  }
12469  else {
12470  while (node >= 0) {
12471  plr_index = multi_find_player_by_ship_name(CTEXT(node), true);
12472  if (plr_index >= 0) {
12473  Net_player[plr_index].m_player->stats.m_score += score;
12474 
12475  if (Net_player[plr_index].m_player->stats.m_score < 0) {
12476  Net_player[plr_index].m_player->stats.m_score = 0;
12477  }
12478  }
12479 
12480  node = CDR(node);
12481  }
12482  }
12483 }
12484 
12486 {
12487  int i, score, team;
12488 
12489  // since we only have a team score in TvT
12490  if ( !(MULTI_TEAM) ) {
12491  return;
12492  }
12493 
12494  score = eval_num(node);
12495  team = eval_num(CDR(node));
12496 
12497  if (team == 0) {
12498  for (i = 0; i < MAX_TVT_TEAMS; i++) {
12499  Multi_team_score[i] += score;
12500  }
12501  }
12502  else if (team > 0 && team <= MAX_TVT_TEAMS) {
12503  Multi_team_score[team - 1] += score;
12504  }
12505  else {
12506  Warning(LOCATION, "Invalid team number. Team %d does not exist", team);
12507  }
12508 }
12509 
12510 
12511 
12512 void sexp_tech_add_ship(int node)
12513 {
12514  int i;
12515  char *name;
12516 
12517  Assert(node >= 0);
12518  // this function doesn't mean anything when not in campaign mode
12519  if ( !(Game_mode & GM_CAMPAIGN_MODE) )
12520  return;
12521 
12522  while (node >= 0) {
12523  name = CTEXT(node);
12524  i = ship_info_lookup(name);
12525  if (i >= 0)
12526  Ship_info[i].flags |= SIF_IN_TECH_DATABASE;
12527  else
12528  Warning(LOCATION, "In tech-add-ship, ship class \"%s\" invalid", name);
12529 
12530  node = CDR(node);
12531  }
12532 }
12533 
12534 void sexp_tech_add_weapon(int node)
12535 {
12536  int i;
12537  char *name;
12538 
12539  Assert(node >= 0);
12540  // this function doesn't mean anything when not in campaign mode
12541  if ( !(Game_mode & GM_CAMPAIGN_MODE) )
12542  return;
12543 
12544  while (node >= 0) {
12545  name = CTEXT(node);
12546  i = weapon_info_lookup(name);
12547  if (i >= 0)
12549  else
12550  Warning(LOCATION, "In tech-add-weapon, weapon class \"%s\" invalid", name);
12551 
12552  node = CDR(node);
12553  }
12554 }
12555 
12556 // Goober5000
12557 void sexp_tech_add_intel(int node)
12558 {
12559  int i;
12560  char *name;
12561 
12562  Assert(node >= 0);
12563  // this function doesn't mean anything when not in campaign mode
12564  if ( !(Game_mode & GM_CAMPAIGN_MODE) )
12565  return;
12566 
12567  while (node >= 0) {
12568  name = CTEXT(node);
12569  i = intel_info_lookup(name);
12570  if (i >= 0)
12572  else
12573  Warning(LOCATION, "In tech-add-intel, intel name \"%s\" invalid", name);
12574 
12575  node = CDR(node);
12576  }
12577 }
12578 
12579 
12580 // Goober5000
12582 {
12583  int i, id, n = node;
12584  char *name;
12585 
12586  Assert(n >= 0);
12587  // this function doesn't mean anything when not in campaign mode
12588  if ( !(Game_mode & GM_CAMPAIGN_MODE) )
12589  return;
12590 
12591  while (n >= 0)
12592  {
12593  // don't use things like CTEXT or eval_num, since we didn't in the preloader
12594  name = Sexp_nodes[n].text;
12595  n = CDR(n);
12596  if (n < 0)
12597  break;
12598  id = atoi(Sexp_nodes[n].text);
12599  n = CDR(n);
12600 
12601  // we already translated this node in the preloader, so just look it up
12602  i = intel_info_lookup(name);
12603  if (i >= 0)
12605  else
12606  Warning(LOCATION, "Intel entry XSTR(\"%s\", %d) invalid", name, id);
12607  }
12608 }
12609 
12610 // Goober5000 - reset all the tech entries to their default states
12612 {
12613  // this function doesn't mean anything when not in campaign mode
12614  if ( !(Game_mode & GM_CAMPAIGN_MODE) )
12615  return;
12616 
12618 }
12619 
12625 {
12626  int sindex;
12627  char *name;
12628 
12629  // this function doesn't mean anything when not in campaign mode
12630  if ( !(Game_mode & GM_CAMPAIGN_MODE) )
12631  return;
12632 
12633  // get the name of the ship and lookup up the ship_info index for it
12634  name = CTEXT(n);
12635  sindex = ship_info_lookup( name );
12636  if ( sindex == -1 )
12637  return;
12638 
12639  // now we have a valid index --
12641 }
12642 
12644 {
12645  int sindex;
12646  char *name;
12647 
12648  // this function doesn't mean anything when not in campaign mode
12649  if ( !(Game_mode & GM_CAMPAIGN_MODE) )
12650  return;
12651 
12652  // get the name of the weapon and lookup up the weapon_info index for it
12653  name = CTEXT(n);
12654  sindex = weapon_info_lookup( name );
12655  if ( sindex == -1 )
12656  return;
12657 
12658  // now we have a valid index --
12660 }
12661 
12667 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)
12668 {
12669  char *ship_name;
12670  int ship_index;
12671  int n = node;
12672 
12673  if (send_multiplayer && MULTIPLAYER_MASTER) {
12675  multi_send_int(object_flag);
12676  /* Uncommenting this will break compatibility with earlier builds but it is pointless to send it until object_flag2
12677  is actually used by the engine
12678  */
12679  // multi_send_int(object_flag2);
12680  multi_send_int(ship_flag);
12681  multi_send_int(ship_flag2);
12682  multi_send_int(p_object_flag);
12683  multi_send_int(p_object_flag2);
12684  multi_send_bool(set_it);
12685  }
12686 
12687  // loop for all ships in the sexp
12688  // NB: if the flag is set, we will continue acting on nodes until we run out of them;
12689  // if not, we will only act on the first one
12690  for (; n >= 0; process_subsequent_nodes ? n = CDR(n) : n = -1)
12691  {
12692  // get ship name
12693  ship_name = CTEXT(n);
12694 
12695  // check to see if ship destroyed or departed. In either case, do nothing.
12696  if (mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL))
12697  continue;
12698 
12699  // see if ship exists in-mission
12700  ship_index = ship_name_lookup(ship_name, include_players_in_ship_lookup ? 1 : 0);
12701 
12702  // if ship is in-mission
12703  if (ship_index >= 0)
12704  {
12705  // save flags for state change comparisons
12706  int object_flag_orig = Objects[Ships[ship_index].objnum].flags;
12707 
12708  // see if we have an object flag to set
12709  if (object_flag)
12710  {
12711  // set or clear?
12712  if (set_it)
12713  Objects[Ships[ship_index].objnum].flags |= object_flag;
12714  else
12715  Objects[Ships[ship_index].objnum].flags &= ~object_flag;
12716  }
12717 
12718  // handle ETS when modifying shields
12719  if (object_flag == OF_NO_SHIELDS) {
12720  if (set_it) {
12721  zero_one_ets(&Ships[ship_index].shield_recharge_index, &Ships[ship_index].weapon_recharge_index, &Ships[ship_index].engine_recharge_index);
12722  } else if (object_flag_orig & OF_NO_SHIELDS) {
12723  set_default_recharge_rates(&Objects[Ships[ship_index].objnum]);
12724  }
12725  }
12726 
12727  // see if we have an object flag2 to set
12728  if (object_flag2)
12729  {
12730 /*
12731  // set or clear?
12732  if (set_it)
12733  Objects[Ships[ship_index].objnum].flags2 |= object_flag2;
12734  else
12735  Objects[Ships[ship_index].objnum].flags2 &= ~object_flag2;
12736 */
12737  }
12738 
12739  // see if we have a ship flag to set
12740  if (ship_flag)
12741  {
12742  // set or clear?
12743  if (set_it)
12744  Ships[ship_index].flags |= ship_flag;
12745  else
12746  Ships[ship_index].flags &= ~ship_flag;
12747  }
12748 
12749  // see if we have a ship flag2 to set
12750  if (ship_flag2)
12751  {
12752  // set or clear?
12753  if (set_it)
12754  Ships[ship_index].flags2 |= ship_flag2;
12755  else
12756  Ships[ship_index].flags2 &= ~ship_flag2;
12757  }
12758 
12759  // the lock afterburner SEXP also needs to set a physics flag
12760  if (ship_flag2 == SF2_AFTERBURNER_LOCKED) {
12761  if (set_it) {
12762  afterburners_stop(&Objects[Ships[ship_index].objnum], 1);
12763  }
12764  }
12765 
12766  if (send_multiplayer && MULTIPLAYER_MASTER) {
12767  multi_send_bool(true);
12768  multi_send_ship(ship_index);
12769  }
12770  }
12771  // if it's not in-mission
12772  else
12773  {
12774  // grab it from the arrival list
12775  p_object *p_objp = mission_parse_get_arrival_ship(ship_name);
12776 
12777  // ships that have had ship-vanish used on them should be skipped
12778  if (!p_objp) {
12779  continue;
12780  }
12781 
12782  // see if we have a p_object flag to set
12783  if (p_object_flag)
12784  {
12785  // set or clear?
12786  if (set_it)
12787  p_objp->flags |= p_object_flag;
12788  else
12789  p_objp->flags &= ~p_object_flag;
12790  }
12791 
12792  // see if we have a p_object flag2 to set
12793  if (p_object_flag2)
12794  {
12795  // set or clear?
12796  if (set_it)
12797  p_objp->flags2 |= p_object_flag2;
12798  else
12799  p_objp->flags2 &= ~p_object_flag2;
12800  }
12801 
12802  if (send_multiplayer && MULTIPLAYER_MASTER) {
12803  multi_send_bool(false);
12804  multi_send_parse_object(p_objp);
12805  }
12806  }
12807  }
12808 
12809  if (send_multiplayer && MULTIPLAYER_MASTER) {
12811  }
12812 }
12813 
12815 {
12816  int object_flag = 0;
12817  // int object_flag2 = 0;
12818  int ship_flag = 0;
12819  int ship_flag2 = 0;
12820  int p_object_flag = 0;
12821  int p_object_flag2 = 0;
12822  bool set_it = false;
12823  bool ship_arrived = true;
12824  ship *shipp = NULL;
12825  p_object *pobjp = NULL;
12826 
12827  multi_get_int(object_flag);
12828  // multi_get_int(object_flag2);
12829  multi_get_int(ship_flag);
12830  multi_get_int(ship_flag2);
12831  multi_get_int(p_object_flag);
12832  multi_get_int(p_object_flag2);
12833  multi_get_bool(set_it);
12834 
12835  // if any of the above failed so will this loop
12836  while (multi_get_bool(ship_arrived))
12837  {
12838 
12839  if (ship_arrived) {
12840  multi_get_ship(shipp);
12841  if (shipp == NULL) {
12842  WarningEx(LOCATION, "Null ship pointer in multi_sexp_deal_with_ship_flag(), tell a coder.\n");
12843  return;
12844  }
12845 
12846  // save flags for state change comparisons
12847  int object_flag_orig = Objects[shipp->objnum].flags;
12848 
12849  if (set_it) {
12850  Objects[shipp->objnum].flags |= object_flag;
12851  // Objects[shipp->objnum].flags2 |= object_flag2;
12852  shipp->flags |= ship_flag;
12853  shipp->flags2 |= ship_flag2;
12854  }
12855  else {
12856  Objects[shipp->objnum].flags &= ~object_flag;
12857  // Objects[shipp->objnum].flags2 &= ~object_flag2;
12858  shipp->flags &= ~ship_flag;
12859  shipp->flags2 &= ~ship_flag2;
12860  }
12861 
12862  // deal with side effects of these flags
12863  if (object_flag == OF_NO_SHIELDS) {
12864  if (set_it) {
12866  } else if (object_flag_orig & OF_NO_SHIELDS) {
12868  }
12869  }
12870 
12871  if (ship_flag2 == SF2_AFTERBURNER_LOCKED) {
12872  if (set_it) {
12873  afterburners_stop(&Objects[shipp->objnum], 1);
12874  }
12875  }
12876 
12877  if ((ship_flag2 == SF2_STEALTH) && !set_it) {
12878  if (shipp->flags & SF_ESCORT) {
12879  hud_add_ship_to_escort(shipp->objnum, 1);
12880  }
12881  }
12882  if ((ship_flag2 == SF2_FRIENDLY_STEALTH_INVIS) && !set_it && (shipp->flags2 & SF2_STEALTH) && (shipp->team == Player_ship->team)) {
12883  if (shipp->flags & SF_ESCORT) {
12884  hud_add_ship_to_escort(shipp->objnum, 1);
12885  }
12886  }
12887  if (ship_flag == SF_HIDDEN_FROM_SENSORS) {
12888  if (set_it) {
12889  if (Player_ai->target_objnum == shipp->objnum) {
12891  }
12892  }
12893  else {
12894  if (shipp->flags & SF_ESCORT) {
12895  hud_add_ship_to_escort(shipp->objnum, 1);
12896  }
12897  }
12898  }
12899  }
12900  else {
12901  multi_get_parse_object(pobjp);
12902  if (pobjp != NULL) {
12903  if (set_it) {
12904  pobjp->flags |= p_object_flag;
12905  pobjp->flags2 |= p_object_flag2;
12906  }
12907  else {
12908  pobjp->flags &= ~p_object_flag;
12909  pobjp->flags2 &= ~p_object_flag2;
12910  }
12911  }
12912  }
12913  }
12914 }
12915 
12921 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, int ai_flag, int ai_flag2, bool set_flag)
12922 {
12923  int i, object_flag_orig;
12924  ship_obj *so;
12926  p_object *p_objp;
12927 
12928  switch (oswpt.type)
12929  {
12930  case OSWPT_TYPE_NONE:
12931  case OSWPT_TYPE_EXITED:
12932  return;
12933 
12934  case OSWPT_TYPE_WHOLE_TEAM:
12935  Assert (oswpt.team >= 0);
12936  oswpt2.clear();
12937  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ){
12938  if (Ships[Objects[so->objnum].instance].team == oswpt.team) {
12939  object_ship_wing_point_team_set_ship(&oswpt2, so, future_ships);
12940 
12941  // recurse
12942  sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
12943  }
12944  }
12945 
12946  if (future_ships) {
12947  for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp)) {
12948  if (p_objp->team == oswpt.team) {
12949  oswpt2.p_objp = p_objp;
12950  oswpt2.type = OSWPT_TYPE_PARSE_OBJECT;
12951  sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
12952  }
12953  }
12954  }
12955  break;
12956 
12957  case OSWPT_TYPE_WING:
12959  // if the wing isn't here, and we're only dealing with ships which are, we're done.
12960  if (!future_ships){
12961  if (oswpt.type == OSWPT_TYPE_WING_NOT_PRESENT) {
12962  return;
12963  }
12964  }
12965  else {
12966  for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp)) {
12967  if (p_objp->wingnum == WING_INDEX(oswpt.wingp)) {
12968  oswpt2.p_objp = p_objp;
12969  oswpt2.type = OSWPT_TYPE_PARSE_OBJECT;
12970  sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
12971  }
12972  }
12973  }
12974 
12975  for (i = 0; i < oswpt.wingp->current_count; i++) {
12976  object_ship_wing_point_team_set_ship(&oswpt2, &Ships[oswpt.wingp->ship_index[i]], future_ships);
12977  sexp_alter_ship_flag_helper(oswpt2, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
12978  }
12979 
12980  break;
12981 
12982  // finally! If we actually have a ship, we can set its flags!
12983  case OSWPT_TYPE_SHIP:
12984  // save flags for state change comparisons
12985  object_flag_orig = oswpt.objp->flags;
12986 
12987  // see if we have an object flag to set
12988  if (object_flag)
12989  {
12990  // set or clear?
12991  if (set_flag)
12992  obj_set_flags(oswpt.objp, oswpt.objp->flags | object_flag);
12993  else
12994  obj_set_flags(oswpt.objp, oswpt.objp->flags & ~object_flag);
12995  }
12996 
12997  // handle ETS when modifying shields
12998  if (object_flag == OF_NO_SHIELDS) {
12999  if (set_flag) {
13001  } else if (object_flag_orig & OF_NO_SHIELDS) {
13003  }
13004  }
13005 
13006  // see if we have an object flag2 to set
13007  if (object_flag2)
13008  {
13009  // Add code here when have flag2 settings
13010  }
13011 
13012  // see if we have a ship flag to set
13013  if (ship_flag)
13014  {
13015  // set or clear?
13016  if (set_flag)
13017  oswpt.shipp->flags |= ship_flag;
13018  else
13019  oswpt.shipp->flags &= ~ship_flag;
13020  }
13021 
13022  // see if we have a ship flag2 to set
13023  if (ship_flag2)
13024  {
13025  // set or clear?
13026  if (set_flag)
13027  oswpt.shipp->flags2 |= ship_flag2;
13028  else
13029  oswpt.shipp->flags2 &= ~ship_flag2;
13030  }
13031 
13032  // the lock afterburner SEXP also needs to set a physics flag
13033  if (ship_flag2 == SF2_AFTERBURNER_LOCKED) {
13034  if (set_flag) {
13035  afterburners_stop(oswpt.objp, 1);
13036  }
13037  }
13038 
13039  // see if we have an ai flag to set
13040  if (ai_flag)
13041  {
13042  // set or clear?
13043  if (set_flag)
13044  Ai_info[oswpt.shipp->ai_index].ai_flags |= ai_flag;
13045  else
13046  Ai_info[oswpt.shipp->ai_index].ai_flags &= ~ai_flag;
13047  }
13048 
13049  // see if we have an object flag2 to set
13050  if (ai_flag2)
13051  {
13052  // Add code here when have flag2 settings
13053  }
13054 
13055  // no break statement. We want to fall through.
13056 
13058  if (!future_ships) {
13059  return;
13060  }
13061 
13062  // see if we have a p_object flag to set
13063  if (parse_obj_flag && oswpt.p_objp != NULL)
13064  {
13065  // set or clear?
13066  if (set_flag)
13067  oswpt.p_objp->flags |= parse_obj_flag;
13068  else
13069  oswpt.p_objp->flags &= ~parse_obj_flag;
13070  }
13071 
13072  // see if we have a p_object flag2 to set
13073  if (parse_obj_flag2 && oswpt.p_objp != NULL)
13074  {
13075  // set or clear?
13076  if (set_flag)
13077  oswpt.p_objp->flags2 |= parse_obj_flag2;
13078  else
13079  oswpt.p_objp->flags2 &= ~parse_obj_flag2;
13080  }
13081  break;
13082 
13083 
13084  }
13085 
13086 }
13087 
13088 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, int ai_flag, int ai_flag2, bool set_flag)
13089 {
13090  ship_obj *so;
13091  p_object *p_objp;
13093 
13094  // set all the ships present in the mission
13095  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
13096  object_ship_wing_point_team_set_ship(&oswpt, so, future_ships);
13097 
13098  sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
13099  }
13100 
13101  // set up all the ships which have yet to arrive
13102  if (future_ships) {
13103  oswpt.clear();
13104  for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
13105  {
13106  oswpt.p_objp = p_objp;
13107  oswpt.type = OSWPT_TYPE_PARSE_OBJECT;
13108  sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
13109  }
13110  }
13111 }
13112 
13113 bool sexp_check_flag_arrays(char *flag_name, int &object_flag, int &object_flag2, int &ship_flags, int &ship_flags2, int &parse_obj_flag, int &parse_obj_flag2, int &ai_flag, int &ai_flag2)
13114 {
13115  int i;
13116  bool send_multi = false;
13117 
13118  for ( i = 0; i < MAX_OBJECT_FLAG_NAMES; i++) {
13119  if (!stricmp(Object_flag_names[i].flag_name, flag_name)) {
13120  // make sure the list writes to the correct list of flags!
13121  if (Object_flag_names[i].flag_list == 1) {
13122  object_flag = Object_flag_names[i].flag;
13123  }
13124  else if (Object_flag_names[i].flag_list == 2) {
13125  object_flag2 = Object_flag_names[i].flag;
13126  }
13127  break;
13128  }
13129  }
13130 
13131  for ( i = 0; i < MAX_SHIP_FLAG_NAMES; i++) {
13132  if (!stricmp(Ship_flag_names[i].flag_name, flag_name)) {
13133  // make sure the list writes to the correct list of flags!
13134  if (Ship_flag_names[i].flag_list == 1) {
13135  ship_flags = Ship_flag_names[i].flag;
13136  }
13137  else if (Ship_flag_names[i].flag_list == 2) {
13138  ship_flags2 = Ship_flag_names[i].flag;
13139  // only ship flags2 and above need to be sent the game handles the first set of flags elsewhere
13140  send_multi = true;
13141  }
13142  break;
13143  }
13144  }
13145 
13146  // parse files already have a list of names in the same order as the flags, so we can do something slightly different here.
13147  for ( i = 0; i < MAX_PARSE_OBJECT_FLAGS; i++) {
13148  if (!stricmp(Parse_object_flags[i], flag_name)) {
13149  parse_obj_flag = (1 << i);
13150  break;
13151  }
13152  }
13153 
13154  for ( i = 0; i < MAX_PARSE_OBJECT_FLAGS_2; i++) {
13155  if (!stricmp(Parse_object_flags_2[i], flag_name)) {
13156  parse_obj_flag2 = (1 << i);
13157  break;
13158  }
13159  }
13160 
13161  for ( i = 0; i < MAX_AI_FLAG_NAMES; i++) {
13162  if (!stricmp(Ai_flag_names[i].flag_name, flag_name)) {
13163  // make sure the list writes to the correct list of flags!
13164  if (Ai_flag_names[i].flag_list == 1) {
13165  ai_flag = Ai_flag_names[i].flag;
13166  }
13167  else if (Ai_flag_names[i].flag_list == 2) {
13168  ai_flag2 = Ai_flag_names[i].flag;
13169  }
13170  break;
13171  }
13172  }
13173 
13174  return send_multi;
13175 }
13176 
13178 {
13179  char *flag_name;
13180  ship *shipp;
13181  int object_flag = 0;
13182  int object_flag2 = 0;
13183  int ship_flags = 0;
13184  int ship_flags2 = 0;
13185  int parse_obj_flag = 0;
13186  int parse_obj_flag2 = 0;
13187  int ai_flag = 0;
13188  int ai_flag2 = 0;
13189 
13190  shipp = sexp_get_ship_from_node(node);
13191 
13192  // return false if the ship doesn't exist
13193  if (shipp == NULL) {
13194  return 0;
13195  }
13196 
13197  node = CDR(node);
13198 
13199  while (node != -1) {
13200  flag_name = CTEXT(node);
13201  sexp_check_flag_arrays(flag_name, object_flag, object_flag2, ship_flags, ship_flags2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2);
13202 
13203  // now check the flags
13204  if (object_flag) {
13205  if (!(Objects[shipp->objnum].flags & object_flag))
13206  return 0;
13207  }
13208  // if we ever get object flags 2 - they go here.
13209 
13210  if (ship_flags) {
13211  if (!(shipp->flags & ship_flags))
13212  return 0;
13213  }
13214  if (ship_flags2) {
13215  if (!(shipp->flags2 & ship_flags2))
13216  return 0;
13217  }
13218 
13219  // we don't check parse flags
13220 
13221  if (ai_flag) {
13222  if (!(Ai_info[shipp->ai_index].ai_flags & ai_flag))
13223  return 0;
13224  }
13225 
13226  // no ai flags 2 yet. When we do, they go here.
13227  node = CDR(node);
13228  }
13229 
13230  // if we're still here, all the flags we were looking for were present
13231  return 1;
13232 }
13233 
13234 void sexp_alter_ship_flag(int node)
13235 {
13236  char *flag_name;
13237  int object_flag = 0;
13238  int object_flag2 = 0;
13239  int ship_flags = 0;
13240  int ship_flags2 = 0;
13241  int parse_obj_flag = 0;
13242  int parse_obj_flag2 = 0;
13243  int ai_flag = 0;
13244  int ai_flag2 = 0;
13245  bool set_flag = false;
13246  bool future_ships = false;
13248 
13249  flag_name = CTEXT(node);
13250 
13251  sexp_check_flag_arrays(flag_name, object_flag, object_flag2, ship_flags, ship_flags2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2);
13252 
13253  node = CDR(node);
13254  if (is_sexp_true(node)) {
13255  set_flag = true;
13256  }
13257 
13258  node = CDR(node);
13259  if (is_sexp_true(node)) {
13260  future_ships = true;
13261  }
13262 
13263 
13264  // start the multiplayer packet
13266  multi_send_int(object_flag);
13267  /* Uncommenting this will break compatibility with earlier builds but it is pointless to send it until object_flag2
13268  is actually used by the engine
13269  */
13270  // multi_send_int(object_flag2);
13271  multi_send_int(ship_flags);
13272  multi_send_int(ship_flags2);
13273  multi_send_int(parse_obj_flag);
13274  multi_send_int(parse_obj_flag2);
13275  multi_send_int(ai_flag);
13276  /* Uncommenting this will break compatibility with earlier builds but it is pointless to send it until ai_flag2
13277  is actually used by the engine
13278  */
13279  // multi_send_int(ai_flag2);
13280  multi_send_bool(set_flag);
13281  multi_send_bool(future_ships);
13282 
13283  node = CDR(node);
13284 
13285  // no 4th argument means do this to every ship in the mission (and if the flag is set, every ship that will be too).
13286  if (node == -1) {
13287  // send a message to the clients saying there were no more arguments
13288  multi_send_bool(false);
13289 
13290  alter_flag_for_all_ships(future_ships, object_flag, object_flag2, ship_flags, ship_flags2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
13291  }
13292 
13293 
13294  else {
13295  // send a message to the clients saying there are more arguments
13296  multi_send_bool(true);
13297 
13298  while (node != -1) {
13299  sexp_get_object_ship_wing_point_team(&oswpt, CTEXT(node), future_ships);
13300 
13301  // no point in setting these flags at all
13302  if (oswpt.type == OSWPT_TYPE_NONE || oswpt.type == OSWPT_TYPE_EXITED ) {
13303  node = CDR(node);
13304  continue;
13305  }
13306 
13307  sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flags, ship_flags2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
13308  node = CDR(node);
13309 
13310  multi_send_int(oswpt.type);
13311 
13312  switch (oswpt.type) {
13313  case OSWPT_TYPE_SHIP:
13314  multi_send_ship(oswpt.shipp);
13315  break;
13316 
13319  break;
13320 
13322  case OSWPT_TYPE_WING:
13324  break;
13325 
13326  case OSWPT_TYPE_WHOLE_TEAM:
13327  multi_send_int(oswpt.team);
13328  break;
13329  }
13330  }
13331  }
13333 }
13334 
13335 
13336 
13338 {
13339  int i;
13340  int object_flag = 0;
13341  int object_flag2 = 0;
13342  int ship_flag = 0;
13343  int ship_flag2 = 0;
13344  int parse_obj_flag = 0;
13345  int parse_obj_flag2 = 0;
13346  bool set_flag = false;
13347  bool future_ships = true;
13348  bool process_data = false;
13349  int ai_flag = 0;
13350  int ai_flag2 = 0;
13351  int type = -1;
13353  ushort wing_sig;
13354 
13355  multi_get_int(object_flag);
13356  // multi_get_int(object_flag2);
13357  multi_get_int(ship_flag);
13358  multi_get_int(ship_flag2);
13359  multi_get_int(parse_obj_flag);
13360  multi_get_int(parse_obj_flag2);
13361  multi_get_int(ai_flag);
13362  multi_get_bool(set_flag);
13363  multi_get_bool(future_ships);
13364 
13365  // if any of the above failed so will this loop
13366  if (!multi_get_bool(process_data))
13367  {
13368  return;
13369  }
13370 
13371  // no more data means do this to every ship in the mission
13372  if (!process_data) {
13373  alter_flag_for_all_ships(future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
13374  }
13375  else {
13376  while (multi_get_int(type)) {
13377  oswpt.clear();
13378  oswpt.type = type;
13379 
13380  switch (oswpt.type) {
13381  case OSWPT_TYPE_SHIP:
13382  if (multi_get_ship(oswpt.shipp)) {
13383  oswpt.objp = &Objects[oswpt.shipp->objnum];
13384  } else {
13385  Warning(LOCATION, "OSWPT had an invalid ship in multi_sexp_alter_ship_flag(), skipping");
13386  continue;
13387  }
13388  break;
13389 
13392  break;
13393 
13395  case OSWPT_TYPE_WING:
13396  multi_get_ushort(wing_sig);
13397  for (i = 0; i < Num_wings; i++) {
13398  if (Wings[i].net_signature == wing_sig) {
13399  oswpt.wingp = &Wings[i];
13400 
13401  // wing leader handling taken from sexp_get_object_ship_wing_point_team
13402  if ((oswpt.wingp->special_ship >= 0) && (oswpt.wingp->ship_index[oswpt.wingp->special_ship] >= 0)) {
13403  oswpt.shipp = &Ships[oswpt.wingp->ship_index[oswpt.wingp->special_ship]];
13404  oswpt.objp = &Objects[oswpt.shipp->objnum];
13405  } else {
13406  oswpt.shipp = &Ships[oswpt.wingp->ship_index[0]];
13407  oswpt.objp = &Objects[oswpt.shipp->objnum];
13408  Warning(LOCATION, "Substituting ship '%s' at index 0 for nonexistent wing leader at index %d!", oswpt.shipp->ship_name, oswpt.wingp->special_ship);
13409  }
13410  break;
13411  }
13412  }
13413 
13414  if (oswpt.wingp == NULL) {
13415  Warning(LOCATION, "Unable to get wing to apply flags to in multi_sexp_alter_ship_flag()");
13416  }
13417  break;
13418 
13419  case OSWPT_TYPE_WHOLE_TEAM:
13420  multi_get_int(oswpt.team);
13421  break;
13422  }
13423  sexp_alter_ship_flag_helper(oswpt, future_ships, object_flag, object_flag2, ship_flag, ship_flag2, parse_obj_flag, parse_obj_flag2, ai_flag, ai_flag2, set_flag);
13424  }
13425  }
13426 }
13427 
13428 
13429 // modified by Goober5000; now it should work properly
13430 // function to deal with breaking/fixing the warp engines on ships/wings.
13431 // --repairable is true when we are breaking the warp drive (can be repaired)
13432 // --damage_it is true when we are sabotaging it, one way or the other; false when fixing it
13433 void sexp_deal_with_warp( int n, bool repairable, bool damage_it )
13434 {
13435  int ship_flag, p_object_flag;
13436 
13437  if (repairable)
13438  {
13439  ship_flag = SF_WARP_BROKEN;
13440  p_object_flag = P_SF_WARP_BROKEN;
13441  }
13442  else
13443  {
13444  ship_flag = SF_WARP_NEVER;
13445  p_object_flag = P_SF_WARP_NEVER;
13446  }
13447 
13448  sexp_deal_with_ship_flag(n, true, 0, 0, ship_flag, 0, p_object_flag, 0, damage_it);
13449 }
13450 
13451 // Goober5000
13453 {
13454  bool set_flag = !is_sexp_true(node);
13455 
13456  sexp_deal_with_ship_flag(CDR(node), true, 0, 0, 0, SF2_NO_SUBSPACE_DRIVE, 0, 0, set_flag);
13457 }
13458 
13463 {
13464  char *team_name, *weapon_name, *ship_name;
13465  int num_weapons, weapon_index, team;
13466 
13467  team_name = CTEXT(n);
13468  num_weapons = eval_num(CDR(n));
13469  weapon_name = CTEXT(CDR(CDR(n)));
13470  ship_name = CTEXT(CDR(CDR(CDR(n))));
13471 
13472  weapon_index = weapon_info_lookup(weapon_name);
13473  if ( weapon_index == -1 ) {
13474  nprintf(("Warning", "couldn't find weapon %s for good-secondary-time\n", weapon_name));
13475  return;
13476  }
13477 
13478  // get the team type from the team_name
13479  team = iff_lookup(team_name);
13480 
13481  // see if the ship has departed or has been destroyed. If so, then we don't need to set up the
13482  // AI stuff
13483  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
13484  return;
13485 
13486  ai_good_secondary_time( team, weapon_index, num_weapons, ship_name );
13487 }
13488 
13489 // Karajorma - Turns the built in messages for pilots and command on or off
13490 void sexp_toggle_builtin_messages (int node, bool enable_messages)
13491 {
13492  char *ship_name;
13493  int wingnum, shipnum, ship_index;
13494 
13495  // If no arguments were supplied then turn off all messages then bail
13496  if (node < 0)
13497  {
13498  if (enable_messages)
13499  {
13501  return;
13502  }
13503  else
13504  {
13506  return;
13507  }
13508  }
13509 
13510  // iterate through all the nodes supplied
13511  while (node >= 0)
13512  {
13513  ship_name = CTEXT(node);
13514 
13515  // check that this isn't a request to silence command.
13516  if ((*ship_name == '#') && !stricmp(&ship_name[1], The_mission.command_sender))
13517  {
13518  // Either disable or enable messages from command
13519  if (enable_messages)
13520  {
13522  }
13523  else
13524  {
13526  }
13527  }
13528  else if (!stricmp(ship_name, "<Any Wingman>"))
13529  {
13530  // Since trying to determine whose wingman in a stand alone multiplayer game opens a can of worms
13531  // Any Wingman silences all ships in wings regardless of whose side they're on.
13532  for (wingnum = 0; wingnum < Num_wings; wingnum++ ) {
13533  for ( shipnum = 0; shipnum < Wings[wingnum].current_count; shipnum++ ) {
13534  ship_index = Wings[wingnum].ship_index[shipnum];
13535  Assert( ship_index != -1 );
13536 
13537  if (enable_messages) {
13538  Ships[ship_index].flags2 &= ~SF2_NO_BUILTIN_MESSAGES;
13539  }
13540  else {
13541  Ships[ship_index].flags2 |= SF2_NO_BUILTIN_MESSAGES;
13542  }
13543  }
13544  }
13545  }
13546  // If it isn't command then assume that we're dealing with a ship
13547  else
13548  {
13549  sexp_deal_with_ship_flag(node, false, 0, 0, 0, SF2_NO_BUILTIN_MESSAGES, 0, P2_SF2_NO_BUILTIN_MESSAGES, !enable_messages);
13550  }
13551 
13552  node = CDR(node);
13553  }
13554 }
13555 
13556 void sexp_set_persona (int node)
13557 {
13558  int persona_index = -1, sindex, i;
13559  char *persona_name;
13560 
13561  persona_name = CTEXT(node);
13562 
13563  for (i = 0 ; i < Num_personas ; i++) {
13564  if (!strcmp(persona_name, Personas[i].name) && (Personas[i].flags & PERSONA_FLAG_WINGMAN)) {
13565  persona_index = i;
13566  break;
13567  }
13568  }
13569 
13570  if (persona_index == -1) {
13571  Warning(LOCATION, "Unable to change to persona type: '%s'. Persona is not a wingman!", persona_name);
13572  return;
13573  }
13574 
13575  node = CDR(node);
13576  Assert (node >=0);
13577 
13578  if (MULTIPLAYER_MASTER) {
13580  multi_send_int(persona_index);
13581  }
13582 
13583  // now loop through the list of ships
13584  for ( ; node >= 0; node = CDR(node) ) {
13585  sindex = ship_name_lookup( CTEXT(node) );
13586 
13587  if (sindex < 0) {
13588  continue;
13589  }
13590 
13591  if (Ships[sindex].objnum < 0) {
13592  continue;
13593  }
13594 
13595  Ships[sindex].persona_index = persona_index;
13596 
13597  if (MULTIPLAYER_MASTER) {
13598  multi_send_ship(sindex);
13599  }
13600  }
13601 
13602  if (MULTIPLAYER_MASTER) {
13604  }
13605 }
13606 
13608 {
13609  ship *shipp = NULL;
13610  int persona_index = -1;
13611 
13612  if (!multi_get_int(persona_index) ) {
13613  return;
13614  }
13615 
13616  while (multi_get_ship(shipp)) {
13617  Assert(persona_index != -1);
13618  if (shipp != NULL) {
13619  shipp->persona_index = persona_index;
13620  }
13621  }
13622 }
13623 
13624 void sexp_set_mission_mood (int node)
13625 {
13626  char *mood;
13627 
13628  mood = CTEXT(node);
13629  for (SCP_vector<SCP_string>::iterator iter = Builtin_moods.begin(); iter != Builtin_moods.end(); ++iter) {
13630  if (!strcmp(iter->c_str(), mood)) {
13631  Current_mission_mood = iter - Builtin_moods.begin();
13632  return;
13633  }
13634  }
13635 
13636  Warning(LOCATION, "Sexp-mission-mood attempted to set mood %s which does not exist in messages.tbl", mood);
13637 }
13638 
13640 {
13641  ship *shipp;
13642 
13643  int requested_bank;
13644  int delay;
13645  int last_fired = -1;
13646 
13647  shipp = sexp_get_ship_from_node(node);
13648  if (shipp == NULL) {
13649  return SEXP_FALSE;
13650  }
13651 
13652  // Get the bank to check
13653  node = CDR(node);
13654  requested_bank = eval_num(node);
13655  if (requested_bank < 0) {
13656  return SEXP_FALSE;
13657  }
13658 
13659  // get the delay
13660  node = CDR(node);
13661  delay = eval_num(node);
13662  if (delay <= 0 ) {
13663  return SEXP_FALSE;
13664  }
13665 
13666  switch (op_num) {
13667  case OP_PRIMARY_FIRED_SINCE:
13668  if (requested_bank >= shipp->weapons.num_primary_banks) {
13669  return SEXP_FALSE;
13670  }
13671  last_fired = shipp->weapons.last_primary_fire_stamp[requested_bank];
13672  break;
13673 
13675  if (requested_bank >= shipp->weapons.num_secondary_banks) {
13676  return SEXP_FALSE;
13677  }
13678  last_fired = shipp->weapons.last_secondary_fire_stamp[requested_bank];
13679  break;
13680  }
13681 
13682  if (last_fired < 0) {
13683  // weapon was never fired
13684  return SEXP_FALSE;
13685  }
13686 
13687  if (timestamp() - delay < last_fired) {
13688  return SEXP_TRUE;
13689  }
13690 
13691  return SEXP_FALSE;
13692 }
13693 
13694 int sexp_has_weapon(int node, int op_num)
13695 {
13696  ship *shipp;
13697  int i;
13698  int requested_bank;
13699  int weapon_index;
13700  int num_weapon_banks = 0;
13701  int *weapon_banks = NULL;
13702 
13703  shipp = sexp_get_ship_from_node(node);
13704  if (shipp == NULL) {
13705  return SEXP_FALSE;
13706  }
13707 
13708  // Get the bank to check
13709  node = CDR(node);
13710  if (!strcmp(CTEXT(node), SEXP_ALL_BANKS_STRING)) {
13711  requested_bank = -1;
13712  }
13713  else {
13714  requested_bank = eval_num(node);
13715  }
13716  node = CDR(node);
13717 
13718  switch (op_num) {
13719  case OP_HAS_PRIMARY_WEAPON:
13720  weapon_banks = shipp->weapons.primary_bank_weapons;
13721  num_weapon_banks = shipp->weapons.num_primary_banks;
13722  break;
13723 
13725  weapon_banks = shipp->weapons.secondary_bank_weapons;
13726  num_weapon_banks = shipp->weapons.num_secondary_banks;
13727  break;
13728 
13729  default:
13730  Warning(LOCATION, "Unrecognised bank type used in has-x-weapon. Returning false");
13731  return SEXP_FALSE;
13732  }
13733 
13734 
13735  //loop through the weapons and test them
13736  while (node > -1) {
13737  weapon_index = weapon_info_lookup(CTEXT(node));
13738  Assertion (weapon_index >= 0, "Weapon name %s is unknown.", CTEXT(node));
13739 
13740  // if we're checking every bank
13741  if (requested_bank == -1) {
13742  for (i = 0; i < num_weapon_banks; i++) {
13743  if (weapon_index == weapon_banks[i]) {
13744  return SEXP_TRUE;
13745  }
13746  }
13747  }
13748 
13749  // if we're only checking one bank
13750  else {
13751  if (weapon_index == weapon_banks[requested_bank]) {
13752  return SEXP_TRUE;
13753  }
13754  }
13755 
13756  node = CDR(node);
13757  }
13758 
13759  return SEXP_FALSE;
13760 }
13761 
13768 int sexp_previous_goal_status( int n, int status )
13769 {
13770  int rval = 0;
13771  char *goal_name, *mission_name;
13772  int i, mission_num, default_value = 0, use_defaults = 1;
13773 
13774  mission_name = CTEXT(n);
13775  goal_name = CTEXT(CDR(n));
13776 
13777  // check for possible next optional argument
13778  n = CDR(CDR(n));
13779  if ( n != -1 ) {
13780  default_value = is_sexp_true(n);
13781  }
13782 
13783  // try to find the given mission name in the current list of missions in the campaign.
13784  if ( Game_mode & GM_CAMPAIGN_MODE ) {
13785  i = mission_campaign_find_mission( mission_name );
13786 
13787  if ( i == -1 ) {
13788  // if mission not found, assume that goal was false (so previous-goal-false returns true)
13789  nprintf(("General", "Couldn't find mission name \"%s\" in current campaign's list of missions.\nReturning %s for goal-status function.", mission_name, (status==GOAL_COMPLETE)?"false":"true"));
13790  if ( status == GOAL_COMPLETE )
13791  rval = SEXP_KNOWN_FALSE;
13792  else
13793  rval = SEXP_KNOWN_TRUE;
13794 
13795  use_defaults = 0;
13796  } else if (Campaign.missions[i].flags & CMISSION_FLAG_SKIPPED) {
13797  use_defaults = 1;
13798  } else {
13799  // now try and find the goal this mission
13800  mission_num = i;
13801  for (i = 0; i < Campaign.missions[mission_num].num_goals; i++) {
13802  if ( !stricmp(Campaign.missions[mission_num].goals[i].name, goal_name) )
13803  break;
13804  }
13805 
13806  if ( i == Campaign.missions[mission_num].num_goals ) {
13807  Warning(LOCATION, "Couldn't find goal name \"%s\" in mission %s.\nReturning %s for goal-true function.", goal_name, mission_name, (status==GOAL_COMPLETE)?"false":"true");
13808  if ( status == GOAL_COMPLETE )
13809  rval = SEXP_KNOWN_FALSE;
13810  else
13811  rval = SEXP_KNOWN_TRUE;
13812 
13813  } else {
13814  // now return KNOWN_TRUE or KNOWN_FALSE based on the status field in the goal structure
13815  if ( Campaign.missions[mission_num].goals[i].status == status )
13816  rval = SEXP_KNOWN_TRUE;
13817  else
13818  rval = SEXP_KNOWN_FALSE;
13819  }
13820 
13821  use_defaults = 0;
13822  }
13823  }
13824 
13825  if (use_defaults) {
13826  // when not in campaign mode, always return KNOWN_TRUE when looking for goal complete, and KNOWN_FALSE
13827  // otherwise
13828  if ( n != -1 ) {
13829  if ( default_value )
13830  rval = SEXP_KNOWN_TRUE;
13831  else
13832  rval = SEXP_KNOWN_FALSE;
13833  } else {
13834  if ( status == GOAL_COMPLETE )
13835  rval = SEXP_KNOWN_TRUE;
13836  else
13837  rval = SEXP_KNOWN_FALSE;
13838  }
13839  }
13840 
13841  return rval;
13842 }
13843 
13844 // sexpression which gets the status of an event from a previous mission. Like the above function but
13845 // dealing with events instead of goals. Again, the status parameter tells the code if we are looking
13846 // for an event_true, event_false, or event_incomplete status
13847 int sexp_previous_event_status( int n, int status )
13848 {
13849  int rval = 0;
13850  char *name, *mission_name;
13851  int i, mission_num, default_value = 0, use_defaults = 1;
13852 
13853  mission_name = CTEXT(n);
13854  name = CTEXT(CDR(n));
13855 
13856  // check for possible optional parameter
13857  n = CDR(CDR(n));
13858  if ( n != -1 ){
13859  default_value = is_sexp_true(n);
13860  }
13861 
13862  if ( Game_mode & GM_CAMPAIGN_MODE ) {
13863  // following function returns -1 when mission isn't found.
13864  i = mission_campaign_find_mission( mission_name );
13865 
13866  // if the mission name wasn't found -- make this return FALSE for the event status.
13867  if ( i == -1 ) {
13868  nprintf(("General", "Couldn't find mission name \"%s\" in current campaign's list of missions.\nReturning %s for event-status function.", mission_name, (status==EVENT_SATISFIED)?"false":"true"));
13869  if ( status == EVENT_SATISFIED ) {
13870  rval = SEXP_KNOWN_FALSE;
13871  } else {
13872  rval = SEXP_KNOWN_TRUE;
13873  }
13874 
13875  use_defaults = 0;
13876  } else if (Campaign.missions[i].flags & CMISSION_FLAG_SKIPPED) {
13877  use_defaults = 1;
13878  } else {
13879  // now try and find the goal this mission
13880  mission_num = i;
13881  for (i = 0; i < Campaign.missions[mission_num].num_events; i++) {
13882  if ( !stricmp(Campaign.missions[mission_num].events[i].name, name) )
13883  break;
13884  }
13885 
13886  if ( i == Campaign.missions[mission_num].num_events ) {
13887  Warning(LOCATION, "Couldn't find event name \"%s\" in mission %s.\nReturning %s for event_status function.", name, mission_name, (status==EVENT_SATISFIED)?"false":"true");
13888  if ( status == EVENT_SATISFIED )
13889  rval = SEXP_KNOWN_FALSE;
13890  else
13891  rval = SEXP_KNOWN_TRUE;
13892 
13893  } else {
13894  // now return KNOWN_TRUE or KNOWN_FALSE based on the status field in the goal structure
13895  if ( Campaign.missions[mission_num].events[i].status == status )
13896  rval = SEXP_KNOWN_TRUE;
13897  else
13898  rval = SEXP_KNOWN_FALSE;
13899  }
13900 
13901  use_defaults = 0;
13902  }
13903  }
13904 
13905  if (use_defaults) {
13906  if ( n != -1 ) {
13907  if ( default_value )
13908  rval = SEXP_KNOWN_TRUE;
13909  else
13910  rval = SEXP_KNOWN_FALSE;
13911  } else {
13912  if ( status == EVENT_SATISFIED )
13913  rval = SEXP_KNOWN_TRUE;
13914  else
13915  rval = SEXP_KNOWN_FALSE;
13916  }
13917  }
13918 
13919  return rval;
13920 }
13921 
13928 int sexp_event_status( int n, int want_true )
13929 {
13930  char *name;
13931  int i, result;
13932 
13933  name = CTEXT(n);
13934 
13935  if (name == NULL) {
13936  Int3();
13937  return SEXP_FALSE;
13938  }
13939 
13940  for (i = 0; i < Num_mission_events; i++ ) {
13941  // look for the event name, check it's status. If formula is gone, we know the state won't ever change.
13942  if ( !stricmp(Mission_events[i].name, name) ) {
13943  result = Mission_events[i].result;
13944  if (Mission_events[i].formula < 0) {
13945  if ( (want_true && result) || (!want_true && !result) )
13946  return SEXP_KNOWN_TRUE;
13947  else
13948  return SEXP_KNOWN_FALSE;
13949 
13950  } else {
13951  if ( (want_true && result) || (!want_true && !result) )
13952  return SEXP_TRUE;
13953  else
13954  return SEXP_FALSE;
13955  }
13956  }
13957  }
13958 
13959  return SEXP_FALSE;
13960 }
13961 
13967 int sexp_event_delay_status( int n, int want_true, bool use_msecs = false)
13968 {
13969  char *name;
13970  int i, result;
13971  fix delay;
13972  int rval = SEXP_FALSE;
13973  int use_as_directive = 0;
13974 
13975  name = CTEXT(n);
13976 
13977  if (name == NULL) {
13978  Int3();
13979  return SEXP_FALSE;
13980  }
13981 
13982  uint64_t tempDelay = eval_num(CDR(n));
13983 
13984  if (use_msecs) {
13985  tempDelay = tempDelay << 16;
13986  tempDelay = tempDelay / 1000;
13987 
13988  delay = (fix) tempDelay;
13989  } else {
13990  delay = i2f(tempDelay);
13991  }
13992 
13993  for (i = 0; i < Num_mission_events; i++ ) {
13994  // look for the event name, check it's status. If formula is gone, we know the state won't ever change.
13995  if ( !stricmp(Mission_events[i].name, name) ) {
13996  if ( (fix) Mission_events[i].timestamp + delay >= Missiontime ) {
13997  rval = SEXP_FALSE;
13998  break;
13999  }
14000 
14001  result = Mission_events[i].result;
14002  if (Mission_events[i].formula < 0) {
14003  if ( (want_true && result) || (!want_true && !result) ) {
14004  rval = SEXP_KNOWN_TRUE;
14005  break;
14006  } else {
14007  rval = SEXP_KNOWN_FALSE;
14008  break;
14009  }
14010  } else {
14011  if ( want_true && result ) { //) || (!want_true && !result) )
14012  rval = SEXP_TRUE;
14013  break;
14014  } else {
14015  rval = SEXP_FALSE;
14016  break;
14017  }
14018  }
14019  }
14020  }
14021 
14022  // check for possible optional parameter
14023  n = CDDR(n);
14024  if (n != -1)
14025  use_as_directive = is_sexp_true(n);
14026 
14027  // zero out Sexp_useful_number if it's not true and we don't want this for specific directive use
14028  if ( !use_as_directive && (rval != SEXP_TRUE) && (rval != SEXP_KNOWN_TRUE) )
14029  Sexp_useful_number = 0; // indicate sexp isn't current yet
14030 
14031  return rval;
14032 }
14033 
14038 {
14039  char *name;
14040  int i;
14041 
14042  name = CTEXT(n);
14043 
14044  if (name == NULL) {
14045  Int3();
14046  return SEXP_FALSE;
14047  }
14048 
14049  for (i = 0; i < Num_mission_events; i++ ) {
14050  if ( !stricmp(Mission_events[i].name, name ) ) {
14051  // if the formula is still >= 0 (meaning it is still getting eval'ed), then
14052  // the event is incomplete
14053  if ( Mission_events[i].formula != -1 )
14054  return SEXP_TRUE;
14055  else
14056  return SEXP_KNOWN_FALSE;
14057  }
14058  }
14059 
14060  return SEXP_FALSE;
14061 }
14062 
14068 int sexp_goal_delay_status( int n, int want_true )
14069 {
14070  char *name;
14071  fix delay, time;
14072 
14073  name = CTEXT(n);
14074  delay = i2f(eval_num(CDR(n)));
14075 
14076  if ( want_true ) {
14077  // if we are looking for a goal true entry and we find a false, then return known false here
14078  if ( mission_log_get_time(LOG_GOAL_FAILED, name, NULL, NULL) )
14079  return SEXP_KNOWN_FALSE;
14080  else if ( mission_log_get_time(LOG_GOAL_SATISFIED, name, NULL, &time) ) {
14081  if ( (Missiontime - time) >= delay )
14082  return SEXP_KNOWN_TRUE;
14083  }
14084  } else {
14085  // if we are looking for a goal false entry and we find a true, then return known false here
14086  if ( mission_log_get_time(LOG_GOAL_SATISFIED, name, NULL, NULL) )
14087  return SEXP_KNOWN_FALSE;
14088  else if ( mission_log_get_time(LOG_GOAL_FAILED, name, NULL, &time) ) {
14089  if ( (Missiontime - time) >= delay )
14090  return SEXP_KNOWN_TRUE;
14091  }
14092  }
14093 
14094  return SEXP_FALSE;
14095 }
14096 
14101 {
14102  char *name;
14103 
14104  name = CTEXT(n);
14105 
14106  if ( mission_log_get_time( LOG_GOAL_SATISFIED, name, NULL, NULL) || mission_log_get_time( LOG_GOAL_FAILED, name, NULL, NULL) )
14107  return SEXP_KNOWN_FALSE;
14108  else
14109  return SEXP_TRUE;
14110 }
14111 
14118 void sexp_protect_ships(int n, bool flag)
14119 {
14120  sexp_deal_with_ship_flag(n, true, OF_PROTECTED, 0, 0, 0, P_OF_PROTECTED, 0, flag);
14121 }
14122 
14129 void sexp_beam_protect_ships(int n, bool flag)
14130 {
14131  sexp_deal_with_ship_flag(n, true, OF_BEAM_PROTECTED, 0, 0, 0, P_OF_BEAM_PROTECTED, 0, flag);
14132 }
14133 
14140 void sexp_turret_protect_ships(int n, bool flag)
14141 {
14142  char *turret_type = CTEXT(n);
14143  n = CDR(n);
14144 
14145  if (!stricmp(turret_type, "beam"))
14146  sexp_deal_with_ship_flag(n, true, OF_BEAM_PROTECTED, 0, 0, 0, P_OF_BEAM_PROTECTED, 0, flag);
14147  else if (!stricmp(turret_type, "flak"))
14148  sexp_deal_with_ship_flag(n, true, OF_FLAK_PROTECTED, 0, 0, 0, P_OF_FLAK_PROTECTED, 0, flag);
14149  else if (!stricmp(turret_type, "laser"))
14151  else if (!stricmp(turret_type, "missile"))
14153  else
14154  Warning(LOCATION, "Invalid turret type '%s'!", turret_type);
14155 }
14156 
14157 // Goober5000 - sets the "don't collide invisible" flag on a list of ships
14158 void sexp_dont_collide_invisible(int n, bool dont_collide)
14159 {
14160  sexp_deal_with_ship_flag(n, true, 0, 0, 0, SF2_DONT_COLLIDE_INVIS, 0, P_SF2_DONT_COLLIDE_INVIS, dont_collide);
14161 }
14162 
14163 // Goober5000 - sets the "immobile" flag on a list of ships
14164 void sexp_set_immobile(int n, bool immobile)
14165 {
14166  sexp_deal_with_ship_flag(n, true, OF_IMMOBILE, 0, 0, 0, 0, P2_OF_IMMOBILE, immobile);
14167 }
14168 
14169 // Goober5000 - sets the "no-ets" flag on a list of ships
14170 void sexp_disable_ets(int n, bool disable)
14171 {
14172  sexp_deal_with_ship_flag(n, true, 0, 0, 0, SF2_NO_ETS, 0, P2_SF2_NO_ETS, disable);
14173 }
14174 
14175 // Goober5000 - sets the vaporize flag on a list of ships
14176 void sexp_ships_vaporize(int n, bool vaporize)
14177 {
14178  sexp_deal_with_ship_flag(n, true, 0, 0, SF_VAPORIZE, 0, P_SF_VAPORIZE, 0, vaporize);
14179 }
14180 
14187 void sexp_ships_visible(int n, bool visible)
14188 {
14189  sexp_deal_with_ship_flag(n, true, 0, 0, SF_HIDDEN_FROM_SENSORS, 0, P_SF_HIDDEN_FROM_SENSORS, 0, !visible, true);
14190 
14191  // we also have to add any escort ships that were made visible
14192  for (; n >= 0; n = CDR(n))
14193  {
14194  int shipnum = ship_name_lookup(CTEXT(n));
14195  if (shipnum < 0)
14196  continue;
14197 
14198  if (!visible && Player_ai->target_objnum == Ships[shipnum].objnum) {
14200  }
14201  else if (visible && (Ships[shipnum].flags & SF_ESCORT)) {
14202  hud_add_ship_to_escort(Ships[shipnum].objnum, 1);
14203  }
14204  }
14205 }
14206 
14207 // Goober5000
14208 void sexp_ships_stealthy(int n, bool stealthy)
14209 {
14210  sexp_deal_with_ship_flag(n, true, 0, 0, 0, SF2_STEALTH, 0, P_SF2_STEALTH, stealthy, true);
14211 
14212  // we also have to add any escort ships that were made visible
14213  if (!stealthy)
14214  {
14215  for (; n >= 0; n = CDR(n))
14216  {
14217  int shipnum = ship_name_lookup(CTEXT(n));
14218  if (shipnum < 0)
14219  continue;
14220 
14221  if (Ships[shipnum].flags & SF_ESCORT)
14222  hud_add_ship_to_escort(Ships[shipnum].objnum, 1);
14223  }
14224  }
14225 }
14226 
14227 // Goober5000
14228 void sexp_friendly_stealth_invisible(int n, bool invisible)
14229 {
14231 
14232  // we also have to add any escort ships that were made visible
14233  if (!invisible)
14234  {
14235  for (; n >= 0; n = CDR(n))
14236  {
14237  int shipnum = ship_name_lookup(CTEXT(n));
14238  if (shipnum < 0)
14239  continue;
14240 
14241  if (Ships[shipnum].flags2 & SF2_STEALTH && Player_ship->team == Ships[shipnum].team)
14242  {
14243  if (Ships[shipnum].flags & SF_ESCORT)
14244  hud_add_ship_to_escort(Ships[shipnum].objnum, 1);
14245  }
14246  }
14247  }
14248 }
14249 
14250 //FUBAR
14251 //generic function to deal with subsystem flag sexps.
14252 //setit only passed for backward compatibility with older sexps.
14253 void sexp_ship_deal_with_subsystem_flag(int node, int ss_flag, bool sendit = false, bool setit = false)
14254 {
14255  ship *shipp = NULL;
14256  ship_subsys *ss = NULL;
14257 
14258  // get ship
14259  shipp = sexp_get_ship_from_node(node);
14260  if (shipp == NULL) {
14261  return;
14262  }
14263 
14264  //replace or not
14265  // OP_SHIP_SUBSYS_TARGETABLE/UNTARGETABLE, OP_SHIP_SUBSYS_TARGETABLE and OP_TURRET_SUBSYS_TARGET_ENABLE/DISABLE
14266  // will have already passed us this data we don't need to set it for them.
14267  // backward compatibility hack for older sexps
14268  if (!((ss_flag == SSF_UNTARGETABLE) || (ss_flag == SSF_NO_SS_TARGETING)))
14269  {
14270  node = CDR(node);
14271  setit = (is_sexp_true(node) ? true : false);
14272  }
14273 
14274  //multiplayer packet start
14275  if (sendit)
14276  {
14278  multi_send_ship(shipp);
14279  multi_send_bool(setit);
14280  }
14281 
14282  //Process subsystems
14283  while(node != -1)
14284  {
14285  // deal with generic subsystem names
14286  int generic_type = get_generic_subsys(CTEXT(node));
14287  if (generic_type) {
14288  for (ss = GET_FIRST(&shipp->subsys_list); ss != END_OF_LIST(&shipp->subsys_list); ss = GET_NEXT(ss)) {
14289  if (generic_type == ss->system_info->type) {
14290  if (setit)
14291  ss->flags |= ss_flag;
14292  else
14293  ss->flags &= ~ss_flag;
14294  }
14295  }
14296  }
14297  else
14298  {
14299  // get the subsystem
14300  ss = ship_get_subsys(shipp, CTEXT(node));
14301  if(ss == NULL)
14302  {
14303  node = CDR(node);
14304  continue;
14305  }
14306 
14307  // set the flag
14308  if(setit)
14309  ss->flags |= ss_flag;
14310  else
14311  ss->flags &= ~ss_flag;
14312  }
14313 
14314  // multiplayer send subsystem name
14315  if (sendit)
14316  multi_send_string(CTEXT(node));
14317 
14318  // next
14319  node = CDR(node);
14320  }
14321 
14322  // mulitplayer end of packet
14323  if (sendit)
14325 }
14327 {
14328  bool setit = false;
14329  ship_subsys *ss = NULL;
14330  ship *shipp = NULL;
14331  char ss_name[MAX_NAME_LEN];
14332 
14333  multi_get_ship(shipp);
14334  multi_get_bool(setit);
14335 
14336  while (multi_get_string(ss_name))
14337  {
14338  // deal with generic subsystem names
14339  int generic_type = get_generic_subsys(ss_name);
14340  if (generic_type) {
14341  for (ss = GET_FIRST(&shipp->subsys_list); ss != END_OF_LIST(&shipp->subsys_list); ss = GET_NEXT(ss)) {
14342  if (generic_type == ss->system_info->type) {
14343  if (setit)
14344  ss->flags |= ss_flag;
14345  else
14346  ss->flags &= ~ss_flag;
14347  }
14348  }
14349  }
14350  else
14351  {
14352  ss = ship_get_subsys(shipp, ss_name);
14353  if(ss != NULL)
14354  {
14355  // set the flag
14356  if(setit)
14357  ss->flags |= ss_flag;
14358  else
14359  ss->flags &= ~ss_flag;
14360  }
14361  }
14362  }
14363 }
14364 // Goober5000
14365 void sexp_ship_tag( int n, int tag )
14366 {
14367  int ship_num, tag_level, tag_time, ssm_index(0);
14368  int ssm_team = 0;
14369 
14370  // check to see if ship destroyed or departed. In either case, do nothing.
14372  return;
14373 
14374  // get the ship num
14375  ship_num = ship_name_lookup(CTEXT(n));
14376  if ( ship_num < 0 )
14377  return;
14378 
14379  // if untag, then unset everything and leave
14380  if (!tag)
14381  {
14382  Ships[ship_num].tag_left = -1.0f;
14383  Ships[ship_num].level2_tag_left = -1.0f;
14384  return;
14385  }
14386 
14387  // get the tag level and time
14388  n = CDR(n);
14389  tag_level = eval_num(n);
14390  n = CDR(n);
14391  tag_time = eval_num(n);
14392 
14393  // get SSM info if needed
14394  vec3d start;
14395  if (tag_level == 3)
14396  {
14397  n = CDR(n);
14398  if (n < 0)
14399  return;
14400  ssm_index = ssm_info_lookup(CTEXT(n));
14401  if (ssm_index < 0)
14402  return;
14403 
14404  n = CDR(n);
14405  if (n < 0)
14406  return;
14407  start.xyz.x = (float)eval_num(n);
14408 
14409  n = CDR(n);
14410  if (n < 0)
14411  return;
14412  start.xyz.y = (float)eval_num(n);
14413 
14414  n = CDR(n);
14415  if (n < 0)
14416  return;
14417  start.xyz.z = (float)eval_num(n);
14418 
14419  n = CDR(n);
14420 
14421  if (n < 0)
14422  {
14423  ssm_team = 0;
14424  }
14425  else
14426  {
14427  ssm_team = iff_lookup(CTEXT(n));
14428  }
14429  }
14430 
14431  ship_apply_tag(ship_num, tag_level, (float)tag_time, &Objects[Ships[ship_num].objnum], &start, ssm_index, ssm_team);
14432 }
14433 
14434 // sexpression to toggle invulnerability flag of ships.
14435 void sexp_ships_invulnerable( int n, bool invulnerable )
14436 {
14437  sexp_deal_with_ship_flag(n, true, OF_INVULNERABLE, 0, 0, 0, P_OF_INVULNERABLE, 0, invulnerable);
14438 }
14439 
14440 void sexp_ships_bomb_targetable(int n, bool targetable)
14441 {
14442  sexp_deal_with_ship_flag(n, true, OF_TARGETABLE_AS_BOMB, 0, 0, 0, 0, P2_OF_TARGETABLE_AS_BOMB, targetable, true);
14443 }
14444 
14445 // Goober5000
14447 {
14448  char *ship_name;
14449  int ship_num, threshold;
14450  int n = -1;
14451 
14452  threshold = eval_num(node);
14453 
14454  n = CDR(node);
14455 
14456  // for all ships
14457  for ( ; n != -1; n = CDR(n) ) {
14458  // check to see if ship destroyed or departed. In either case, do nothing.
14459  ship_name = CTEXT(n);
14460 
14461  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) ) {
14462  continue;
14463  }
14464 
14465  // get the ship num. If we get a -1 for the number here, ship has yet to arrive.
14466  ship_num = ship_name_lookup(ship_name);
14467 
14468  if (ship_num != -1) {
14469  Ships[ship_num].ship_guardian_threshold = threshold;
14470  }
14471  }
14472 }
14473 
14474 // Goober5000
14476 {
14477  char *ship_name, *hull_name;
14478  int ship_num, threshold;
14479  ship_subsys *ss;
14480  int n = -1;
14481 
14482  threshold = eval_num(num);
14483 
14484  n = CDR(num);
14485 
14486  // check to see if ship destroyed or departed. In either case, do nothing.
14487  ship_name = CTEXT(n);
14488 
14489  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) ) {
14490  return;
14491  }
14492 
14493  // get the ship num. If we get a -1 for the number here, ship has yet to arrive.
14494  ship_num = ship_name_lookup(ship_name);
14495 
14496  if (ship_num == -1) {
14497  return;
14498  }
14499 
14500  n = CDR(n);
14501 
14502  // for all subsystems
14503  for ( ; n != -1; n = CDR(n) ) {
14504  // check for HULL
14505  hull_name = CTEXT(n);
14506 
14507  if (hull_name != NULL) {
14508  int generic_type = get_generic_subsys(hull_name);
14509  if ( !strcmp(hull_name, SEXP_HULL_STRING) ) {
14510  Ships[ship_num].ship_guardian_threshold = threshold;
14511  }
14512  else if (generic_type) {
14513  // search through all subsystems
14514  for (ss = GET_FIRST(&Ships[ship_num].subsys_list); ss != END_OF_LIST(&Ships[ship_num].subsys_list); ss = GET_NEXT(ss)) {
14515  if (generic_type == ss->system_info->type) {
14516  ss->subsys_guardian_threshold = threshold;
14517  }
14518  }
14519  }
14520  else {
14521  ss = ship_get_subsys(&Ships[ship_num], hull_name);
14522  if ( ss == NULL ) {
14523  if (ship_class_unchanged(ship_num)) {
14524  Warning(LOCATION, "Invalid subsystem passed to ship-subsys-guardian-threshold: %s does not have a %s subsystem", ship_name, hull_name);
14525  }
14526  }
14527  else {
14528  ss->subsys_guardian_threshold = threshold;
14529  }
14530  }
14531  }
14532  }
14533 }
14534 
14535 // sexpression to toggle KEEP ALIVE flag of ship object
14536 void sexp_ships_guardian( int n, int guardian )
14537 {
14538  char *ship_name;
14539  int num;
14540 
14541  for ( ; n != -1; n = CDR(n) )
14542  {
14543  ship_name = CTEXT(n);
14544 
14545  // check to see if ship destroyed or departed. In either case, do nothing.
14546  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
14547  continue;
14548 
14549  // get the ship num. If we get a -1 for the number here, ship has yet to arrive. Store this ship
14550  // in a list until created
14551  num = ship_name_lookup(ship_name);
14552  if ( num != -1 ) {
14554  } else {
14555  p_object *p_objp = mission_parse_get_arrival_ship(ship_name);
14556  if (p_objp)
14557  {
14558  if ( guardian )
14559  p_objp->flags |= P_SF_GUARDIAN;
14560  else
14561  p_objp->flags &= ~P_SF_GUARDIAN;
14562  }
14563  }
14564  }
14565 }
14566 
14568 {
14569  int new_ship_class = -1;
14570  char *new_ship_name;
14571  vec3d new_ship_pos = vmd_zero_vector;
14572  angles new_ship_ang = {0.0f, 0.0f, 0.0f};
14573  matrix new_ship_ori = vmd_identity_matrix;
14574  bool change_angles = false;
14575 
14576  Assert( n >= 0 );
14577 
14578  // get ship name - none means don't specify it
14579  // if ship with this name already exists, ship_create will respond appropriately
14580  if (!stricmp(CTEXT(n), SEXP_NONE_STRING))
14581  {
14582  new_ship_name = NULL;
14583  }
14584  else
14585  {
14586  new_ship_name = CTEXT(n);
14587  }
14588 
14589  //Get ship class
14590  n = CDR(n);
14591  new_ship_class = ship_info_lookup(CTEXT(n));
14592 
14593  if(new_ship_class == -1) {
14594  Warning(LOCATION, "Invalid ship class passed to ship-create; ship type '%s' does not exist", CTEXT(n));
14595  return;
14596  }
14597 
14598  n = CDR(n);
14599  new_ship_pos.xyz.x = (float) eval_num(n);
14600  n = CDR(n);
14601  new_ship_pos.xyz.y = (float) eval_num(n);
14602  n = CDR(n);
14603  new_ship_pos.xyz.z = (float) eval_num(n);
14604 
14605  n = CDR(n);
14606  if(n != -1) {
14607  new_ship_ang.p = fl_radians(eval_num(n) % 360);
14608  change_angles = true;
14609  }
14610 
14611  n = CDR(n);
14612  if(n != -1) {
14613  new_ship_ang.b = fl_radians(eval_num(n) % 360);
14614  change_angles = true;
14615  }
14616 
14617  n = CDR(n);
14618  if(n != -1) {
14619  new_ship_ang.h = fl_radians(eval_num(n) % 360);
14620  change_angles = true;
14621  }
14622 
14623  //This is a costly function, so only do it if needed
14624  if(change_angles) {
14625  vm_angles_2_matrix(&new_ship_ori, &new_ship_ang);
14626  }
14627 
14628  ship_create(&new_ship_ori, &new_ship_pos, new_ship_class, new_ship_name);
14629 }
14630 
14631 // Goober5000
14633 {
14634  int weapon_class, parent_objnum, target_objnum, weapon_objnum;
14635  ship_subsys *targeted_ss;
14636 
14637  vec3d weapon_pos = vmd_zero_vector;
14638  angles weapon_angles = {0.0f, 0.0f, 0.0f};
14639  matrix weapon_orient = vmd_identity_matrix;
14640  int is_locked;
14641  bool change_angles = false;
14642 
14643  Assert( n >= 0 );
14644 
14645  parent_objnum = -1;
14646  if (stricmp(CTEXT(n), SEXP_NONE_STRING))
14647  {
14648  int parent_ship = ship_name_lookup(CTEXT(n));
14649 
14650  if (parent_ship >= 0)
14651  parent_objnum = Ships[parent_ship].objnum;
14652  }
14653  n = CDR(n);
14654 
14655  weapon_class = weapon_info_lookup(CTEXT(n));
14656  n = CDR(n);
14657  if (weapon_class < 0)
14658  {
14659  Warning(LOCATION, "Invalid weapon class passed to weapon-create; weapon type '%s' does not exist", CTEXT(n));
14660  return;
14661  }
14662 
14663  weapon_pos.xyz.x = (float) eval_num(n);
14664  n = CDR(n);
14665  weapon_pos.xyz.y = (float) eval_num(n);
14666  n = CDR(n);
14667  weapon_pos.xyz.z = (float) eval_num(n);
14668  n = CDR(n);
14669 
14670  if (n >= 0)
14671  {
14672  weapon_angles.p = fl_radians(eval_num(n) % 360);
14673  n = CDR(n);
14674  change_angles = true;
14675  }
14676 
14677  if (n >= 0)
14678  {
14679  weapon_angles.b = fl_radians(eval_num(n) % 360);
14680  n = CDR(n);
14681  change_angles = true;
14682  }
14683 
14684  if (n >= 0)
14685  {
14686  weapon_angles.h = fl_radians(eval_num(n) % 360);
14687  n = CDR(n);
14688  change_angles = true;
14689  }
14690 
14691  // This is a costly function, so only do it if needed
14692  if (change_angles)
14693  {
14694  vm_angles_2_matrix(&weapon_orient, &weapon_angles);
14695  }
14696 
14697  target_objnum = -1;
14698  if (n >= 0)
14699  {
14700  int target_ship = ship_name_lookup(CTEXT(n));
14701 
14702  if (target_ship >= 0)
14703  target_objnum = Ships[target_ship].objnum;
14704 
14705  n = CDR(n);
14706  }
14707 
14708  targeted_ss = NULL;
14709  if (n >= 0)
14710  {
14711  if (target_objnum >= 0)
14712  targeted_ss = ship_get_subsys(&Ships[Objects[target_objnum].instance], CTEXT(n));
14713 
14714  n = CDR(n);
14715  }
14716 
14717  is_locked = (target_objnum >= 0) ? 1 : 0; // assume full lock; this lets lasers track if people want them to
14718 
14719  // create the weapon
14720  weapon_objnum = weapon_create(&weapon_pos, &weapon_orient, weapon_class, parent_objnum, -1, is_locked);
14721 
14722  // maybe make the weapon track its target
14723  if (is_locked)
14724  weapon_set_tracking_info(weapon_objnum, parent_objnum, target_objnum, is_locked, targeted_ss);
14725 }
14726 
14727 // make ship vanish without a trace (and what its docked to)
14729 {
14730  char *ship_name;
14731  int num;
14732 
14733  // if MULTIPLAYER bail
14734  if (Game_mode & GM_MULTIPLAYER) {
14735  return;
14736  }
14737 
14738  for ( ; n != -1; n = CDR(n) ) {
14739  ship_name = CTEXT(n);
14740 
14741  // check to see if ship destroyed or departed. In either case, do nothing.
14742  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
14743  continue;
14744 
14745  // get the ship num. If we get a -1 for the number here, ship has yet to arrive
14746  num = ship_name_lookup(ship_name);
14747  if ( num != -1 )
14749  }
14750 }
14751 
14753 {
14754  char *ship_name;
14755  int ship_num;
14756  object *ship_obj_p;
14757 
14758  // if MULTIPLAYER bail
14759  if (Game_mode & GM_MULTIPLAYER) {
14760  return;
14761  }
14762 
14763  for ( ; n != -1; n = CDR(n) ) {
14764  ship_name = CTEXT(n);
14765 
14766  // check to see if ship destroyed or departed. In either case, do nothing.
14767  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
14768  continue;
14769  ship_num = ship_name_lookup(ship_name);
14770 
14771  // if it still exists, destroy it
14772  if (ship_num >= 0) {
14773  ship_obj_p = &Objects[Ships[ship_num].objnum];
14774 
14775  //if its the player don't destroy
14776  if (ship_obj_p == Player_obj)
14777  continue;
14778  ship_destroy_instantly(ship_obj_p,ship_num);
14779  }
14780  }
14781 }
14782 
14783 void sexp_shields_off(int n, bool shields_off ) //-Sesquipedalian
14784 {
14785  sexp_deal_with_ship_flag(n, true, OF_NO_SHIELDS, 0, 0, 0, P_OF_NO_SHIELDS, 0, shields_off, true);
14786 }
14787 
14788 // Goober5000
14790 {
14791  Assert(shipp);
14792 
14793  ai_info *aip = &Ai_info[shipp->ai_index];
14794 
14795  if (kdamage > 0)
14796  {
14797  aip->ai_flags |= AIF_KAMIKAZE;
14798  aip->kamikaze_damage = kdamage;
14799  }
14800  else
14801  {
14802  aip->ai_flags &= ~AIF_KAMIKAZE;
14803  aip->kamikaze_damage = 0;
14804  }
14805 }
14806 
14807 // Goober5000
14808 void sexp_parse_ship_kamikaze(p_object *parse_obj, int kdamage)
14809 {
14810  Assert(parse_obj);
14811 
14812  if (kdamage > 0)
14813  {
14814  parse_obj->flags |= P_AIF_KAMIKAZE;
14815  parse_obj->kamikaze_damage = kdamage;
14816  }
14817  else
14818  {
14819  parse_obj->flags &= ~P_AIF_KAMIKAZE;
14820  parse_obj->kamikaze_damage = 0;
14821  }
14822 }
14823 
14824 // Goober5000 - redone, added wing stuff
14825 void sexp_kamikaze(int n, int kamikaze)
14826 {
14827  int kdamage;
14828 
14829  kdamage = 0;
14830  if (kamikaze)
14831  {
14832  kdamage = eval_num(n);
14833  n = CDR(n);
14834  }
14835 
14836  for ( ; n != -1; n = CDR(n) )
14837  {
14840 
14841  switch (oswpt.type)
14842  {
14843  // change ingame ship
14844  case OSWPT_TYPE_SHIP:
14845  {
14846  sexp_ingame_ship_kamikaze(oswpt.shipp, kdamage);
14847 
14848  break;
14849  }
14850 
14851  // change ship yet to arrive
14853  {
14854  sexp_parse_ship_kamikaze(oswpt.p_objp, kdamage);
14855 
14856  break;
14857  }
14858 
14859  // change wing (we must set the flags for all ships present as well as all ships yet to arrive)
14860  case OSWPT_TYPE_WING:
14862  {
14863  // current ships
14864  for (int i = 0; i < oswpt.wingp->current_count; i++)
14865  sexp_ingame_ship_kamikaze(&Ships[oswpt.wingp->ship_index[i]], kdamage);
14866 
14867  // ships yet to arrive
14868  for (p_object *p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
14869  {
14870  if (p_objp->wingnum == WING_INDEX(oswpt.wingp))
14871  sexp_parse_ship_kamikaze(p_objp, kdamage);
14872  }
14873  }
14874  }
14875  }
14876 }
14877 
14878 // Goober5000
14879 void sexp_ingame_ship_alt_name(ship *shipp, int alt_index)
14880 {
14881  Assert((shipp != NULL) && (alt_index < Mission_alt_type_count));
14882 
14883  // we might be clearing it
14884  if (alt_index < 0)
14885  {
14886  shipp->alt_type_index = -1;
14887  return;
14888  }
14889 
14890  // see if this is actually the ship class
14891  if (!stricmp(Ship_info[shipp->ship_info_index].name, Mission_alt_types[alt_index]))
14892  {
14893  shipp->alt_type_index = -1;
14894  return;
14895  }
14896 
14897  shipp->alt_type_index = alt_index;
14898 }
14899 
14900 // Goober5000
14901 void sexp_parse_ship_alt_name(p_object *parse_obj, int alt_index)
14902 {
14903  Assert((parse_obj != NULL) && (alt_index < Mission_alt_type_count));
14904 
14905  // we might be clearing it
14906  if (alt_index < 0)
14907  {
14908  parse_obj->alt_type_index = -1;
14909  return;
14910  }
14911 
14912  // see if this is actually the ship class
14913  if (!stricmp(Ship_class_names[parse_obj->ship_class], Mission_alt_types[alt_index]))
14914  {
14915  parse_obj->alt_type_index = -1;
14916  return;
14917  }
14918 
14919  parse_obj->alt_type_index = alt_index;
14920 }
14921 
14922 // Goober5000
14924 {
14925  int n = node, new_alt_index;
14926  char *new_alt_name;
14927 
14928  // get the alt-name
14929  new_alt_name = CTEXT(n);
14930  n = CDR(n);
14931 
14932  // and its index
14933  if (!*new_alt_name || !stricmp(new_alt_name, SEXP_ANY_STRING))
14934  {
14935  new_alt_index = -1;
14936  }
14937  else
14938  {
14939  new_alt_index = mission_parse_lookup_alt(new_alt_name);
14940  if (new_alt_index < 0)
14941  new_alt_index = mission_parse_add_alt(new_alt_name);
14942  }
14943 
14944  for ( ; n != -1; n = CDR(n) )
14945  {
14948 
14949  switch (oswpt.type)
14950  {
14951  // change ingame ship
14952  case OSWPT_TYPE_SHIP:
14953  {
14954  sexp_ingame_ship_alt_name(oswpt.shipp, new_alt_index);
14955  break;
14956  }
14957 
14958  // change ship yet to arrive
14960  {
14961  sexp_parse_ship_alt_name(oswpt.p_objp, new_alt_index);
14962  break;
14963  }
14964 
14965  // change wing (we must set the flags for all ships present as well as all ships yet to arrive)
14966  case OSWPT_TYPE_WING:
14968  {
14969  // current ships
14970  for (int i = 0; i < oswpt.wingp->current_count; i++)
14971  sexp_ingame_ship_alt_name(&Ships[oswpt.wingp->ship_index[i]], new_alt_index);
14972 
14973  // ships yet to arrive
14974  for (p_object *p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
14975  {
14976  if (p_objp->wingnum == WING_INDEX(oswpt.wingp))
14977  sexp_parse_ship_alt_name(p_objp, new_alt_index);
14978  }
14979  break;
14980  }
14981  }
14982  }
14983 }
14984 
14985 // FUBAR
14987 {
14988  char *new_callsign;
14989  int sindex, cindex;
14990  ship *shipp = NULL;
14991 
14992  // get the callsign
14993  new_callsign = CTEXT(node);
14994  node = CDR(node);
14995 
14996  // and its index
14997  if (!*new_callsign || !stricmp(new_callsign, SEXP_ANY_STRING))
14998  {
14999  cindex = -1;
15000  }
15001  else
15002  {
15003  cindex = mission_parse_lookup_callsign(new_callsign);
15004  if (cindex < 0)
15005  cindex = mission_parse_add_callsign(new_callsign);
15006  }
15007 
15008  // packets for multi
15010  multi_send_string(new_callsign);
15011 
15012  while ( node >= 0 )
15013  {
15014  sindex = ship_name_lookup(CTEXT(node));
15015  if (sindex >= 0)
15016  {
15017  shipp = &Ships[sindex];
15018  shipp->callsign_index = cindex;
15019  multi_send_ship(shipp);
15020  }
15021  node = CDR(node);
15022  }
15023 
15025 }
15026 
15028 {
15029  char new_callsign[TOKEN_LENGTH];
15030  int cindex;
15031  ship *shipp = NULL;
15032 
15033  multi_get_string(new_callsign);
15034  if (!new_callsign[0] || !stricmp(new_callsign, SEXP_ANY_STRING))
15035  {
15036  cindex = -1;
15037  }
15038  else
15039  {
15040  cindex = mission_parse_lookup_callsign(new_callsign);
15041  if (cindex < 0)
15042  {
15043  cindex = mission_parse_add_callsign(new_callsign);
15044  }
15045  }
15046 
15047  while (multi_get_ship(shipp))
15048  {
15049  if (shipp != NULL)
15050  {
15051  shipp->callsign_index = cindex;
15052  }
15053  }
15054 }
15055 
15056 // Goober5000
15058 {
15059  int i;
15060 
15061  // we'll suppose it's the string for now
15062  Player->death_message = CTEXT(n);
15063 
15064  // but use an actual message if one exists
15065  for (i=0; i<Num_messages; i++)
15066  {
15067  if (!stricmp(Messages[i].name, Player->death_message.c_str()))
15068  {
15069  Player->death_message = Messages[i].message;
15070  break;
15071  }
15072  }
15073 
15074  // apply localization
15076 
15078 }
15079 
15080 int sexp_key_pressed(int node)
15081 {
15082  int z, t;
15083 
15084  Assert(node != -1);
15085  z = translate_key_to_index(CTEXT(node), false);
15086  if (z < 0){
15087  return SEXP_FALSE;
15088  }
15089 
15090  if (!Control_config[z].used){
15091  return SEXP_FALSE;
15092  }
15093 
15094  if (CDR(node) < 0){
15095  return SEXP_TRUE;
15096  }
15097 
15098  t = eval_num(CDR(node));
15099  return timestamp_has_time_elapsed(Control_config[z].used, t * 1000);
15100 }
15101 
15102 void sexp_key_reset(int node)
15103 {
15104  int n, z;
15105 
15106  for (n = node; n != -1; n = CDR(n))
15107  {
15108  z = translate_key_to_index(CTEXT(n), false);
15109  if (z >= 0)
15110  Control_config[z].used = 0;
15111  }
15112 }
15113 
15114 void sexp_ignore_key(int node)
15115 {
15116  int ignore_count;
15117  int ignored_key;
15118 
15119 
15120  ignore_count = eval_num(node);
15121 
15123  multi_send_int(ignore_count);
15124 
15125  node = CDR(node);
15126  while (node > -1) {
15127  // get the key
15128  ignored_key = translate_key_to_index(CTEXT(node), false);
15129 
15130  if (ignored_key > -1) {
15131  Ignored_keys[ignored_key] = ignore_count;
15132  }
15133 
15134  multi_send_int(ignored_key);
15135 
15136  node = CDR(node);
15137  }
15138 
15140 }
15141 
15143 {
15144  int ignored_key, ignore_count;
15145 
15146  multi_get_int(ignore_count);
15147 
15148  while (multi_get_int(ignored_key)) {
15149  Ignored_keys[ignored_key] = ignore_count;
15150  }
15151 }
15152 
15153 int sexp_targeted(int node)
15154 {
15155  int z;
15156  ship_subsys *ptr;
15157 
15158  z = ship_query_state(CTEXT(node));
15159  if (z == 1){
15160  return SEXP_KNOWN_FALSE; // ship isn't around, nor will it ever be
15161  } else if (z == -1) {
15162  return SEXP_CANT_EVAL;
15163  }
15164 
15165  z = ship_name_lookup(CTEXT(node), 1);
15166  if ((z < 0) || !Player_ai || (Ships[z].objnum != Player_ai->target_objnum)){
15167  return SEXP_FALSE;
15168  }
15169 
15170  if (CDR(node) >= 0) {
15171  z = eval_num(CDR(node)) * 1000;
15172  if (!timestamp_has_time_elapsed(Players_target_timestamp, z)){
15173  return SEXP_FALSE;
15174  }
15175 
15176  if (CDR(CDR(node)) >= 0) {
15177  ptr = Player_ai->targeted_subsys;
15178  if (!ptr || subsystem_stricmp(ptr->system_info->subobj_name, CTEXT(CDR(CDR(node))))){
15179  return SEXP_FALSE;
15180  }
15181  }
15182  }
15183 
15184  return SEXP_TRUE;
15185 }
15186 
15187 int sexp_node_targeted(int node)
15188 {
15189  int z;
15190 
15191  CJumpNode *jnp = jumpnode_get_by_name(CTEXT(node));
15192 
15193  if (jnp==NULL || !Player_ai || (jnp->GetSCPObjectNumber() != Player_ai->target_objnum)){
15194  return SEXP_FALSE;
15195  }
15196 
15197  if (CDR(node) >= 0) {
15198  z = eval_num(CDR(node)) * 1000;
15199  if (!timestamp_has_time_elapsed(Players_target_timestamp, z)){
15200  return SEXP_FALSE;
15201  }
15202  }
15203 
15204  return SEXP_TRUE;
15205 }
15206 
15207 int sexp_speed(int node)
15208 {
15209  if (Training_context & TRAINING_CONTEXT_SPEED) {
15210  if (Training_context_speed_set){
15211  if (timestamp_has_time_elapsed(Training_context_speed_timestamp, eval_num(node) * 1000)){
15212  return SEXP_KNOWN_TRUE;
15213  }
15214  }
15215  }
15216 
15217  return SEXP_FALSE;
15218 }
15219 
15221 {
15222  player *the_player;
15223 
15224  the_player = get_player_from_ship_node(node);
15225 
15226  if (the_player != NULL) {
15227  float max_speed = Ship_info[Ships[Objects[the_player->objnum].instance].ship_info_index].max_speed;
15228  return (int)(the_player->ci.forward_cruise_percent / 100.0f * max_speed);
15229  }
15230 
15231  return 0;
15232 }
15233 
15234 // CommanderDJ
15236 {
15237  //get and sanity check the player first
15238  player *the_player;
15239  the_player = get_player_from_ship_node(node);
15240 
15241  if(the_player != NULL)
15242  {
15243  //now the throttle percentage
15244  node = CDR(node);
15245  int throttle_percent = eval_num(node);
15246  CLAMP(throttle_percent, 0, 100);
15247 
15248  //now actually set the throttle
15249  the_player->ci.forward_cruise_percent = (float) throttle_percent;
15250  }
15251 }
15252 
15253 // Goober5000
15255 {
15256  int sindex, num_banks, num_depleted_banks;
15257  ship *shipp;
15258 
15259  // get ship
15260  sindex = ship_name_lookup(CTEXT(node));
15261  if (sindex < 0) {
15262  return SEXP_FALSE;
15263  }
15264 
15265  shipp = &Ships[sindex];
15266  if (shipp->objnum < 0) {
15267  return SEXP_FALSE;
15268  }
15269 
15270  // see if ship has ballistic primary weapons
15271  if (!(Ship_info[shipp->ship_info_index].flags & SIF_BALLISTIC_PRIMARIES))
15272  return SEXP_FALSE;
15273 
15274  // get num primary banks
15275  num_banks = shipp->weapons.num_primary_banks;
15276  num_depleted_banks = 0;
15277 
15278  // get number of depleted banks
15279  for (int idx=0; idx<num_banks; idx++)
15280  {
15281  // is this a ballistic bank?
15283  {
15284  // is this bank out of ammo?
15285  if (shipp->weapons.primary_bank_ammo[idx] == 0)
15286  {
15287  num_depleted_banks++;
15288  }
15289  }
15290  }
15291 
15292  // are they all depleted?
15293  return (num_depleted_banks == num_banks);
15294 }
15295 
15297 {
15298  int sindex, num_banks, num_depleted_banks;
15299  ship *shipp;
15300 
15301  // get ship
15302  sindex = ship_name_lookup(CTEXT(node));
15303  if (sindex < 0) {
15304  return SEXP_FALSE;
15305  }
15306 
15307  shipp = &Ships[sindex];
15308  if (shipp->objnum < 0) {
15309  return SEXP_FALSE;
15310  }
15311 
15312  // get num secondary banks
15313  num_banks = shipp->weapons.num_secondary_banks;
15314  num_depleted_banks = 0;
15315 
15316  // get number of depleted banks
15317  for (int idx=0; idx<num_banks; idx++) {
15318  if (shipp->weapons.secondary_bank_ammo[idx] == 0) {
15319  num_depleted_banks++;
15320  }
15321  }
15322 
15323  // are they all depleted?
15324  return (num_depleted_banks == num_banks);
15325 }
15326 
15327 int sexp_facing(int node)
15328 {
15329  float a1, a2;
15330  vec3d v1, v2;
15331 
15332  if (!Player_obj) {
15333  return SEXP_FALSE;
15334  }
15335 
15336  ship *target_shipp = sexp_get_ship_from_node(node);
15337  if (target_shipp == NULL) {
15338  // hasn't arrived yet
15339  if (mission_parse_get_arrival_ship(CTEXT(node)) != NULL) {
15340  return SEXP_CANT_EVAL;
15341  }
15342  // not found and won't arrive: invalid
15343  return SEXP_KNOWN_FALSE;
15344  }
15345  double angle = atof(CTEXT(CDR(node)));
15346 
15347  v1 = Player_obj->orient.vec.fvec;
15348  vm_vec_normalize(&v1);
15349 
15350  vm_vec_sub(&v2, &Objects[target_shipp->objnum].pos, &Player_obj->pos);
15351  vm_vec_normalize(&v2);
15352 
15353  a1 = vm_vec_dot(&v1, &v2);
15354  a2 = cosf(fl_radians(angle));
15355  if (a1 >= a2){
15356  return SEXP_TRUE;
15357  }
15358 
15359  return SEXP_FALSE;
15360 }
15361 
15362 int sexp_is_facing(int node)
15363 {
15364  object *origin_objp, *target_objp;
15365  float a1, a2;
15366  vec3d v1, v2;
15367 
15368  ship *origin_shipp = sexp_get_ship_from_node(node);
15369  if (origin_shipp == NULL) {
15370  // hasn't arrived yet
15371  if (mission_parse_get_arrival_ship(CTEXT(node)) != NULL) {
15372  return SEXP_CANT_EVAL;
15373  }
15374  // not found and won't arrive: invalid
15375  return SEXP_KNOWN_FALSE;
15376  }
15377  node = CDR(node);
15378 
15381 
15382  if (oswpt.type == OSWPT_TYPE_SHIP && sexp_get_ship_from_node(node) == NULL) {
15383  return SEXP_KNOWN_FALSE;
15384  }
15385 
15386  // only true if ship has departed or not yet arrived
15387  if (oswpt.type == OSWPT_TYPE_EXITED || oswpt.type == OSWPT_TYPE_PARSE_OBJECT) {
15388  return SEXP_CANT_EVAL;
15389  }
15390 
15391  if (oswpt.type == OSWPT_TYPE_NONE)
15392  return SEXP_CANT_EVAL;
15393 
15394  origin_objp = &Objects[origin_shipp->objnum];
15395  target_objp = oswpt.objp;
15396 
15397  node = CDR(node);
15398 
15399  double angle = atof(CTEXT(node));
15400  node = CDR(node);
15401 
15402  // check optional distance argument
15403  if (node > 0 && (sexp_distance3(origin_objp, target_objp) > eval_num(node))) {
15404  return SEXP_FALSE;
15405  }
15406 
15407  v1 = origin_objp->orient.vec.fvec;
15408  vm_vec_normalize(&v1);
15409 
15410  vm_vec_sub(&v2, &target_objp->pos, &origin_objp->pos);
15411  vm_vec_normalize(&v2);
15412 
15413  a1 = vm_vec_dot(&v1, &v2);
15414  a2 = cosf(fl_radians(angle));
15415  if (a1 >= a2){
15416  return SEXP_TRUE;
15417  }
15418 
15419  return SEXP_FALSE;
15420 }
15421 
15422 // is ship facing first waypoint in waypoint path
15423 int sexp_facing2(int node)
15424 {
15425  float a1, a2;
15426  vec3d v1, v2;
15427 
15428  // bail if Player_obj is not good
15429  if (!Player_obj) {
15430  return SEXP_CANT_EVAL;
15431  }
15432 
15433  // get player fvec
15434  v1 = Player_obj->orient.vec.fvec;
15435  vm_vec_normalize(&v1);
15436 
15437  // get waypoint name
15438  char *waypoint_name = CTEXT(node);
15439 
15440  // get position of first waypoint
15441  waypoint_list *wp_list = find_matching_waypoint_list(waypoint_name);
15442 
15443  if (wp_list == NULL) {
15444  return SEXP_CANT_EVAL;
15445  }
15446 
15447  vm_vec_sub(&v2, wp_list->get_waypoints().front().get_pos(), &Player_obj->pos);
15448  vm_vec_normalize(&v2);
15449  a1 = vm_vec_dot(&v1, &v2);
15450  a2 = cosf(fl_radians(atof(CTEXT(CDR(node)))));
15451  if (a1 >= a2){
15452  return SEXP_TRUE;
15453  }
15454 
15455  return SEXP_FALSE;
15456 }
15457 
15458 int sexp_order(int n)
15459 {
15460  char *order_to = CTEXT(n);
15461  char *order = CTEXT(CDR(n));
15462  char *target = NULL;
15463 
15464  //target
15465  n = CDDR(n);
15466  if (n != -1)
15467  target = CTEXT(n);
15468 
15469  return hud_query_order_issued(order_to, order, target);
15470 }
15471 
15473 {
15474  char *order_to = CTEXT(n);
15475  char *order = CTEXT(CDR(n));
15476  char *target = NULL;
15477  char *order_from = NULL;
15478  char *special = NULL;
15479  int timestamp = 0;
15480 
15481  // delay
15482  n = CDDR(n);
15483  if (n != -1) {
15484  timestamp = eval_sexp(n);
15485  n = CDR(n);
15486  }
15487 
15488  //target
15489  if (n != -1) {
15490  target = CTEXT(n);
15491  n = CDR(n);
15492  }
15493 
15494  // player order comes from
15495  if (n != -1) {
15496  order_from = CTEXT(n);
15497  n = CDR(n);
15498  }
15499 
15500  // optional special argument
15501  if (n != -1)
15502  special = CTEXT(n);
15503 
15504  return hud_query_order_issued(order_to, order, target, timestamp, order_from, special);
15505 }
15506 
15507 // Karajorma
15509 {
15510  Squadmsg_history.clear();
15511 }
15512 
15514 {
15515  if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
15516  if (Training_context_at_waypoint > Training_context_goal_waypoint){
15517  return SEXP_TRUE;
15518  }
15519  }
15520 
15521  return SEXP_FALSE;
15522 }
15523 
15525 {
15526  if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
15527  if (Training_context_at_waypoint < Training_context_goal_waypoint - 1){
15528  return SEXP_TRUE;
15529  }
15530  }
15531 
15532  return SEXP_FALSE;
15533 }
15534 
15536 {
15537  if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
15538  if ((uint) Training_context_goal_waypoint == Training_context_path->get_waypoints().size()){
15539  return SEXP_TRUE;
15540  }
15541  }
15542 
15543  return SEXP_FALSE;
15544 }
15545 
15547 {
15548  int t = -1, delay = 0;
15549 
15550  if(physics_paused){
15551  return;
15552  }
15553 
15554  Assert(node >= 0);
15555  Assert(Event_index >= 0);
15556 
15557  if ((CDR(node) >= 0) && (CDR(CDR(node)) >= 0)) {
15558  delay = eval_num(CDR(CDR(node))) * 1000;
15559  t = CDR(CDR(CDR(node)));
15560  if (t >= 0){
15561  t = eval_num(t);
15562  }
15563  }
15564 
15566  multi_send_int(t);
15567  multi_send_int(delay);
15568 
15569  if ((Mission_events[Event_index].repeat_count > 1) || (CDR(node) < 0)){
15570  message_training_queue(CTEXT(node), timestamp(delay), t);
15571  multi_send_string(CTEXT(node));
15572  } else {
15573  message_training_queue(CTEXT(CDR(node)), timestamp(delay), t);
15574  multi_send_string(CTEXT(CDR(node)));
15575  }
15577 }
15578 
15580 {
15581  int t, delay;
15582  char message[TOKEN_LENGTH];
15583 
15584  multi_get_int(t);
15585  multi_get_int(delay);
15586  if (multi_get_string(message)) {
15587  message_training_queue(message, timestamp(delay), t);
15588  }
15589 
15590 }
15591 
15593 {
15594  int sindex;
15595 
15596  // get the firing ship
15597  sindex = ship_name_lookup(CTEXT(node));
15598  if(sindex < 0){
15599  return 0;
15600  }
15601  if(Ships[sindex].objnum < 0){
15602  return 0;
15603  }
15604 
15605  // shield recharge pct
15606  return (int)(100.0f * Energy_levels[Ships[sindex].shield_recharge_index]);
15607 }
15608 
15610 {
15611  int sindex;
15612 
15613  // get the firing ship
15614  sindex = ship_name_lookup(CTEXT(node));
15615  if(sindex < 0){
15616  return 0;
15617  }
15618  if(Ships[sindex].objnum < 0){
15619  return 0;
15620  }
15621 
15622  // shield recharge pct
15623  return (int)(100.0f * Energy_levels[Ships[sindex].engine_recharge_index]);
15624 }
15625 
15627 {
15628  int sindex;
15629 
15630  // get the firing ship
15631  sindex = ship_name_lookup(CTEXT(node));
15632  if(sindex < 0){
15633  return 0;
15634  }
15635  if(Ships[sindex].objnum < 0){
15636  return 0;
15637  }
15638 
15639  // shield recharge pct
15640  return (int)(100.0f * Energy_levels[Ships[sindex].weapon_recharge_index]);
15641 }
15642 
15646 int sexp_get_ets_value(int node)
15647 {
15648  int sindex;
15649  SCP_string ets_type;
15650 
15651  ets_type = CTEXT(node);
15652  node = CDR(node);
15653 
15654  sindex = ship_name_lookup(CTEXT(node));
15655  if (sindex < 0) {
15656  return SEXP_FALSE;
15657  }
15658  if (Ships[sindex].objnum < 0) {
15659  return SEXP_FALSE;
15660  }
15661 
15662  if (!stricmp(ets_type.c_str(), "engine")) {
15663  return Ships[sindex].engine_recharge_index;
15664  } else if (!stricmp(ets_type.c_str(), "shield")) {
15665  return Ships[sindex].shield_recharge_index;
15666  } else if (!stricmp(ets_type.c_str(), "weapon")) {
15667  return Ships[sindex].weapon_recharge_index;
15668  } else {
15669  return SEXP_FALSE;
15670  }
15671 }
15672 
15676 void sexp_set_ets_values(int node)
15677 {
15678  int sindex;
15680 
15681  ets_idx[ENGINES] = eval_num(node);
15682  node = CDR(node);
15683  ets_idx[SHIELDS] = eval_num(node);
15684  node = CDR(node);
15685  ets_idx[WEAPONS] = eval_num(node);
15686  node = CDR(node);
15687 
15688  // sanity check inputs
15689  sanity_check_ets_inputs(ets_idx);
15690 
15692 
15693  // apply ETS settings to specified ships
15694  for ( ; node != -1; node = CDR(node)) {
15695  sindex = ship_name_lookup(CTEXT(node));
15696 
15697  if (sindex >= 0 && validate_ship_ets_indxes(sindex, ets_idx)) {
15698  Ships[sindex].engine_recharge_index = ets_idx[ENGINES];
15699  Ships[sindex].shield_recharge_index = ets_idx[SHIELDS];
15700  Ships[sindex].weapon_recharge_index = ets_idx[WEAPONS];
15701 
15702  multi_send_ship(sindex);
15703  multi_send_int(ets_idx[ENGINES]);
15704  multi_send_int(ets_idx[SHIELDS]);
15705  multi_send_int(ets_idx[WEAPONS]);
15706  }
15707  }
15709 }
15710 
15712 {
15713  int sindex;
15715 
15716  while (multi_get_ship(sindex)) {
15717  multi_get_int(ets_idx[ENGINES]);
15718  multi_get_int(ets_idx[SHIELDS]);
15719  multi_get_int(ets_idx[WEAPONS]);
15720 
15721  Ships[sindex].engine_recharge_index = ets_idx[ENGINES];
15722  Ships[sindex].shield_recharge_index = ets_idx[SHIELDS];
15723  Ships[sindex].weapon_recharge_index = ets_idx[WEAPONS];
15724  }
15725 }
15726 
15728 {
15729  int sindex, idx;
15730  float max_quad, check;
15731  ship_info *sip;
15732  object *objp;
15733 
15734  // get the ship
15735  sindex = ship_name_lookup(CTEXT(node));
15736  if(sindex < 0){
15737  return SEXP_FALSE;
15738  }
15739  if((Ships[sindex].objnum < 0) || (Ships[sindex].objnum >= MAX_OBJECTS)){
15740  return SEXP_FALSE;
15741  }
15742  if((Ships[sindex].ship_info_index < 0) || (Ships[sindex].ship_info_index >= static_cast<int>(Ship_info.size()))){
15743  return SEXP_FALSE;
15744  }
15745  objp = &Objects[Ships[sindex].objnum];
15746  sip = &Ship_info[Ships[sindex].ship_info_index];
15747  if(!(sip->flags & SIF_SMALL_SHIP)){
15748  return SEXP_FALSE;
15749  }
15750  max_quad = get_max_shield_quad(objp);
15751 
15752  // shield pct
15753  check = (float)eval_num(CDR(node));
15754 
15755  // check his quadrants
15756  for(idx=0; idx<objp->n_quadrants; idx++){
15757  if( ((objp->shield_quadrant[idx] / max_quad) * 100.0f) <= check ){
15758  return SEXP_TRUE;
15759  }
15760  }
15761 
15762  // all good
15763  return SEXP_FALSE;
15764 }
15765 
15766 // Goober5000
15768 {
15769  ship *shipp;
15770  int sindex;
15771  int check, idx;
15772  int ret_sum[MAX_SHIP_PRIMARY_BANKS];
15773  int ret = 0;
15774 
15775  // get the ship
15776  sindex = ship_name_lookup(CTEXT(node));
15777  if(sindex < 0)
15778  {
15779  return 0;
15780  }
15781  if((Ships[sindex].objnum < 0) || (Ships[sindex].objnum >= MAX_OBJECTS))
15782  {
15783  return 0;
15784  }
15785  shipp = &Ships[sindex];
15786 
15787  // bank to check
15788  check = eval_num(CDR(node));
15789 
15790  // bogus check?
15791  if(check < 0){
15792  return 0;
15793  }
15794 
15795  // cumulative sum?
15796  if(check >= shipp->weapons.num_primary_banks)
15797  {
15798  for(idx=0; idx<shipp->weapons.num_primary_banks; idx++)
15799  {
15800  // ballistic
15802  {
15803  ret_sum[idx] = (int)(((float)shipp->weapons.primary_bank_ammo[idx] / (float)shipp->weapons.primary_bank_start_ammo[idx]) * 100.0f);
15804  }
15805  // non-ballistic
15806  else
15807  {
15808  ret_sum[idx] = 100;
15809  }
15810  }
15811 
15812  // add it up
15813  ret = 0;
15814  for(idx=0; idx<shipp->weapons.num_primary_banks; idx++)
15815  {
15816  ret += ret_sum[idx];
15817  }
15818  ret = (int)((float)ret / (float)shipp->weapons.num_primary_banks);
15819  }
15820  else
15821  {
15822  // ballistic
15824  {
15825  ret = (int)(((float)shipp->weapons.primary_bank_ammo[check] / (float)shipp->weapons.primary_bank_start_ammo[check]) * 100.0f);
15826  }
15827  // non-ballistic
15828  else
15829  {
15830  ret = 100;
15831  }
15832  }
15833 
15834  // return
15835  return ret;
15836 }
15837 
15839 {
15840  ship *shipp;
15841  int sindex;
15842  int check, idx;
15843  int ret_sum[MAX_SHIP_SECONDARY_BANKS];
15844  int ret = 0;
15845 
15846  // get the ship
15847  sindex = ship_name_lookup(CTEXT(node));
15848  if(sindex < 0){
15849  return 0;
15850  }
15851  if((Ships[sindex].objnum < 0) || (Ships[sindex].objnum >= MAX_OBJECTS)){
15852  return 0;
15853  }
15854  shipp = &Ships[sindex];
15855 
15856  // bank to check
15857  check = eval_num(CDR(node));
15858 
15859  // bogus check?
15860  if(check < 0){
15861  return 0;
15862  }
15863 
15864  // cumulative sum?
15865  if(check >= shipp->weapons.num_secondary_banks){
15866  for(idx=0; idx<shipp->weapons.num_secondary_banks; idx++){
15867  ret_sum[idx] = (int)(((float)shipp->weapons.secondary_bank_ammo[idx] / (float)shipp->weapons.secondary_bank_start_ammo[idx]) * 100.0f);
15868  }
15869 
15870  // add it up
15871  ret = 0;
15872  for(idx=0; idx<shipp->weapons.num_secondary_banks; idx++){
15873  ret += ret_sum[idx];
15874  }
15875  ret = (int)((float)ret / (float)shipp->weapons.num_secondary_banks);
15876  } else {
15877  ret = (int)(((float)shipp->weapons.secondary_bank_ammo[check] / (float)shipp->weapons.secondary_bank_start_ammo[check]) * 100.0f);
15878  }
15879 
15880  // return
15881  return ret;
15882 }
15883 
15884 
15885 // Karajorma - returns the number of bullets left in an ballistic ammo bank. Unlike primary_ammo_pct
15886 // it does this as a numerical value rather than as a percentage of the maximum
15888 {
15889  ship *shipp;
15890  int ammo_left = 0;
15891  int sindex;
15892  int check;
15893 
15894  // get the ship
15895  sindex = ship_name_lookup(CTEXT(node));
15896  if(sindex < 0)
15897  {
15898  return 0;
15899  }
15900  if((Ships[sindex].objnum < 0) || (Ships[sindex].objnum >= MAX_OBJECTS))
15901  {
15902  return 0;
15903  }
15904  shipp = &Ships[sindex];
15905 
15906  // bank to check
15907  check = eval_num(CDR(node));
15908 
15909  // bogus check?
15910  if(check < 0){
15911  return 0;
15912  }
15913 
15914  // cumulative sum?
15915  if(check >= shipp->weapons.num_primary_banks)
15916  {
15917  for(int bank=0; bank<shipp->weapons.num_primary_banks; bank++)
15918  {
15919  // Only ballistic weapons need to be counted
15921  {
15922  ammo_left += shipp->weapons.primary_bank_ammo[bank] ;
15923  }
15924  }
15925  }
15926  else
15927  {
15928  // Again only ballistic weapons need to be counted
15930  {
15931  ammo_left = shipp->weapons.primary_bank_ammo[check] ;
15932  }
15933  }
15934 
15935  // return
15936  return ammo_left;
15937 }
15938 
15939 
15940 // Karajorma - sets the amount of ammo in a certain ballistic weapon bank to the specified value
15941 void sexp_set_primary_ammo (int node)
15942 {
15943  int sindex;
15944  int requested_bank ;
15945  int requested_weapons ;
15946  int rearm_limit = 0;
15947 
15948  // Check that a ship has been supplied
15949  sindex = ship_name_lookup(CTEXT(node));
15950  if (sindex < 0)
15951  {
15952  return ;
15953  }
15954 
15955  // Get the bank to set the number on
15956  requested_bank = eval_num(CDR(node));
15957  if (requested_bank < 0)
15958  {
15959  return ;
15960  }
15961 
15962  // Get the number of weapons requested
15963  node = CDR(node);
15964  requested_weapons = eval_num(CDR(node));
15965  if (requested_weapons < 0)
15966  {
15967  return ;
15968  }
15969 
15970  node = CDDR(node);
15971 
15972  // If a rearm limit hasn't been specified simply change the ammo.Otherwise read in the rearm limit
15973  if (node < 0) {
15974  set_primary_ammo (sindex, requested_bank, requested_weapons);
15975  }
15976  else {
15977  rearm_limit = eval_num(node);
15978  set_primary_ammo (sindex, requested_bank, requested_weapons, rearm_limit);
15979  }
15980 }
15981 
15982 //Karajorma - Helper function for the set-primary-ammo and weapon functions
15983 void set_primary_ammo (int ship_index, int requested_bank, int requested_ammo, int rearm_limit, bool update)
15984 {
15985  ship *shipp;
15986  int maximum_allowed ;
15987 
15988  // Check that it's valid
15989  if((Ships[ship_index].objnum < 0) || (Ships[ship_index].objnum >= MAX_OBJECTS)){
15990  return ;
15991  }
15992  shipp = &Ships[ship_index];
15993 
15994  // Can only set one bank at a time. Check that someone hasn't asked for the contents of all
15995  // the banks or a non-existant bank
15996  if ((requested_bank > shipp->weapons.num_primary_banks) || requested_bank < 0)
15997  {
15998  return ;
15999  }
16000 
16001  // Check that this isn't a non-ballistic bank as it's pointless to set the amount of ammo for those
16002  if (!(Weapon_info[shipp->weapons.primary_bank_weapons[requested_bank]].wi_flags2 & WIF2_BALLISTIC))
16003  {
16004  return ;
16005  }
16006 
16007  //Check that a valid number of weapons have been specified.
16008  if (requested_ammo < 0)
16009  {
16010  return ;
16011  }
16012 
16013  // Is the number requested larger than the maximum allowed for that particular bank?
16014  maximum_allowed = fl2i((Ship_info[shipp->ship_info_index].primary_bank_ammo_capacity[requested_bank]
16015  / Weapon_info[shipp->weapons.primary_bank_weapons[requested_bank]].cargo_size)+0.5);
16016  if (maximum_allowed < requested_ammo)
16017  {
16018  requested_ammo = maximum_allowed ;
16019  }
16020 
16021  // Set the number of weapons
16022  shipp->weapons.primary_bank_ammo[requested_bank] = requested_ammo ;
16023 
16024  // If a rearm limit has been specified set it.
16025  if (rearm_limit >= 0)
16026  {
16027  // Don't allow more weapons than the bank can actually hold.
16028  if (rearm_limit > maximum_allowed)
16029  {
16030  rearm_limit = maximum_allowed;
16031  }
16032 
16033  shipp->weapons.primary_bank_start_ammo[requested_bank] = rearm_limit;
16034  }
16035 
16036  // The change needs to be passed on if this is a multiplayer game
16037  if (MULTIPLAYER_MASTER & update)
16038  {
16039  send_weapon_or_ammo_changed_packet(ship_index, 0, requested_bank, requested_ammo, rearm_limit, -1);
16040  }
16041 }
16042 
16043 // Karajorma - returns the number of missiles left in an ammo bank. Unlike secondary_ammo_pct
16044 // it does this as a numerical value rather than as a percentage of the maximum
16046 {
16047  int ammo_left = 0 ;
16048  ship *shipp ;
16049  int sindex ;
16050  int check ;
16051 
16052  // Get the ship
16053  sindex = ship_name_lookup(CTEXT(node));
16054  if (sindex < 0)
16055  {
16056  return 0;
16057  }
16058  if((Ships[sindex].objnum < 0) || (Ships[sindex].objnum >= MAX_OBJECTS)){
16059  return 0;
16060  }
16061  shipp = &Ships[sindex];
16062 
16063  // bank to check
16064  check = eval_num(CDR(node));
16065 
16066  // bogus check?
16067  if(check < 0){
16068  return 0;
16069  }
16070 
16071  // Are we looking at the number of secondaries in all banks?
16072  if(check > shipp->weapons.num_secondary_banks)
16073  {
16074  for(int bank=0; bank<shipp->weapons.num_secondary_banks; bank++)
16075  {
16076  ammo_left += shipp->weapons.secondary_bank_ammo[bank] ;
16077  }
16078  }
16079  // If not return the value for the bank requested.
16080  else
16081  {
16082  ammo_left = shipp->weapons.secondary_bank_ammo[check] ;
16083  }
16084 
16085  return ammo_left ;
16086 }
16087 
16088 // Karajorma - sets the amount of ammo in a certain weapon bank to the specified value
16089 void sexp_set_secondary_ammo (int node)
16090 {
16091  int sindex;
16092  int requested_bank;
16093  int requested_weapons;
16094  int rearm_limit;
16095 
16096  // Check that a ship has been supplied
16097  sindex = ship_name_lookup(CTEXT(node));
16098  if (sindex < 0)
16099  {
16100  return ;
16101  }
16102 
16103  // Get the bank to set the number on
16104  requested_bank = eval_num(CDR(node));
16105  if (requested_bank < 0)
16106  {
16107  return ;
16108  }
16109 
16110  // Get the number of weapons requested
16111  node = CDR(node);
16112  requested_weapons = eval_num(CDR(node));
16113  if (requested_weapons < 0)
16114  {
16115  return ;
16116  }
16117 
16118  node = CDDR(node);
16119 
16120  // If a rearm limit hasn't been specified simply change the ammo.Otherwise read in the rearm limit
16121  if (node < 0) {
16122  set_secondary_ammo(sindex, requested_bank, requested_weapons);
16123  }
16124  else {
16125  rearm_limit = eval_num(node);
16126  set_secondary_ammo(sindex, requested_bank, requested_weapons, rearm_limit);
16127  }
16128 }
16129 
16130 //Karajorma - Helper function for the set-secondary-ammo and weapon functions
16131 void set_secondary_ammo (int ship_index, int requested_bank, int requested_ammo, int rearm_limit, bool update)
16132 {
16133  ship *shipp;
16134  int maximum_allowed;
16135  // Check that it's valid
16136  if((Ships[ship_index].objnum < 0) || (Ships[ship_index].objnum >= MAX_OBJECTS)){
16137  return ;
16138  }
16139  shipp = &Ships[ship_index];
16140 
16141  // Can only set one bank at a time. Check that someone hasn't asked for the contents of all
16142  // the banks or a non-existant bank
16143  if ((requested_bank > shipp->weapons.num_secondary_banks) || requested_bank < 0)
16144  {
16145  return ;
16146  }
16147 
16148  if (requested_ammo < 0)
16149  {
16150  return ;
16151  }
16152 
16153  // Is the number requested larger than the maximum allowed for that particular bank?
16154  maximum_allowed = fl2i(shipp->weapons.secondary_bank_capacity[requested_bank]
16155  / Weapon_info[shipp->weapons.secondary_bank_weapons[requested_bank]].cargo_size);
16156  if (maximum_allowed < requested_ammo)
16157  {
16158  requested_ammo = maximum_allowed ;
16159  }
16160 
16161  // Set the number of weapons
16162  shipp->weapons.secondary_bank_ammo[requested_bank] = requested_ammo ;
16163 
16164  // If a rearm limit has been specified set it.
16165  if (rearm_limit >= 0)
16166  {
16167  // Don't allow more weapons than the bank can actually hold.
16168  if (rearm_limit > maximum_allowed)
16169  {
16170  rearm_limit = maximum_allowed;
16171  }
16172 
16173  shipp->weapons.secondary_bank_start_ammo[requested_bank] = rearm_limit;
16174  }
16175 
16176  // The change needs to be passed on if this is a multiplayer game and we're not already updating the weapon
16177  if (MULTIPLAYER_MASTER && update)
16178  {
16179  send_weapon_or_ammo_changed_packet(ship_index, 1, requested_bank, requested_ammo, rearm_limit, -1);
16180  }
16181 }
16182 
16183 // Karajorma - Changes the weapon in the requested bank to the one supplied. Optionally sets the ammo and
16184 // rearm limit too.
16185 void sexp_set_weapon (int node, bool primary)
16186 {
16187  ship *shipp;
16188  int sindex, requested_bank, windex, requested_ammo=-1, rearm_limit=-1;
16189 
16190  Assert (node != -1);
16191 
16192  // Check that a ship has been supplied
16193  sindex = ship_name_lookup(CTEXT(node));
16194  if (sindex < 0)
16195  {
16196  return ;
16197  }
16198 
16199  // Check that it's valid
16200  if((Ships[sindex].objnum < 0) || (Ships[sindex].objnum >= MAX_OBJECTS)){
16201  return ;
16202  }
16203  shipp = &Ships[sindex];
16204 
16205  // Get the bank to change the weapon of
16206  requested_bank = eval_num(CDR(node));
16207 
16208  // Skip to the node holding the weapon name
16209  node = CDDR(node);
16210 
16211  windex = weapon_info_lookup(CTEXT(node));
16212  if (windex < 0)
16213  {
16214  return;
16215  }
16216 
16217  if (primary)
16218  {
16219  // Change the weapon
16220  shipp->weapons.primary_bank_weapons[requested_bank] = windex ;
16221  }
16222  else
16223  {
16224  // Change the weapon
16225  shipp->weapons.secondary_bank_weapons[requested_bank] = windex ;
16226  }
16227 
16228 
16229  // Check to see if the optional ammo and rearm_limit settings were supplied
16230  node = CDR(node);
16231  if (node >= 0) {
16232  requested_ammo = eval_num(node);
16233 
16234  if (requested_ammo < 0) {
16235  requested_ammo = 0;
16236  }
16237  node = CDR(node);
16238 
16239  // If nothing was supplied then set the rearm limit to a negative value so that it is ignored
16240  if (node < 0) {
16241  rearm_limit = -1;
16242  }
16243  else {
16244  rearm_limit = eval_num(node);
16245  }
16246 
16247  // Set the ammo but do not send an ammo changed update packet as we'll do that later from here
16248  if (primary) {
16249  set_primary_ammo (sindex, requested_bank, requested_ammo, rearm_limit, false);
16250  }
16251  else {
16252  set_secondary_ammo (sindex, requested_bank, requested_ammo, rearm_limit, false);
16253  }
16254  }
16255  else {
16256  // read the data
16257  if (primary) {
16258  requested_ammo = shipp->weapons.primary_bank_ammo[requested_bank];
16259  rearm_limit = shipp->weapons.primary_bank_start_ammo[requested_bank];
16260  }
16261  else {
16262  requested_ammo = shipp->weapons.secondary_bank_ammo[requested_bank];
16263  rearm_limit = shipp->weapons.secondary_bank_start_ammo[requested_bank];
16264  }
16265  }
16266 
16267  // Now pass this info on to clients if need be.
16268  if (MULTIPLAYER_MASTER)
16269  {
16270  if (primary) {
16271  send_weapon_or_ammo_changed_packet(sindex, 0, requested_bank, requested_ammo, rearm_limit, windex);
16272  }
16273  else {
16274  send_weapon_or_ammo_changed_packet(sindex, 1, requested_bank, requested_ammo, rearm_limit, windex);
16275  }
16276  }
16277 }
16278 
16280 {
16281  ship *shipp;
16282 
16283  shipp = sexp_get_ship_from_node(node);
16284 
16285  if (shipp !=NULL) {
16286  return shipp->cmeasure_count;
16287  }
16288  else {
16289  return SEXP_NAN;
16290  }
16291 }
16292 
16294 {
16295  ship *shipp;
16296  int num_cmeasures;
16297 
16298  shipp = sexp_get_ship_from_node(node);
16299 
16300  if (shipp == NULL) {
16301  return;
16302  }
16303  node = CDR(node);
16304  num_cmeasures = eval_num(node);
16305  if (num_cmeasures < 0) {
16306  num_cmeasures = 0;
16307  }
16308  else if (num_cmeasures > Ship_info[shipp->ship_info_index].cmeasure_max) {
16309  num_cmeasures = Ship_info[shipp->ship_info_index].cmeasure_max;
16310  }
16311 
16312  shipp->cmeasure_count = num_cmeasures;
16313 
16315  multi_send_ship(shipp);
16316  multi_send_int(num_cmeasures);
16318 }
16319 
16321 {
16322  int num_cmeasures = 0;
16323  ship *shipp;
16324 
16325  multi_get_ship(shipp);
16326  if (shipp == NULL) {
16327  return;
16328  }
16329  if (multi_get_int(num_cmeasures)) {
16330  shipp->cmeasure_count = num_cmeasures;
16331  }
16332 }
16333 
16334 // KeldorKatarn - Locks or unlocks the afterburner on the requested ship
16335 void sexp_deal_with_afterburner_lock (int node, bool lock)
16336 {
16337  Assert (node != -1);
16338  sexp_deal_with_ship_flag(node, true, 0, 0, 0, SF2_AFTERBURNER_LOCKED, 0, 0, (lock ? 1:0), true);
16339 }
16340 
16341 // Karajorma - locks or unlocks primary weapons on the requested ship
16342 void sexp_deal_with_primary_lock (int node, bool lock)
16343 {
16344  Assert (node != -1);
16345  sexp_deal_with_ship_flag(node, true, 0, 0, 0, SF2_PRIMARIES_LOCKED, 0, P2_SF2_PRIMARIES_LOCKED, (lock ? 1:0), true);
16346 
16347 }
16348 
16349 void sexp_deal_with_secondary_lock (int node, bool lock)
16350 {
16351  Assert (node != -1);
16352  sexp_deal_with_ship_flag(node, true, 0, 0, 0, SF2_SECONDARIES_LOCKED, 0, P2_SF2_SECONDARIES_LOCKED, (lock ? 1:0), true);
16353 
16354 }
16355 
16356 //Karajorma - Changes the subsystem name displayed on the HUD.
16358 {
16359  ship *shipp;
16360  int ship_index;
16361  char *new_name;
16362  ship_subsys *subsystem_to_rename;
16363 
16364  Assert (node != -1);
16365 
16366  // Check that a ship has been supplied
16367  ship_index = ship_name_lookup(CTEXT(node));
16368  if (ship_index < 0) {
16369  return;
16370  }
16371 
16372  shipp = &Ships[ship_index];
16373  node = CDR(node);
16374 
16375  if (node < 0) {
16376  return;
16377  }
16378 
16379  new_name = CTEXT(node);
16380  node = CDR(node);
16381 
16382  if (MULTIPLAYER_MASTER) {
16384  multi_send_ship(shipp);
16385  multi_send_string(new_name);
16386  }
16387 
16388  // loop through all the subsystems the SEXP has provided
16389  while (node >= 0) {
16390 
16391  //Get the new subsystem name
16392  subsystem_to_rename = ship_get_subsys(&Ships[ship_index], CTEXT(node));
16393  if (subsystem_to_rename != NULL) {
16394  ship_subsys_set_name(subsystem_to_rename, new_name);
16395 
16396  if (MULTIPLAYER_MASTER) {
16397  multi_send_string(CTEXT(node));
16398  }
16399  }
16400 
16401  node = CDR(node);
16402  }
16403 
16404  if (MULTIPLAYER_MASTER) {
16406  }
16407 }
16408 
16410 {
16411  ship *shipp = NULL;
16412  char new_name[TOKEN_LENGTH];
16413  char subsys_name[MAX_NAME_LEN];
16414  ship_subsys *subsystem_to_rename;
16415 
16416  multi_get_ship(shipp);
16417  multi_get_string(new_name);
16418  while (multi_get_string(subsys_name)) {
16419  subsystem_to_rename = ship_get_subsys(shipp, subsys_name);
16420  if (subsystem_to_rename != NULL) {
16421  ship_subsys_set_name(subsystem_to_rename, new_name);
16422  }
16423  }
16424 }
16425 
16426 // Goober5000
16428 {
16429  int ship_num, class_num = ship_info_lookup(CTEXT(n));
16430  Assert(class_num != -1);
16431 
16432  n = CDR(n);
16433 
16434  if (MULTIPLAYER_MASTER) {
16436  multi_send_int(class_num);
16437  }
16438 
16439  // all ships in the sexp
16440  for ( ; n != -1; n = CDR(n))
16441  {
16442  ship_num = ship_name_lookup(CTEXT(n), 1);
16443 
16444  // If the ship hasn't arrived we still want the ability to change its class.
16445  if (ship_num == -1)
16446  {
16447  // Get the name of the ship that we are interested in
16448  char* ship_name = CTEXT(n);
16449  p_object *pobj ;
16450  bool match_found = false;
16451 
16452 
16453  // Search the Ship_arrival_list to see if the ship is waiting to arrive
16454  for (pobj = GET_FIRST(&Ship_arrival_list); pobj != END_OF_LIST(&Ship_arrival_list); pobj = GET_NEXT(pobj))
16455  {
16456  if (!(strcmp(pobj->name, ship_name)))
16457  {
16458  match_found = true;
16459  break;
16460  }
16461  }
16462 
16463  if (match_found)
16464  {
16465  swap_parse_object(pobj, class_num);
16466 
16467  if (MULTIPLAYER_MASTER) {
16468  multi_send_bool(false);
16469  multi_send_parse_object(pobj);
16470  }
16471  }
16472  }
16473  // If the ship is already in the mission
16474  else
16475  {
16476  // don't mess with a ship that's occupied
16477  if (!(Ships[ship_num].flags & (SF_DYING | SF_ARRIVING | SF_DEPARTING)))
16478  {
16479  change_ship_type(ship_num, class_num, 1);
16480  if (&Ships[ship_num] == Player_ship) {
16481  set_current_hud();
16482  }
16483 
16484  if (MULTIPLAYER_MASTER) {
16485  multi_send_bool(true);
16486  multi_send_ship(ship_num);
16487  }
16488  }
16489  }
16490  }
16491 
16492  if (MULTIPLAYER_MASTER) {
16494  }
16495 }
16496 
16498 {
16499  int class_num = -1;
16500  int ship_num = -1;
16501  bool ship_arrived;
16502  p_object *pobjp = NULL;
16503 
16504  multi_get_int(class_num);
16505  while (multi_get_bool(ship_arrived)) {
16506  if (ship_arrived) {
16507  multi_get_ship(ship_num);
16508  if ((class_num >= 0) && (ship_num >= 0)) {
16509  change_ship_type(ship_num, class_num, 1);
16510  if (&Ships[ship_num] == Player_ship) {
16511  set_current_hud();
16512  }
16513  }
16514  }
16515  else {
16516  multi_get_parse_object(pobjp);
16517  if ((class_num >= 0) && (pobjp != NULL)) {
16518  swap_parse_object(pobjp, class_num);
16519  }
16520  }
16521  }
16522 }
16523 
16524 // Goober5000
16525 void ship_copy_damage(ship *target_shipp, ship *source_shipp)
16526 {
16527  int i;
16528  object *target_objp = &Objects[target_shipp->objnum];
16529  object *source_objp = &Objects[source_shipp->objnum];
16530  ship_subsys *source_ss;
16531  ship_subsys *target_ss;
16532 
16533  if (target_shipp->ship_info_index != source_shipp->ship_info_index)
16534  {
16535  nprintf(("SEXP", "Copying damage of ship %s to ship %s which has a different ship class. Strange results might occur.\n", source_shipp->ship_name, target_shipp->ship_name));
16536  }
16537 
16538 
16539  // copy hull...
16540  target_shipp->special_hitpoints = source_shipp->special_hitpoints;
16541  target_shipp->ship_max_hull_strength = source_shipp->ship_max_hull_strength;
16542  target_objp->hull_strength = source_objp->hull_strength;
16543 
16544  // ...and shields
16545  target_shipp->ship_max_shield_strength = source_shipp->ship_max_shield_strength;
16546  for (i = 0; i < MIN(target_objp->n_quadrants, source_objp->n_quadrants); i++)
16547  target_objp->shield_quadrant[i] = source_objp->shield_quadrant[i];
16548 
16549 
16550  // search through all subsystems on source ship and map them onto target ship
16551  for (source_ss = GET_FIRST(&source_shipp->subsys_list); source_ss != GET_LAST(&source_shipp->subsys_list); source_ss = GET_NEXT(source_ss))
16552  {
16553  // find subsystem to configure
16554  target_ss = ship_get_subsys(target_shipp, source_ss->system_info->subobj_name);
16555  if (target_ss == NULL)
16556  continue;
16557 
16558  // copy
16559  target_ss->max_hits = source_ss->max_hits;
16560  target_ss->current_hits = source_ss->current_hits;
16561  target_ss->submodel_info_1.blown_off = source_ss->submodel_info_1.blown_off;
16562  target_ss->submodel_info_2.blown_off = source_ss->submodel_info_2.blown_off;
16563  }
16564 }
16565 
16566 extern int insert_subsys_status(p_object *pobjp);
16567 
16568 // Goober5000
16569 void parse_copy_damage(p_object *target_pobjp, ship *source_shipp)
16570 {
16571  object *source_objp = &Objects[source_shipp->objnum];
16572  ship_subsys *source_ss;
16573  subsys_status *target_sssp;
16574 
16575  if (target_pobjp->ship_class != source_shipp->ship_info_index)
16576  {
16577  nprintf(("SEXP", "Copying damage of ship %s to ship %s which has a different ship class. Strange results might occur.\n", source_shipp->ship_name, target_pobjp->name));
16578  }
16579 
16580  // copy hull...
16581  target_pobjp->special_hitpoints = source_shipp->special_hitpoints;
16582  target_pobjp->ship_max_hull_strength = source_shipp->ship_max_hull_strength;
16583  target_pobjp->initial_hull = fl2i(get_hull_pct(source_objp) * 100.0f);
16584 
16585  // ...and shields
16586  target_pobjp->ship_max_shield_strength = source_shipp->ship_max_shield_strength;
16587  target_pobjp->initial_shields = fl2i(get_shield_pct(source_objp) * 100.0f);
16588  target_pobjp->max_shield_recharge = source_shipp->max_shield_recharge;
16589 
16590 
16591  // search through all subsystems on source ship and map them onto target ship
16592  for (source_ss = GET_FIRST(&source_shipp->subsys_list); source_ss != GET_LAST(&source_shipp->subsys_list); source_ss = GET_NEXT(source_ss))
16593  {
16594  // find subsystem to configure
16595  target_sssp = parse_get_subsys_status(target_pobjp, source_ss->system_info->subobj_name);
16596 
16597  // gak... none allocated; we need to allocate one!
16598  if (target_sssp == NULL)
16599  {
16600  // jam in the new subsystem at the end of the existing list for this parse object
16601  int new_idx = insert_subsys_status(target_pobjp);
16602  target_sssp = &Subsys_status[new_idx];
16603 
16604  strcpy_s(target_sssp->name, source_ss->system_info->subobj_name);
16605  }
16606 
16607  // copy
16608  if (source_ss->max_hits == 0.0f)
16609  {
16610  Warning(LOCATION, "Why does %s's subsystem %s have a maximum strength of 0?", source_shipp->ship_name, source_ss->system_info->subobj_name);
16611  target_sssp->percent = 100.0f;
16612  }
16613  else
16614  {
16615  target_sssp->percent = 100.0f - (source_ss->current_hits / source_ss->max_hits) * 100.0f;
16616  }
16617  }
16618 }
16619 
16620 // Goober5000
16622 {
16623  int n, source_shipnum, target_shipnum;
16624  p_object *target_pobjp;
16625 
16626  // source ship must be present
16627  source_shipnum = ship_name_lookup(CTEXT(node));
16628  if (source_shipnum < 0)
16629  return;
16630 
16631  // loop through all subsequent arguments
16632  for (n = CDR(node); n != -1; n = CDR(n))
16633  {
16634  // maybe it's present in-mission
16635  target_shipnum = ship_name_lookup(CTEXT(n));
16636  if (target_shipnum >= 0)
16637  {
16638  ship_copy_damage(&Ships[target_shipnum], &Ships[source_shipnum]);
16639  continue;
16640  }
16641 
16642  // maybe it's on the arrival list
16643  target_pobjp = mission_parse_get_arrival_ship(CTEXT(n));
16644  if (target_pobjp != NULL)
16645  {
16646  parse_copy_damage(target_pobjp, &Ships[source_shipnum]);
16647  continue;
16648  }
16649 
16650  // must have departed or not even existed... do nothing
16651  }
16652 }
16653 
16654 
16655 //-Bobboau
16656 void sexp_activate_deactivate_glow_points(int n, bool activate)
16657 {
16658  int sindex;
16659  size_t i;
16660 
16661  for ( ; n != -1; n = CDR(n))
16662  {
16663  sindex = ship_name_lookup(CTEXT(n), 1);
16664  if (sindex >= 0)
16665  {
16666  for (i = 0; i < Ships[sindex].glow_point_bank_active.size(); i++)
16667  Ships[sindex].glow_point_bank_active[i] = activate;
16668  }
16669  }
16670 }
16671 
16672 //-Bobboau
16674 {
16675  int sindex, num;
16676 
16677  sindex = ship_name_lookup(CTEXT(n), 1);
16678  if (sindex >= 0)
16679  {
16680  for ( n = CDR(n); n != -1; n = CDR(n))
16681  {
16682  num = eval_num(n);
16683  if (num >= 0 && num < (int)Ships[sindex].glow_point_bank_active.size())
16684  {
16685  Ships[sindex].glow_point_bank_active[num] = activate;
16686  }
16687  }
16688  }
16689 }
16690 
16691 //-Bobboau
16692 void sexp_activate_deactivate_glow_maps(int n, int activate)
16693 {
16694  int sindex;
16695  ship *shipp;
16696 
16697  for ( ; n != -1; n = CDR(n))
16698  {
16699  sindex = ship_name_lookup(CTEXT(n), 1);
16700  if (sindex >= 0)
16701  {
16702  shipp = &Ships[sindex];
16703 
16704  if (activate)
16705  shipp->flags2 &= ~SF2_GLOWMAPS_DISABLED;
16706  else
16707  shipp->flags2 |= SF2_GLOWMAPS_DISABLED;
16708  }
16709  }
16710 }
16711 
16713 {
16714  int red, green, blue;
16715  int level = 0;
16716 
16717  Assert(node > -1);
16718  red = eval_num(node);
16719  if (red < 0 || red > 255) {
16720  red = 0;
16721  }
16722 
16723  node = CDR(node);
16724  Assert(node > -1);
16725  green = eval_num(node);
16726  if (green < 0 || green > 255) {
16727  green = 0;
16728  }
16729 
16730  node = CDR(node);
16731  Assert(node > -1);
16732  blue = eval_num(node);
16733  if (blue < 0 || blue > 255) {
16734  blue = 0;
16735  }
16736 
16737  level |= red;
16738  level |= green << 8;
16739  level |= blue << 16;
16740 
16741  // setting the ambient light level for the mission won't actually do anything as it is parsed at mission
16742  // start but it should be updated in case someone changes that later
16744 
16745  // call the graphics function to actually set the level
16746  gr_set_ambient_light(red, green, blue);
16747 
16748  // do the multiplayer callback
16749  if (MULTIPLAYER_MASTER) {
16751  multi_send_int(level);
16753  }
16754 }
16755 
16757 {
16758  int level = 0;
16759  if (multi_get_int(level)) {
16761  gr_set_ambient_light((level & 0xff),((level >> 8) & 0xff), ((level >> 16) & 0xff));
16762  }
16763 }
16764 
16765 void sexp_set_post_effect(int node)
16766 {
16767  char *name = CTEXT(node);
16768 
16769  if (name == NULL) {
16770  return;
16771  }
16772 
16773  int amount = eval_num(CDR(node));
16774 
16775  if (amount < 0 || amount > 100)
16776  amount = 0;
16777 
16778  gr_post_process_set_effect(name, amount);
16779 }
16780 
16781 // Goober5000
16783 {
16784  matrix m;
16785  angles a;
16786 
16787  a.p = fl_radians(eval_num(n) % 360);
16788  n = CDR(n);
16789 
16790  a.b = fl_radians(eval_num(n) % 360);
16791  n = CDR(n);
16792 
16793  a.h = fl_radians(eval_num(n) % 360);
16794  n = CDR(n);
16795 
16796  vm_angles_2_matrix(&m, &a);
16798 }
16799 
16800 // taylor - load and set a skybox model
16802 {
16803  char new_skybox_model[TOKEN_LENGTH+1]; //max input is TOKEN_LENGTH, +1 for NUL
16804  strcpy_s(new_skybox_model, CTEXT(n));
16805  int new_skybox_model_flags = DEFAULT_NMODEL_FLAGS;
16806 
16807  // check if we need to reset the animated texture timestamp
16808  n = CDR(n);
16809  if (n == -1 || is_sexp_true(n)) {
16811  }
16812 
16813  if (n != -1) n = CDR(n);
16814 
16815  // gather any flags
16816  while (n != -1) {
16817  // this should check all entries in Skybox_flags
16818  if ( !stricmp("add-lighting", CTEXT(n) )) {
16819  new_skybox_model_flags &= ~MR_NO_LIGHTING;
16820  }
16821  else if ( !stricmp("no-transparency", CTEXT(n) )) {
16822  new_skybox_model_flags &= ~MR_ALL_XPARENT;
16823  }
16824  else if ( !stricmp("add-zbuffer", CTEXT(n) )) {
16825  new_skybox_model_flags &= ~MR_NO_ZBUFFER;
16826  }
16827  else if ( !stricmp("add-culling", CTEXT(n) )) {
16828  new_skybox_model_flags &= ~MR_NO_CULL;
16829  }
16830  else if ( !stricmp("no-glowmaps", CTEXT(n) )) {
16831  new_skybox_model_flags |= MR_NO_GLOWMAPS;
16832  }
16833  else if ( !stricmp("force-clamp", CTEXT(n) )) {
16834  new_skybox_model_flags |= MR_FORCE_CLAMP;
16835  }
16836  else {
16837  Warning(LOCATION, "Invalid flag passed to set-skybox-model: %s\n", CTEXT(n));
16838  }
16839  n = CDR(n);
16840  }
16841  if ( !stricmp("default", new_skybox_model )) {
16842  stars_set_background_model( The_mission.skybox_model, NULL, new_skybox_model_flags );
16843  } else {
16844  // stars_level_init() will set the actual mission skybox after this gets
16845  // evaluated during parse. by setting it now we get everything loaded so
16846  // there is less slowdown when it actually swaps out - taylor
16847  stars_set_background_model( new_skybox_model, NULL, new_skybox_model_flags );
16848  }
16849 }
16850 
16851 // taylor - preload a skybox model. this doesn't set anything as viewable, just loads it into memory
16853 {
16854  int i;
16855 
16856  if ( !stricmp("default", name) ) {
16857  // if there isn't a mission skybox model then don't load one
16858  if ( strlen(The_mission.skybox_model) ) {
16859  i = model_load( The_mission.skybox_model, 0, NULL );
16861  }
16862  } else {
16863  i = model_load( name, 0, NULL );
16865  }
16866 }
16867 
16868 void sexp_beam_fire(int node, bool at_coords)
16869 {
16870  int sindex, n = node;
16871  beam_fire_info fire_info;
16872  int idx;
16873 
16874  // zero stuff out
16875  memset(&fire_info, 0, sizeof(beam_fire_info));
16876  fire_info.accuracy = 0.000001f; // this will guarantee a hit
16877 
16878  // get the firing ship
16879  sindex = ship_name_lookup(CTEXT(n));
16880  n = CDR(n);
16881  if (sindex < 0) {
16882  return;
16883  }
16884  if (Ships[sindex].objnum < 0) {
16885  return;
16886  }
16887  fire_info.shooter = &Objects[Ships[sindex].objnum];
16888 
16889  // get the subsystem
16890  fire_info.turret = ship_get_subsys(&Ships[sindex], CTEXT(n));
16891  n = CDR(n);
16892  if (fire_info.turret == NULL) {
16893  return;
16894  }
16895 
16896  if (at_coords) {
16897  // get the target coordinates
16898  fire_info.target_pos1.xyz.x = fire_info.target_pos2.xyz.x = static_cast<float>(eval_num(n));
16899  n = CDR(n);
16900  fire_info.target_pos1.xyz.y = fire_info.target_pos2.xyz.y = static_cast<float>(eval_num(n));
16901  n = CDR(n);
16902  fire_info.target_pos1.xyz.z = fire_info.target_pos2.xyz.z = static_cast<float>(eval_num(n));
16903  n = CDR(n);
16904  fire_info.bfi_flags |= BFIF_TARGETING_COORDS;
16905  fire_info.target = NULL;
16906  fire_info.target_subsys = NULL;
16907  } else {
16908  // get the target
16909  sindex = ship_name_lookup(CTEXT(n));
16910  n = CDR(n);
16911  if (sindex < 0) {
16912  return;
16913  }
16914  if (Ships[sindex].objnum < 0) {
16915  return;
16916  }
16917  fire_info.target = &Objects[Ships[sindex].objnum];
16918 
16919  // see if the optional subsystem can be found
16920  fire_info.target_subsys = NULL;
16921  if (n >= 0) {
16922  fire_info.target_subsys = ship_get_subsys(&Ships[sindex], CTEXT(n));
16923  n = CDR(n);
16924  }
16925  }
16926 
16927  // optionally force firing
16928  if (n >= 0 && is_sexp_true(n)) {
16929  fire_info.bfi_flags |= BFIF_FORCE_FIRING;
16930  n = CDR(n);
16931  }
16932 
16933  // get the second set of coordinates
16934  if (at_coords) {
16935  if (n >= 0) {
16936  fire_info.target_pos2.xyz.x = static_cast<float>(eval_num(n));
16937  n = CDR(n);
16938  }
16939  if (n >= 0) {
16940  fire_info.target_pos2.xyz.y = static_cast<float>(eval_num(n));
16941  n = CDR(n);
16942  }
16943  if (n >= 0) {
16944  fire_info.target_pos2.xyz.z = static_cast<float>(eval_num(n));
16945  n = CDR(n);
16946  }
16947  }
16948 
16949  // --- done getting arguments ---
16950 
16951  // if it has no primary weapons
16952  if (fire_info.turret->weapons.num_primary_banks <= 0) {
16953  Warning(LOCATION, "Couldn't fire turret on ship %s; subsystem %s has no primary weapons", CTEXT(node), CTEXT(CDR(node)));
16954  return;
16955  }
16956 
16957  // if the turret is destroyed
16958  if (!(fire_info.bfi_flags & BFIF_FORCE_FIRING) && fire_info.turret->current_hits <= 0.0f) {
16959  return;
16960  }
16961 
16962  // hmm, this could be wacky. Let's just simply select the first beam weapon in the turret
16963  fire_info.beam_info_index = -1;
16964  for (idx=0; idx<fire_info.turret->weapons.num_primary_banks; idx++) {
16966  "sexp_beam_fire: found invalid weapon index (%i), get a coder\n!", fire_info.turret->weapons.primary_bank_weapons[idx]);
16967  // store the weapon info index
16969  fire_info.beam_info_index = fire_info.turret->weapons.primary_bank_weapons[idx];
16970  }
16971  }
16972 
16973  // fire the beam
16974  if (fire_info.beam_info_index != -1) {
16975  beam_fire(&fire_info);
16976  } else {
16977  // it would appear the turret doesn't have any beam weapons
16978  Warning(LOCATION, "Couldn't fire turret on ship %s; subsystem %s has no beam weapons", CTEXT(node), CTEXT(CDR(node)));
16979  }
16980 }
16981 
16983 {
16984  int sindex;
16985  beam_fire_info fire_info;
16986  memset(&fire_info, 0, sizeof(beam_fire_info));
16987  fire_info.accuracy = 0.000001f; // this will guarantee a hit
16988  fire_info.bfi_flags |= BFIF_FLOATING_BEAM;
16989  fire_info.turret = NULL; // A free-floating beam isn't fired from a subsystem.
16990 
16991  fire_info.beam_info_index = weapon_info_lookup(CTEXT(n));
16992  n = CDR(n);
16993  if (fire_info.beam_info_index < 0)
16994  {
16995  Warning(LOCATION, "Invalid weapon class passed to beam-create; weapon type '%s' does not exist!\n", CTEXT(n));
16996  return;
16997  }
16998  if (!(Weapon_info[fire_info.beam_info_index].wi_flags & WIF_BEAM)) {
16999  Warning(LOCATION, "Invalid weapon class passed to beam-create; weapon type '%s' is not a beam!\n", CTEXT(n));
17000  return;
17001  }
17002 
17003  fire_info.shooter = NULL;
17004  if (stricmp(CTEXT(n), SEXP_NONE_STRING))
17005  {
17006  sindex = ship_name_lookup(CTEXT(n));
17007 
17008  if (sindex >= 0)
17009  fire_info.shooter = &Objects[Ships[sindex].objnum];
17010  }
17011  n = CDR(n);
17012 
17013  fire_info.team = static_cast<char>(iff_lookup(CTEXT(n)));
17014  n = CDR(n);
17015 
17016  fire_info.starting_pos.xyz.x = static_cast<float>(eval_num(n));
17017  n = CDR(n);
17018  fire_info.starting_pos.xyz.y = static_cast<float>(eval_num(n));
17019  n = CDR(n);
17020  fire_info.starting_pos.xyz.z = static_cast<float>(eval_num(n));
17021  n = CDR(n);
17022 
17023  fire_info.target = NULL;
17024  fire_info.target_subsys = NULL;
17025 
17026  sindex = -1;
17027  if (stricmp(CTEXT(n), SEXP_NONE_STRING))
17028  {
17029  sindex = ship_name_lookup(CTEXT(n));
17030 
17031  if (sindex >= 0)
17032  fire_info.target = &Objects[Ships[sindex].objnum];
17033  } else {
17034  fire_info.bfi_flags |= BFIF_TARGETING_COORDS;
17035  }
17036  n = CDR(n);
17037 
17038  if (n >= 0)
17039  {
17040  if (stricmp(CTEXT(n), SEXP_NONE_STRING)) {
17041  if (sindex >= 0)
17042  fire_info.target_subsys = ship_get_subsys(&Ships[sindex], CTEXT(n));
17043  }
17044 
17045  n = CDR(n);
17046  }
17047 
17048  if (n >= 0) {
17049  fire_info.target_pos1.xyz.x = fire_info.target_pos2.xyz.x = static_cast<float>(eval_num(n));
17050  n = CDR(n);
17051  }
17052  if (n >= 0) {
17053  fire_info.target_pos1.xyz.y = fire_info.target_pos2.xyz.y = static_cast<float>(eval_num(n));
17054  n = CDR(n);
17055  }
17056  if (n >= 0) {
17057  fire_info.target_pos1.xyz.z = fire_info.target_pos2.xyz.z = static_cast<float>(eval_num(n));
17058  n = CDR(n);
17059  }
17060 
17061  if (n >= 0) {
17062  fire_info.target_pos2.xyz.x = static_cast<float>(eval_num(n));
17063  n = CDR(n);
17064  }
17065  if (n >= 0) {
17066  fire_info.target_pos2.xyz.y = static_cast<float>(eval_num(n));
17067  n = CDR(n);
17068  }
17069  if (n >= 0) {
17070  fire_info.target_pos2.xyz.z = static_cast<float>(eval_num(n));
17071  n = CDR(n);
17072  }
17073 
17074  beam_fire(&fire_info);
17075 }
17076 
17077 void sexp_beam_free(int node)
17078 {
17079  int sindex;
17080  ship_subsys *turret = NULL;
17081 
17082  // get the firing ship
17083  sindex = ship_name_lookup(CTEXT(node));
17084  if(sindex < 0){
17085  return;
17086  }
17087  if(Ships[sindex].objnum < 0){
17088  return;
17089  }
17090 
17091  node = CDR(node);
17092  for ( ; node >= 0; node = CDR(node) ) {
17093  // get the subsystem
17094  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17095  if(turret == NULL){
17096  continue;
17097  }
17098 
17099  // flag it as beam free :)
17100  if (!(turret->weapons.flags & SW_FLAG_BEAM_FREE))
17101  {
17102  turret->weapons.flags |= SW_FLAG_BEAM_FREE;
17103  turret->turret_next_fire_stamp = timestamp((int) frand_range(50.0f, 4000.0f));
17104  }
17105  }
17106 }
17107 
17108 void sexp_set_thrusters(int node)
17109 {
17110  bool activate = is_sexp_true(node) > 0;
17111  node = CDR(node);
17112 
17113  for(; node >= 0; node = CDR(node)) {
17114  int sindex = ship_name_lookup(CTEXT(node));
17115 
17116  if (sindex < 0) {
17117  continue;
17118  }
17119 
17120  if (Ships[sindex].objnum < 0) {
17121  continue;
17122  }
17123 
17124  if (activate)
17125  Ships[sindex].flags2 &= ~SF2_NO_THRUSTERS;
17126  else
17127  Ships[sindex].flags2 |= SF2_NO_THRUSTERS;
17128  }
17129 }
17130 
17131 void sexp_beam_free_all(int node)
17132 {
17133  ship_subsys *subsys;
17134  int sindex;
17135 
17136  for (int n = node; n >= 0; n = CDR(n)) {
17137  // get the firing ship
17138  sindex = ship_name_lookup( CTEXT(n) );
17139 
17140  if (sindex < 0) {
17141  continue;
17142  }
17143 
17144  if (Ships[sindex].objnum < 0) {
17145  continue;
17146  }
17147 
17148  // free all beam weapons
17149  subsys = GET_FIRST(&Ships[sindex].subsys_list);
17150 
17151  while ( subsys != END_OF_LIST(&Ships[sindex].subsys_list) ) {
17152  // just mark all turrets as beam free
17153  if ((subsys->system_info->type == SUBSYSTEM_TURRET) && (!(subsys->weapons.flags & SW_FLAG_BEAM_FREE)))
17154  {
17155  subsys->weapons.flags |= SW_FLAG_BEAM_FREE;
17156  subsys->turret_next_fire_stamp = timestamp((int) frand_range(50.0f, 4000.0f));
17157  }
17158 
17159  // next item
17160  subsys = GET_NEXT(subsys);
17161  }
17162  }
17163 }
17164 
17165 void sexp_beam_lock(int node)
17166 {
17167  int sindex;
17168  ship_subsys *turret = NULL;
17169 
17170  // get the firing ship
17171  sindex = ship_name_lookup(CTEXT(node));
17172  if(sindex < 0){
17173  return;
17174  }
17175  if(Ships[sindex].objnum < 0){
17176  return;
17177  }
17178 
17179  node = CDR(node);
17180  for ( ; node >= 0; node = CDR(node) ) {
17181  // get the subsystem
17182  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17183  if(turret == NULL){
17184  continue;
17185  }
17186 
17187  // flag it as not beam free
17188  turret->weapons.flags &= ~(SW_FLAG_BEAM_FREE);
17189  }
17190 }
17191 
17192 void sexp_beam_lock_all(int node)
17193 {
17194  ship_subsys *subsys;
17195  int sindex;
17196 
17197  for (int n = node; n >= 0; n = CDR(n)) {
17198  // get the firing ship
17199  sindex = ship_name_lookup( CTEXT(n) );
17200 
17201  if (sindex < 0) {
17202  continue;
17203  }
17204 
17205  if (Ships[sindex].objnum < 0) {
17206  continue;
17207  }
17208 
17209  // lock all beam weapons
17210  subsys = GET_FIRST(&Ships[sindex].subsys_list);
17211 
17212  while ( subsys != END_OF_LIST(&Ships[sindex].subsys_list) ) {
17213  // just mark all turrets as not beam free
17214  if (subsys->system_info->type == SUBSYSTEM_TURRET) {
17215  subsys->weapons.flags &= ~(SW_FLAG_BEAM_FREE);
17216  }
17217 
17218  // next item
17219  subsys = GET_NEXT(subsys);
17220  }
17221  }
17222 }
17223 
17224 void sexp_turret_free(int node)
17225 {
17226  int sindex;
17227  ship_subsys *turret = NULL;
17228 
17229  // get the firing ship
17230  sindex = ship_name_lookup(CTEXT(node));
17231  if(sindex < 0){
17232  return;
17233  }
17234  if(Ships[sindex].objnum < 0){
17235  return;
17236  }
17237 
17238  node = CDR(node);
17239  for ( ; node >= 0; node = CDR(node) ) {
17240  // get the subsystem
17241  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17242  if(turret == NULL){
17243  continue;
17244  }
17245 
17246  // flag turret as no longer locked :)
17247  if (turret->weapons.flags & SW_FLAG_TURRET_LOCK)
17248  {
17249  turret->weapons.flags &= (~SW_FLAG_TURRET_LOCK);
17250  turret->turret_next_fire_stamp = timestamp((int) frand_range(50.0f, 4000.0f));
17251  }
17252  }
17253 }
17254 
17255 void sexp_turret_free_all(int node)
17256 {
17257  ship_subsys *subsys;
17258  int sindex;
17259 
17260  for (int n = node; n >= 0; n = CDR(n)) {
17261  // get the firing ship
17262  sindex = ship_name_lookup( CTEXT(n) );
17263 
17264  if (sindex < 0) {
17265  continue;
17266  }
17267 
17268  if (Ships[sindex].objnum < 0) {
17269  continue;
17270  }
17271 
17272  // free all turrets
17273  subsys = GET_FIRST(&Ships[sindex].subsys_list);
17274 
17275  while ( subsys != END_OF_LIST(&Ships[sindex].subsys_list) ) {
17276  // just mark all turrets as free
17277  if ((subsys->system_info->type == SUBSYSTEM_TURRET) && (subsys->weapons.flags & SW_FLAG_TURRET_LOCK)) {
17278  subsys->weapons.flags &= (~SW_FLAG_TURRET_LOCK);
17279  subsys->turret_next_fire_stamp = timestamp((int) frand_range(50.0f, 4000.0f));
17280  }
17281 
17282  // next item
17283  subsys = GET_NEXT(subsys);
17284  }
17285  }
17286 }
17287 
17288 void sexp_turret_lock(int node)
17289 {
17290  int sindex;
17291  ship_subsys *turret = NULL;
17292 
17293  // get the firing ship
17294  sindex = ship_name_lookup(CTEXT(node));
17295  if(sindex < 0){
17296  return;
17297  }
17298  if(Ships[sindex].objnum < 0){
17299  return;
17300  }
17301 
17302  node = CDR(node);
17303  for ( ; node >= 0; node = CDR(node) ) {
17304  // get the subsystem
17305  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17306  if(turret == NULL){
17307  continue;
17308  }
17309 
17310  // flag turret as locked
17311  turret->weapons.flags |= SW_FLAG_TURRET_LOCK;
17312  }
17313 }
17314 
17315 void sexp_turret_lock_all(int node)
17316 {
17317  ship_subsys *subsys;
17318  int sindex;
17319 
17320  for (int n = node; n >= 0; n = CDR(n)) {
17321  // get the firing ship
17322  sindex = ship_name_lookup( CTEXT(n) );
17323 
17324  if (sindex < 0) {
17325  continue;
17326  }
17327 
17328  if (Ships[sindex].objnum < 0) {
17329  continue;
17330  }
17331 
17332  // lock all turrets
17333  subsys = GET_FIRST(&Ships[sindex].subsys_list);
17334 
17335  while ( subsys != END_OF_LIST(&Ships[sindex].subsys_list) ) {
17336  // just mark all turrets as locked
17337  if (subsys->system_info->type == SUBSYSTEM_TURRET) {
17338  subsys->weapons.flags |= SW_FLAG_TURRET_LOCK;
17339  }
17340 
17341  // next item
17342  subsys = GET_NEXT(subsys);
17343  }
17344  }
17345 }
17346 
17348 {
17349  ship_subsys *subsys;
17350  int sindex;
17351 
17352  // get the firing ship
17353  sindex = ship_name_lookup(CTEXT(node));
17354  if(sindex < 0){
17355  return;
17356  }
17357  if(Ships[sindex].objnum < 0){
17358  return;
17359  }
17360 
17361  // mark all turrets to only target tagged ships
17362  subsys = GET_FIRST(&Ships[sindex].subsys_list);
17363  while(subsys != END_OF_LIST(&Ships[sindex].subsys_list)){
17364  // just mark all turrets as locked
17365  if(subsys->system_info->type == SUBSYSTEM_TURRET){
17366  subsys->weapons.flags |= SW_FLAG_TAGGED_ONLY;
17367  }
17368 
17369  // next item
17370  subsys = GET_NEXT(subsys);
17371  }
17372 }
17373 
17375 {
17376  ship_subsys *subsys;
17377  int sindex;
17378 
17379  // get the firing ship
17380  sindex = ship_name_lookup(CTEXT(node));
17381  if(sindex < 0){
17382  return;
17383  }
17384  if(Ships[sindex].objnum < 0){
17385  return;
17386  }
17387 
17388  // mark all turrets so not restricted to only tagged ships
17389  subsys = GET_FIRST(&Ships[sindex].subsys_list);
17390  while(subsys != END_OF_LIST(&Ships[sindex].subsys_list)){
17391  // just mark all turrets as locked
17392  if(subsys->system_info->type == SUBSYSTEM_TURRET){
17393  subsys->weapons.flags &= (~SW_FLAG_TAGGED_ONLY);
17394  }
17395 
17396  // next item
17397  subsys = GET_NEXT(subsys);
17398  }
17399 }
17400 
17402 {
17403  int sindex;
17404  int windex; //hehe
17405  ship_subsys *turret = NULL;
17406  ship_weapon *swp = NULL;
17407 
17408  // get the firing ship
17409  sindex = ship_name_lookup(CTEXT(node));
17410  if(sindex < 0 || Ships[sindex].objnum < 0){
17411  return;
17412  }
17413 
17414  //Get subsystem
17415  node = CDR(node);
17416  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17417  if(turret == NULL){
17418  return;
17419  }
17420  swp = &turret->weapons;
17421 
17422  node = CDR(node);
17423  windex = weapon_info_lookup(CTEXT(node));
17424  if(windex < 0) {
17425  return;
17426  }
17427 
17428  //Get the slot
17429  float capacity, size;
17430  int prim_slot = 0;
17431  int sec_slot = 0;
17432 
17433  node = CDR(node);
17434  prim_slot = eval_num(node);
17435 
17436  node = CDR(node);
17437  sec_slot = eval_num(node);
17438 
17439  if(prim_slot)
17440  {
17441  if(prim_slot > MAX_SHIP_PRIMARY_BANKS) {
17442  return;
17443  }
17444 
17445  if(prim_slot > swp->num_primary_banks) {
17446  swp->num_primary_banks++;
17447  prim_slot = swp->num_primary_banks;
17448  }
17449 
17450  //Get an index
17451  prim_slot--;
17452 
17453  //Get the max capacity
17454  capacity = (float) swp->primary_bank_capacity[prim_slot];
17455  size = (float) Weapon_info[windex].cargo_size;
17456 
17457  //Set various vars
17458  swp->primary_bank_start_ammo[prim_slot] = (int) (capacity / size);
17459  swp->primary_bank_ammo[prim_slot] = swp->primary_bank_start_ammo[prim_slot];
17460  swp->primary_bank_weapons[prim_slot] = windex;
17461  swp->primary_bank_rearm_time[prim_slot] = timestamp(0);
17462  swp->primary_bank_fof_cooldown[prim_slot] = 0.0f;
17463  }
17464  else if(sec_slot)
17465  {
17466  if(sec_slot > MAX_SHIP_PRIMARY_BANKS) {
17467  return;
17468  }
17469 
17470  if(sec_slot > swp->num_secondary_banks) {
17471  swp->num_secondary_banks++;
17472  sec_slot = swp->num_secondary_banks;
17473  }
17474 
17475  //Get an index
17476  sec_slot--;
17477 
17478  //Get the max capacity
17479  capacity = (float) swp->secondary_bank_capacity[sec_slot];
17480  size = (float) Weapon_info[windex].cargo_size;
17481 
17482  //Set various vars
17483  swp->secondary_bank_start_ammo[sec_slot] = (int) (capacity / size);
17484  swp->secondary_bank_ammo[sec_slot] = swp->secondary_bank_start_ammo[sec_slot];
17485  swp->secondary_bank_weapons[sec_slot] = windex;
17486  swp->secondary_bank_rearm_time[sec_slot] = timestamp(0);
17487  }
17488 }
17489 
17490 void sexp_set_armor_type(int node)
17491 {
17492  int sindex;
17493  int armor, rset;
17494  ship_subsys *ss = NULL;
17495  ship *shipp = NULL;
17496  ship_info *sip = NULL;
17497 
17498  // get ship
17499  sindex = ship_name_lookup(CTEXT(node));
17500  if(sindex < 0) {
17501  return;
17502  }
17503  if(Ships[sindex].objnum < 0) {
17504  return;
17505  }
17506  shipp = &Ships[sindex];
17507  sip = &Ship_info[shipp->ship_info_index];
17508 
17509  // set or reset
17510  node = CDR(node);
17511  rset = is_sexp_true(node);
17512 
17513  // get armor
17514  node = CDR(node);
17515  if (!stricmp(SEXP_NONE_STRING, CTEXT(node))) {
17516  armor = -1;
17517  } else {
17518  armor = armor_type_get_idx(CTEXT(node));
17519  }
17520 
17521  //Set armor
17522  while(node != -1)
17523  {
17524  if (!stricmp(SEXP_HULL_STRING, CTEXT(node)))
17525  {
17526  // we are setting the ship itself
17527  if (!rset)
17528  shipp->armor_type_idx = sip->armor_type_idx;
17529  else
17530  shipp->armor_type_idx = armor;
17531  }
17532  else if (!stricmp(SEXP_SHIELD_STRING, CTEXT(node)))
17533  {
17534  // we are setting the ships shields
17535  if (!rset)
17537  else
17538  shipp->shield_armor_type_idx = armor;
17539  }
17540  else
17541  {
17542  // get the subsystem
17543  ss = ship_get_subsys(&Ships[sindex], CTEXT(node));
17544  if(ss == NULL){
17545  node = CDR(node);
17546  continue;
17547  }
17548 
17549  // set the range
17550  if (!rset)
17552  else
17553  ss->armor_type_idx = armor;
17554  }
17555  // next
17556  node = CDR(node);
17557  }
17558 }
17559 
17561 {
17562  int windex, damage, swave, rset;
17563  size_t t;
17564 
17565  // weapon or shockwave
17566  swave = is_sexp_true(node);
17567 
17568  // get damage type
17569  node = CDR(node);
17570  if (!stricmp(SEXP_NONE_STRING, CTEXT(node)))
17571  damage = -1;
17572  else
17573  {
17574  for(t = 0; t < Damage_types.size(); t++)
17575  {
17576  if ( !stricmp(Damage_types[t].name, CTEXT(node)))
17577  break;
17578  }
17579  if (t == Damage_types.size())
17580  return;
17581  damage = (int)t;
17582  }
17583 
17584  //Set or reset to defualt
17585  node = CDR(node);
17586  rset = is_sexp_true(node);
17587 
17588  //Set Damage
17589  node = CDR(node);
17590  while(node != -1)
17591  {
17592  // get the weapon
17593  windex = weapon_info_lookup(CTEXT(node));
17594  if(windex >= 0)
17595  {
17596  // set the damage type
17597  if (swave)
17598  if (!rset)
17600  else
17601  Weapon_info[windex].damage_type_idx = damage;
17602  else
17603  if (!rset)
17605  else
17606  Weapon_info[windex].shockwave.damage_type_idx = damage;
17607  // next
17608  }
17609  node = CDR(node);
17610  }
17611 }
17612 
17614 {
17615  int sindex, damage, debris, rset;
17616  size_t t;
17617  ship *shipp = NULL;
17618 
17619  // collision or debris
17620  debris = is_sexp_true(node);
17621 
17622  // get damage type
17623  node = CDR(node);
17624  if (!stricmp(SEXP_NONE_STRING, CTEXT(node)))
17625  damage = -1;
17626  else
17627  {
17628  for(t = 0; t < Damage_types.size(); t++)
17629  {
17630  if ( !stricmp(Damage_types[t].name, CTEXT(node)))
17631  break;
17632  }
17633  if (t == Damage_types.size())
17634  return;
17635  damage = (int)t;
17636  }
17637 
17638  //Set or reset to defualt
17639  node = CDR(node);
17640  rset = is_sexp_true(node);
17641 
17642  //Set Damage
17643  node = CDR(node);
17644  while(node != -1)
17645  {
17646  // get the ship
17647  sindex = ship_name_lookup(CTEXT(node));
17648  if(sindex >= 0)
17649  {
17650  shipp = &Ships[sindex];
17651  // set the damage type
17652  if (debris)
17653  {
17654  if (!rset)
17655  shipp->collision_damage_type_idx = Ship_info[shipp->ship_info_index].collision_damage_type_idx;
17656  else
17657  shipp->collision_damage_type_idx = damage;
17658  }
17659  else
17660  {
17661  if (!rset)
17662  shipp->debris_damage_type_idx = Ship_info[shipp->ship_info_index].debris_damage_type_idx;
17663  else
17664  shipp->debris_damage_type_idx = damage;
17665  }
17666  // next
17667  }
17668  node = CDR(node);
17669  }
17670 }
17672 {
17673  int sindex, damage, rset;
17674  size_t t;
17675 
17676  // get damage type
17677  if (!stricmp(SEXP_NONE_STRING, CTEXT(node)))
17678  damage = -1;
17679  else
17680  {
17681  for(t = 0; t < Damage_types.size(); t++)
17682  {
17683  if ( !stricmp(Damage_types[t].name, CTEXT(node)))
17684  break;
17685  }
17686  if (t == Damage_types.size())
17687  return;
17688  damage = (int)t;
17689  }
17690 
17691  //Set or reset to defualt
17692  node = CDR(node);
17693  rset = is_sexp_true(node);
17694 
17695  //Set Damage
17696  node = CDR(node);
17697  while(node != -1)
17698  {
17699  // get the ship
17700  sindex = ship_info_lookup(CTEXT(node));
17701  if(sindex >= 0)
17702  {
17703  // set the damage type
17704  if (!rset)
17705  Ship_info[sindex].shockwave.damage_type_idx = Ship_info[sindex].shockwave.damage_type_idx_sav;
17706  else
17707  Ship_info[sindex].shockwave.damage_type_idx = damage;
17708  // next
17709  }
17710  node = CDR(node);
17711  }
17712 }
17714 {
17715  int damage, rset;
17716  size_t t;
17717 
17718  // get damage type
17719  if (!stricmp(SEXP_NONE_STRING, CTEXT(node)))
17720  damage = -1;
17721  else
17722  {
17723  for(t = 0; t < Damage_types.size(); t++)
17724  {
17725  if ( !stricmp(Damage_types[t].name, CTEXT(node)))
17726  break;
17727  }
17728  if (t == Damage_types.size())
17729  return;
17730  damage = (int)t;
17731  }
17732 
17733  //Set or reset to defualt
17734  node = CDR(node);
17735  rset = is_sexp_true(node);
17736 
17737  //Set Damage
17738  node = CDR(node);
17739  for(t = 0; t < Asteroid_info.size(); t++)
17740  if (!rset)
17741  Asteroid_info[t].damage_type_idx = Asteroid_info[t].damage_type_idx_sav;
17742  else
17743  Asteroid_info[t].damage_type_idx = damage;
17744 }
17746 {
17747  int sindex;
17748  ship_subsys *turret = NULL;
17749  int oindex;
17750  int i;
17751 
17752  // get ship
17753  sindex = ship_name_lookup(CTEXT(node));
17754  if(sindex < 0){
17755  return;
17756  }
17757  if(Ships[sindex].objnum < 0){
17758  return;
17759  }
17760 
17761  //Get turret subsys
17762  node = CDR(node);
17763  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17764  if(turret == NULL){
17765  return;
17766  }
17767 
17768  //Reset order
17769  for(i = 0; i < NUM_TURRET_ORDER_TYPES; i++) {
17770  turret->turret_targeting_order[i] = -1;
17771  }
17772 
17773  oindex = 0;
17774  node = CDR(node);
17775  while(node != -1)
17776  {
17777  if(oindex >= NUM_TURRET_ORDER_TYPES) {
17778  break;
17779  }
17780 
17781  for(i = 0; i < NUM_TURRET_ORDER_TYPES; i++) {
17782  if(!stricmp(Turret_target_order_names[i], CTEXT(node))) {
17783  turret->turret_targeting_order[oindex] = i;
17784  }
17785  }
17786 
17787  oindex++;
17788  node = CDR(node);
17789  }
17790 }
17792 {
17793  int sindex;
17794  ship_subsys *turret = NULL;
17795 
17796  // get ship
17797  sindex = ship_name_lookup(CTEXT(node));
17798  if(sindex < 0){
17799  return;
17800  }
17801  if(Ships[sindex].objnum < 0){
17802  return;
17803  }
17804 
17805  //store direction preference
17806  node = CDR(node);
17807  int dirpref = eval_num(node);
17808  node = CDR(node);
17809 
17810  //Set range
17811  while(node != -1){
17812  // get the subsystem
17813  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17814  if(turret == NULL){
17815  node = CDR(node);
17816  continue;
17817  }
17818 
17819  // set the range
17820  if(dirpref < 0)
17821  turret->optimum_range = turret->system_info->optimum_range;
17822  else
17823  if (dirpref == 0) {
17824  turret->favor_current_facing = 0.0f;
17825  } else {
17826  CAP(dirpref, 1, 100);
17827  turret->favor_current_facing = 1.0f + (((float) (100 - dirpref)) / 10.0f);
17828  }
17829 
17830  // next
17831  node = CDR(node);
17832  }
17833 }
17834 
17836 {
17837  int sindex;
17838  ship_subsys *turret = NULL;
17839 
17840  // get ship
17841  sindex = ship_name_lookup(CTEXT(node));
17842  if(sindex < 0){
17843  return;
17844  }
17845  if(Ships[sindex].objnum < 0){
17846  return;
17847  }
17848 
17849  //store rof
17850  node = CDR(node);
17851  float rof = (float)eval_num(node);
17852  node = CDR(node);
17853 
17854  //Set rof
17855  while(node != -1){
17856  // get the subsystem
17857  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17858  if(turret == NULL){
17859  node = CDR(node);
17860  continue;
17861  }
17862 
17863  // set the range
17864  if(rof < 0)
17865  turret->rof_scaler = turret->system_info->turret_rof_scaler ;
17866  else
17867  turret->rof_scaler = rof/100;
17868 
17869  // next
17870  node = CDR(node);
17871  }
17872 }
17873 
17875 {
17876  int sindex;
17877  ship_subsys *turret = NULL;
17878 
17879  // get ship
17880  sindex = ship_name_lookup(CTEXT(node));
17881  if(sindex < 0){
17882  return;
17883  }
17884  if(Ships[sindex].objnum < 0){
17885  return;
17886  }
17887 
17888  //store range
17889  node = CDR(node);
17890  float range = (float)eval_num(node);
17891  node = CDR(node);
17892 
17893  //Set range
17894  while(node != -1){
17895  // get the subsystem
17896  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17897  if(turret == NULL){
17898  node = CDR(node);
17899  continue;
17900  }
17901 
17902  // set the range
17903  if(range < 0)
17904  turret->optimum_range = turret->system_info->optimum_range;
17905  else
17906  turret->optimum_range = range;
17907 
17908  // next
17909  node = CDR(node);
17910  }
17911 }
17912 
17914 {
17915  int sindex;
17916  ship_subsys *turret = NULL;
17917  int i;
17918  int j;
17919 
17920  // get ship
17921  sindex = ship_name_lookup(CTEXT(node));
17922  if(sindex < 0){
17923  return;
17924  }
17925  if(Ships[sindex].objnum < 0){
17926  return;
17927  }
17928 
17929  //Get turret subsys
17930  node = CDR(node);
17931  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
17932  if(turret == NULL){
17933  return;
17934  }
17935 
17936  //Reset or new list
17937  node = CDR(node);
17938  if(!(is_sexp_true(node))) { //Reset
17940  for (j = 0; j < 32; j++) {
17941  turret->target_priority[j] = turret->system_info->target_priority[j];
17942  }
17943  }
17944  else { //New List
17945  node = CDR(node);
17946  //clear the list
17947  turret->num_target_priorities = 0;
17948  for (i = 0; i < 32; i++) {
17949  turret->target_priority[i] = -1;
17950  }
17951  int num_groups = Ai_tp_list.size();
17952  // set the target priorities
17953  while(node != -1){
17954  if(turret->num_target_priorities < 32){
17955  for(j = 0; j < num_groups; j++) {
17956  if ( !stricmp(Ai_tp_list[j].name, CTEXT(node))) {
17957  turret->target_priority[turret->num_target_priorities] = j;
17958  turret->num_target_priorities++;
17959  }
17960  }
17961  }
17962  // next
17963  node = CDR(node);
17964  }
17965  }
17966 }
17967 
17969 {
17970  int sindex;
17971  ship_subsys *turret = NULL;
17972  int oindex;
17973  int i;
17974  int new_target_order[NUM_TURRET_ORDER_TYPES];
17975 
17976  // get ship
17977  sindex = ship_name_lookup(CTEXT(node));
17978  if(sindex < 0){
17979  return;
17980  }
17981  if(Ships[sindex].objnum < 0){
17982  return;
17983  }
17984 
17985  //Reset order
17986  for(i = 0; i < NUM_TURRET_ORDER_TYPES; i++) {
17987  new_target_order[i] = -1;
17988  }
17989 
17990  oindex = 0;
17991  node = CDR(node);
17992  while(node != -1)
17993  {
17994  if(oindex >= NUM_TURRET_ORDER_TYPES) {
17995  break;
17996  }
17997 
17998  for(i = 0; i < NUM_TURRET_ORDER_TYPES; i++) {
17999  if(!stricmp(Turret_target_order_names[i], CTEXT(node))) {
18000  new_target_order[oindex] = i;
18001  }
18002  }
18003 
18004  oindex++;
18005  node = CDR(node);
18006  }
18007 
18008  turret = GET_FIRST(&Ships[sindex].subsys_list);
18009  while(turret != END_OF_LIST(&Ships[sindex].subsys_list))
18010  {
18011  memcpy(turret->turret_targeting_order, new_target_order, NUM_TURRET_ORDER_TYPES*sizeof(int));
18012 
18013  // next item
18014  turret = GET_NEXT(turret);
18015  }
18016 }
18017 
18018 // DahBlount
18020 {
18021  int sindex;
18022  ship_subsys *turret = NULL;
18023  ship_weapon *swp;
18024  int bank, check, ammo_left = 0;
18025 
18026  sindex = ship_name_lookup(CTEXT(node));
18027  if (sindex < 0) {
18028  return 0;
18029  }
18030  if (Ships[sindex].objnum < 0) {
18031  return 0;
18032  }
18033 
18034  node = CDR(node);
18035 
18036  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
18037  if (turret == NULL) {
18038  return 0;
18039  }
18040  if (!(turret->system_info->flags2 & MSS_FLAG2_TURRET_USE_AMMO)) {
18041  return 0;
18042  }
18043 
18044  swp = &turret->weapons;
18045 
18046  node = CDR(node);
18047 
18048  check = eval_num(node);
18049  if (check < 0) {
18050  return 0;
18051  }
18052 
18053  if (check >= swp->num_primary_banks)
18054  {
18055  for (bank = 0; bank < swp->num_primary_banks; bank++)
18056  {
18057  // Only ballistic weapons need to be counted
18059  {
18060  ammo_left += swp->primary_bank_ammo[bank];
18061  }
18062  }
18063  } else {
18064  // Again only ballistic weapons need to be counted
18066  {
18067  ammo_left = swp->primary_bank_ammo[check];
18068  }
18069  }
18070 
18071  return ammo_left;
18072 }
18073 
18074 // DahBlount - Sets a turrets primary ammo capacity
18076 {
18077  int sindex;
18078  ship_subsys *turret = NULL;
18079  int requested_bank;
18080  int requested_weapons;
18081 
18082  // Check that a ship has been supplied
18083  sindex = ship_name_lookup(CTEXT(node));
18084  if (sindex < 0)
18085  {
18086  return;
18087  }
18088 
18089  node = CDR(node);
18090 
18091  // Get the turret
18092  char *subsys = CTEXT(node);
18093  turret = ship_get_subsys(&Ships[sindex], subsys);
18094  if (turret == NULL) {
18095  return;
18096  }
18097 
18098  node = CDR(node);
18099 
18100  // Get the bank to set the number on
18101  requested_bank = eval_num(node);
18102  if (requested_bank < 0)
18103  {
18104  return;
18105  }
18106 
18107  // Get the number of weapons requested
18108  node = CDR(node);
18109  requested_weapons = eval_num(node);
18110  if (requested_weapons < 0)
18111  {
18112  return;
18113  }
18114 
18115  set_turret_primary_ammo(turret, requested_bank, requested_weapons);
18116 
18117  // Multiplayer call back
18119  multi_send_int(sindex);
18120  multi_send_string(subsys);
18121  multi_send_int(requested_bank);
18122  multi_send_int(requested_weapons);
18124 }
18125 
18127 {
18128  int sindex, requested_bank, requested_weapons;
18129  char subsys[TOKEN_LENGTH];
18130  multi_get_int(sindex);
18131  multi_get_string(subsys);
18132  multi_get_int(requested_bank);
18133  multi_get_int(requested_weapons);
18134 
18135  ship_subsys *turret = ship_get_subsys(&Ships[sindex], subsys);
18136 
18137  set_turret_primary_ammo(turret, requested_bank, requested_weapons);
18138 }
18139 
18140 // DahBlount - Helper function for setting turret primary ammo
18141 void set_turret_primary_ammo(ship_subsys *turret, int requested_bank, int requested_ammo, bool update)
18142 {
18143  // Can only set one bank at a time. Check that someone hasn't asked for the contents of all
18144  // the banks or a non-existant bank
18145  if ((requested_bank > turret->weapons.num_primary_banks) || requested_bank < 0)
18146  {
18147  return;
18148  }
18149 
18150  // Check that this isn't a non-ballistic bank as it's pointless to set the amount of ammo for those
18151  if (!(Weapon_info[turret->weapons.primary_bank_weapons[requested_bank]].wi_flags2 & WIF2_BALLISTIC))
18152  {
18153  return;
18154  }
18155 
18156  if (requested_ammo < 0)
18157  {
18158  return;
18159  }
18160 
18161  // Is the number requested larger than the maximum allowed for that particular bank?
18162  int maximum_allowed = fl2i(turret->weapons.primary_bank_capacity[requested_bank]
18163  / Weapon_info[turret->weapons.primary_bank_weapons[requested_bank]].cargo_size);
18164  if (maximum_allowed < requested_ammo)
18165  {
18166  requested_ammo = maximum_allowed;
18167  }
18168 
18169  // Set the number of weapons
18170  turret->weapons.primary_bank_ammo[requested_bank] = requested_ammo;
18171 }
18172 
18173 // DahBlount - Gets a turrets secondary ammo capacity
18175 {
18176  int sindex;
18177  ship_subsys *turret = NULL;
18178  ship_weapon *swp;
18179  int bank, check, ammo_left = 0;
18180 
18181  sindex = ship_name_lookup(CTEXT(node));
18182  if (sindex < 0) {
18183  return 0;
18184  }
18185  if (Ships[sindex].objnum < 0) {
18186  return 0;
18187  }
18188 
18189  node = CDR(node);
18190 
18191  turret = ship_get_subsys(&Ships[sindex], CTEXT(node));
18192  if (turret == NULL) {
18193  return 0;
18194  }
18195  if (!(turret->system_info->flags2 & MSS_FLAG2_TURRET_USE_AMMO)) {
18196  return 0;
18197  }
18198 
18199  swp = &turret->weapons;
18200 
18201  node = CDR(node);
18202 
18203  check = eval_num(node);
18204  if (check < 0) {
18205  return 0;
18206  }
18207 
18208  if (check >= swp->num_secondary_banks)
18209  {
18210  for (bank = 0; bank < swp->num_secondary_banks; bank++)
18211  {
18212  ammo_left += swp->secondary_bank_ammo[bank];
18213  }
18214  } else {
18215  ammo_left = swp->primary_bank_ammo[check];
18216  }
18217 
18218  return ammo_left;
18219 }
18220 
18221 // DahBlount - Sets a turrets secondary ammo capacity
18223 {
18224  int sindex;
18225  ship_subsys *turret = NULL;
18226  int requested_bank;
18227  int requested_weapons;
18228 
18229  // Check that a ship has been supplied
18230  sindex = ship_name_lookup(CTEXT(node));
18231  if (sindex < 0)
18232  {
18233  return;
18234  }
18235 
18236  node = CDR(node);
18237 
18238  // Get the turret
18239  char *subsys = CTEXT(node);
18240  turret = ship_get_subsys(&Ships[sindex], subsys);
18241  if (turret == NULL) {
18242  return;
18243  }
18244 
18245  node = CDR(node);
18246 
18247  // Get the bank to set the number on
18248  requested_bank = eval_num(node);
18249  if (requested_bank < 0)
18250  {
18251  return;
18252  }
18253 
18254  // Get the number of weapons requested
18255 
18256  node = CDR(node);
18257 
18258  requested_weapons = eval_num(node);
18259  if (requested_weapons < 0)
18260  {
18261  return;
18262  }
18263 
18264  set_turret_secondary_ammo(turret, requested_bank, requested_weapons);
18265 
18266  // Multiplayer call back
18268  multi_send_int(sindex);
18269  multi_send_string(subsys);
18270  multi_send_int(requested_bank);
18271  multi_send_int(requested_weapons);
18273 }
18274 
18276 {
18277  int sindex, requested_bank, requested_weapons;
18278  char subsys[TOKEN_LENGTH];
18279  multi_get_int(sindex);
18280  multi_get_string(subsys);
18281  multi_get_int(requested_bank);
18282  multi_get_int(requested_weapons);
18283 
18284  ship_subsys *turret = ship_get_subsys(&Ships[sindex], subsys);
18285 
18286  set_turret_secondary_ammo(turret, requested_bank, requested_weapons);
18287 }
18288 
18289 // DahBlount - Helper function for setting turret secondary ammo
18290 void set_turret_secondary_ammo(ship_subsys *turret, int requested_bank, int requested_ammo, bool update)
18291 {
18292  // Can only set one bank at a time. Check that someone hasn't asked for the contents of all
18293  // the banks or a non-existant bank
18294  if ((requested_bank > turret->weapons.num_secondary_banks) || requested_bank < 0)
18295  {
18296  return;
18297  }
18298 
18299  if (requested_ammo < 0)
18300  {
18301  return;
18302  }
18303 
18304  // Is the number requested larger than the maximum allowed for that particular bank?
18305  int maximum_allowed = fl2i(turret->weapons.secondary_bank_capacity[requested_bank]
18306  / Weapon_info[turret->weapons.secondary_bank_weapons[requested_bank]].cargo_size);
18307  if (maximum_allowed < requested_ammo)
18308  {
18309  requested_ammo = maximum_allowed;
18310  }
18311 
18312  // Set the number of weapons
18313  turret->weapons.secondary_bank_ammo[requested_bank] = requested_ammo;
18314 }
18315 
18316 // Goober5000
18317 void sexp_set_subsys_rotation_lock_free(int node, int locked)
18318 {
18319  int ship_num;
18320  ship_subsys *rotate;
18321 
18322  // get the ship
18323  ship_num = ship_name_lookup(CTEXT(node));
18324  if (ship_num < 0)
18325  return;
18326 
18327  if (Ships[ship_num].objnum < 0)
18328  return;
18329 
18330  node = CDR(node);
18331 
18332  // loop for all specified subsystems
18333  for ( ; node >= 0; node = CDR(node) )
18334  {
18335  // get the rotating subsystem
18336  rotate = ship_get_subsys(&Ships[ship_num], CTEXT(node));
18337  if (rotate == NULL)
18338  continue;
18339 
18340  // set rotate or not, depending on flag
18341  if (locked)
18342  {
18343  rotate->flags &= ~SSF_ROTATES;
18344  if (rotate->subsys_snd_flags & SSSF_ROTATE)
18345  {
18346  obj_snd_delete_type(Ships[ship_num].objnum, rotate->system_info->rotation_snd, rotate);
18347  rotate->subsys_snd_flags &= ~SSSF_ROTATE;
18348  }
18349  }
18350  else
18351  {
18352  rotate->flags |= SSF_ROTATES;
18353  if (rotate->system_info->rotation_snd >= 0)
18354  {
18355  obj_snd_assign(Ships[ship_num].objnum, rotate->system_info->rotation_snd, &rotate->system_info->pnt, 0, OS_SUBSYS_ROTATION, rotate);
18356  rotate->subsys_snd_flags |= SSSF_ROTATE;
18357  }
18358  }
18359  }
18360 }
18361 
18362 // Goober5000
18364 {
18365  int ship_num;
18366  ship_subsys *rotate;
18367 
18368  // get the ship
18369  ship_num = ship_name_lookup(CTEXT(node));
18370  if (ship_num < 0)
18371  return;
18372 
18373  if (Ships[ship_num].objnum < 0)
18374  return;
18375 
18376  node = CDR(node);
18377 
18378  // loop for all specified subsystems
18379  for ( ; node >= 0; node = CDR(node) )
18380  {
18381  // get the rotating subsystem
18382  rotate = ship_get_subsys(&Ships[ship_num], CTEXT(node));
18383  if (rotate == NULL)
18384  continue;
18385 
18386  // switch direction of rotation
18387  rotate->turn_rate *= -1.0f;
18388  rotate->submodel_info_1.cur_turn_rate *= -1.0f;
18389  rotate->submodel_info_1.desired_turn_rate *= -1.0f;
18390  }
18391 }
18392 
18393 // Goober5000
18395 {
18396  int ship_num, n = node;
18397  float turn_time, turn_accel;
18398  ship_subsys *rotate;
18399 
18400  // get the ship
18401  ship_num = ship_name_lookup(CTEXT(n));
18402  if (ship_num < 0)
18403  return;
18404  if (Ships[ship_num].objnum < 0)
18405  return;
18406  n = CDR(n);
18407 
18408  // get the rotating subsystem
18409  rotate = ship_get_subsys(&Ships[ship_num], CTEXT(n));
18410  if (rotate == NULL)
18411  return;
18412  n = CDR(n);
18413 
18414  // get and set the turn time
18415  turn_time = eval_num(n) / 1000.0f;
18416  rotate->submodel_info_1.desired_turn_rate = PI2 / turn_time;
18417  n = CDR(n);
18418 
18419  // maybe get and set the turn accel
18420  if (n != -1)
18421  {
18422  turn_accel = eval_num(n) / 1000.0f;
18423  rotate->submodel_info_1.turn_accel = PI2 / turn_accel;
18424  }
18425  else
18426  rotate->submodel_info_1.cur_turn_rate = PI2 / turn_time;
18427 }
18428 
18430 {
18431  int ship_num, animation_type, animation_subtype, direction, n = node;
18432  bool instant;
18433 
18434  // get the ship
18435  ship_num = ship_name_lookup(CTEXT(n));
18436  if (ship_num < 0)
18437  return;
18438  if (Ships[ship_num].objnum < 0)
18439  return;
18440  n = CDR(n);
18441 
18442  // get the type
18443  animation_type = model_anim_match_type(CTEXT(n));
18444  if (animation_type == TRIGGER_TYPE_NONE)
18445  {
18446  Warning(LOCATION, "Unable to match animation type \"%s\"!", CTEXT(n));
18447  return;
18448  }
18449  n = CDR(n);
18450 
18451  // get the subtype
18452  animation_subtype = eval_num(n);
18453  n = CDR(n);
18454 
18455  // get the direction, 1 or -1
18456  direction = eval_num(n);
18457  if (direction != 1 && direction != -1)
18458  {
18459  Warning(LOCATION, "Direction is %d; it must be 1 or -1!", direction);
18460  return;
18461  }
18462  n = CDR(n);
18463 
18464  // instant or not
18465  if (n >= 0)
18466  {
18467  instant = (is_sexp_true(n) != 0);
18468  n = CDR(n);
18469  }
18470  else
18471  instant = false;
18472 
18473  // do we narrow it to a specific subsystem?
18474  if (n >= 0)
18475  {
18476  ship_subsys *ss = ship_get_subsys(&Ships[ship_num], CTEXT(n));
18477  if (ss == NULL)
18478  {
18479  Warning(LOCATION, "Subsystem \"%s\" not found on ship \"%s\"!", CTEXT(n), CTEXT(node));
18480  return;
18481  }
18482  model_anim_start_type(ss, animation_type, animation_subtype, direction, instant);
18483  }
18484  else
18485  {
18486  model_anim_start_type(&Ships[ship_num], animation_type, animation_subtype, direction, instant);
18487  }
18488 }
18489 
18491 {
18492  ship_subsys *subsys;
18493  int sindex;
18494 
18495  // get the firing ship
18496  sindex = ship_name_lookup(CTEXT(node));
18497  if(sindex < 0){
18498  return;
18499  }
18500  if(Ships[sindex].objnum < 0){
18501  return;
18502  }
18503 
18504  node = CDR(node);
18505  for ( ; node >= 0; node = CDR(node) ) {
18506  // get the subsystem
18507  subsys = ship_get_subsys(&Ships[sindex], CTEXT(node));
18508  if(subsys == NULL){
18509  continue;
18510  }
18511 
18512  // flag turret as slaved to tag
18513  subsys->weapons.flags |= SW_FLAG_TAGGED_ONLY;
18514  }
18515 }
18516 
18518 {
18519  ship_subsys *subsys;
18520  int sindex;
18521 
18522  // get the firing ship
18523  sindex = ship_name_lookup(CTEXT(node));
18524  if(sindex < 0){
18525  return;
18526  }
18527  if(Ships[sindex].objnum < 0){
18528  return;
18529  }
18530 
18531  node = CDR(node);
18532  for ( ; node >= 0; node = CDR(node) ) {
18533  // get the subsystem
18534  subsys = ship_get_subsys(&Ships[sindex], CTEXT(node));
18535  if(subsys == NULL){
18536  continue;
18537  }
18538 
18539  // flag turret as slaved to tag
18540  subsys->weapons.flags &= (~SW_FLAG_TAGGED_ONLY);
18541  }
18542 }
18543 
18545 {
18546  int sindex;
18547  int flag;
18548 
18549  // get the firing ship
18550  sindex = ship_name_lookup(CTEXT(node));
18551  if(sindex < 0){
18552  return;
18553  }
18554  if(Ships[sindex].objnum < 0){
18555  return;
18556  }
18557 
18558  // determine whether to add or remove it
18559  flag = eval_num(CDR(node));
18560 
18561  // add/remove
18562  if(flag){
18563  Ships[sindex].escort_priority = flag ;
18564  hud_add_ship_to_escort(Ships[sindex].objnum, 1);
18565  } else {
18566  hud_remove_ship_from_escort(Ships[sindex].objnum);
18567  }
18568 
18570  multi_send_int(sindex);
18571  multi_send_int(flag);
18573 }
18574 
18576 {
18577  int sindex;
18578  int flag;
18579 
18580  multi_get_int(sindex);
18581  if (!(multi_get_int(flag))) {
18582  return;
18583  }
18584 
18585  // add/remove
18586  if(flag){
18587  Ships[sindex].escort_priority = flag ;
18588  hud_add_ship_to_escort(Ships[sindex].objnum, 1);
18589  } else {
18590  hud_remove_ship_from_escort(Ships[sindex].objnum);
18591  }
18592 }
18593 
18594 //given: two escort priorities and a list of ships
18595 //do: sets the most damaged one to the first priority and the rest to the second.
18597 {
18598  int n;
18599  int priority1; //escort priority to set the most damaged ship
18600  int priority2; //"" "" to set the other ships
18601 
18602  ship* shipp;
18603  float smallest_hull_pct=1; //smallest hull pct found
18604  int small_shipnum=-1; //index in Ships[] of the above
18605  float current_hull_pct; //hull pct of current ship we are evaluating
18606  int shipnum=-1; //index in Ships[] of the above
18607 
18608  priority1=eval_num(node);
18609  priority2=eval_num(CDR(node));
18610 
18611  //go to start of ship list
18612  n=CDR(CDR(node));
18613 
18614  //loop through the ships
18615  for ( ; n != -1; n = CDR(n) )
18616  {
18617  // check to see if ship destroyed or departed. In either case, do nothing.
18619  continue;
18620 
18621  shipnum=ship_name_lookup(CTEXT(n));
18622 
18623  //it may be dead
18624  if (shipnum < 0)
18625  continue;
18626 
18627  if (Ships[shipnum].objnum < 0)
18628  continue;
18629 
18630  shipp=&Ships[shipnum];
18631 
18632  //calc hull integrity and compare
18633  current_hull_pct = get_hull_pct(&Objects[Ships[shipnum].objnum]);
18634 
18635  if (current_hull_pct < smallest_hull_pct)
18636  {
18637  if (small_shipnum != -1) // avoid negative array index during 1st loop iteration
18638  {
18639  Ships[small_shipnum].escort_priority=priority2; //give the previous smallest the lower priority
18640  }
18641 
18642  smallest_hull_pct=current_hull_pct;
18643  small_shipnum=shipnum;
18644 
18645  shipp->escort_priority=priority1; //give the new smallest the higher priority
18646  hud_add_ship_to_escort(Ships[shipnum].objnum,1);
18647  }
18648  else //if its bigger to begin with give it lower priority
18649  {
18650  shipp->escort_priority=priority2;
18651  hud_add_ship_to_escort(Ships[shipnum].objnum,1);
18652  }
18653  }
18654 }
18655 
18656 // Goober5000 - set stuff for mission support ship
18658 {
18659  int i, temp_val;
18660 
18661  // get arrival location
18662  temp_val = -1;
18663  for (i=0; i<MAX_ARRIVAL_NAMES; i++)
18664  {
18665  if (!stricmp(CTEXT(n), Arrival_location_names[i]))
18666  temp_val = i;
18667  }
18668  if (temp_val < 0)
18669  {
18670  Warning(LOCATION, "Support ship arrival location '%s' not found.\n", CTEXT(n));
18671  return;
18672  }
18674 
18675  // get arrival anchor
18676  n = CDR(n);
18677  if (!stricmp(CTEXT(n), "<no anchor>"))
18678  {
18679  // if no anchor, set arrival location to hyperspace
18681  }
18682  else
18683  {
18684  // anchor must exist - look for it
18685  temp_val = -1;
18686  for (i=0; i<Num_parse_names; i++)
18687  {
18688  if (!stricmp(CTEXT(n), Parse_names[i]))
18689  temp_val = i;
18690  }
18691  // if not found, make a new entry
18692  if (temp_val < 0)
18693  {
18694  strcpy_s(Parse_names[Num_parse_names], CTEXT(n));
18695  temp_val = Num_parse_names;
18696  Num_parse_names++;
18697  }
18699  }
18700 
18701  // get departure location
18702  n = CDR(n);
18703  temp_val = -1;
18704  for (i=0; i<MAX_DEPARTURE_NAMES; i++)
18705  {
18706  if (!stricmp(CTEXT(n), Departure_location_names[i]))
18707  temp_val = i;
18708  }
18709  if (temp_val < 0)
18710  {
18711  Warning(LOCATION, "Support ship departure location '%s' not found.\n", CTEXT(n));
18712  return;
18713  }
18715 
18716  // get departure anchor
18717  n = CDR(n);
18718  if (!stricmp(CTEXT(n), "<no anchor>"))
18719  {
18720  // if no anchor, set departure location to hyperspace
18722  }
18723  else
18724  {
18725  // anchor must exist - look for it
18726  temp_val = -1;
18727  for (i=0; i<Num_parse_names; i++)
18728  {
18729  if (!stricmp(CTEXT(n), Parse_names[i]))
18730  temp_val = i;
18731  }
18732  // if not found, make a new entry
18733  if (temp_val < 0)
18734  {
18735  strcpy_s(Parse_names[Num_parse_names], CTEXT(n));
18736  temp_val = Num_parse_names;
18737  Num_parse_names++;
18738  }
18740  }
18741 
18742  // get ship class
18743  n = CDR(n);
18744  temp_val = ship_info_lookup(CTEXT(n));
18745  if ((temp_val < 0) && ((stricmp(CTEXT(n), "<species support ship class>")) && (stricmp(CTEXT(n), "<any support ship class>"))) )
18746  {
18747  Warning(LOCATION, "Support ship class '%s' not found.\n", CTEXT(n));
18748  return;
18749  }
18750  if ((temp_val >= 0) && !(Ship_info[temp_val].flags & SIF_SUPPORT))
18751  {
18752  Warning(LOCATION, "Ship %s is not a support ship!", Ship_info[temp_val].name);
18753  return;
18754  }
18756 
18757  // get max number of ships allowed
18758  n = CDR(n);
18760 
18761  // get the number of concurrent ships allowed
18762  n = CDR(n);
18763  if ( n == -1 ) {
18764  // 7th arg not specified, set default
18766  } else {
18768  }
18769 }
18770 
18771 // Goober5000 - set stuff for arriving ships or wings
18773 {
18774  int i, arrival_location, arrival_anchor, arrival_mask, arrival_distance, arrival_delay, n = node;
18775  bool show_warp;
18777 
18778  // get ship or wing
18780  n = CDR(n);
18781 
18782  // get arrival location
18783  arrival_location = -1;
18784  for (i=0; i<MAX_ARRIVAL_NAMES; i++)
18785  {
18786  if (!stricmp(CTEXT(n), Arrival_location_names[i]))
18787  arrival_location = i;
18788  }
18789  if (arrival_location < 0)
18790  {
18791  Warning(LOCATION, "Arrival location '%s' not found.\n", CTEXT(n));
18792  return;
18793  }
18794  n = CDR(n);
18795 
18796  // get arrival anchor
18797  arrival_anchor = -1;
18798  if ((n < 0) || !stricmp(CTEXT(n), "<no anchor>"))
18799  {
18800  // if no anchor, set arrival location to hyperspace
18801  arrival_location = 0;
18802  }
18803  else
18804  {
18805  // anchor must exist - look for it
18806  for (i=0; i<Num_parse_names; i++)
18807  {
18808  if (!stricmp(CTEXT(n), Parse_names[i]))
18809  arrival_anchor = i;
18810  }
18811  // if not found, make a new entry
18812  if (arrival_anchor < 0)
18813  {
18814  strcpy_s(Parse_names[Num_parse_names], CTEXT(n));
18815  arrival_anchor = Num_parse_names;
18816  Num_parse_names++;
18817  }
18818  }
18819  n = CDR(n);
18820 
18821  // get arrival path mask
18822  arrival_mask = 0;
18823  if (n >= 0)
18824  arrival_mask = eval_num(n);
18825  n = CDR(n);
18826 
18827  // get arrival distance
18828  arrival_distance = 0;
18829  if (n >= 0)
18830  arrival_distance = eval_num(n);
18831  n = CDR(n);
18832 
18833  // get arrival delay
18834  arrival_delay = 0;
18835  if (n >= 0)
18836  arrival_delay = eval_num(n);
18837  n = CDR(n);
18838 
18839  // get warp effect
18840  show_warp = true;
18841  if (n >= 0)
18842  show_warp = (is_sexp_true(n) != 0);
18843 
18844  // now set all that information depending on the first argument
18845  if (oswpt.type == OSWPT_TYPE_SHIP)
18846  {
18847  oswpt.shipp->arrival_location = arrival_location;
18848  oswpt.shipp->arrival_anchor = arrival_anchor;
18849  oswpt.shipp->arrival_path_mask = arrival_mask;
18850  oswpt.shipp->arrival_distance = arrival_distance;
18851  oswpt.shipp->arrival_delay = arrival_delay;
18852 
18853  if (show_warp)
18854  oswpt.shipp->flags &= ~SF_NO_ARRIVAL_WARP;
18855  else
18856  oswpt.shipp->flags |= SF_NO_ARRIVAL_WARP;
18857  }
18858  else if (oswpt.type == OSWPT_TYPE_WING || oswpt.type == OSWPT_TYPE_WING_NOT_PRESENT)
18859  {
18860  oswpt.wingp->arrival_location = arrival_location;
18861  oswpt.wingp->arrival_anchor = arrival_anchor;
18862  oswpt.wingp->arrival_path_mask = arrival_mask;
18863  oswpt.wingp->arrival_distance = arrival_distance;
18864  oswpt.wingp->arrival_delay = arrival_delay;
18865 
18866  if (show_warp)
18867  oswpt.wingp->flags &= ~WF_NO_ARRIVAL_WARP;
18868  else
18869  oswpt.wingp->flags |= WF_NO_ARRIVAL_WARP;
18870  }
18871  else if (oswpt.type == OSWPT_TYPE_PARSE_OBJECT)
18872  {
18873  oswpt.p_objp->arrival_location = arrival_location;
18874  oswpt.p_objp->arrival_anchor = arrival_anchor;
18875  oswpt.p_objp->arrival_path_mask = arrival_mask;
18876  oswpt.p_objp->arrival_distance = arrival_distance;
18877  oswpt.p_objp->arrival_delay = arrival_delay;
18878 
18879  if (show_warp)
18880  oswpt.p_objp->flags &= ~P_SF_NO_ARRIVAL_WARP;
18881  else
18882  oswpt.p_objp->flags |= P_SF_NO_ARRIVAL_WARP;
18883  }
18884 }
18885 
18886 // Goober5000 - set stuff for departing ships or wings
18888 {
18889  int i, departure_location, departure_anchor, departure_mask, departure_delay, n = node;
18890  bool show_warp;
18892 
18893  // get ship or wing
18895  n = CDR(n);
18896 
18897  // get departure location
18898  departure_location = -1;
18899  for (i=0; i<MAX_DEPARTURE_NAMES; i++)
18900  {
18901  if (!stricmp(CTEXT(n), Departure_location_names[i]))
18902  departure_location = i;
18903  }
18904  if (departure_location < 0)
18905  {
18906  Warning(LOCATION, "Departure location '%s' not found.\n", CTEXT(n));
18907  return;
18908  }
18909  n = CDR(n);
18910 
18911  // get departure anchor
18912  departure_anchor = -1;
18913  if ((n < 0) || !stricmp(CTEXT(n), "<no anchor>"))
18914  {
18915  // if no anchor, set departure location to hyperspace
18916  departure_location = 0;
18917  }
18918  else
18919  {
18920  // anchor must exist - look for it
18921  for (i=0; i<Num_parse_names; i++)
18922  {
18923  if (!stricmp(CTEXT(n), Parse_names[i]))
18924  departure_anchor = i;
18925  }
18926  // if not found, make a new entry
18927  if (departure_anchor < 0)
18928  {
18929  strcpy_s(Parse_names[Num_parse_names], CTEXT(n));
18930  departure_anchor = Num_parse_names;
18931  Num_parse_names++;
18932  }
18933  }
18934  n = CDR(n);
18935 
18936  // get departure path mask
18937  departure_mask = 0;
18938  if (n >= 0)
18939  departure_mask = eval_num(n);
18940  n = CDR(n);
18941 
18942  // get departure delay
18943  departure_delay = 0;
18944  if (n >= 0)
18945  departure_delay = eval_num(n);
18946  n = CDR(n);
18947 
18948  // get warp effect
18949  show_warp = true;
18950  if (n >= 0)
18951  show_warp = (is_sexp_true(n) != 0);
18952 
18953  // now set all that information depending on the first argument
18954  if (oswpt.type == OSWPT_TYPE_SHIP)
18955  {
18956  oswpt.shipp->departure_location = departure_location;
18957  oswpt.shipp->departure_anchor = departure_anchor;
18958  oswpt.shipp->departure_path_mask = departure_mask;
18959  oswpt.shipp->departure_delay = departure_delay;
18960 
18961  if (show_warp)
18962  oswpt.shipp->flags &= ~SF_NO_DEPARTURE_WARP;
18963  else
18964  oswpt.shipp->flags |= SF_NO_DEPARTURE_WARP;
18965  }
18966  else if (oswpt.type == OSWPT_TYPE_WING || oswpt.type == OSWPT_TYPE_WING_NOT_PRESENT)
18967  {
18968  oswpt.wingp->departure_location = departure_location;
18969  oswpt.wingp->departure_anchor = departure_anchor;
18970  oswpt.wingp->departure_path_mask = departure_mask;
18971  oswpt.wingp->departure_delay = departure_delay;
18972 
18973  if (show_warp)
18974  oswpt.wingp->flags &= ~WF_NO_DEPARTURE_WARP;
18975  else
18976  oswpt.wingp->flags |= WF_NO_DEPARTURE_WARP;
18977  }
18978  else if (oswpt.type == OSWPT_TYPE_PARSE_OBJECT)
18979  {
18980  oswpt.p_objp->departure_location = departure_location;
18981  oswpt.p_objp->departure_anchor = departure_anchor;
18982  oswpt.p_objp->departure_path_mask = departure_mask;
18983  oswpt.p_objp->departure_delay = departure_delay;
18984 
18985  if (show_warp)
18986  oswpt.p_objp->flags &= ~P_SF_NO_DEPARTURE_WARP;
18987  else
18989  }
18990 }
18991 
18992 // Goober5000
18993 // set *all* the escort priorities of ships in escort list as follows: most damaged ship gets
18994 // first priority in the argument list, next damaged gets next priority, etc.; if there are more
18995 // ships than priorities, all remaining ships get the final priority on the list
18996 // -- As indicated in the argument specification, there must be at least one argument but no more
18997 // than MAX_COMPLETE_ESCORT_LIST arguments
18999 {
19000  typedef struct
19001  {
19002  int index;
19003  float hull;
19004  } my_escort_ship;
19005 
19006  int priority[MAX_COMPLETE_ESCORT_LIST];
19007  my_escort_ship escort_ship[MAX_COMPLETE_ESCORT_LIST];
19008  int i, j, num_escort_ships, num_priorities, temp_i;
19009  float temp_f;
19010  ship *shipp;
19011 
19012  // build list of priorities
19013  num_priorities = 0;
19014  for ( ; n != -1; n = CDR(n) )
19015  {
19016  priority[num_priorities] = eval_num(n);
19017  num_priorities++;
19018  }
19019 
19020  // build custom list of escort ships
19021  num_escort_ships = 0;
19022  for (i = 0; i < MAX_SHIPS; i++)
19023  {
19024  shipp = &Ships[i];
19025 
19026  // make sure it exists
19027  if ( shipp->objnum < 0 )
19028  continue;
19029 
19030  // make sure it's on the escort list
19031  if ( !(shipp->flags & SF_ESCORT) )
19032  continue;
19033 
19034  // set index
19035  escort_ship[num_escort_ships].index = i;
19036 
19037  // calc and set hull integrity
19038  escort_ship[num_escort_ships].hull = get_hull_pct(&Objects[shipp->objnum]);
19039 
19040  num_escort_ships++;
19041  }
19042 
19043  // sort it bubbly, lowest hull to highest hull
19044  for (i = 0; i < num_escort_ships; i++)
19045  {
19046  for (j = 0; j < i; j++)
19047  {
19048  if (escort_ship[i].hull < escort_ship[j].hull)
19049  {
19050  // swap
19051  temp_i = escort_ship[i].index;
19052  temp_f = escort_ship[i].hull;
19053  escort_ship[i].index = escort_ship[j].index;
19054  escort_ship[i].hull = escort_ship[j].hull;
19055  escort_ship[j].index = temp_i;
19056  escort_ship[j].hull = temp_f;
19057  }
19058  }
19059  }
19060 
19061  // loop through and assign priorities
19062  for (i = 0; i < num_escort_ships; i++)
19063  {
19064  if (i >= num_priorities)
19065  Ships[escort_ship[i].index].escort_priority = priority[num_priorities - 1];
19066  else
19067  Ships[escort_ship[i].index].escort_priority = priority[i];
19068  }
19069 
19070  // redo the escort list
19072 }
19073 
19075 {
19076  int sindex;
19077  ship_subsys *awacs;
19078 
19079  // get the firing ship
19080  sindex = ship_name_lookup(CTEXT(node));
19081  if(sindex < 0){
19082  return;
19083  }
19084  if(Ships[sindex].objnum < 0){
19085  return;
19086  }
19087 
19088  // get the awacs subsystem
19089  awacs = ship_get_subsys(&Ships[sindex], CTEXT(CDR(node)));
19090  if(awacs == NULL){
19091  return;
19092  }
19093 
19094  if (!(awacs->system_info->flags & MSS_FLAG_AWACS))
19095  return;
19096 
19097  // set the new awacs radius
19098  awacs->awacs_radius = (float)eval_num(CDR(CDR(node)));
19099 }
19100 
19101 // Goober5000
19103 {
19104  char *ship_name = CTEXT(n);
19105  int ship_num, range = eval_num(CDR(n));
19106 
19107  // check to see if ship destroyed or departed. In either case, do nothing.
19108  if ( mission_log_get_time(LOG_SHIP_DEPARTED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SHIP_DESTROYED, ship_name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_name, NULL, NULL) )
19109  return;
19110 
19111  // get the ship
19112  ship_num = ship_name_lookup(ship_name);
19113 
19114  // ship not yet in mission? do nothing
19115  if (ship_num < 0)
19116  return;
19117 
19118  // set the new range
19119  Ships[ship_num].primitive_sensor_range = range;
19120 }
19121 
19122 
19123 //*************************************************************************************************
19124 // Kazan
19125 // AutoNav/AutoPilot system SEXPS
19126 
19127 //text: set-nav-carry
19128 //args: 1+, Ship/Wing name
19129 void set_nav_carry_status(int node)
19130 {
19131  int n=node, i;
19132  char *name;
19133  bool skip;
19134 
19135  while (n != -1)
19136  {
19137  name = CTEXT(n);
19138  skip = false;
19139 
19140  for (i = 0; i < MAX_WINGS; i++)
19141  {
19142  if (!stricmp(Wings[i].name, name))
19143  {
19144  Wings[i].flags |= WF_NAV_CARRY;
19145  skip = true;
19146  break;
19147  }
19148  }
19149 
19150  if (!skip)
19151  {
19152  for (i = 0; i < MAX_SHIPS; i++)
19153  {
19154  if (Ships[i].objnum != -1 && !stricmp(Ships[i].ship_name, name))
19155  {
19157  break;
19158  }
19159  }
19160  }
19161 
19162  // move to next ship/wing in list
19163  n = CDR(n);
19164  }
19165 }
19166 
19167 //text: unset-nav-carry
19168 //args: 1+, Ship/Wing name
19170 {
19171  int n=node, i;
19172  char *name;
19173  bool skip;
19174 
19175 
19176  while (n != -1)
19177  {
19178  name = CTEXT(n);
19179  skip = false;
19180 
19181  for (i = 0; i < MAX_WINGS; i++)
19182  {
19183  if (!stricmp(Wings[i].name, name))
19184  {
19185  Wings[i].flags &= ~WF_NAV_CARRY;
19186  skip = true;
19187  break;
19188 
19189  }
19190  }
19191 
19192  if (!skip)
19193  {
19194  for (i = 0; i < MAX_SHIPS; i++)
19195  {
19196  if (Ships[i].objnum != -1 && !stricmp(Ships[i].ship_name, name))
19197  {
19199  break;
19200  }
19201  }
19202  }
19203 
19204  // move to next ship/wing in list
19205  n = CDR(n);
19206  }
19207 }
19208 
19209 
19210 //text: set-nav-needslink
19211 //args: 1+, Ship/Wing name
19212 void set_nav_needslink(int node)
19213 {
19214  int n=node, i;
19215  char *name;
19216 
19217  while (n != -1)
19218  {
19219  name = CTEXT(n);
19220 
19221  for (i = 0; i < MAX_SHIPS; i++)
19222  {
19223  if (Ships[i].objnum != -1 && !stricmp(Ships[i].ship_name, name))
19224  {
19227  break;
19228  }
19229  }
19230  // move to next ship/wing in list
19231  n = CDR(n);
19232  }
19233 }
19234 
19235 //text: unset-nav-needslink
19236 //args: 1+, Ship/Wing name
19237 void unset_nav_needslink(int node)
19238 {
19239  int n=node, i;
19240  char *name;
19241 
19242  while (n != -1)
19243  {
19244  name = CTEXT(n);
19245 
19246 
19247  for (i = 0; i < MAX_SHIPS; i++)
19248  {
19249  if (Ships[i].objnum != -1 && !stricmp(Ships[i].ship_name, name))
19250  {
19252  break;
19253  }
19254  }
19255 
19256 
19257  // move to next ship/wing in list
19258  n = CDR(n);
19259  }
19260 }
19261 
19262 void add_nav_waypoint(char *nav, char *WP_path, int vert, char *oswpt_name)
19263 {
19264  int i;
19266  bool add_for_this_player = true;
19267 
19268  if (oswpt_name != NULL) {
19269  sexp_get_object_ship_wing_point_team(&oswpt, oswpt_name);
19270 
19271  // we can't assume this nav should be visible to the player any more
19272  add_for_this_player = false;
19273 
19274  switch (oswpt.type)
19275  {
19276  case OSWPT_TYPE_WHOLE_TEAM:
19277  if (oswpt.team == Player_ship->team) {
19278  add_for_this_player = true;
19279  }
19280  break;
19281 
19282  case OSWPT_TYPE_SHIP:
19283  if (oswpt.shipp == Player_ship) {
19284  add_for_this_player = true;
19285  }
19286  break;
19287  case OSWPT_TYPE_WING:
19288  for ( i = 0; i < oswpt.wingp->current_count; i++) {
19289  if (Ships[oswpt.wingp->ship_index[i]].objnum == Player_ship->objnum) {
19290  add_for_this_player = true;
19291  }
19292  }
19293 
19294 
19295  // for all other oswpt types we simply ignore this
19296  default:
19297  break;
19298  }
19299  }
19300 
19301  AddNav_Waypoint(nav, WP_path, vert, add_for_this_player ? 0 : NP_HIDDEN);
19302 }
19303 
19304 
19305 //text: add-nav-waypoint
19306 //args: 4, Nav Name, Waypoint Path Name, Waypoint Path point, ShipWingTeam
19307 void add_nav_waypoint(int node)
19308 {
19309  char *nav_name = CTEXT(node);
19310  char *way_name = CTEXT(CDR(node));
19311  int vert = eval_num(CDR(CDR(node)));
19312  char *oswpt_name;
19313 
19314  node = CDR(CDR(CDR(node)));
19315  if (node >=0) {
19316  oswpt_name = CTEXT(node);
19317  }
19318  else {
19319  oswpt_name = NULL;
19320  }
19321 
19322  add_nav_waypoint(nav_name, way_name, vert, oswpt_name);
19323 
19325  multi_send_string(nav_name);
19326  multi_send_string(way_name);
19327  multi_send_int(vert);
19328 
19329  if (oswpt_name != NULL) {
19330  multi_send_string(oswpt_name);
19331  }
19332 
19334 }
19335 
19337 {
19338  char nav_name[TOKEN_LENGTH];
19339  char way_name[TOKEN_LENGTH];
19340  char oswpt_name[TOKEN_LENGTH];
19341  int vert;
19342 
19343  if (!multi_get_string(nav_name)) {
19344  return;
19345  }
19346 
19347  if (!multi_get_string(way_name)) {
19348  return;
19349  }
19350 
19351  if (!multi_get_int(vert)) {
19352  return;
19353  }
19354 
19355  if (!multi_get_string(oswpt_name)) {
19356  add_nav_waypoint(nav_name, way_name, vert, NULL);
19357  }
19358  else {
19359  add_nav_waypoint(nav_name, way_name, vert, oswpt_name);
19360  }
19361 
19362  AddNav_Waypoint(nav_name, way_name, vert, 0);
19363 }
19364 
19365 
19366 //text: add-nav-ship
19367 //args: 2, Nav Name, Ship Name
19368 void add_nav_ship(int node)
19369 {
19370  char *nav_name = CTEXT(node);
19371  char *ship_name = CTEXT(CDR(node));
19372  AddNav_Ship(nav_name, ship_name, 0);
19373 
19375  multi_send_string(nav_name);
19376  multi_send_string(ship_name);
19378 }
19379 
19381 {
19382  char nav_name[TOKEN_LENGTH];
19383  char ship_name[TOKEN_LENGTH];
19384 
19385  if (!multi_get_string(nav_name)) {
19386  return;
19387  }
19388 
19389  if (!multi_get_string(ship_name)) {
19390  return;
19391  }
19392 
19393  AddNav_Ship(nav_name, ship_name, 0);
19394 }
19395 
19396 
19397 //text: del-nav
19398 //args: 1, Nav Name
19399 void del_nav(int node)
19400 {
19401  char *nav_name = CTEXT(node);
19402  DelNavPoint(nav_name);
19403 
19405  multi_send_string(nav_name);
19407 
19408 }
19409 
19411 {
19412  char nav_name[TOKEN_LENGTH];
19413 
19414  if (!multi_get_string(nav_name)) {
19415  return;
19416  }
19417 
19418  DelNavPoint(nav_name);
19419 }
19420 
19421 //text: use-nav-cinematics
19422 //args: 1, boolean enable/disable
19424 {
19425  if (is_sexp_true(node))
19426  {
19428  }
19429  else
19430  {
19432  }
19433 }
19434 
19435 //text: use-autopilot
19436 //args: 1, boolean enable/disable
19437 void set_use_ap(int node)
19438 {
19439  if (is_sexp_true(node))
19440  {
19442  }
19443  else
19444  {
19446  }
19447 }
19448 
19449 //text: hide-nav
19450 //args: 1, Nav Name
19451 void hide_nav(int node)
19452 {
19453  char *nav_name = CTEXT(node);
19454  Nav_Set_Hidden(nav_name);
19455 }
19456 
19457 //text: restrict-nav
19458 //args: 1, nav name
19459 void restrict_nav(int node)
19460 {
19461  char *nav_name = CTEXT(node);
19462  Nav_Set_NoAccess(nav_name);
19463 }
19464 
19465 //text: unhide-nav
19466 //args: 1, Nav name
19467 void unhide_nav(int node)
19468 {
19469  char *nav_name = CTEXT(node);
19470  Nav_UnSet_Hidden(nav_name);
19471 }
19472 
19473 //text: unrestrict-nav
19474 //args: 1, nav name
19475 void unrestrict_nav(int node)
19476 {
19477  char *nav_name = CTEXT(node);
19478  Nav_UnSet_NoAccess(nav_name);
19479 
19480 }
19481 
19482 //text: set-nav-visited
19483 //args: 1, Nav Name
19484 void set_nav_visited(int node)
19485 {
19486  char *nav_name = CTEXT(node);
19487  Nav_Set_Visited(nav_name);
19488 }
19489 
19490 //text: unset-nav-visited
19491 //args: 1, Nav Name
19492 void unset_nav_visited(int node)
19493 {
19494  char *nav_name = CTEXT(node);
19495  Nav_UnSet_Visited(nav_name);
19496 }
19497 
19498 
19499 //text: is-nav-visited
19500 //args: 1, Nav Name
19501 //rets: true/false
19502 int is_nav_visited(int node)
19503 {
19504  char *nav_name = CTEXT(node);
19505  return IsVisited(nav_name);
19506 }
19507 
19508 
19509 //text: is-nav_linked
19510 //args: 1, Ship name
19511 //rets: true/false
19512 int is_nav_linked(int node)
19513 {
19514  char *ship_name = CTEXT(node);
19515  for (int i = 0; i < MAX_SHIPS; i++)
19516  {
19517  if (Ships[i].objnum != -1 && !stricmp(Ships[i].ship_name, ship_name))
19518  {
19519  return (Ships[i].flags2 & SF2_NAVPOINT_CARRY) != 0;
19520  }
19521  }
19522  return 0;
19523 }
19524 
19525 //text: distance-to-nav
19526 //args: 1, Nav Name
19527 //rets: distance to nav
19528 int distance_to_nav(int node)
19529 {
19530  char *nav_name = CTEXT(node);
19531  return DistanceTo(nav_name);
19532 }
19533 
19534 void select_nav(int node)
19535 {
19536  char *nav_name = CTEXT(node);
19537  SelectNav(nav_name);
19538 }
19539 
19541 {
19542  DeselectNav();
19543 }
19544 
19545 
19546 //*************************************************************************************************
19547 
19548 
19549 int sexp_is_tagged(int node)
19550 {
19551  int sindex;
19552 
19553  // get the firing ship
19554  sindex = ship_name_lookup(CTEXT(node));
19555  if(sindex < 0){
19556  return SEXP_FALSE;
19557  }
19558  if(Ships[sindex].objnum < 0){
19559  return SEXP_FALSE;
19560  }
19561  object *caller = &Objects[Ships[sindex].objnum];
19562  if(ship_is_tagged(caller)) { // This line and the one above were added.
19563  return SEXP_TRUE;
19564  }
19565 
19566  // not tagged
19567  return SEXP_FALSE;
19568 }
19569 
19570 // Joint effort of Sesquipedalian and Goober5000. Sesq found the code, mucked around making
19571 // sexps with it and learned things, Goober taught Sesq and made the sexp work properly. =D
19572 // Returns true so long as the player has held a missile lock for the specified time.
19573 // If the optional ship and/or ship's subsystem are specified, returns true when that
19574 // has been locked onto, but otherwise returns as long as anything has been locked onto.
19575 int sexp_missile_locked(int node)
19576 {
19577  int z;
19578 
19579  // if we aren't targeting anything, it's false
19580  if ((Players_target == -1) || (Players_target == UNINITIALIZED))
19581  return SEXP_FALSE;
19582 
19583  // if we aren't locked on to anything, it's false
19584  if (!Players_mlocked)
19585  return SEXP_FALSE;
19586 
19587  // do we have a specific ship?
19588  if (CDR(node) != -1)
19589  {
19590  // if we're not targeting the specific ship, it's false
19591  if (stricmp(Ships[Objects[Players_target].instance].ship_name, CTEXT(CDR(node))))
19592  return SEXP_FALSE;
19593 
19594  // do we have a specific subsystem?
19595  if (CDR(CDR(node)) != -1)
19596  {
19597  // if we aren't targeting a subsystem at all, it's false
19598  if (!Player_ai->targeted_subsys)
19599  return SEXP_FALSE;
19600 
19601  // if we're not targeting the specific subsystem, it's false
19603  return SEXP_FALSE;
19604  }
19605  }
19606 
19607  // if we've gotten this far, we must have satisfied whatever conditions the sexp imposed
19608  // finally, test if we've locked for a certain period of time
19609  z = eval_num(node) * 1000;
19610  if (timestamp_has_time_elapsed(Players_mlocked_timestamp, z))
19611  {
19612  return SEXP_TRUE;
19613  }
19614 
19615  return SEXP_FALSE;
19616 }
19617 
19618 int sexp_is_player (int node)
19619 {
19620  int sindex, np_index;
19621  p_object *p_objp;
19622 
19623  int standard_check = is_sexp_true(node);
19624 
19625  if (!(Game_mode & GM_MULTIPLAYER)){
19626  sindex = ship_name_lookup(CTEXT(CDR(node)));
19627 
19628  // There can only be one player ship in singleplayer so if more than one ship is specifed the sexp is false
19629  if (CDDR(node) < 0 ) {
19630  return SEXP_FALSE;
19631  }
19632 
19633  if(sindex >= 0){
19634  if(Player_obj == &Objects[Ships[sindex].objnum]){
19635  if (standard_check) {
19636  if (Player_use_ai) {
19637  return SEXP_FALSE;
19638  }
19639  }
19640  return SEXP_TRUE;
19641  }
19642  }
19643  return SEXP_FALSE;
19644  }
19645 
19646  // For multiplayer we need to decide what to do about respawning players
19647  else {
19648  node = CDR(node);
19649  while (node >= 0) {
19650  // reset the netplayer index
19651  np_index = -1;
19652 
19653  sindex = ship_name_lookup(CTEXT(node));
19654  if(sindex >= 0){
19655  if(Ships[sindex].objnum >= 0) {
19656  // try and find the player
19657  np_index = multi_find_player_by_object(&Objects[Ships[sindex].objnum]);
19658  }
19659  }
19660 
19661  if (standard_check && np_index < 0) {
19662  // Respawning ships don't have an objnum so we need to take a different approach
19663  p_objp = mission_parse_get_arrival_ship(CTEXT(node));
19664  if (p_objp != NULL) {
19665  np_index = multi_find_player_by_parse_object(p_objp);
19666  }
19667  }
19668 
19669  // if we couldn't find a valid netplayer index then the ship isn't a player
19670  if((np_index < 0) || (np_index >= MAX_PLAYERS)){
19671  return SEXP_FALSE;
19672  }
19673 
19674  node = CDR(node);
19675  }
19676 
19677  // if we reached this far they all checked out
19678  return SEXP_TRUE;
19679  }
19680 }
19681 
19682 void sexp_set_respawns(int node)
19683 {
19684  int num_respawns;
19685  p_object *p_objp;
19686 
19687  // we're wasting our time if you can't respawn
19688  if (!(Game_mode & GM_MULTIPLAYER)) {
19689  return;
19690  }
19691 
19692  num_respawns = eval_num(node);
19693 
19694  node = CDR(node);
19695 
19696  // send the information to clients
19698  multi_send_int(num_respawns);
19699 
19700  while (node != -1) {
19701  // get the parse object for the ship
19702  p_objp = mission_parse_get_arrival_ship(CTEXT(node));
19703  if (p_objp != NULL) {
19704  p_objp->respawn_count = num_respawns;
19705  }
19706 
19707  multi_send_string(CTEXT(node));
19708 
19709  node = CDR(node);
19710  }
19711 
19713 }
19714 
19716 {
19717  p_object *p_objp;
19718  int num_respawns;
19719  char parse_name[NAME_LENGTH];
19720 
19721  multi_get_int(num_respawns);
19722  while (multi_get_string(parse_name)) {
19723  // get the parse object for the ship
19724  p_objp = mission_parse_get_arrival_ship(parse_name);
19725  if (p_objp != NULL) {
19726  p_objp->respawn_count = num_respawns;
19727  }
19728  }
19729 }
19730 
19731 // helper function for the remove-weapons SEXP
19732 void actually_remove_weapons(int weapon_info_index)
19733 {
19734  int i;
19735 
19736  for (i = 0; i<MAX_WEAPONS; i++) {
19737  // weapon doesn't match the optional weapon
19738  if ((weapon_info_index > -1) && (Weapons[i].weapon_info_index != weapon_info_index)) {
19739  continue;
19740  }
19741 
19742  if (Weapons[i].objnum >= 0) {
19744  }
19745  }
19746 }
19747 
19748 void sexp_remove_weapons(int node)
19749 {
19750  int weapon_info_index = -1;
19751 
19752  // if we have the optional argument, read it in
19753  if (node >= 0) {
19754  weapon_info_index = weapon_info_lookup(CTEXT(node));
19755  if (weapon_info_index == -1) {
19756  char *buf = CTEXT(node);
19757  mprintf(("Remove-weapons attempted to remove %s. Weapon not found. Remove-weapons will remove all weapons currently in the mission\n", buf));
19758  }
19759  }
19760 
19761  actually_remove_weapons(weapon_info_index);
19762 
19763  // send the information to clients
19765  multi_send_int(weapon_info_index);
19767 }
19768 
19770 {
19771  int weapon_info_index = -1;
19772 
19773  multi_get_int(weapon_info_index);
19774 
19775  actually_remove_weapons(weapon_info_index);
19776 }
19777 
19778 
19779 int sexp_return_player_data(int node, int type)
19780 {
19781  int sindex, np_index = -1;
19782  player *p = NULL;
19783  p_object *p_objp;
19784 
19785  sindex = ship_name_lookup(CTEXT(node));
19786 
19787  if(Game_mode & GM_MULTIPLAYER){
19788  if(sindex >= 0){
19789  if(Ships[sindex].objnum >= 0) {
19790  // try and find the player
19791  np_index = multi_find_player_by_object(&Objects[Ships[sindex].objnum]);
19792  }
19793  }
19794 
19795  if (np_index < 0) {
19796  // Respawning ships don't have an objnum so we need to take a different approach
19797  p_objp = mission_parse_get_arrival_ship(CTEXT(node));
19798  np_index = multi_find_player_by_parse_object(p_objp);
19799  }
19800 
19801  if((np_index >= 0) && (np_index < MAX_PLAYERS)){
19802  p = Net_players[np_index].m_player;
19803  }
19804  }
19805  // if we're in single player, we're only concerned with ourself
19806  else {
19807  if(sindex < 0){
19808  return 0;
19809  }
19810  if(Ships[sindex].objnum < 0){
19811  return 0;
19812  }
19813 
19814  if(Player_obj == &Objects[Ships[sindex].objnum]){
19815  p = Player;
19816  }
19817  }
19818 
19819  // now, if we have a valid player, return his kills
19820  if(p != NULL) {
19821  switch (type) {
19822  case OP_NUM_KILLS:
19823  return p->stats.m_kill_count_ok;
19824 
19825  case OP_NUM_ASSISTS:
19826  return p->stats.m_assists;
19827 
19828  case OP_SHIP_SCORE:
19829  return p->stats.m_score;
19830 
19831  case OP_SHIP_DEATHS:
19832  return p->stats.m_player_deaths;
19833 
19834  case OP_RESPAWNS_LEFT:
19835  // Dogfight missions have no respawn limit
19836  if (MULTI_NOT_DOGFIGHT) {
19837  if ( Net_players[np_index].flags & NETINFO_FLAG_RESPAWNING) {
19838  // since the player hasn't actually respawned yet he hasn't used up a number or spawns equal to his deaths
19839  // so add an extra life back.
19840  return Netgame.respawn - p->stats.m_player_deaths + 1;
19841  }
19842  else {
19843  return Netgame.respawn - p->stats.m_player_deaths;
19844  }
19845  }
19846  break;
19847 
19848  default:
19849  Int3();
19850  }
19851  }
19852  // AI ships also have a respawn count so we can return valid data for that at least
19853  else if ( (Game_mode & GM_MULTIPLAYER) && (type == OP_SHIP_DEATHS || type == OP_RESPAWNS_LEFT ) ) {
19854  p_objp = mission_parse_get_arrival_ship(CTEXT(node));
19855  if (p_objp == NULL) {
19856  return 0;
19857  }
19858 
19859  if (p_objp->flags & P_OF_PLAYER_START) {
19860  switch (type) {
19861  case OP_SHIP_DEATHS:
19862  // when an AI ship is finally killed its respawn count won't be updated so get the number of deaths
19863  // from the log instead
19865 
19866  case OP_RESPAWNS_LEFT:
19867  return Netgame.respawn - p_objp->respawn_count;
19868 
19869  default:
19870  Int3();
19871  }
19872  }
19873  }
19874 
19875  // AI ships
19876  return 0;
19877 }
19878 
19879 int sexp_num_type_kills(int node)
19880 {
19881  int sindex, st_index;
19882  int idx, total;
19883  player *p = NULL;
19884 
19885  // get the ship we're interested in
19886  sindex = ship_name_lookup(CTEXT(node));
19887  if(sindex < 0){
19888  return 0;
19889  }
19890  if(Ships[sindex].objnum < 0){
19891  return 0;
19892  }
19893 
19894  int np_index;
19895 
19896  // in multiplayer, search through all players
19897  if(Game_mode & GM_MULTIPLAYER){
19898  // try and find the player
19899  np_index = multi_find_player_by_object(&Objects[Ships[sindex].objnum]);
19900  if((np_index >= 0) && (np_index < MAX_PLAYERS)){
19901  p = Net_players[np_index].m_player;
19902  }
19903  }
19904  // if we're in single player, we're only concerned with ourself
19905  else {
19906  // me
19907  if(Player_obj == &Objects[Ships[sindex].objnum]){
19908  p = Player;
19909  }
19910  }
19911 
19912  // bad
19913  if(p == NULL){
19914  return 0;
19915  }
19916 
19917  // lookup ship type name
19918  st_index = ship_type_name_lookup(CTEXT(CDR(node)));
19919  if(st_index < 0){
19920  return 0;
19921  }
19922 
19923  // look stuff up
19924  total = 0;
19925  for(idx = 0; idx < static_cast<int>(Ship_info.size()); idx++) {
19926  if((p->stats.m_okKills[idx] > 0) && ship_class_query_general_type(idx)==st_index){
19927  total += p->stats.m_okKills[idx];
19928  }
19929  }
19930 
19931  // total
19932  return total;
19933 }
19934 
19936 {
19937  int sindex, si_index;
19938  player *p = NULL;
19939 
19940  // get the ship we're interested in
19941  sindex = ship_name_lookup(CTEXT(node));
19942  if(sindex < 0){
19943  return 0;
19944  }
19945  if(Ships[sindex].objnum < 0){
19946  return 0;
19947  }
19948 
19949  int np_index;
19950 
19951  // in multiplayer, search through all players
19952  if(Game_mode & GM_MULTIPLAYER){
19953  // try and find the player
19954  np_index = multi_find_player_by_object(&Objects[Ships[sindex].objnum]);
19955  if((np_index >= 0) && (np_index < MAX_PLAYERS)){
19956  p = Net_players[np_index].m_player;
19957  }
19958  }
19959  // if we're in single player, we're only concerned with ourself
19960  else {
19961  // me
19962  if(Player_obj == &Objects[Ships[sindex].objnum]){
19963  p = Player;
19964  }
19965  }
19966 
19967  // bad
19968  if(p == NULL){
19969  return 0;
19970  }
19971 
19972  // get the ship type we're looking for
19973  si_index = ship_info_lookup(CTEXT(CDR(node)));
19974  if((si_index < 0) || (si_index >= static_cast<int>(Ship_info.size()))){
19975  return 0;
19976  }
19977 
19978  // return the count
19979  return p->stats.m_okKills[si_index];
19980 }
19981 
19983 {
19984  int sindex, low, high, n, idx, rand, exclusion_list[MAX_MODEL_SUBSYSTEMS];
19985  ship_subsys *subsys;
19986  ship *shipp;
19987 
19988  // get ship
19989  sindex = ship_name_lookup(CTEXT(node));
19990  if(sindex < 0){
19991  return;
19992  }
19993  if(Ships[sindex].objnum < 0){
19994  return;
19995  }
19996  shipp = &Ships[sindex];
19997 
19998  // get low
19999  low = eval_num(CDR(node));
20000  if (low < 0) {
20001  low = 0;
20002  }
20003 
20004  // get high
20005  high = eval_num(CDR(CDR(node)));
20006  if (high > 100) {
20007  high = 100;
20008  }
20009 
20010  if (low > high) {
20011  Int3();
20012  return;
20013  }
20014 
20015  n = CDR(CDR(CDR(node)));
20016 
20017  // init exclusion list
20018  memset(exclusion_list, 0, sizeof(int) * Ship_info[shipp->ship_info_index].n_subsystems);
20019 
20020  // get exclusion list
20021  while( n != -1) {
20022  int exclude_index = ship_get_subsys_index(shipp, CTEXT(n), 0);
20023  if (exclude_index >= 0) {
20024  exclusion_list[exclude_index] = 1;
20025  }
20026 
20027  n = CDR(n);
20028  }
20029 
20030  // apply to all others
20031  for (idx=0; idx<Ship_info[shipp->ship_info_index].n_subsystems; idx++) {
20032  if ( exclusion_list[idx] == 0 ) {
20033  // get non excluded subsystem
20034  subsys = ship_get_indexed_subsys(shipp, idx, NULL);
20035  if (subsys == NULL) {
20036  nprintf(("Warning", "Nonexistent subsystem for index %d on ship %s for sabotage subsystem\n", idx, shipp->ship_name));
20037  continue;
20038  }
20039 
20040  // randomize its hit points
20041  rand = rand_internal(low, high);
20042  subsys->current_hits = 0.01f * rand * subsys->max_hits;
20043  }
20044  }
20045 }
20046 
20047 void sexp_supernova_start(int node)
20048 {
20049  supernova_start(eval_num(node));
20050 }
20051 
20052 void sexp_supernova_stop(int node)
20053 {
20054  supernova_stop();
20055 }
20056 
20058 {
20059  int sindex;
20060  int bank;
20061  ship *shipp;
20062 
20063  // lookup ship
20064  sindex = ship_name_lookup(CTEXT(node));
20065  if(sindex < 0){
20066  return SEXP_FALSE;
20067  }
20068  if(Ships[sindex].objnum < 0){
20069  return SEXP_FALSE;
20070  }
20071  shipp = &Ships[sindex];
20072 
20073  // bogus value?
20074  bank = eval_num(CDR(node));
20075  if(bank >= shipp->weapons.num_secondary_banks){
20076  return SEXP_FALSE;
20077  }
20078 
20079  // is this the bank currently selected
20080  if( bank == shipp->weapons.current_secondary_bank ){
20081  return SEXP_TRUE;
20082  }
20083 
20084  // nope
20085  return SEXP_FALSE;
20086 }
20087 
20089 {
20090  int sindex;
20091  int bank;
20092  ship *shipp;
20093 
20094  // lookup ship
20095  sindex = ship_name_lookup(CTEXT(node));
20096  if(sindex < 0){
20097  return SEXP_FALSE;
20098  }
20099  if(Ships[sindex].objnum < 0){
20100  return SEXP_FALSE;
20101  }
20102  shipp = &Ships[sindex];
20103 
20104  // bogus value?
20105  bank = eval_num(CDR(node));
20106  if(bank >= shipp->weapons.num_primary_banks){
20107  return SEXP_FALSE;
20108  }
20109 
20110  // is this the bank currently selected
20111  if( (bank == shipp->weapons.current_primary_bank) || (shipp->flags & SF_PRIMARY_LINKED) ){
20112  return SEXP_TRUE;
20113  }
20114 
20115  // nope
20116  return SEXP_FALSE;
20117 }
20118 
20119 // Return SEXP_TRUE if quadrant quadnum is near max.
20120 int shield_quad_near_max(int quadnum)
20121 {
20122  if (quadnum >= Player_obj->n_quadrants)
20123  return SEXP_FALSE;
20124 
20125  float remaining = 0.0f;
20126  for (int i=0; i<Player_obj->n_quadrants; i++) {
20127  if (i == quadnum){
20128  continue;
20129  }
20130  remaining += Player_obj->shield_quadrant[i];
20131  }
20132 
20133  if ((remaining < 2.0f) || (Player_obj->shield_quadrant[quadnum] > get_max_shield_quad(Player_obj) - 5.0f)) {
20134  return SEXP_TRUE;
20135  } else {
20136  return SEXP_FALSE;
20137  }
20138 }
20139 
20140 // Return truth value for special SEXP.
20141 // Used in training#5, perhaps in other missions.
20143 {
20144  switch (index) {
20145  case 0: // Ship "Freighter 1" is aspect locked by player.
20146  if (Player_ai->target_objnum != -1) {
20147  if (!(stricmp(Ships[Objects[Player_ai->target_objnum].instance].ship_name, "Freighter 1"))) {
20149  return SEXP_TRUE;
20150  }
20151  }
20152  return SEXP_FALSE;
20153 
20154  case 1: // Fired Interceptors
20155  object *objp;
20156  for (objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp)) {
20157  if (objp->type == OBJ_WEAPON) {
20158  if (!stricmp(Weapon_info[Weapons[objp->instance].weapon_info_index].name, "Interceptor#weak")) {
20159  int target = Weapons[objp->instance].target_num;
20160  if (target != -1) {
20161  if (Objects[target].type == OBJ_SHIP) {
20162  if (!(stricmp(Ships[Objects[target].instance].ship_name, "Freighter 1")))
20163  return SEXP_TRUE;
20164  }
20165  }
20166  }
20167  }
20168  }
20169  return SEXP_FALSE;
20170 
20171  case 2: // Ship "Freighter 1", subsystem "Weapons" is aspect locked by player.
20172  if (Player_ai->target_objnum != -1) {
20173  if (!(stricmp(Ships[Objects[Player_ai->target_objnum].instance].ship_name, "Freighter 1"))) {
20176  return SEXP_TRUE;
20177  }
20178  }
20179  }
20180  }
20181  return SEXP_FALSE;
20182 
20183  case 3: // Player ship suffering shield damage on front.
20187  return SEXP_TRUE;
20188  } else {
20189  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20190  return SEXP_FALSE;
20191  }
20192  break;
20193 
20194  case 4: // Player ship suffering much damage.
20195  if (!(Ship_info[Player_ship->ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS)) {
20196  nprintf(("AI", "Frame %i\n", Framecount));
20199  if (Player_obj->shield_quadrant[FRONT_QUAD] < 2.0f)
20200  return SEXP_TRUE;
20201  else
20202  return SEXP_FALSE;
20203  } else {
20204  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20205  return SEXP_FALSE;
20206  }
20207  break;
20208 
20209  case 5: // Player's shield is quick repaired
20210  if (!(Ship_info[Player_ship->ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS)) {
20211  nprintf(("AI", "Frame %i, recharged to %7.3f\n", Framecount, Player_obj->shield_quadrant[FRONT_QUAD]));
20212 
20214 
20217 
20219  return SEXP_TRUE;
20220  else
20221  return SEXP_FALSE;
20222  } else {
20223  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20224  return SEXP_FALSE;
20225  }
20226  break;
20227 
20228  case 6: // 3 of player's shield quadrants are reduced to 0.
20229  if (!(Ship_info[Player_ship->ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS)) {
20230  Player_obj->shield_quadrant[1] = 1.0f;
20231  Player_obj->shield_quadrant[2] = 1.0f;
20232  Player_obj->shield_quadrant[3] = 1.0f;
20234  } else {
20235  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20236  return SEXP_FALSE;
20237  }
20238  return SEXP_TRUE;
20239 
20240  case 7: // Make sure front quadrant has been maximized, or close to it.
20241  if (!(Ship_info[Player_ship->ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS)) {
20242  if (shield_quad_near_max(FRONT_QUAD)) return SEXP_TRUE; else return SEXP_FALSE;
20243  } else {
20244  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20245  return SEXP_FALSE;
20246  }
20247  break;
20248 
20249  case 8: // Make sure rear quadrant has been maximized, or close to it.
20250  if (!(Ship_info[Player_ship->ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS)) {
20251  if (shield_quad_near_max(REAR_QUAD)) return SEXP_TRUE; else return SEXP_FALSE;
20252  } else {
20253  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20254  return SEXP_FALSE;
20255  }
20256  break;
20257 
20258  case 9: // Zero left and right quadrants in preparation for maximizing rear quadrant.
20259  if (!(Ship_info[Player_ship->ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS)) {
20263  return SEXP_TRUE;
20264  } else {
20265  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20266  return SEXP_FALSE;
20267  }
20268  break;
20269 
20270  case 10: // Return true if player is low on Interceptors.
20272  return SEXP_TRUE;
20273  else
20274  return SEXP_FALSE;
20275  break;
20276 
20277  case 11: // Return true if player has plenty of Interceptors.
20279  return SEXP_TRUE;
20280  else
20281  return SEXP_FALSE;
20282  break;
20283 
20284  case 12: // Return true if player is low on Interceptors.
20286  return SEXP_TRUE;
20287  else
20288  return SEXP_FALSE;
20289  break;
20290 
20291  case 13: // Zero front shield quadrant. Added for Jim Boone on August 26, 1999 by MK.
20292  if (!(Ship_info[Player_ship->ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS)) {
20295  return SEXP_TRUE;
20296  } else {
20297  nprintf(("Warning", "Shield-related Special-check SEXPs do not work on ship %s because it uses model point shields.\n", Player_ship->ship_name));
20298  return SEXP_FALSE;
20299  }
20300  break;
20301 
20302  case 100: // Return true if player is out of countermeasures.
20303  if (Player_ship->cmeasure_count <= 0)
20304  return SEXP_TRUE;
20305  else
20306  return SEXP_FALSE;
20307 
20308  default:
20309  Int3(); // Unsupported node type.
20310  }
20311 
20312  return SEXP_FALSE;
20313 }
20314 
20315 // Karajorma / Goober5000
20317 {
20318  bool first_ch = true;
20319  char *ch, *buf_ch, buf[TOKEN_LENGTH];
20320  Assert (n != -1);
20321 
20322  // copy all numeric characters to buf
20323  // also, copy a sign symbol if we haven't copied numbers yet
20324  buf_ch = buf;
20325  for (ch = CTEXT(n); *ch != 0; ch++)
20326  {
20327  if ((first_ch && (*ch == '-' || *ch == '+')) || strchr("0123456789", *ch))
20328  {
20329  *buf_ch = *ch;
20330  buf_ch++;
20331 
20332  first_ch = false;
20333  }
20334 
20335  // don't save the fractional parts of decimal numbers
20336  if (*ch == '.')
20337  break;
20338  }
20339 
20340  // terminate string
20341  *buf_ch = '\0';
20342 
20343  return atoi(buf);
20344 }
20345 
20346 // Goober5000
20348 {
20349  int i, sexp_variable_index;
20350  char new_text[TOKEN_LENGTH];
20351 
20352  // Only do single player or multi host
20353  if ( MULTIPLAYER_CLIENT )
20354  return;
20355 
20356  i = eval_num(n);
20357  n = CDR(n);
20358 
20359  // get sexp_variable index
20360  Assert(Sexp_nodes[n].first == -1);
20361  sexp_variable_index = atoi(Sexp_nodes[n].text);
20362 
20363  // verify variable set
20364  Assert(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET);
20365 
20366  // check variable type
20367  if (!(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_STRING))
20368  {
20369  Warning(LOCATION, "Cannot assign a string to a non-string variable!");
20370  return;
20371  }
20372 
20373  // write string
20374  sprintf(new_text, "%d", i);
20375 
20376  // assign to variable
20377  sexp_modify_variable(new_text, sexp_variable_index);
20378 }
20379 
20380 // Goober5000
20382 {
20383  int sexp_variable_index;
20384  char new_text[TOKEN_LENGTH * 2];
20385 
20386  // Only do single player or multi host
20387  if ( MULTIPLAYER_CLIENT )
20388  return;
20389 
20390  char *str1 = CTEXT(n);
20391  n = CDR(n);
20392  char *str2 = CTEXT(n);
20393  n = CDR(n);
20394 
20395  // get sexp_variable index
20396  Assert(Sexp_nodes[n].first == -1);
20397  sexp_variable_index = atoi(Sexp_nodes[n].text);
20398 
20399  // verify variable set
20400  Assert(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET);
20401 
20402  // check variable type
20403  if (!(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_STRING))
20404  {
20405  Warning(LOCATION, "Cannot assign a string to a non-string variable!");
20406  return;
20407  }
20408 
20409  // concatenate strings
20410  strcpy_s(new_text, str1);
20411  strcat_s(new_text, str2);
20412 
20413  // check length
20414  if (strlen(new_text) >= TOKEN_LENGTH)
20415  {
20416  Warning(LOCATION, "Concatenated string is too long and will be truncated.");
20417  new_text[TOKEN_LENGTH] = 0;
20418  }
20419 
20420  // assign to variable
20421  sexp_modify_variable(new_text, sexp_variable_index);
20422 }
20423 
20424 // Goober5000
20426 {
20427  return strlen(CTEXT(node));
20428 }
20429 
20430 // Goober5000
20432 {
20433  int n = node;
20434  int sexp_variable_index;
20435  char new_text[TOKEN_LENGTH];
20436 
20437  // Only do single player or multi host
20438  if ( MULTIPLAYER_CLIENT )
20439  return;
20440 
20441  char *parent = CTEXT(n);
20442  n = CDR(n);
20443  int pos = eval_num(n);
20444  n = CDR(n);
20445  int len = eval_num(n);
20446  n = CDR(n);
20447 
20448  // get sexp_variable index
20449  Assert(Sexp_nodes[n].first == -1);
20450  sexp_variable_index = atoi(Sexp_nodes[n].text);
20451 
20452  // verify variable set
20453  Assert(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET);
20454 
20455  // check variable type
20456  if (!(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_STRING))
20457  {
20458  Warning(LOCATION, "Cannot assign a string to a non-string variable!");
20459  return;
20460  }
20461 
20462  int parent_len = strlen(parent);
20463 
20464  // sanity
20465  if (pos >= parent_len)
20466  {
20467  Warning(LOCATION, "( string-get-substring %s %d %d ) failed: starting position is larger than the string length!", parent, pos, len);
20468  return;
20469  }
20470 
20471  // sanity
20472  if (pos + len > parent_len)
20473  len = parent_len - pos;
20474 
20475  // copy substring
20476  memset(new_text, 0, TOKEN_LENGTH);
20477  strncpy(new_text, &parent[pos], len);
20478 
20479  // assign to variable
20480  sexp_modify_variable(new_text, sexp_variable_index);
20481 }
20482 
20483 // Goober5000
20485 {
20486  int n = node;
20487  int sexp_variable_index;
20488  char new_text[TOKEN_LENGTH * 2];
20489 
20490  // Only do single player or multi host
20491  if ( MULTIPLAYER_CLIENT )
20492  return;
20493 
20494  char *parent = CTEXT(n);
20495  n = CDR(n);
20496  int pos = eval_num(n);
20497  n = CDR(n);
20498  int len = eval_num(n);
20499  n = CDR(n);
20500  char *new_substring = CTEXT(n);
20501  n = CDR(n);
20502 
20503  // get sexp_variable index
20504  Assert(Sexp_nodes[n].first == -1);
20505  sexp_variable_index = atoi(Sexp_nodes[n].text);
20506 
20507  // verify variable set
20508  Assert(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET);
20509 
20510  // check variable type
20511  if (!(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_STRING))
20512  {
20513  Warning(LOCATION, "Cannot assign a string to a non-string variable!");
20514  return;
20515  }
20516 
20517  int parent_len = strlen(parent);
20518  int new_len = strlen(new_substring);
20519 
20520  // sanity
20521  if (pos >= parent_len)
20522  {
20523  Warning(LOCATION, "( string-set-substring %s %d %d %s ) failed: starting position is larger than the string length!", parent, pos, len, new_substring);
20524  return;
20525  }
20526 
20527  // make the common case fast
20528  if (len == 1 && new_len == 1)
20529  {
20530  strcpy_s(new_text, parent);
20531  new_text[pos] = new_substring[0];
20532  }
20533  else
20534  {
20535  // sanity
20536  if (pos + len > parent_len)
20537  len = parent_len - pos;
20538 
20539  // copy parent string up to the substring pos
20540  strncpy(new_text, parent, pos);
20541 
20542  // add new substring
20543  strcpy(&new_text[pos], new_substring);
20544 
20545  // add rest of parent string
20546  strcat_s(new_text, &parent[pos + len]);
20547 
20548  // check length
20549  if (strlen(new_text) >= TOKEN_LENGTH)
20550  {
20551  Warning(LOCATION, "Concatenated string is too long and will be truncated.");
20552  new_text[TOKEN_LENGTH] = 0;
20553  }
20554  }
20555 
20556  // assign to variable
20557  sexp_modify_variable(new_text, sexp_variable_index);
20558 }
20559 
20560 // breaks into the code or sends a warning
20561 void sexp_debug(int node)
20562 {
20563  int i;
20564  char *id;
20565  char temp_buf[MESSAGE_LENGTH] = {""};
20566 
20567  #ifdef NDEBUG
20568  int no_release_message;
20569  no_release_message = is_sexp_true(node);
20570  #endif
20571 
20572  node = CDR(node);
20573  Assertion (node >= 0, "No message defined in debug SEXP");
20574  id = CTEXT(node);
20575 
20576  for (i=0; i<Num_messages; i++) {
20577  // find the message
20578  if ( !stricmp(id, Messages[i].name) ) {
20579  //replace variables if necessary
20580  strcpy_s(temp_buf, Messages[i].message);
20582  break;
20583  }
20584  }
20585 
20586  //send the message
20587  #ifndef NDEBUG
20588  Warning(LOCATION, "%s", temp_buf);
20589  #else
20590  if (!no_release_message) {
20591  ReleaseWarning(LOCATION, "%s", temp_buf);
20592  }
20593  #endif
20594 }
20595 
20596 // custom sexp operator for handling misc training stuff
20598 {
20599  int num, rtn;
20600 
20601  num = eval_num(node);
20602  if (num == SPECIAL_CHECK_TRAINING_FAILURE)
20604 
20605  // To MK: do whatever you want with this number here.
20606  rtn = process_special_sexps(eval_num(node));
20607 
20608  return rtn;
20609 }
20610 
20611 // sexpression to flash a hud gauge. gauge name is text valud of node
20612 void sexp_flash_hud_gauge( int node )
20613 {
20614  char *name;
20615  int i;
20616 
20617  name = CTEXT(node);
20618  for (i = 0; i < NUM_HUD_GAUGES; i++ ) {
20619  if ( !stricmp(HUD_gauge_text[i], name) ) {
20620  hud_gauge_start_flash(i); // call HUD function to flash gauge
20621 
20623  multi_send_int(i);
20625 
20626  break;
20627  }
20628  }
20629 }
20630 
20632 {
20633  int i;
20634 
20635  if (multi_get_int(i)) {
20637  }
20638 }
20639 
20641 {
20643  if (wp_list == NULL)
20644  return;
20645 
20646  Training_context |= TRAINING_CONTEXT_FLY_PATH;
20647  Training_context_path = wp_list;
20648  Training_context_distance = (float) atof(CTEXT(CDR(node)));
20649  Training_context_goal_waypoint = 0;
20650  Training_context_at_waypoint = -1;
20651 }
20652 
20654 {
20655  Training_context |= TRAINING_CONTEXT_SPEED;
20656  Training_context_speed_min = eval_num(node);
20657  Training_context_speed_max = eval_num(CDR(node));
20658  Training_context_speed_set = 0;
20659 }
20660 
20661 void sexp_scramble_messages(int node, bool scramble)
20662 {
20663  if (node < 0)
20664  {
20665  // scramble messages on player ship... this isn't multi compatible, but neither was the old version of the sexp
20666  if (scramble)
20668  else
20670  return;
20671  }
20672 
20673  sexp_deal_with_ship_flag(node, true, 0, 0, 0, SF2_SCRAMBLE_MESSAGES, 0, P2_SF2_SCRAMBLE_MESSAGES, scramble, false, true);
20674 }
20675 
20676 void toggle_cutscene_bars(float delta_speed, int set)
20677 {
20678  //Do we want the bars?
20679  if (set) {
20681  }
20682  else {
20684  }
20685 
20686  if(delta_speed > 0.0f) {
20687  Cutscene_bars_progress = 0.0f;
20689  Cutscene_delta_time = delta_speed;
20690  }
20691  else {
20693  }
20694 }
20695 
20696 void sexp_toggle_cutscene_bars(int node, int set)
20697 {
20698  float delta_speed = 0.0f;
20699 
20700  if(node != -1)
20701  delta_speed = eval_num(node)/1000.0f;
20702 
20703  toggle_cutscene_bars(delta_speed, set);
20704 
20706  multi_send_float(delta_speed);
20708 }
20709 
20711 {
20712  float delta_speed;
20713 
20714  if(multi_get_float(delta_speed) ) {
20715  toggle_cutscene_bars(delta_speed, set);
20716  }
20717 }
20718 
20719 void sexp_fade(bool fade_in, int duration, ubyte R, ubyte G, ubyte B)
20720 {
20721  if (duration > 0)
20722  {
20724  Fade_end_timestamp = timestamp(duration);
20725  Fade_type = fade_in ? FI_FADEIN : FI_FADEOUT;
20727  }
20728  else
20729  {
20730  Fade_type = FI_NONE;
20731  gr_create_shader(&Viewer_shader, R, G, B, fade_in ? 0 : 255);
20732  }
20733 }
20734 
20735 static int Fade_out_r = -1;
20736 static int Fade_out_g = -1;
20737 static int Fade_out_b = -1;
20738 
20739 void sexp_fade(int n, bool fade_in)
20740 {
20741  int duration = 0;
20742  int R = -1;
20743  int G = -1;
20744  int B = -1;
20745 
20746  if (n != -1)
20747  {
20748  duration = eval_num(n);
20749  n = CDR(n);
20750 
20751  if (n != -1)
20752  {
20753  R = eval_num(n);
20754  if (R < 0 || R > 255) R = -1;
20755  n = CDR(n);
20756 
20757  if (n != -1)
20758  {
20759  G = eval_num(n);
20760  if (G < 0 || G > 255) G = -1;
20761  n = CDR(n);
20762 
20763  if (n != -1)
20764  {
20765  B = eval_num(n);
20766  if (B < 0 || B > 255) B = -1;
20767  n = CDR(n);
20768  }
20769  }
20770  }
20771  }
20772 
20773  // select legacy (or default) fade color
20774  if (R < 0 || G < 0 || B < 0)
20775  {
20776  // fade white
20777  if (R == 1)
20778  {
20779  R = G = B = 255;
20780  }
20781  // fade red
20782  else if (R == 2)
20783  {
20784  R = 255;
20785  G = B = 0;
20786  }
20787  // default: fade black
20788  else
20789  {
20790  // Mantis #2944: if we're fading in, and we previously faded out to some specific color, use that same color to fade in
20791  if (fade_in && (Fade_out_r >= 0) && (Fade_out_g >= 0) && (Fade_out_b >= 0))
20792  {
20793  R = Fade_out_r;
20794  G = Fade_out_g;
20795  B = Fade_out_b;
20796  }
20797  else
20798  {
20799  R = G = B = 0;
20800  }
20801  }
20802  }
20803 
20804  // Mantis #2944, if we're fading out to some specific color, save that color
20805  if (!fade_in && ((R > 0) || (G > 0) || (B > 0)))
20806  {
20807  Fade_out_r = R;
20808  Fade_out_g = G;
20809  Fade_out_b = B;
20810  }
20811 
20812  sexp_fade(fade_in, duration, (ubyte) R, (ubyte) G, (ubyte) B);
20813 
20815  multi_send_int(duration);
20816  multi_send_int(R);
20817  multi_send_int(G);
20818  multi_send_int(B);
20820 }
20821 
20822 void multi_sexp_fade(bool fade_in)
20823 {
20824  int duration = 0;
20825  int R = 0;
20826  int G = 0;
20827  int B = 0;
20828 
20829  if (multi_get_int(duration))
20830  if (multi_get_int(R))
20831  if (multi_get_int(G))
20832  multi_get_int(B);
20833 
20834  sexp_fade(fade_in, duration, (ubyte) R, (ubyte) G, (ubyte) B);
20835 }
20836 
20838 {
20839  static camid sexp_camera;
20840  if(!reset)
20841  {
20843  {
20844  camera *cam = cam_get_current().getCamera();
20845  if(cam != NULL)
20846  return cam;
20847  }
20848  }
20849  if(!sexp_camera.isValid())
20850  {
20851  sexp_camera = cam_create("SEXP camera");
20852  }
20853 
20854  cam_set_camera(sexp_camera);
20855 
20856  return sexp_camera.getCamera();
20857 }
20858 
20859 void sexp_set_camera(int node)
20860 {
20861  if(node == -1)
20862  {
20863  sexp_get_set_camera(true);
20864  return;
20865  }
20866 
20867  char *cam_name = CTEXT(node);
20868  camid cid = cam_lookup(cam_name);
20869  if(!cid.isValid())
20870  {
20871  cid = cam_create(cam_name);
20872  }
20873  cam_set_camera(cid);
20874 }
20875 
20877 {
20878  camera *cam = sexp_get_set_camera();
20879 
20880  if(cam == NULL)
20881  return;
20882 
20883  vec3d camera_vec;
20884  float camera_time = 0.0f;
20885  float camera_acc_time = 0.0f;
20886  float camera_dec_time = 0.0f;
20887 
20888  camera_vec.xyz.x = i2fl(eval_num(n));
20889  n = CDR(n);
20890  camera_vec.xyz.y = i2fl(eval_num(n));
20891  n = CDR(n);
20892  camera_vec.xyz.z = i2fl(eval_num(n));
20893  n = CDR(n);
20894 
20895  if(n != -1)
20896  {
20897  camera_time = eval_num(n) / 1000.0f;
20898  n = CDR(n);
20899  if(n != -1)
20900  {
20901  camera_dec_time = camera_acc_time = eval_num(n) / 1000.0f;
20902  n = CDR(n);
20903  if(n != -1)
20904  {
20905  camera_dec_time = eval_num(n) / 1000.0f;
20906  }
20907  }
20908  }
20909 
20910  cam->set_position(&camera_vec, camera_time, camera_acc_time, camera_dec_time);
20911 
20912  //multiplayer callback
20914  multi_send_float(camera_vec.xyz.x);
20915  multi_send_float(camera_vec.xyz.y);
20916  multi_send_float(camera_vec.xyz.z);
20917  multi_send_float(camera_time);
20918  multi_send_float(camera_acc_time);
20919  multi_send_float(camera_dec_time);
20921 }
20922 
20923 //CommanderDJ
20925 {
20926  camera *cam = sexp_get_set_camera();
20927 
20928  if(cam == NULL) {
20929  Int3();
20930  return;
20931  }
20932 
20933  vec3d camera_vec;
20934  float camera_time = 0.0f;
20935  float camera_acc_time = 0.0f;
20936  float camera_dec_time = 0.0f;
20937 
20938  multi_get_float(camera_vec.xyz.x);
20939  multi_get_float(camera_vec.xyz.y);
20940  multi_get_float(camera_vec.xyz.z);
20941  multi_get_float(camera_time);
20942  multi_get_float(camera_acc_time);
20943  multi_get_float(camera_dec_time);
20944 
20945  cam->set_position(&camera_vec, camera_time, camera_acc_time, camera_dec_time);
20946 }
20947 
20949 {
20950  camera *cam = sexp_get_set_camera();
20951  if(cam == NULL)
20952  return;
20953 
20954  angles rot_angles;
20955  float rot_time = 0.0f;
20956  float rot_acc_time = 0.0f;
20957  float rot_dec_time = 0.0f;
20958 
20959  //Angles are in degrees
20960  rot_angles.p = fl_radians(eval_num(n) % 360);
20961  n = CDR(n);
20962  rot_angles.b = fl_radians(eval_num(n) % 360);
20963  n = CDR(n);
20964  rot_angles.h = fl_radians(eval_num(n) % 360);
20965  n = CDR(n);
20966  if(n != -1)
20967  {
20968  rot_time = eval_num(n) / 1000.0f;
20969  n = CDR(n);
20970  if(n != -1)
20971  {
20972  rot_dec_time = rot_acc_time = eval_num(n) / 1000.0f;
20973  n = CDR(n);
20974  if(n != -1)
20975  {
20976  rot_dec_time = eval_num(n) / 1000.0f;
20977  }
20978  }
20979  }
20980 
20981  cam->set_rotation(&rot_angles, rot_time, rot_acc_time, rot_dec_time);
20982 
20984  multi_send_float(rot_angles.b);
20985  multi_send_float(rot_angles.h);
20986  multi_send_float(rot_angles.p);
20987  multi_send_float(rot_time);
20988  multi_send_float(rot_acc_time);
20989  multi_send_float(rot_dec_time);
20991 }
20992 
20994 {
20995  camera *cam = sexp_get_set_camera();
20996  if(cam == NULL)
20997  return;
20998 
20999  angles rot_angles;
21000  float rot_time = 0.0f;
21001  float rot_acc_time = 0.0f;
21002  float rot_dec_time = 0.0f;
21003 
21004  multi_get_float(rot_angles.b);
21005  multi_get_float(rot_angles.h);
21006  multi_get_float(rot_angles.p);
21007  multi_get_float(rot_time);
21008  multi_get_float(rot_acc_time);
21009  multi_get_float(rot_dec_time);
21010 
21011  cam->set_rotation(&rot_angles, rot_time, rot_acc_time, rot_dec_time);
21012 }
21013 
21015 {
21016  camera *cam = sexp_get_set_camera();
21017  if(cam == NULL)
21018  return;
21019 
21020  vec3d location;
21021  float rot_time = 0.0f;
21022  float rot_acc_time = 0.0f;
21023  float rot_dec_time = 0.0f;
21024 
21025  location.xyz.x = i2fl(eval_num(n));
21026  n = CDR(n);
21027  location.xyz.y = i2fl(eval_num(n));
21028  n = CDR(n);
21029  location.xyz.z = i2fl(eval_num(n));
21030  n = CDR(n);
21031  if(n != -1)
21032  {
21033  rot_time = eval_num(n) / 1000.0f;
21034  n = CDR(n);
21035  if(n != -1)
21036  {
21037  rot_dec_time = rot_acc_time = eval_num(n) / 1000.0f;
21038  n = CDR(n);
21039  if(n != -1)
21040  {
21041  rot_dec_time = eval_num(n) / 1000.0f;
21042  }
21043  }
21044  }
21045 
21046  cam->set_rotation_facing(&location, rot_time, rot_acc_time, rot_dec_time);
21047 
21048  //multiplayer callback
21050  multi_send_float(location.xyz.x);
21051  multi_send_float(location.xyz.y);
21052  multi_send_float(location.xyz.z);
21053  multi_send_float(rot_time);
21054  multi_send_float(rot_acc_time);
21055  multi_send_float(rot_dec_time);
21057 }
21058 
21060 {
21061  camera *cam = sexp_get_set_camera();
21062  if(cam == NULL)
21063  return;
21064 
21065  vec3d location;
21066  float rot_time = 0.0f;
21067  float rot_acc_time = 0.0f;
21068  float rot_dec_time = 0.0f;
21069 
21070  multi_get_float(location.xyz.x);
21071  multi_get_float(location.xyz.y);
21072  multi_get_float(location.xyz.z);
21073  multi_get_float(rot_time);
21074  multi_get_float(rot_acc_time);
21075  multi_get_float(rot_dec_time);
21076 
21077  cam->set_rotation_facing(&location, rot_time, rot_acc_time, rot_dec_time);
21078 }
21079 
21080 //CommanderDJ
21084 void actually_set_camera_facing_object(char *object_name, float rot_time, float rot_acc_time, float rot_dec_time)
21085 {
21087  sexp_get_object_ship_wing_point_team(&oswpt, object_name);
21088 
21089  switch (oswpt.type)
21090  {
21091  case OSWPT_TYPE_EXITED:
21092  {
21093  Warning(LOCATION, "Camera tried to face destroyed/departed object %s", object_name);
21094  return;
21095  }
21096 
21097  case OSWPT_TYPE_SHIP:
21098  case OSWPT_TYPE_WING:
21099  case OSWPT_TYPE_WAYPOINT:
21100  {
21101  camera *cam = sexp_get_set_camera();
21102  if(cam == NULL)
21103  return;
21104  cam->set_rotation_facing(&oswpt.objp->pos, rot_time, rot_acc_time, rot_dec_time);
21105  return;
21106  }
21107  }
21108 }
21109 
21111 {
21112  char *object_name = CTEXT(n);
21113  float rot_time = 0.0f;
21114  float rot_acc_time = 0.0f;
21115  float rot_dec_time = 0.0f;
21116 
21117  //Now get the rotation time values
21118  n = CDR(n);
21119  if(n != -1)
21120  {
21121  rot_time = eval_num(n) / 1000.0f;
21122  n = CDR(n);
21123  if(n != -1)
21124  {
21125  rot_dec_time = rot_acc_time = eval_num(n) / 1000.0f;
21126  n = CDR(n);
21127  if(n != -1)
21128  {
21129  rot_dec_time = eval_num(n) / 1000.0f;
21130  }
21131  }
21132  }
21133  actually_set_camera_facing_object(object_name, rot_time, rot_acc_time, rot_dec_time);
21134 
21135  //multiplayer callback
21137  multi_send_string(object_name);
21138  multi_send_float(rot_time);
21139  multi_send_float(rot_acc_time);
21140  multi_send_float(rot_dec_time);
21142 }
21143 
21144 //CommanderDJ
21146 {
21147  char object_name[TOKEN_LENGTH];
21148  float rot_time = 0.0f;
21149  float rot_acc_time = 0.0f;
21150  float rot_dec_time = 0.0f;
21151 
21152  multi_get_string(object_name);
21153  multi_get_float(rot_time);
21154  multi_get_float(rot_acc_time);
21155  multi_get_float(rot_dec_time);
21156 
21157  actually_set_camera_facing_object(object_name, rot_time, rot_acc_time, rot_dec_time);
21158 }
21159 
21160 extern float VIEWER_ZOOM_DEFAULT;
21162 {
21163  camera *cam = sexp_get_set_camera();
21164 
21165  if(cam == NULL)
21166  return;
21167 
21168  float camera_time = 0.0f;
21169  float camera_acc_time = 0.0f;
21170  float camera_dec_time = 0.0f;
21171 
21172  float camera_fov = fl_radians(eval_num(n) % 360);
21173  n = CDR(n);
21174 
21175  if(n != -1)
21176  {
21177  camera_time = eval_num(n) / 1000.0f;
21178  n = CDR(n);
21179  if(n != -1)
21180  {
21181  camera_dec_time = camera_acc_time = eval_num(n) / 1000.0f;
21182  n = CDR(n);
21183  if(n != -1)
21184  {
21185  camera_dec_time = eval_num(n) / 1000.0f;
21186  }
21187  }
21188  }
21189 
21190  cam->set_fov(camera_fov, camera_time, camera_acc_time, camera_dec_time);
21191 
21192 
21194  multi_send_float(camera_fov);
21195  multi_send_float(camera_time);
21196  multi_send_float(camera_acc_time);
21197  multi_send_float(camera_dec_time);
21199 }
21200 
21201 //CommanderDJ
21203 {
21204  camera *cam = sexp_get_set_camera();
21205 
21206  if(cam == NULL)
21207  return;
21208 
21209  float camera_fov = VIEWER_ZOOM_DEFAULT;
21210  float camera_time = 0.0f;
21211  float camera_acc_time = 0.0f;
21212  float camera_dec_time = 0.0f;
21213 
21214  multi_get_float(camera_fov);
21215  multi_get_float(camera_time);
21216  multi_get_float(camera_acc_time);
21217  multi_get_float(camera_dec_time);
21218 
21219  cam->set_fov(camera_fov, camera_time, camera_acc_time, camera_dec_time);
21220 }
21221 
21222 //Internal helper function for set-target and set-host
21223 object *sexp_camera_get_objsub(int node, int *o_submodel)
21224 {
21225  //Get arguments
21226  int n = node;
21227  char *obj_name = NULL;
21228  char *sub_name = NULL;
21229 
21230  obj_name = CTEXT(n);
21231  n = CDR(n);
21232  if(n != -1)
21233  sub_name = CTEXT(n);
21234 
21235  //Important variables
21236  object *objp = NULL;
21237  int submodel = -1;
21238 
21239  //*****Process obj_name
21241  sexp_get_object_ship_wing_point_team(&oswpt, obj_name);
21242 
21243  switch (oswpt.type)
21244  {
21245  case OSWPT_TYPE_SHIP:
21246  case OSWPT_TYPE_WING:
21247  case OSWPT_TYPE_WAYPOINT:
21248  objp = oswpt.objp;
21249  break;
21250 
21251  default:
21252  objp = NULL;
21253  }
21254 
21255  //*****Process submodel
21256  if(objp != NULL && sub_name != NULL && oswpt.type == OSWPT_TYPE_SHIP)
21257  {
21258  if(stricmp(sub_name, SEXP_NONE_STRING))
21259  {
21260  ship_subsys *ss = ship_get_subsys(&Ships[objp->instance], sub_name);
21261  if (ss != NULL)
21262  {
21263  submodel = ss->system_info->subobj_num;
21264  }
21265  }
21266  }
21267 
21268  if(o_submodel != NULL)
21269  *o_submodel = submodel;
21270 
21271  return objp;
21272 }
21273 
21274 void sexp_set_camera_host(int node)
21275 {
21276  //Try to get current camera
21277  camera *cam = sexp_get_set_camera();
21278 
21279  if(cam == NULL)
21280  return;
21281 
21282  //*****Get variables
21283  int submodel = -1;
21284  object *objp = sexp_camera_get_objsub(node, &submodel);
21285 
21286  //*****Set
21287  cam->set_object_host(objp, submodel);
21288 }
21289 
21291 {
21292  //Try to get current camera
21293  camera *cam = sexp_get_set_camera();
21294 
21295  if(cam == NULL)
21296  return;
21297 
21298  //*****Get variables
21299  int submodel = -1;
21300  object *objp = sexp_camera_get_objsub(node, &submodel);
21301 
21302  //*****Set
21303  cam->set_object_target(objp, submodel);
21304 
21306  multi_send_object(objp);
21307  multi_send_int(submodel);
21309 }
21310 
21312 {
21313  int submodel;
21314  object *objp;
21315 
21316  //Try to get current camera
21317  camera *cam = sexp_get_set_camera();
21318 
21319  if(cam == NULL)
21320  return;
21321 
21322  multi_get_object(objp);
21323  multi_get_int(submodel);
21324 
21325  cam->set_object_target(objp, submodel);
21326 }
21327 
21328 void sexp_set_fov(int n)
21329 {
21330  camera *cam = Main_camera.getCamera();
21331  if(cam == NULL) {
21333  cam = Main_camera.getCamera();
21334  }
21335 
21336  //Cap FOV to something reasonable.
21337  float new_fov = (float)(eval_num(n) % 360);
21338  Sexp_fov = fl_radians(new_fov);
21339 
21341  multi_send_float(new_fov);
21343 }
21344 
21346 {
21347  float new_fov;
21348 
21349  camera *cam = Main_camera.getCamera();
21350  if(cam == NULL) {
21352  cam = Main_camera.getCamera();
21353  }
21354 
21355  multi_get_float(new_fov);
21356  Sexp_fov = fl_radians(new_fov);
21357 }
21358 
21360 {
21361  camera *cam = Main_camera.getCamera();
21362  if(cam == NULL)
21363  return -1;
21364  else if(Sexp_fov > 0.0f)
21365  // SEXP override has been set
21366  return (int) fl_degrees(Sexp_fov);
21367  else
21368  return (int) fl_degrees(cam->get_fov());
21369 }
21370 
21375 {
21376  camera *cam = Main_camera.getCamera();
21377  if(cam == NULL)
21378  return;
21379 
21380  Sexp_fov = 0.0;
21381  //cam->set_fov(VIEWER_ZOOM_DEFAULT);
21382 
21384 }
21385 
21387 {
21388  camera *cam = Main_camera.getCamera();
21389  if(cam == NULL)
21390  return;
21391 
21392  Sexp_fov = 0.0;
21393 }
21394 
21395 void sexp_reset_camera(int node)
21396 {
21397  bool cam_reset = false;
21398  camera *cam = cam_get_current().getCamera();
21399  if(cam != NULL)
21400  {
21401  if(is_sexp_true(node))
21402  {
21403  cam->reset();
21404  cam_reset = true;
21405  }
21406  }
21407  cam_reset_camera();
21409  multi_send_bool(cam_reset);
21411 }
21412 
21414 {
21415  camera *cam = cam_get_current().getCamera();
21416  bool cam_reset = false;
21417 
21418  multi_get_bool(cam_reset);
21419  if((cam != NULL) && cam_reset) {
21420  cam->reset();
21421  }
21422  cam_reset_camera();
21423 }
21424 
21425 void sexp_show_subtitle(int node)
21426 {
21427  //These should be set to the default if not required to be explicitly defined
21428  int x_pos, y_pos, width=0;
21429  char *text, *imageanim=NULL;
21430  float display_time, fade_time=0.0f;
21431  int r=255, g=255, b=255;
21432  bool center_x=false, center_y=false;
21433  int n = -1;
21434  bool post_shaded = false;
21435 
21436  x_pos = eval_num(node);
21437  if (gr_screen.center_w != 1024)
21438  x_pos = (int) ((x_pos / 1024.0f) * gr_screen.center_w);
21439 
21440  n = CDR(node);
21441  y_pos = eval_num(n);
21442  if (gr_screen.center_h != 768)
21443  y_pos = (int) ((y_pos / 768.0f) * gr_screen.center_h);
21444 
21445  n = CDR(n);
21446  text = CTEXT(n);
21447 
21448  n = CDR(n);
21449  display_time = eval_num(n)/1000.0f; //is in ms
21450 
21451  n = CDR(n);
21452  if(n != -1)
21453  {
21454  imageanim = CTEXT(n);
21455 
21456  n = CDR(n);
21457  if(n != -1)
21458  {
21459  fade_time = eval_num(n)/1000.0f; //also in ms
21460 
21461  n = CDR(n);
21462  if(n != -1)
21463  {
21464  center_x = is_sexp_true(n) != 0;
21465 
21466  n = CDR(n);
21467  if(n != -1)
21468  {
21469  center_y = is_sexp_true(n) != 0;
21470 
21471  n = CDR(n);
21472  if(n != -1)
21473  {
21474  width = eval_num(n);
21475 
21476  n = CDR(n);
21477  if(n != -1)
21478  {
21479  r = eval_num(n);
21480 
21481  n = CDR(n);
21482  if(n != -1)
21483  {
21484  g = eval_num(n);
21485 
21486  n = CDR(n);
21487  if(n != -1)
21488  {
21489  b = eval_num(n);
21490 
21491  n = CDR(n);
21492  if ( n !=-1 )
21493  {
21494  post_shaded = is_sexp_true(n) != 0;
21495  }
21496  }
21497  }
21498  }
21499  }
21500  }
21501  }
21502  }
21503  }
21504 
21505  if(r > 255)
21506  r = 255;
21507  if(g > 255)
21508  g = 255;
21509  if(b > 255)
21510  b = 255;
21511 
21512  //FINALLY !!
21513  color new_color;
21514  gr_init_alphacolor(&new_color, r, g, b, 255);
21515 
21516  subtitle new_subtitle(x_pos, y_pos, text, imageanim, display_time, fade_time, &new_color, -1, center_x, center_y, width, 0, post_shaded);
21517  Subtitles.push_back(new_subtitle);
21518 }
21519 
21521 {
21522  Subtitles.clear();
21523 
21525 }
21526 
21528 {
21529  Subtitles.clear();
21530 }
21531 
21533 {
21534  int i, n = node, message_index = -1;
21535  char text[MESSAGE_LENGTH];
21536 
21537  // we'll suppose it's the string for now
21538  char *ctext = CTEXT(n);
21539 
21540  // but use an actual message if one exists
21541  for (i=0; i<Num_messages; i++)
21542  {
21543  if (!stricmp(Messages[i].name, ctext))
21544  {
21545  ctext = Messages[i].message;
21546  message_index = i;
21547  break;
21548  }
21549  }
21550 
21551  // translate things like keypresses, e.g. $T$ for targeting key
21552  // (we don't need to do variable replacements because the subtitle code already does that)
21553  message_translate_tokens(text, ctext);
21554 
21555  n = CDR(n);
21556 
21557  int x_pct = eval_num(n);
21558  n = CDR(n);
21559 
21560  int y_pct = eval_num(n);
21561  n = CDR(n);
21562 
21563  bool center_x = is_sexp_true(n) != 0;
21564  n = CDR(n);
21565 
21566  bool center_y = is_sexp_true(n) != 0;
21567  n = CDR(n);
21568 
21569  float display_time = eval_num(n) / 1000.0f;
21570  n = CDR(n);
21571 
21572  float fade_time = 0.0f;
21573  if (n >= 0)
21574  {
21575  fade_time = eval_num(n) / 1000.0f;
21576  n = CDR(n);
21577  }
21578 
21579  int width_pct = 0;
21580  if (n >= 0)
21581  {
21582  width_pct = eval_num(n);
21583  n = CDR(n);
21584  }
21585 
21586  int red = 255;
21587  if (n >= 0)
21588  {
21589  red = eval_num(n);
21590  n = CDR(n);
21591  }
21592 
21593  int green = 255;
21594  if (n >= 0)
21595  {
21596  green = eval_num(n);
21597  n = CDR(n);
21598  }
21599 
21600  int blue = 255;
21601  if (n >= 0)
21602  {
21603  blue = eval_num(n);
21604  n = CDR(n);
21605  }
21606 
21607  int fontnum = -1;
21608  if (n >= 0)
21609  {
21610  char *font_name = CTEXT(n);
21611  n = CDR(n);
21612 
21613  // perform font lookup
21614  for (int j = 0; j < Num_fonts; j++)
21615  {
21616  if (!stricmp(font_name, Fonts[j].filename))
21617  {
21618  fontnum = j;
21619  break;
21620  }
21621  }
21622  }
21623 
21624  bool post_shaded = false;
21625  if (n >= 0)
21626  {
21627  post_shaded = is_sexp_true(n) != 0;
21628  n = CDR(n);
21629  }
21630 
21631  // check bounds
21632  if (x_pct < -100)
21633  x_pct = -100;
21634  if (x_pct > 100)
21635  x_pct = 100;
21636  if (y_pct < -100)
21637  y_pct = -100;
21638  if (y_pct > 100)
21639  y_pct = 100;
21640  if (width_pct > 100)
21641  width_pct = 100;
21642  if (red > 255)
21643  red = 255;
21644  if (green > 255)
21645  green = 255;
21646  if (blue > 255)
21647  blue = 255;
21648 
21649  color new_color;
21650  gr_init_alphacolor(&new_color, red, green, blue, 255);
21651 
21652  // calculate pixel positions
21653  int x_pos = (int) (gr_screen.center_w * (x_pct / 100.0f));
21654  int y_pos = (int) (gr_screen.center_h * (y_pct / 100.0f));
21655  int width = (int) (gr_screen.center_w * (width_pct / 100.0f));
21656 
21657  // add the subtitle
21658  subtitle new_subtitle(x_pos, y_pos, text, NULL, display_time, fade_time, &new_color, fontnum, center_x, center_y, width, 0, post_shaded);
21659  Subtitles.push_back(new_subtitle);
21660 
21662  multi_send_int(x_pct);
21663  multi_send_int(y_pct);
21664  multi_send_int (message_index);
21665  // only send the text if it is not a message. If it is a message, we've already sent the index anyway.
21666  if (message_index == -1) {
21667  multi_send_string(text);
21668  }
21669  multi_send_float(display_time);
21670  multi_send_float(fade_time);
21671  multi_send_int(red);
21672  multi_send_int(green);
21673  multi_send_int(blue);
21674  multi_send_int(fontnum);
21675  multi_send_bool(center_x);
21676  multi_send_bool(center_y);
21677  multi_send_int(width_pct);
21678  multi_send_bool(post_shaded);
21680 }
21681 
21683 {
21684  int x_pct, y_pct, width_pct, fontnum, message_index = -1;
21685  char text[MESSAGE_LENGTH];
21686  float display_time, fade_time=0.0f;
21687  int red=255, green=255, blue=255;
21688  bool center_x=false, center_y=false;
21689  bool post_shaded = false;
21690  color new_color;
21691 
21692  multi_get_int(x_pct);
21693  multi_get_int(y_pct);
21694  multi_get_int(message_index);
21695  if (message_index == -1) {
21696  multi_get_string(text);
21697  }
21698  else {
21699  char *ctext = Messages[message_index].message;
21700  message_translate_tokens(text, ctext);
21701  }
21702  multi_get_float(display_time);
21703  multi_get_float(fade_time);
21704  multi_get_int(red);
21707  multi_get_int(fontnum);
21708  multi_get_bool(center_x);
21709  multi_get_bool(center_y);
21710  multi_get_int(width_pct);
21711  multi_get_bool(post_shaded);
21712 
21713  gr_init_alphacolor(&new_color, red, green, blue, 255);
21714 
21715  // calculate pixel positions
21716  int x_pos = (int)(gr_screen.center_w * (x_pct / 100.0f));
21717  int y_pos = (int)(gr_screen.center_h * (y_pct / 100.0f));
21718  int width = (int)(gr_screen.center_w * (width_pct / 100.0f));
21719 
21720  // add the subtitle
21721  subtitle new_subtitle(x_pos, y_pos, text, NULL, display_time, fade_time, &new_color, fontnum, center_x, center_y, width, 0, post_shaded);
21722  Subtitles.push_back(new_subtitle);
21723 
21724 }
21725 
21727 {
21728  int n = node;
21729 
21730  char *image = CTEXT(n);
21731  n = CDR(n);
21732 
21733  int x_pct = eval_num(n);
21734  n = CDR(n);
21735 
21736  int y_pct = eval_num(n);
21737  n = CDR(n);
21738 
21739  bool center_x = is_sexp_true(n) != 0;
21740  n = CDR(n);
21741 
21742  bool center_y = is_sexp_true(n) != 0;
21743  n = CDR(n);
21744 
21745  int width_pct = eval_num(n);
21746  n = CDR(n);
21747 
21748  int height_pct = eval_num(n);
21749  n = CDR(n);
21750 
21751  float display_time = eval_num(n) / 1000.0f;
21752  n = CDR(n);
21753 
21754  float fade_time = 0.0f;
21755  if (n >= 0)
21756  {
21757  fade_time = eval_num(n) / 1000.0f;
21758  n = CDR(n);
21759  }
21760 
21761  bool post_shaded = false;
21762  if (n >= 0)
21763  {
21764  post_shaded = is_sexp_true(n) != 0;
21765  n = CDR(n);
21766  }
21767 
21768  // check bounds
21769  if (x_pct < -100)
21770  x_pct = -100;
21771  if (x_pct > 100)
21772  x_pct = 100;
21773  if (y_pct < -100)
21774  y_pct = -100;
21775  if (y_pct > 100)
21776  y_pct = 100;
21777  if (width_pct < 0)
21778  width_pct = 0;
21779  if (width_pct > 100)
21780  width_pct = 100;
21781  if (height_pct < 0)
21782  height_pct = 0;
21783  if (height_pct > 100)
21784  height_pct = 100;
21785 
21786  // calculate pixel positions
21787  int x_pos = (int)(gr_screen.center_w * (x_pct / 100.0f));
21788  int y_pos = (int)(gr_screen.center_h * (y_pct / 100.0f));
21789  int width = (int)(gr_screen.center_w * (width_pct / 100.0f));
21790  int height = (int)(gr_screen.center_h * (height_pct / 100.0f));
21791 
21792  // add the subtitle
21793  subtitle new_subtitle(x_pos, y_pos, NULL, image, display_time, fade_time, NULL, -1, center_x, center_y, width, height, post_shaded);
21794  Subtitles.push_back(new_subtitle);
21795 
21797  multi_send_int(x_pos);
21798  multi_send_int(y_pos);
21799  multi_send_string(image);
21800  multi_send_float(display_time);
21801  multi_send_float(fade_time);
21802  multi_send_bool(center_x);
21803  multi_send_bool(center_y);
21804  multi_send_int(width);
21805  multi_send_int(height);
21806  multi_send_bool(post_shaded);
21808 }
21809 
21811 {
21812  int x_pos, y_pos, width=0, height=0;
21813  char image[TOKEN_LENGTH];
21814  float display_time, fade_time=0.0f;
21815  bool center_x=false, center_y=false;
21816  bool post_shaded = false;
21817 
21818  multi_get_int(x_pos);
21819  multi_get_int(y_pos);
21820  multi_get_string(image);
21821  multi_get_float(display_time);
21822  multi_get_float(fade_time);
21823  multi_get_bool(center_x);
21824  multi_get_bool(center_y);
21825  multi_get_int(width);
21827  multi_get_bool(post_shaded);
21828 
21829  // add the subtitle
21830  subtitle new_subtitle(x_pos, y_pos, NULL, image, display_time, fade_time, NULL, -1, center_x, center_y, width, height, post_shaded);
21831  Subtitles.push_back(new_subtitle);
21832 
21833 }
21834 
21836 {
21837  float new_multiplier = 0.0f;
21838  float new_change_time = 0.0f;
21839  float current_multiplier = 0.0f;
21840 
21842 
21843  new_multiplier = eval_num(n)/100.0f; //percent->decimal
21844  multi_send_float(new_multiplier);
21845 
21846 
21847  //Time to change
21848  n = CDR(n);
21849  if(n != -1) {
21850  new_change_time = eval_num(n)/1000.0f; //ms->seconds
21851  multi_send_float(new_change_time);
21852  }
21853 
21854  //Override current time compression with this value
21855  n = CDR(n);
21856  if(n != -1) {
21857  current_multiplier = eval_num(n)/100.0f;
21858  set_time_compression(current_multiplier);
21859  multi_send_float(current_multiplier);
21860  }
21861 
21863 
21864  set_time_compression(new_multiplier, new_change_time);
21865  lock_time_compression(true);
21866 }
21867 
21869 {
21870  float new_change_time = 0.0f;
21871  float new_multiplier = 0.0f;
21872  float current_multiplier = 0.0f;
21873 
21874  multi_get_float(new_multiplier);
21875  multi_get_float(new_change_time);
21876  if (multi_get_float(current_multiplier)) {
21877  set_time_compression(current_multiplier);
21878  }
21879 
21880  set_time_compression(new_multiplier, new_change_time);
21881  lock_time_compression(true);
21882 }
21883 
21885 {
21887  lock_time_compression(false);
21888 
21891 }
21892 
21894 {
21896  lock_time_compression(false);
21897 }
21898 
21899 extern bool Perspective_locked;
21900 
21902 {
21903  Perspective_locked = (is_sexp_true(n) != 0);
21904  n=CDR(n);
21905 
21906  if(n != -1)
21907  {
21908  n = eval_num(n);
21909  switch(n)
21910  {
21911  case 0:
21912  Viewer_mode = 0;
21913  break;
21914  case 1:
21916  break;
21917  case 2:
21919  break;
21920  case 3:
21922  break;
21923  }
21924  }
21925 }
21926 
21928 {
21929  int time = eval_num(n);
21930  float intensity = (float) eval_num(CDR(n)) * 0.01f;
21931 
21932  game_shudder_apply(time, intensity);
21933 
21935  multi_send_int(time);
21936  multi_send_float(intensity);
21938 }
21939 
21941 {
21942  int time;
21943  float intensity;
21944 
21945  multi_get_int(time);
21946  if (multi_get_float(intensity)) {
21947  game_shudder_apply(time, intensity);
21948  }
21949 }
21950 
21951 void sexp_set_jumpnode_name(int n) //CommanderDJ
21952 {
21953  char *old_name = CTEXT(n); //for multi
21954 
21955  CJumpNode *jnp = jumpnode_get_by_name(old_name);
21956 
21957  if(jnp==NULL) {
21958  return;
21959  }
21960 
21961  n=CDR(n);
21962  char *new_name = CTEXT(n); //for multi
21963  jnp->SetName(new_name);
21964 
21965  //multiplayer callback
21967  multi_send_string(old_name);
21968  multi_send_string(new_name);
21970 }
21971 
21972 void multi_sexp_set_jumpnode_name() //CommanderDJ
21973 {
21974  char old_name[TOKEN_LENGTH];
21975  char new_name[TOKEN_LENGTH];
21976 
21977  multi_get_string(old_name);
21978  multi_get_string(new_name);
21979 
21980  CJumpNode *jnp = jumpnode_get_by_name(old_name);
21981 
21982  if(jnp==NULL)
21983  return;
21984 
21985  jnp->SetName(new_name);
21986 }
21987 
21989 {
21991 
21992  if(jnp==NULL)
21993  return;
21994 
21995  char* jumpnode_name = CTEXT(n); //for multi
21996 
21997  n=CDR(n);
21998 
21999  int red = eval_num(n);
22000  int green = eval_num(CDR(n));
22001  int blue = eval_num(CDR(CDR(n)));
22002  int alpha = eval_num(CDR(CDR(CDR(n))));
22003 
22004  jnp->SetAlphaColor(red, green, blue, alpha);
22005 
22007  multi_send_string(jumpnode_name);
22008  multi_send_int(red);
22009  multi_send_int(green);
22010  multi_send_int(blue);
22011  multi_send_int(alpha);
22013 }
22014 
22015 //CommanderDJ
22017 {
22018  char jumpnode_name[TOKEN_LENGTH];
22019  int red, blue, green, alpha;
22020 
22021  multi_get_string(jumpnode_name);
22022  CJumpNode *jnp = jumpnode_get_by_name(jumpnode_name);
22023 
22024  if(jnp==NULL) {
22026  return;
22027  }
22028 
22029  multi_get_int(red);
22030  multi_get_int(green);
22031  multi_get_int(blue);
22032  multi_get_int(alpha);
22033 
22034  jnp->SetAlphaColor(red, green, blue, alpha);
22035 }
22036 
22038 {
22039  char* jumpnode_name = CTEXT(n);
22040  CJumpNode *jnp = jumpnode_get_by_name(jumpnode_name);
22041 
22042  if(jnp==NULL)
22043  return;
22044 
22045  n=CDR(n);
22046  char* model_name = CTEXT(n);
22047  n=CDR(n);
22048  bool show_polys = (is_sexp_true(n) != 0);
22049 
22050  jnp->SetModel(model_name, show_polys);
22051 
22053  multi_send_string(jumpnode_name);
22054  multi_send_string(model_name);
22055  multi_send_bool(show_polys);
22057 }
22058 
22060 {
22061  char jumpnode_name[TOKEN_LENGTH];
22062  char model_name[TOKEN_LENGTH];
22063  bool show_polys;
22064 
22065  multi_get_string(jumpnode_name);
22066  multi_get_string(model_name);
22067 
22068  CJumpNode *jnp = jumpnode_get_by_name(jumpnode_name);
22069 
22070  if(jnp==NULL) {
22072  return;
22073  }
22074 
22075  show_polys = multi_get_bool(show_polys);
22076 
22077  jnp->SetModel(model_name, show_polys);
22078 }
22079 
22080 void sexp_show_hide_jumpnode(int node, bool show)
22081 {
22083 
22084  for (int n = node; n >= 0; n = CDR(n))
22085  {
22087  if (jnp != NULL)
22088  {
22089  jnp->SetVisibility(show);
22091  }
22092  }
22093 
22095 }
22096 
22098 {
22099  char jumpnode_name[TOKEN_LENGTH];
22100 
22101  while (multi_get_string(jumpnode_name))
22102  {
22103  CJumpNode *jnp = jumpnode_get_by_name(jumpnode_name);
22104  if (jnp != NULL)
22105  jnp->SetVisibility(show);
22106  }
22107 }
22108 
22109 //WMC - This is a bit of a hack, however, it's easier than
22110 //coding in a whole new Script_system function.
22111 int sexp_script_eval(int node, int return_type, bool concat_args = false)
22112 {
22113  int n = node;
22114 
22115  switch(return_type)
22116  {
22117  case OPR_NUMBER:
22118  {
22119  char* s = CTEXT(n);
22120  int r = -1;
22121  bool success = Script_system.EvalString(CTEXT(n), "|i", &r);
22122 
22123  if(!success)
22124  Warning(LOCATION, "sexp-script-eval failed to evaluate string \"%s\"; check your syntax", s);
22125 
22126  return r;
22127  }
22128  case OPR_STRING:
22129  {
22130  char* ret = NULL;
22131  char* s = CTEXT(n);
22132 
22133  bool success = Script_system.EvalString(s, "|s", &ret);
22134  n = CDR(n);
22135 
22136  if(!success)
22137  Warning(LOCATION, "sexp-script-eval failed to evaluate string \"%s\"; check your syntax", s);
22138 
22139  if (n != -1 && success)
22140  {
22141  Assert(Sexp_nodes[n].first == -1);
22142  int variable_index = atoi(Sexp_nodes[n].text);
22143 
22144  // verify variable set
22145  Assert(Sexp_variables[variable_index].type & SEXP_VARIABLE_SET);
22146 
22147  if (!(Sexp_variables[variable_index].type & SEXP_VARIABLE_STRING))
22148  {
22149  Warning(LOCATION, "Variable for script-eval has to be a string variable!");
22150  }
22151  else if (ret != NULL)
22152  {
22153  // assign to variable
22154  sexp_modify_variable(ret, variable_index);
22155  }
22156 
22157  n = CDR(n);
22158  }
22159  }
22160  break;
22161  case OPR_NULL:
22162  {
22163  SCP_string script_cmd;
22164  while (n != -1)
22165  {
22166  char* s = CTEXT(n);
22167 
22168  if (concat_args)
22169  {
22170  script_cmd.append(CTEXT(n));
22171  }
22172  else
22173  {
22174  bool success = Script_system.EvalString(s, NULL, NULL);
22175 
22176  if (!success)
22177  Warning(LOCATION, "sexp-script-eval failed to evaluate string \"%s\"; check your syntax", s);
22178  }
22179 
22180  n = CDR(n);
22181  }
22182 
22183  if (concat_args)
22184  {
22185  bool success = Script_system.EvalString(script_cmd.c_str(), NULL, NULL);
22186 
22187  if (!success)
22188  Warning(LOCATION, "sexp-script-eval failed to evaluate string \"%s\"; check your syntax", script_cmd.c_str());
22189  }
22190  }
22191  break;
22192  default:
22193  Error(LOCATION, "Bad type passed to sexp_script_eval - get a coder");
22194  break;
22195  }
22196 
22197  return -1;
22198 }
22199 
22201 {
22202  char s[TOKEN_LENGTH];
22203  bool success = true;
22204  int execute_on_server;
22205  int sindex;
22206  player *p;
22207 
22208  strcpy_s(s, CTEXT(node));
22209 
22210  node = CDR(node);
22211 
22212  execute_on_server = is_sexp_true(node);
22213 
22214  node = CDR(node);
22215 
22217  multi_send_string(s);
22218  // evalutate on all clients
22219  if (node == -1) {
22220  multi_send_bool(true);
22221  execute_on_server = 1;
22222  }
22223  // we have to send to all clients but we need to send a list of ships so that they know if they evaluate or not
22224  else {
22225  multi_send_bool(false);
22226 
22227  do {
22228  p = get_player_from_ship_node(node, true);
22229 
22230  // not a player ship so skip it
22231  if (p == NULL ){
22232  node = CDR(node);
22233  continue;
22234  }
22235  else {
22236  // if this is me, flag that we should execute the script
22237  if (p == Player) {
22238  execute_on_server = 1;
22239  }
22240  // otherwise notify the clients
22241  else {
22242  sindex = ship_name_lookup(CTEXT(node));
22243  multi_send_ship(sindex);
22244  }
22245  }
22246 
22247  node = CDR(node);
22248  } while (node != -1);
22249  }
22250 
22252 
22253  if (execute_on_server) {
22254  success = Script_system.EvalString(s, NULL, NULL, s);
22255  }
22256 
22257  if(!success) {
22258  Warning(LOCATION, "sexp-script-eval failed to evaluate string \"%s\"; check your syntax", s);
22259  }
22260 }
22261 
22263 {
22264  int sindex;
22265  char s[TOKEN_LENGTH];
22266  bool sent_to_all = false;
22267  bool success = true;
22268 
22269  multi_get_string(s);
22270  multi_get_bool(sent_to_all);
22271 
22272  if (sent_to_all) {
22273  success = Script_system.EvalString(s, NULL, NULL, s);
22274  }
22275  // go through all the ships that were sent and see if any of them match this client.
22276  else {
22277  while (multi_get_ship(sindex)) {
22278  Assertion(sindex >= 0, "Illegal value for the ship index sent in multi_sexp_script_eval_multi()! Ship %d does not exist!", sindex);
22279  if (Player->objnum == Ships[sindex].objnum) {
22280  success = Script_system.EvalString(s, NULL, NULL, s);
22281  }
22282  }
22283  }
22284 
22285  if(!success) {
22286  Warning(LOCATION, "sexp-script-eval failed to evaluate string \"%s\"; check your syntax", s);
22287  }
22288 }
22289 
22290 
22291 void sexp_force_glide(int node)
22292 {
22293  ship *shipp;
22294  int sindex;
22295 
22296  // get ship
22297  sindex = ship_name_lookup(CTEXT(node));
22298 
22299  if (sindex < 0) {
22300  return;
22301  }
22302 
22303  shipp = &Ships[sindex];
22304  if (shipp->objnum < 0) {
22305  return;
22306  }
22307 
22308  //Can this ship glide?
22309  if (!Ship_info[shipp->ship_info_index].can_glide)
22310  return;
22311 
22312  int glide = is_sexp_true(CDR(node));
22313 
22314  object_set_gliding(&Objects[shipp->objnum], (glide > 0), true);
22315 
22316  return;
22317 }
22318 
22319 bool test_point_within_box(vec3d *test_point, vec3d *box_corner_1, vec3d *box_corner_2, object *reference_ship_obj)
22320 {
22321  vec3d tempv, test_point_buf;
22322 
22323  // If reference_ship is specified, rotate test_point into its reference frame
22324  if (reference_ship_obj != NULL)
22325  {
22326  vm_vec_sub(&tempv, test_point, &reference_ship_obj->pos);
22327  vm_vec_rotate(&test_point_buf, &tempv, &reference_ship_obj->orient);
22328 
22329  test_point = &test_point_buf;
22330  }
22331 
22332  // Check to see if the test point is within the specified box as defined by two extreme corners
22333  return ((test_point->xyz.x >= box_corner_1->xyz.x && test_point->xyz.x <= box_corner_2->xyz.x) &&
22334  (test_point->xyz.y >= box_corner_1->xyz.y && test_point->xyz.y <= box_corner_2->xyz.y) &&
22335  (test_point->xyz.z >= box_corner_1->xyz.z && test_point->xyz.z <= box_corner_2->xyz.z));
22336 }
22337 
22339 {
22340  int i;
22341  Assert(n >= 0);
22342 
22345  n = CDR(n);
22346 
22347  // Get box corners
22348  float x1 = (float) eval_num(n);
22349  n = CDR(n);
22350  float x2 = (float) eval_num(n);
22351  n = CDR(n);
22352  float y1 = (float) eval_num(n);
22353  n = CDR(n);
22354  float y2 = (float) eval_num(n);
22355  n = CDR(n);
22356  float z1 = (float) eval_num(n);
22357  n = CDR(n);
22358  float z2 = (float) eval_num(n);
22359  n = CDR(n);
22360  vec3d box_corner_1;
22361  box_corner_1.xyz.x = MIN(x1, x2);
22362  box_corner_1.xyz.y = MIN(y1, y2);
22363  box_corner_1.xyz.z = MIN(z1, z2);
22364  vec3d box_corner_2;
22365  box_corner_2.xyz.x = MAX(x1, x2);
22366  box_corner_2.xyz.y = MAX(y1, y2);
22367  box_corner_2.xyz.z = MAX(z1, z2);
22368 
22369  // Ship to define reference frame is optional
22370  object* reference_ship_obj = NULL;
22371  if (n != -1)
22372  {
22373  int sindex = ship_name_lookup(CTEXT(n));
22374 
22375  if (sindex < 0 || Ships[sindex].objnum < 0)
22376  return SEXP_FALSE;
22377 
22378  reference_ship_obj = &Objects[Ships[sindex].objnum];
22379  }
22380 
22381  // Check position of object
22382  switch (oswpt.type)
22383  {
22384  case OSWPT_TYPE_EXITED:
22385  return SEXP_KNOWN_FALSE;
22386 
22387  case OSWPT_TYPE_WING:
22388  for (i = 0; i < oswpt.wingp->current_count; i++)
22389  if (!test_point_within_box(&Objects[Ships[oswpt.wingp->ship_index[i]].objnum].pos, &box_corner_1, &box_corner_2, reference_ship_obj))
22390  return SEXP_FALSE;
22391  return SEXP_TRUE;
22392 
22393  case OSWPT_TYPE_SHIP:
22394  case OSWPT_TYPE_WAYPOINT:
22395  return test_point_within_box(&oswpt.objp->pos, &box_corner_1, &box_corner_2, reference_ship_obj);
22396 
22397  default:
22398  return SEXP_FALSE;
22399  }
22400 }
22401 
22402 int sexp_is_in_mission(int node)
22403 {
22404  for (int n = node; n != -1; n = CDR(n))
22405  if (ship_name_lookup(CTEXT(n)) < 0)
22406  return SEXP_FALSE;
22407 
22408  return SEXP_TRUE;
22409 }
22410 
22411 void sexp_manipulate_colgroup(int node, bool add_to_group) {
22412  object* objp;
22413  ship* shipp;
22414  int colgroup_id;
22415 
22416  shipp = sexp_get_ship_from_node(node);
22417 
22418  if (shipp == NULL)
22419  return;
22420 
22421  objp = &Objects[shipp->objnum];
22422  colgroup_id = objp->collision_group_id;
22423 
22424  node = CDR(node);
22425 
22426  while (node != -1) {
22427 
22428  int group = eval_num(node);
22429 
22430  if (group < 0 || group > 31) {
22431  WarningEx(LOCATION, "Invalid collision group id %d specified for object %s. Valid IDs range from 0 to 31.\n", group, shipp->ship_name);
22432  } else {
22433  if (add_to_group) {
22434  colgroup_id |= (1<<group);
22435  } else {
22436  colgroup_id &= !(1<<group);
22437  }
22438  }
22439 
22440  node = CDR(node);
22441  }
22442 
22443  objp->collision_group_id = colgroup_id;
22444 }
22445 
22446 int sexp_get_colgroup(int node) {
22447  ship* shipp;
22448 
22449  shipp = sexp_get_ship_from_node(CDR(node));
22450 
22451  return Objects[shipp->objnum].collision_group_id;
22452 }
22453 
22455  int i = 0;
22456  for (SCP_vector<ship_effect>::iterator sei = Ship_effects.begin(); sei != Ship_effects.end(); ++sei) {
22457  if (!stricmp(name, sei->name))
22458  return i;
22459  i++;
22460  }
22461  return -1;
22462 }
22463 
22465 {
22466  char *name;
22467  int ship_index, wing_index;
22468 
22469  Assert ( n != -1 );
22470 
22471  int effect_num = get_effect_from_name(CTEXT(n));
22472  if (effect_num == -1) {
22473  WarningEx(LOCATION, "Invalid effect name passed to ship-effect\n");
22474  return;
22475  }
22476  n = CDR(n);
22477  int effect_duration = eval_num(n);
22478  n = CDR(n);
22479 
22480  ship_index = -1;
22481  wing_index = -1;
22482  while (n != -1) {
22483  name = CTEXT(n);
22484 
22485  // check to see if this ship/wing has arrived yet.
22486  if (sexp_query_has_yet_to_arrive(name)) {
22487  n = CDR(n);
22488  continue;
22489  }
22490 
22491  // check to see if this ship/wing has departed.
22492  if ( mission_log_get_time (LOG_SHIP_DEPARTED, name, NULL, NULL) || mission_log_get_time (LOG_WING_DEPARTED, name, NULL, NULL) ) {
22493  n = CDR(n);
22494  continue;
22495  }
22496 
22497  // check to see if this ship/wing has been destroyed.
22498  if ( mission_log_get_time(LOG_SHIP_DESTROYED, name, NULL, NULL) || mission_log_get_time(LOG_WING_DESTROYED, name, NULL, NULL) || mission_log_get_time(LOG_SELF_DESTRUCTED, name, NULL, NULL)) {
22499  n = CDR(n);
22500  continue;
22501  }
22502 
22503  ship *sp;
22504  if((wing_index = wing_name_lookup(name)) >= 0)
22505  {
22506  wing *wp = &Wings[wing_index];
22507  for(int i = 0; i < wp->current_count; i++)
22508  {
22509  if(wp->ship_index[i] >= 0)
22510  {
22511  sp = &Ships[wp->ship_index[i]];
22512  sp->shader_effect_active = true;
22513  sp->shader_effect_num = effect_num;
22514  sp->shader_effect_duration = effect_duration;
22516  }
22517  }
22518  }
22519  else
22520  {
22521  if((ship_index = ship_name_lookup(name)) >= 0)
22522  {
22523  sp = &Ships[ship_index];
22524  sp->shader_effect_active = true;
22525  sp->shader_effect_num = effect_num;
22526  sp->shader_effect_duration = effect_duration;
22528  }
22529  else
22530  mprintf(("Invalid Shipname in SEXP ship-effect\n"));
22531  }
22532 
22533  // move to next ship/wing in list
22534  n = CDR(n);
22535  }
22536 }
22537 
22539  SCP_string new_color = CTEXT(n);
22540  SCP_vector<ship*> shippointers;
22541  n = CDR(n);
22542  int fade_time = eval_num(n);
22543 
22544  n = CDR(n);
22545 
22546  while (n != -1) {
22548 
22549  if (shipp != NULL) {
22550  shippointers.push_back(shipp);
22551  }
22552 
22553  n = CDR(n);
22554  }
22555 
22557  multi_send_string(new_color);
22558  multi_send_int(fade_time);
22559  multi_send_int(shippointers.size());
22560 
22561  for (SCP_vector<ship*>::iterator shipp = shippointers.begin(); shipp != shippointers.end(); ++shipp) {
22562  ship* shp = *shipp;
22563  multi_send_ship(shp);
22564  if (fade_time == 0) {
22565  shp->team_name = new_color;
22566  } else {
22567  shp->secondary_team_name = new_color;
22568  shp->team_change_time = fade_time;
22570  }
22571  }
22572 
22574 }
22575 
22577  SCP_string new_color = "<none>";
22578  int fade_time = 0;
22579  int n_ships = 0;
22580 
22581  multi_get_string(new_color);
22582  multi_get_int(fade_time);
22583  multi_get_int(n_ships);
22584 
22585  for (int i = 0; i < n_ships; ++i) {
22586  ship* shipp;
22587  multi_get_ship(shipp);
22588  if (fade_time == 0) {
22589  shipp->team_name = new_color;
22590  } else {
22591  shipp->secondary_team_name = new_color;
22592  shipp->team_change_time = fade_time;
22594  }
22595  }
22596 }
22597 
22598 void sexp_call_ssm_strike(int node) {
22599  int ssm_index = ssm_info_lookup(CTEXT(node));
22600  node = CDR(node);
22601  int calling_team = iff_lookup(CTEXT(node));
22602  if (ssm_index < 0 || calling_team < 0)
22603  return;
22604 
22605  for (int n = node; n != -1; n = CDR(n)) {
22606  int ship_num = ship_name_lookup(CTEXT(n));
22607  // don't do anything if the ship isn't there
22608  if (ship_num >= 0) {
22609  int obj_num = Ships[ship_num].objnum;
22610  object *target_ship = &Objects[obj_num];
22611  vec3d start = target_ship->pos;
22612 
22613  vm_vec_scale_add(&start, &start, &target_ship->orient.vec.fvec, -1);
22614 
22615  ssm_create(target_ship, &start, ssm_index, NULL, calling_team);
22616  }
22617  }
22618 }
22619 
22620 extern int Cheats_enabled;
22622  if (Cheats_enabled) {
22623  return SEXP_KNOWN_TRUE;
22624  }
22625 
22626  return SEXP_FALSE;
22627 }
22628 
22629 void sexp_set_motion_debris(int node) {
22630  Motion_debris_override = is_sexp_true(node) != 0;
22631 }
22632 
22636 int get_generic_subsys(char *subsys_name)
22637 {
22638  if (!strcmp(subsys_name, SEXP_ALL_ENGINES_STRING)) {
22639  return SUBSYSTEM_ENGINE;
22640  } else if (!strcmp(subsys_name, SEXP_ALL_TURRETS_STRING)) {
22641  return SUBSYSTEM_TURRET;
22642  }
22643 
22644  Assert(SUBSYSTEM_NONE == 0);
22645  return SUBSYSTEM_NONE;
22646 }
22647 
22648 // Karajorma - returns false if the ship class has changed since the mission was parsed in
22649 // Changes can be from use of the change-ship-class SEXP, loadout or any future method
22650 bool ship_class_unchanged(int ship_index)
22651 {
22652  p_object *p_objp;
22653 
22654  ship *shipp = &Ships[ship_index];
22655  p_objp = mission_parse_get_parse_object(shipp->ship_name);
22656 
22657  if ((p_objp != NULL) && (p_objp->ship_class == shipp->ship_info_index)) {
22658  return true;
22659  }
22660 
22661  return false;
22662 }
22663 
22664 // Goober5000 - needed because any nonzero integer value is "true"
22665 int is_sexp_true(int cur_node, int referenced_node)
22666 {
22667  int result = eval_sexp(cur_node, referenced_node);
22668 
22669  return (result == SEXP_TRUE); // note: any SEXP_KNOWN_TRUE result will return SEXP_TRUE
22670 }
22671 
22672 
22677 {
22678  int matches = 0;
22679  mission_event *current_event = &Mission_events[Event_index];
22680 
22681  switch (result) {
22682  case SEXP_TRUE:
22683  matches |= MLF_SEXP_TRUE;
22684  break;
22685 
22686  case SEXP_FALSE:
22687  matches |= MLF_SEXP_FALSE;
22688  break;
22689 
22690  default:
22691  Error(LOCATION, "SEXP has a value which isn't true or false.");
22692  }
22693 
22694  if (( result == SEXP_TRUE ) || (result == SEXP_KNOWN_TRUE)) {
22695  // now deal with the flags depending on repeat and trigger counts
22696  switch (current_event->mission_log_flags) {
22697  case MLF_FIRST_REPEAT_ONLY:
22698  if (current_event->repeat_count > 1) {
22699  matches |= MLF_FIRST_REPEAT_ONLY;
22700  }
22701  break;
22702 
22703  case MLF_LAST_REPEAT_ONLY:
22704  if (current_event->repeat_count == 1) {
22705  matches |= MLF_LAST_REPEAT_ONLY;
22706  }
22707  break;
22708 
22709  case MLF_FIRST_TRIGGER_ONLY:
22710  if (current_event->trigger_count > 1) {
22711  matches |= MLF_FIRST_TRIGGER_ONLY;
22712  }
22713  break;
22714 
22715  case MLF_LAST_TRIGGER_ONLY:
22716  if ((current_event->trigger_count == 1) && (current_event->flags & MEF_USING_TRIGGER_COUNT)) {
22717  matches |= MLF_LAST_TRIGGER_ONLY;
22718  }
22719  break;
22720  }
22721  }
22722 
22723  return matches;
22724 }
22725 
22727 {
22729  if (!(Mission_events[Event_index].mission_log_flags & MLF_STATE_CHANGE)){
22730  return;
22731  }
22732 
22733  for (int i = 0; i < (int)Current_event_log_buffer->size(); i++) {
22734  Mission_events[Event_index].backup_log_buffer.push_back(Current_event_log_buffer->at(i));
22735  }
22736 }
22737 
22739 {
22740  mission_event *this_event = &Mission_events[Event_index];
22741 
22742  // if the old log is empty, all we do is record the result for the next evaluation
22743  // the old log should only be empty at mission start
22744  if (this_event->backup_log_buffer.empty()) {
22745  this_event->previous_result = result;
22746  return;
22747  }
22748 
22749  // if there's no change in state, we don't write the previous state to the log
22750  if ((this_event->mission_log_flags & MLF_STATE_CHANGE) && (result == this_event->previous_result)) {
22752  return;
22753  }
22754 
22755  log_string(LOGFILE_EVENT_LOG, "Event has changed state. Old state");
22756  while (!this_event->backup_log_buffer.empty()) {
22757  log_string(LOGFILE_EVENT_LOG, this_event->backup_log_buffer.back().c_str());
22758  this_event->backup_log_buffer.pop_back();
22759  }
22760  log_string(LOGFILE_EVENT_LOG, "New state");
22761 
22762  // backup the current buffer as this may be a repeating event
22764 }
22765 
22770 {
22771  char buffer [256];
22772 
22773  int mask = generate_event_log_flags_mask(result);
22774  sprintf(buffer, "Event: %s at mission time %d seconds (%d milliseconds)", Mission_events[Event_index].name, f2i(Missiontime), f2i((longlong)Missiontime * 1000));
22775  Current_event_log_buffer->push_back(buffer);
22776 
22777  if (!Snapshot_all_events && (!(mask &= Mission_events[Event_index].mission_log_flags))) {
22779  Current_event_log_buffer->clear();
22780  return;
22781  }
22782 
22783  // remove some of the flags
22786  }
22787 
22788  if (Mission_events[Event_index].mission_log_flags & MLF_STATE_CHANGE) {
22790  }
22791 
22792  while (!Current_event_log_buffer->empty()) {
22793  log_string(LOGFILE_EVENT_LOG, Current_event_log_buffer->back().c_str());
22794  Current_event_log_buffer->pop_back();
22795  }
22797 
22798 }
22799 
22804 {
22805  switch (result) {
22806  case SEXP_TRUE:
22807  return "TRUE";
22808 
22809  case SEXP_FALSE:
22810  return "FALSE";
22811 
22812  case SEXP_KNOWN_FALSE:
22813  return "ALWAYS FALSE";
22814 
22815  case SEXP_KNOWN_TRUE:
22816  return "ALWAYS TRUE";
22817 
22818  case SEXP_UNKNOWN:
22819  return "UNKNOWN";
22820 
22821  case SEXP_NAN:
22822  return "NOT A NUMBER";
22823 
22824  case SEXP_NAN_FOREVER:
22825  return "CAN NEVER BE A NUMBER";
22826 
22827  case SEXP_CANT_EVAL:
22828  return "CAN'T EVALUATE";
22829 
22830  default:
22831  return NULL;
22832  }
22833 }
22834 
22839 {
22840  Assertion ((Current_event_log_buffer != NULL) &&
22841  (Current_event_log_variable_buffer != NULL)&&
22842  (Current_event_log_argument_buffer != NULL), "Attempting to write to a non-existent log buffer");
22843 
22844  if (op_num == -1) {
22845  nprintf(("SEXP", "ERROR: op_num function returned %i, this should not happen. Contact a coder.\n", op_num));
22846  return; //How does this happen?
22847  }
22848 
22849  char buffer[TOKEN_LENGTH];
22850  SCP_string tmp;
22851  tmp.append(Operators[op_num].text);
22852  tmp.append(" returned ");
22853 
22854  if ((Operators[op_num].type & (SEXP_INTEGER_OPERATOR|SEXP_ARITHMETIC_OPERATOR)) || (sexp_get_result_as_text(result) == NULL)) {
22855  sprintf(buffer, "%d", result);
22856  tmp.append(buffer);
22857  }
22858  else {
22859  tmp.append(sexp_get_result_as_text(result));
22860  }
22861 
22862  if (True_loop_argument_sexps && !Sexp_replacement_arguments.empty()) {
22863  tmp.append(" for argument ");
22864  tmp.append(Sexp_replacement_arguments.back());
22865  }
22866 
22867  if (!Current_event_log_argument_buffer->empty()) {
22868  tmp.append(" for the following arguments");
22869  while (!Current_event_log_argument_buffer->empty()) {
22870  tmp.append("\n");
22871  tmp.append(Current_event_log_argument_buffer->back().c_str());
22872  Current_event_log_argument_buffer->pop_back();
22873  }
22874  }
22875 
22876  if (!Current_event_log_variable_buffer->empty()) {
22877  tmp.append("\nVariables:\n");
22878  while (!Current_event_log_variable_buffer->empty()) {
22879  tmp.append(Current_event_log_variable_buffer->back().c_str());
22880  Current_event_log_variable_buffer->pop_back();
22881  tmp.append("[");
22882  tmp.append(Current_event_log_variable_buffer->back().c_str());
22883  Current_event_log_variable_buffer->pop_back();
22884  tmp.append("]");
22885  }
22886  }
22887 
22888  Current_event_log_buffer->push_back(tmp);
22889 }
22890 
22894 int eval_sexp(int cur_node, int referenced_node)
22895 {
22896  int node, type, sexp_val = UNINITIALIZED;
22897  if (cur_node == -1) // empty list, i.e. sexp: ( )
22898  return SEXP_FALSE;
22899 
22900  Assert(cur_node >= 0); // we have special sexp nodes <= -1!!! MWA
22901  // which should be intercepted before we get here. HOFFOSS
22902  type = SEXP_NODE_TYPE(cur_node);
22903  Assert( (type == SEXP_LIST) || (type == SEXP_ATOM) );
22904 
22905  // trap known true and known false sexpressions. We don't trap on SEXP_NAN sexpressions since
22906  // they may yet evaluate to true or false.
22907 
22908  if (Sexp_nodes[cur_node].value == SEXP_KNOWN_TRUE) {
22909  if (Log_event) {
22911  }
22912  return SEXP_TRUE;
22913  }
22914  else if (Sexp_nodes[cur_node].value == SEXP_KNOWN_FALSE) {
22915  if (Log_event) {
22917  }
22918  return SEXP_FALSE;
22919  }
22920  else if (Sexp_nodes[cur_node].value == SEXP_NAN_FOREVER) {
22921  if (Log_event) {
22923  }
22924  return SEXP_FALSE;
22925  }
22926 
22927  if (Sexp_nodes[cur_node].first != -1) {
22928  node = CAR(cur_node);
22929  sexp_val = eval_sexp(node);
22930  Sexp_nodes[cur_node].value = Sexp_nodes[node].value; // higher level node gets node value
22931  return sexp_val;
22932 
22933  } else {
22934  int op_num;
22935 
22936  node = CDR(cur_node); // makes reading the next bit of code a little easier.
22937 
22938  op_num = get_operator_const(cur_node);
22939  // add the op_num to the stack if it is an actual operator rather than a number
22940  if (op_num) {
22941  Current_sexp_operator.push_back(op_num);
22942  }
22943  switch ( op_num ) {
22944  // arithmetic operators will always return just their value
22945  case OP_PLUS:
22946  sexp_val = add_sexps(node);
22947  break;
22948 
22949  case OP_MINUS:
22950  sexp_val = sub_sexps(node);
22951  break;
22952 
22953  case OP_MUL:
22954  sexp_val = mul_sexps(node);
22955  break;
22956 
22957  case OP_MOD:
22958  sexp_val = mod_sexps(node);
22959  break;
22960 
22961  case OP_DIV:
22962  sexp_val = div_sexps(node);
22963  break;
22964 
22965  case OP_RAND:
22966  case OP_RAND_MULTIPLE:
22967  sexp_val = rand_sexp( node, (op_num == OP_RAND_MULTIPLE) );
22968  break;
22969 
22970  case OP_ABS:
22971  sexp_val = abs_sexp(node);
22972  break;
22973 
22974  case OP_MIN:
22975  sexp_val = min_sexp(node);
22976  break;
22977 
22978  case OP_MAX:
22979  sexp_val = max_sexp(node);
22980  break;
22981 
22982  case OP_AVG:
22983  sexp_val = avg_sexp(node);
22984  break;
22985 
22986  case OP_POW:
22987  sexp_val = pow_sexp(node);
22988  break;
22989 
22990  case OP_SIGNUM:
22991  sexp_val = signum_sexp(node);
22992  break;
22993 
22994  case OP_SET_BIT:
22995  case OP_UNSET_BIT:
22996  sexp_val = sexp_set_bit(node, op_num == OP_SET_BIT);
22997  break;
22998 
22999  case OP_IS_BIT_SET:
23000  sexp_val = sexp_is_bit_set(node);
23001  break;
23002 
23003  case OP_BITWISE_AND:
23004  sexp_val = sexp_bitwise_and(node);
23005  break;
23006 
23007  case OP_BITWISE_OR:
23008  sexp_val = sexp_bitwise_or(node);
23009  break;
23010 
23011  case OP_BITWISE_NOT:
23012  sexp_val = sexp_bitwise_not(node);
23013  break;
23014 
23015  case OP_BITWISE_XOR:
23016  sexp_val = sexp_bitwise_xor(node);
23017  break;
23018 
23019  // boolean operators can have one of the special sexp values (known true, known false, unknown)
23020  case OP_TRUE:
23021  sexp_val = SEXP_KNOWN_TRUE;
23022  break;
23023 
23024  case OP_FALSE:
23025  sexp_val = SEXP_KNOWN_FALSE;
23026  break;
23027 
23028  case OP_OR:
23029  sexp_val = sexp_or(node);
23030  break;
23031 
23032  case OP_AND:
23033  sexp_val = sexp_and(node);
23034  break;
23035 
23036  case OP_AND_IN_SEQUENCE:
23037  sexp_val = sexp_and_in_sequence(node);
23038  break;
23039 
23040  case OP_XOR:
23041  sexp_val = sexp_xor(node);
23042  break;
23043 
23044  case OP_EQUALS:
23045  case OP_GREATER_THAN:
23046  case OP_LESS_THAN:
23047  case OP_NOT_EQUAL:
23048  case OP_GREATER_OR_EQUAL:
23049  case OP_LESS_OR_EQUAL:
23050  sexp_val = sexp_number_compare( node, op_num );
23051  break;
23052 
23054  case OP_STRING_LESS_THAN:
23055  case OP_STRING_EQUALS:
23056  sexp_val = sexp_string_compare( node, op_num );
23057  break;
23058 
23059  case OP_IS_IFF:
23060  sexp_val = sexp_is_iff(node);
23061  break;
23062 
23063  case OP_NOT:
23064  sexp_val = sexp_not(node);
23065  break;
23066 
23067  case OP_PREVIOUS_GOAL_TRUE:
23068  sexp_val = sexp_previous_goal_status( node, GOAL_COMPLETE );
23069  break;
23070 
23072  sexp_val = sexp_previous_goal_status( node, GOAL_FAILED );
23073  break;
23074 
23076  sexp_val = sexp_previous_goal_status( node, GOAL_INCOMPLETE );
23077  break;
23078 
23080  sexp_val = sexp_previous_event_status( node, EVENT_SATISFIED );
23081  break;
23082 
23084  sexp_val = sexp_previous_event_status( node, EVENT_FAILED );
23085  break;
23086 
23088  sexp_val = sexp_previous_event_status( node, EVENT_INCOMPLETE );
23089  break;
23090 
23091  case OP_EVENT_TRUE:
23092  case OP_EVENT_FALSE:
23093  sexp_val = sexp_event_status( node, (op_num == OP_EVENT_TRUE?1:0) );
23094  if ((sexp_val != SEXP_TRUE) && (sexp_val != SEXP_KNOWN_TRUE))
23095  Sexp_useful_number = 0; // indicate sexp isn't current yet
23096  break;
23097 
23098  case OP_EVENT_TRUE_DELAY:
23099  case OP_EVENT_FALSE_DELAY:
23100  sexp_val = sexp_event_delay_status( node, (op_num == OP_EVENT_TRUE_DELAY?1:0) );
23101  break;
23102 
23105  sexp_val = sexp_event_delay_status( node, (op_num == OP_EVENT_TRUE_MSECS_DELAY?1:0), true );
23106  break;
23107 
23108  case OP_GOAL_TRUE_DELAY:
23109  case OP_GOAL_FALSE_DELAY:
23110  sexp_val = sexp_goal_delay_status( node, (op_num == OP_GOAL_TRUE_DELAY?1:0) );
23111  break;
23112 
23113  case OP_EVENT_INCOMPLETE:
23114  sexp_val = sexp_event_incomplete(node);
23115  if ((sexp_val != SEXP_TRUE) && (sexp_val != SEXP_KNOWN_TRUE))
23116  Sexp_useful_number = 0; // indicate sexp isn't current yet
23117  break;
23118 
23119  case OP_GOAL_INCOMPLETE:
23120  sexp_val = sexp_goal_incomplete(node);
23121  break;
23122 
23123  // destroy type sexpressions
23124  case OP_IS_DESTROYED:
23125  sexp_val = sexp_is_destroyed( node, NULL );
23126  break;
23127 
23129  sexp_val = sexp_was_destroyed_by_delay(node);
23130  break;
23131 
23133  sexp_val = sexp_is_subsystem_destroyed(node);
23134  break;
23135 
23136  case OP_HAS_ARRIVED:
23137  sexp_val = sexp_has_arrived( node, NULL );
23138  break;
23139 
23140  case OP_HAS_DEPARTED:
23141  sexp_val = sexp_has_departed( node, NULL );
23142  break;
23143 
23144  case OP_IS_DISABLED:
23145  sexp_val = sexp_is_disabled( node, NULL );
23146  break;
23147 
23148  case OP_IS_DISARMED:
23149  sexp_val = sexp_is_disarmed( node, NULL );
23150  break;
23151 
23152  case OP_WAYPOINTS_DONE:
23153  sexp_val = sexp_are_waypoints_done(node);
23154  break;
23155 
23156  // objective operators that use a delay
23157  case OP_IS_DESTROYED_DELAY:
23158  sexp_val = sexp_is_destroyed_delay(node);
23159  break;
23160 
23162  sexp_val = sexp_is_subsystem_destroyed_delay(node);
23163  break;
23164 
23165  case OP_HAS_DOCKED:
23166  case OP_HAS_UNDOCKED:
23167  case OP_HAS_DOCKED_DELAY:
23168  case OP_HAS_UNDOCKED_DELAY:
23169  sexp_val = sexp_has_docked_or_undocked(node, op_num);
23170  break;
23171 
23172  case OP_HAS_ARRIVED_DELAY:
23173  sexp_val = sexp_has_arrived_delay(node);
23174  break;
23175 
23176  case OP_HAS_DEPARTED_DELAY:
23177  sexp_val = sexp_has_departed_delay(node);
23178  break;
23179 
23180  case OP_IS_DISABLED_DELAY:
23181  sexp_val = sexp_is_disabled_delay(node);
23182  break;
23183 
23184  case OP_IS_DISARMED_DELAY:
23185  sexp_val = sexp_is_disarmed_delay(node);
23186  break;
23187 
23189  sexp_val = sexp_are_waypoints_done_delay(node);
23190  break;
23191 
23193  sexp_val = sexp_ship_type_destroyed(node);
23194  break;
23195 
23196  // time based sexpressions
23197  case OP_HAS_TIME_ELAPSED:
23198  sexp_val = sexp_has_time_elapsed(node);
23199  break;
23200 
23201  case OP_MODIFY_VARIABLE:
23202  sexp_modify_variable(node);
23203  sexp_val = SEXP_TRUE; // SEXP_TRUE means only do once.
23204  break;
23205 
23207  sexp_val = sexp_get_variable_by_index(node);
23208  break;
23209 
23212  sexp_val = SEXP_TRUE;
23213  break;
23214 
23217  sexp_val = SEXP_TRUE;
23218  break;
23219 
23222  sexp_val = SEXP_TRUE;
23223  break;
23224 
23226  sexp_val = sexp_time_destroyed(node);
23227  break;
23228 
23230  sexp_val = sexp_time_wing_destroyed(node);
23231  break;
23232 
23233  case OP_TIME_SHIP_ARRIVED:
23234  sexp_val = sexp_time_ship_arrived(node);
23235  break;
23236 
23237  case OP_TIME_WING_ARRIVED:
23238  sexp_val = sexp_time_wing_arrived(node);
23239  break;
23240 
23241  case OP_TIME_SHIP_DEPARTED:
23242  sexp_val = sexp_time_ship_departed(node);
23243  break;
23244 
23245  case OP_TIME_WING_DEPARTED:
23246  sexp_val = sexp_time_wing_departed(node);
23247  break;
23248 
23249  case OP_MISSION_TIME:
23250  sexp_val = sexp_mission_time();
23251  break;
23252 
23253  case OP_MISSION_TIME_MSECS:
23254  sexp_val = sexp_mission_time_msecs();
23255  break;
23256 
23257  case OP_TIME_DOCKED:
23258  sexp_val = sexp_time_docked(node);
23259  break;
23260 
23261  case OP_TIME_UNDOCKED:
23262  sexp_val = sexp_time_undocked(node);
23263  break;
23264 
23265  case OP_AFTERBURNER_LEFT:
23266  sexp_val = sexp_get_energy_pct(node, op_num);
23267  break;
23268 
23269  case OP_WEAPON_ENERGY_LEFT:
23270  sexp_val = sexp_get_energy_pct(node, op_num);
23271  break;
23272 
23273  case OP_SHIELDS_LEFT:
23274  sexp_val = sexp_shields_left(node);
23275  break;
23276 
23277  case OP_HITS_LEFT:
23278  sexp_val = sexp_hits_left(node);
23279  break;
23280 
23282  sexp_val = sexp_hits_left_subsystem(node);
23283  break;
23284 
23286  sexp_val = sexp_hits_left_subsystem_generic(node);
23287  break;
23288 
23290  sexp_val = sexp_hits_left_subsystem_specific(node);
23291  break;
23292 
23293  case OP_SIM_HITS_LEFT:
23294  sexp_val = sexp_sim_hits_left(node);
23295  break;
23296 
23298  sexp_val = sexp_special_warp_dist(node);
23299  break;
23300 
23301  case OP_DISTANCE:
23302  sexp_val = sexp_distance(node);
23303  break;
23304 
23305  case OP_DISTANCE_SUBSYSTEM:
23306  sexp_val = sexp_distance_subsystem(node);
23307  break;
23308 
23309  case OP_NUM_WITHIN_BOX:
23310  sexp_val = sexp_num_within_box(node);
23311  break;
23312 
23313  case OP_IS_IN_BOX:
23314  sexp_val = sexp_is_in_box(node);
23315  break;
23316 
23317  case OP_IS_IN_MISSION:
23318  sexp_val = sexp_is_in_mission(node);
23319  break;
23320 
23321  case OP_IS_SHIP_VISIBLE:
23322  sexp_val = sexp_is_ship_visible(node);
23323  break;
23324 
23325  case OP_IS_SHIP_STEALTHY:
23326  sexp_val = sexp_is_ship_stealthy(node);
23327  break;
23328 
23330  sexp_val = sexp_is_friendly_stealth_visible(node);
23331  break;
23332 
23333  case OP_TEAM_SCORE:
23334  sexp_val = sexp_team_score(node);
23335  break;
23336 
23337  case OP_LAST_ORDER_TIME:
23338  sexp_val = sexp_last_order_time(node);
23339  break;
23340 
23341  case OP_NUM_PLAYERS:
23342  sexp_val = sexp_num_players();
23343  break;
23344 
23346  sexp_val = sexp_skill_level_at_least(node);
23347  break;
23348 
23349  case OP_IS_CARGO_KNOWN:
23350  case OP_CARGO_KNOWN_DELAY:
23351  sexp_val = sexp_is_cargo_known( node, (op_num==OP_IS_CARGO_KNOWN)?0:1 );
23352  break;
23353 
23355  sexp_val = sexp_has_been_tagged_delay(node);
23356  break;
23357 
23358  case OP_ARE_SHIP_FLAGS_SET:
23359  sexp_val = sexp_are_ship_flags_set(node);
23360  break;
23361 
23363  sexp_val = sexp_cap_subsys_cargo_known_delay(node);
23364  break;
23365 
23367  sexp_val = sexp_was_promotion_granted(node);
23368  break;
23369 
23370  case OP_WAS_MEDAL_GRANTED:
23371  sexp_val = sexp_was_medal_granted(node);
23372  break;
23373 
23374  case OP_GET_DAMAGE_CAUSED:
23375  sexp_val = sexp_get_damage_caused(node);
23376  break;
23377 
23384  break;
23385 
23386  case OP_DEPART_NODE_DELAY:
23387  sexp_val = sexp_depart_node_delay(node);
23388  break;
23389 
23391  sexp_val = sexp_destroyed_departed_delay(node);
23392  break;
23393 
23394  // conditional sexpressions
23395  case OP_WHEN:
23396  case OP_WHEN_ARGUMENT:
23397  case OP_IF_THEN_ELSE:
23398  sexp_val = eval_when( node, op_num );
23399  break;
23400 
23401  case OP_PERFORM_ACTIONS:
23402  sexp_val = eval_perform_actions( node );
23403  break;
23404 
23405  case OP_COND:
23406  sexp_val = eval_cond(node);
23407  break;
23408 
23409  // Goober5000: special case; evaluate like when, but flush the sexp tree
23410  // and return SEXP_NAN so this will always be re-evaluated
23411  case OP_EVERY_TIME:
23413  eval_when( node, op_num );
23414  flush_sexp_tree(node);
23415  sexp_val = SEXP_NAN;
23416  break;
23417 
23418  // Goober5000
23419  case OP_ANY_OF:
23420  sexp_val = eval_any_of( cur_node, referenced_node );
23421  break;
23422 
23423  // Goober5000
23424  case OP_EVERY_OF:
23425  sexp_val = eval_every_of( cur_node, referenced_node );
23426  break;
23427 
23428  // Goober5000 and Karajorma
23429  case OP_RANDOM_OF:
23430  case OP_RANDOM_MULTIPLE_OF:
23431  sexp_val = eval_random_of( cur_node, referenced_node, (op_num == OP_RANDOM_MULTIPLE_OF) );
23432  break;
23433 
23434  // Goober5000
23435  case OP_NUMBER_OF:
23436  sexp_val = eval_number_of( cur_node, referenced_node );
23437  break;
23438 
23439  // Karajorma
23440  case OP_IN_SEQUENCE:
23441  sexp_val = eval_in_sequence( cur_node, referenced_node );
23442  break;
23443 
23444  // Goober5000
23445  case OP_FOR_COUNTER:
23446  sexp_val = eval_for_counter( cur_node, referenced_node );
23447  break;
23448 
23449  // Karajorma
23453  sexp_val = SEXP_TRUE;
23454  break;
23455 
23456  // Goober5000
23458  case OP_VALIDATE_ARGUMENT:
23460  sexp_val = SEXP_TRUE;
23461  break;
23462 
23464  // do-for-valid-arguments should only ever be called within eval_when()
23465  Int3();
23466  break;
23467 
23469  sexp_val = sexp_num_valid_arguments( cur_node );
23470  break;
23471 
23472  // sexpressions with side effects
23473  case OP_CHANGE_IFF:
23474  sexp_change_iff(node);
23475  sexp_val = SEXP_TRUE;
23476  break;
23477 
23478  case OP_ADD_SHIP_GOAL:
23479  sexp_add_ship_goal(node);
23480  sexp_val = SEXP_TRUE;
23481  break;
23482 
23483  case OP_ADD_WING_GOAL:
23484  sexp_add_wing_goal(node);
23485  sexp_val = SEXP_TRUE;
23486  break;
23487 
23488  case OP_ADD_GOAL:
23489  sexp_add_goal(node);
23490  sexp_val = SEXP_TRUE;
23491  break;
23492 
23493  case OP_REMOVE_GOAL:
23494  sexp_remove_goal(node);
23495  sexp_val = SEXP_TRUE;
23496  break;
23497 
23498  case OP_CLEAR_SHIP_GOALS:
23499  sexp_clear_ship_goals(node);
23500  sexp_val = SEXP_TRUE;
23501  break;
23502 
23503  case OP_CLEAR_WING_GOALS:
23504  sexp_clear_wing_goals(node);
23505  sexp_val = SEXP_TRUE;
23506  break;
23507 
23508  case OP_CLEAR_GOALS:
23509  sexp_clear_goals(node);
23510  sexp_val = SEXP_TRUE;
23511  break;
23512 
23513  case OP_PROTECT_SHIP:
23514  case OP_UNPROTECT_SHIP:
23515  sexp_protect_ships(node, (op_num == OP_PROTECT_SHIP));
23516  sexp_val = SEXP_TRUE;
23517  break;
23518 
23519  case OP_BEAM_PROTECT_SHIP:
23521  sexp_beam_protect_ships(node, (op_num == OP_BEAM_PROTECT_SHIP));
23522  sexp_val = SEXP_TRUE;
23523  break;
23524 
23528  sexp_val = SEXP_TRUE;
23529  break;
23530 
23531  case OP_SHIP_STEALTHY:
23532  case OP_SHIP_UNSTEALTHY:
23533  sexp_ships_stealthy(node, (op_num == OP_SHIP_STEALTHY));
23534  sexp_val = SEXP_TRUE;
23535  break;
23536 
23540  sexp_val = SEXP_TRUE;
23541  break;
23542 
23543  case OP_SHIP_INVISIBLE:
23544  case OP_SHIP_VISIBLE:
23545  sexp_ships_visible(node, (op_num == OP_SHIP_VISIBLE));
23546  sexp_val = SEXP_TRUE;
23547  break;
23548 
23549  // Goober5000
23550  case OP_SHIP_TAG:
23551  case OP_SHIP_UNTAG:
23552  sexp_ship_tag(node, (op_num == OP_SHIP_TAG));
23553  sexp_val = SEXP_TRUE;
23554  break;
23555 
23558  sexp_val = SEXP_TRUE;
23559  break;
23560 
23563  sexp_val = SEXP_TRUE;
23564  break;
23565 
23566  case OP_SET_DEATH_MESSAGE:
23567  sexp_set_death_message(node);
23568  sexp_val = SEXP_TRUE;
23569  break;
23570 
23571  case OP_ALTER_SHIP_FLAG:
23572  sexp_alter_ship_flag(node);
23573  sexp_val = SEXP_TRUE;
23574  break;
23575 
23576  case OP_SHIP_VULNERABLE:
23577  case OP_SHIP_INVULNERABLE:
23578  sexp_ships_invulnerable(node, (op_num == OP_SHIP_INVULNERABLE));
23579  sexp_val = SEXP_TRUE;
23580  break;
23581 
23585  sexp_val = SEXP_TRUE;
23586  break;
23587 
23588  case OP_SHIP_GUARDIAN:
23589  case OP_SHIP_NO_GUARDIAN:
23590  sexp_ships_guardian(node, (op_num == OP_SHIP_GUARDIAN));
23591  sexp_val = SEXP_TRUE;
23592  break;
23593 
23596  sexp_val = SEXP_TRUE;
23597  break;
23598 
23601  sexp_val = SEXP_TRUE;
23602  break;
23603 
23606  sexp_val = SEXP_TRUE;
23607  break;
23608 
23611  sexp_val = SEXP_TRUE;
23612  break;
23613 
23615  sexp_val = SEXP_TRUE;
23617  break;
23618 
23620  sexp_val = SEXP_TRUE;
23622  break;
23623 
23626  sexp_val = SEXP_TRUE;
23627  break;
23628 
23631  sexp_val = SEXP_TRUE;
23632  break;
23633 
23636  sexp_val = SEXP_TRUE;
23637  break;
23638 
23641  sexp_val = SEXP_TRUE;
23642  break;
23643 
23644  case OP_SHIP_CREATE:
23645  sexp_ship_create(node);
23646  sexp_val = SEXP_TRUE;
23647  break;
23648 
23649  case OP_WEAPON_CREATE:
23650  sexp_weapon_create(node);
23651  sexp_val = SEXP_TRUE;
23652  break;
23653 
23654  case OP_SHIP_VANISH:
23655  sexp_ship_vanish(node);
23656  sexp_val = SEXP_TRUE;
23657  break;
23658 
23659  case OP_DESTROY_INSTANTLY:
23660  sexp_destroy_instantly(node);
23661  sexp_val = SEXP_TRUE;
23662  break;
23663 
23664  //-Sesquipedalian
23665  case OP_SHIELDS_ON:
23666  case OP_SHIELDS_OFF:
23667  sexp_shields_off(node, (op_num == OP_SHIELDS_OFF));
23668  sexp_val = SEXP_TRUE;
23669  break;
23670 
23671  //-Sesquipedalian
23672  case OP_KAMIKAZE:
23673  sexp_kamikaze(node, (op_num == OP_KAMIKAZE));
23674  sexp_val = SEXP_TRUE;
23675  break;
23676 
23677  case OP_SET_CARGO:
23678  sexp_set_cargo(node);
23679  sexp_val = SEXP_TRUE;
23680  break;
23681 
23682  case OP_IS_CARGO:
23683  sexp_val = sexp_is_cargo(node);
23684  break;
23685 
23686  case OP_CHANGE_AI_CLASS:
23687  sexp_change_ai_class(node);
23688  sexp_val = SEXP_TRUE;
23689  break;
23690 
23691  case OP_IS_AI_CLASS:
23692  sexp_val = sexp_is_ai_class(node);
23693  break;
23694 
23695  case OP_IS_SHIP_TYPE:
23696  sexp_val = sexp_is_ship_type(node);
23697  break;
23698 
23699  case OP_IS_SHIP_CLASS:
23700  sexp_val = sexp_is_ship_class(node);
23701  break;
23702 
23703  case OP_CHANGE_SOUNDTRACK:
23704  sexp_change_soundtrack(node);
23705  sexp_val = SEXP_TRUE;
23706  break;
23707 
23710  sexp_val = SEXP_TRUE;
23711  break;
23712 
23715  sexp_val = SEXP_TRUE;
23716  break;
23717 
23720  sexp_val = SEXP_TRUE;
23721  break;
23722 
23725  sexp_val = SEXP_TRUE;
23726  break;
23727 
23730  sexp_val = SEXP_TRUE;
23731  break;
23732 
23735  sexp_val = SEXP_TRUE;
23736  break;
23737 
23740  sexp_val = SEXP_TRUE;
23741  break;
23742 
23743  case OP_HUD_DISABLE:
23744  sexp_hud_disable(node);
23745  sexp_val = SEXP_TRUE;
23746  break;
23747 
23750  sexp_val = SEXP_TRUE;
23751  break;
23752 
23753  case OP_HUD_SET_TEXT:
23754  sexp_hud_set_text(node);
23755  sexp_val = SEXP_TRUE;
23756  break;
23757 
23758  case OP_HUD_SET_TEXT_NUM:
23759  sexp_hud_set_text_num(node);
23760  sexp_val = SEXP_TRUE;
23761  break;
23762 
23763  case OP_HUD_SET_COORDS:
23764  sexp_hud_set_coords(node);
23765  sexp_val = SEXP_TRUE;
23766  break;
23767 
23768  case OP_HUD_SET_FRAME:
23769  sexp_hud_set_frame(node);
23770  sexp_val = SEXP_TRUE;
23771  break;
23772 
23773  case OP_HUD_SET_COLOR:
23774  sexp_hud_set_color(node);
23775  sexp_val = SEXP_TRUE;
23776  break;
23777 
23780  sexp_val = SEXP_TRUE;
23781  break;
23782 
23783  case OP_HUD_DISPLAY_GAUGE:
23784  sexp_hud_display_gauge(node);
23785  sexp_val = SEXP_TRUE;
23786  break;
23787 
23788  case OP_HUD_SET_MESSAGE:
23789  sexp_hud_set_message(node);
23790  sexp_val = SEXP_TRUE;
23791  break;
23792 
23793  // Goober5000
23794  case OP_PLAYER_USE_AI:
23795  case OP_PLAYER_NOT_USE_AI:
23797  sexp_val = SEXP_TRUE;
23798  break;
23799 
23800  //Karajorma
23801  case OP_ALLOW_TREASON:
23802  sexp_allow_treason(node);
23803  sexp_val = SEXP_TRUE;
23804  break;
23805 
23806  //Karajorma
23807  case OP_SET_PLAYER_ORDERS:
23808  sexp_set_player_orders(node);
23809  sexp_val = SEXP_TRUE;
23810  break;
23811 
23812  // Goober5000
23813  case OP_EXPLOSION_EFFECT:
23814  sexp_explosion_effect(node);
23815  sexp_val = SEXP_TRUE;
23816  break;
23817 
23818  // Goober5000
23819  case OP_WARP_EFFECT:
23820  sexp_warp_effect(node);
23821  sexp_val = SEXP_TRUE;
23822  break;
23823 
23824  case OP_SEND_MESSAGE:
23825  sexp_send_message(node);
23826  sexp_val = SEXP_TRUE;
23827  break;
23828 
23829  // Karajorma
23833  sexp_val = SEXP_TRUE;
23834  break;
23835 
23836  case OP_SET_PERSONA:
23837  sexp_set_persona (node);
23838  sexp_val = SEXP_TRUE;
23839  break;
23840 
23841  case OP_SET_MISSION_MOOD:
23842  sexp_set_mission_mood (node);
23843  sexp_val = SEXP_TRUE;
23844  break;
23845 
23846  case OP_SEND_MESSAGE_LIST:
23847  sexp_send_message_list(node);
23848  sexp_val = SEXP_TRUE;
23849  break;
23850 
23853  sexp_val = SEXP_TRUE;
23854  break;
23855 
23856  case OP_SELF_DESTRUCT:
23857  sexp_self_destruct(node);
23858  sexp_val = SEXP_TRUE;
23859  break;
23860 
23861  case OP_NEXT_MISSION:
23862  sexp_next_mission(node);
23863  sexp_val = SEXP_TRUE;
23864  break;
23865 
23866  case OP_END_OF_CAMPAIGN:
23867  sexp_end_of_campaign(node);
23868  sexp_val = SEXP_TRUE;
23869  break;
23870 
23871  case OP_END_CAMPAIGN:
23872  sexp_end_campaign(node);
23873  sexp_val = SEXP_TRUE;
23874  break;
23875 
23876  case OP_SABOTAGE_SUBSYSTEM:
23878  sexp_val = SEXP_TRUE;
23879  break;
23880 
23881  case OP_REPAIR_SUBSYSTEM:
23882  sexp_repair_subsystem(node);
23883  sexp_val = SEXP_TRUE;
23884  break;
23885 
23888  sexp_val = SEXP_TRUE;
23889  break;
23890 
23893  sexp_val = SEXP_TRUE;
23894  break;
23895 
23896  case OP_INVALIDATE_GOAL:
23897  case OP_VALIDATE_GOAL:
23898  sexp_change_goal_validity( node, (op_num==OP_INVALIDATE_GOAL?0:1) );
23899  sexp_val = SEXP_TRUE;
23900  break;
23901 
23902  case OP_TRANSFER_CARGO:
23903  sexp_transfer_cargo(node);
23904  sexp_val = SEXP_TRUE;
23905  break;
23906 
23907  case OP_EXCHANGE_CARGO:
23908  sexp_exchange_cargo(node);
23909  sexp_val = SEXP_TRUE;
23910  break;
23911 
23912 
23913  case OP_JETTISON_CARGO:
23914  sexp_jettison_cargo(node);
23915  sexp_val = SEXP_TRUE;
23916  break;
23917 
23918  case OP_SET_DOCKED:
23919  sexp_set_docked(node);
23920  sexp_val = SEXP_TRUE;
23921  break;
23922 
23923  case OP_CARGO_NO_DEPLETE:
23924  sexp_cargo_no_deplete(node);
23925  sexp_val = SEXP_TRUE;
23926  break;
23927 
23928  case OP_SET_SCANNED: // Goober5000
23929  case OP_SET_UNSCANNED:
23930  sexp_set_scanned_unscanned(node, op_num == OP_SET_SCANNED);
23931  sexp_val = SEXP_TRUE;
23932  break;
23933 
23936  sexp_val = SEXP_TRUE;
23937  break;
23938 
23939  //-WMC
23940  case OP_MISSION_SET_NEBULA:
23942  sexp_val = SEXP_TRUE;
23943  break;
23944 
23947  sexp_val = SEXP_TRUE;
23948  break;
23949 
23952  sexp_val = SEXP_TRUE;
23953  break;
23954 
23957  sexp_val = SEXP_TRUE;
23958  break;
23959 
23960  case OP_ADD_SUN_BITMAP:
23961  sexp_add_sun_bitmap(node);
23962  sexp_val = SEXP_TRUE;
23963  break;
23964 
23965  case OP_REMOVE_SUN_BITMAP:
23966  sexp_remove_sun_bitmap(node);
23967  sexp_val = SEXP_TRUE;
23968  break;
23969 
23972  sexp_val = SEXP_TRUE;
23973  break;
23974 
23975  case OP_NEBULA_TOGGLE_POOF:
23977  sexp_val = SEXP_TRUE;
23978  break;
23979 
23982  sexp_val = SEXP_TRUE;
23983  break;
23984 
23985  case OP_END_MISSION:
23986  sexp_end_mission(node);
23987  sexp_val = SEXP_TRUE;
23988  break;
23989 
23990  // Goober5000
23993  sexp_val = SEXP_TRUE;
23994  break;
23995 
23996  // Goober5000
23997  case OP_FORCE_JUMP:
23998  sexp_force_jump();
23999  sexp_val = SEXP_TRUE;
24000  break;
24001 
24002  // sexpressions for setting flag for good/bad time for someone to reasm
24003  case OP_GOOD_REARM_TIME:
24005  sexp_val = SEXP_TRUE;
24006  break;
24007 
24008  case OP_GRANT_PROMOTION:
24010  sexp_val = SEXP_TRUE;
24011  break;
24012 
24013  case OP_GRANT_MEDAL:
24014  sexp_grant_medal(node);
24015  sexp_val = SEXP_TRUE;
24016  break;
24017 
24018  case OP_SHIP_VAPORIZE:
24019  case OP_SHIP_NO_VAPORIZE:
24020  sexp_ships_vaporize( node, (op_num == OP_SHIP_VAPORIZE) );
24021  sexp_val = SEXP_TRUE;
24022  break;
24023 
24026  sexp_val = SEXP_TRUE;
24027  break;
24028 
24030  case OP_COLLIDE_INVISIBLE:
24032  sexp_val = SEXP_TRUE;
24033  break;
24034 
24035  case OP_SET_MOBILE:
24036  case OP_SET_IMMOBILE:
24037  sexp_set_immobile(node, (op_num == OP_SET_IMMOBILE));
24038  sexp_val = SEXP_TRUE;
24039  break;
24040 
24041  case OP_IGNORE_KEY:
24042  sexp_ignore_key(node);
24043  sexp_val = SEXP_TRUE;
24044  break;
24045 
24046  // Goober5000 - sigh, was this messed up all along?
24047  case OP_WARP_BROKEN:
24048  case OP_WARP_NOT_BROKEN:
24049  case OP_WARP_NEVER:
24050  case OP_WARP_ALLOWED:
24051  sexp_deal_with_warp( node, (op_num==OP_WARP_BROKEN) || (op_num==OP_WARP_NOT_BROKEN),
24052  (op_num==OP_WARP_BROKEN) || (op_num==OP_WARP_NEVER) );
24053  sexp_val = SEXP_TRUE;
24054  break;
24055 
24056  // Goober5000
24057  case OP_SET_SUBSPACE_DRIVE:
24059  break;
24060 
24063  sexp_val = SEXP_TRUE;
24064  break;
24065 
24066  // sexpressions to allow shpis/weapons during the course of a mission
24067  case OP_ALLOW_SHIP:
24068  sexp_allow_ship(node);
24069  sexp_val = SEXP_TRUE;
24070  break;
24071 
24072  case OP_ALLOW_WEAPON:
24073  sexp_allow_weapon(node);
24074  sexp_val = SEXP_TRUE;
24075  break;
24076 
24077  case OP_TECH_ADD_SHIP:
24078  sexp_tech_add_ship(node);
24079  sexp_val = SEXP_TRUE;
24080  break;
24081 
24082  case OP_TECH_ADD_WEAPON:
24083  sexp_tech_add_weapon(node);
24084  sexp_val = SEXP_TRUE;
24085  break;
24086 
24087  case OP_TECH_ADD_INTEL:
24088  sexp_tech_add_intel(node);
24089  sexp_val = SEXP_TRUE;
24090  break;
24091 
24094  sexp_val = SEXP_TRUE;
24095  break;
24096 
24099  sexp_val = SEXP_TRUE;
24100  break;
24101 
24104  sexp_val = SEXP_TRUE;
24105  break;
24106 
24107  case OP_CHANGE_TEAM_SCORE:
24108  sexp_change_team_score(node);
24109  sexp_val = SEXP_TRUE;
24110  break;
24111 
24112  // in the case of a red_alert mission, simply call the red alert function to close
24113  // the current campaign's mission and move forward to the next mission
24114  case OP_RED_ALERT:
24116  sexp_val = SEXP_TRUE;
24117  break;
24118 
24119  case OP_SET_OBJECT_SPEED_X:
24120  case OP_SET_OBJECT_SPEED_Y:
24121  case OP_SET_OBJECT_SPEED_Z:
24123  sexp_val = SEXP_TRUE;
24124  break;
24125 
24126  case OP_GET_OBJECT_SPEED_X:
24127  case OP_GET_OBJECT_SPEED_Y:
24128  case OP_GET_OBJECT_SPEED_Z:
24129  sexp_val = sexp_get_object_speed(node, op_num - OP_GET_OBJECT_SPEED_X);
24130  break;
24131 
24132  case OP_GET_OBJECT_X:
24133  case OP_GET_OBJECT_Y:
24134  case OP_GET_OBJECT_Z:
24135  sexp_val = sexp_get_object_coordinate(node, op_num - OP_GET_OBJECT_X);
24136  break;
24137 
24138  case OP_GET_OBJECT_PITCH:
24139  case OP_GET_OBJECT_BANK:
24140  case OP_GET_OBJECT_HEADING:
24141  sexp_val = sexp_get_object_angle(node, op_num - OP_GET_OBJECT_PITCH);
24142  break;
24143 
24146  sexp_val = SEXP_TRUE;
24147  break;
24148 
24151  sexp_val = SEXP_TRUE;
24152  break;
24153 
24154  case OP_SET_OBJECT_FACING:
24157  sexp_val = SEXP_TRUE;
24158  break;
24159 
24160  case OP_SHIP_MANEUVER:
24161  case OP_SHIP_ROT_MANEUVER:
24162  case OP_SHIP_LAT_MANEUVER:
24163  sexp_set_ship_maneuver(node, op_num);
24164  sexp_val = SEXP_TRUE;
24165  break;
24166 
24167  // training operators
24168  case OP_KEY_PRESSED:
24169  sexp_val = sexp_key_pressed(node);
24170  break;
24171 
24172  case OP_SPECIAL_CHECK:
24173  sexp_val = sexp_special_training_check(node);
24174  break;
24175 
24176  case OP_KEY_RESET:
24177  sexp_key_reset(node);
24178  sexp_val = SEXP_KNOWN_TRUE; // only do it first time in repeating events.
24179  break;
24180 
24181  case OP_KEY_RESET_MULTIPLE:
24182  sexp_key_reset(node);
24183  sexp_val = SEXP_TRUE;
24184  break;
24185 
24186  case OP_MISSILE_LOCKED:
24187  sexp_val = sexp_missile_locked(node);
24188  break;
24189 
24190  case OP_TARGETED:
24191  sexp_val = sexp_targeted(node);
24192  break;
24193 
24194  case OP_NODE_TARGETED:
24195  sexp_val = sexp_node_targeted(node);
24196  break;
24197 
24198  case OP_SPEED:
24199  sexp_val = sexp_speed(node);
24200  break;
24201 
24202  case OP_GET_THROTTLE_SPEED:
24203  sexp_val = sexp_get_throttle_speed(node);
24204  break;
24205 
24208  sexp_val = SEXP_TRUE;
24209  break;
24210 
24211  case OP_PRIMARIES_DEPLETED:
24212  sexp_val = sexp_primaries_depleted(node);
24213  break;
24214 
24216  sexp_val = sexp_secondaries_depleted(node);
24217  break;
24218 
24219  case OP_FACING:
24220  sexp_val = sexp_facing(node);
24221  break;
24222 
24223  case OP_IS_FACING:
24224  sexp_val = sexp_is_facing(node);
24225  break;
24226 
24227  case OP_FACING2:
24228  sexp_val = sexp_facing2(node);
24229  break;
24230 
24231  case OP_ORDER:
24232  sexp_val = sexp_order(node);
24233  break;
24234 
24235  case OP_QUERY_ORDERS:
24236  sexp_val = sexp_query_orders(node);
24237  break;
24238 
24239  // Karajorma
24240  case OP_RESET_ORDERS:
24241  sexp_reset_orders(node);
24242  sexp_val = SEXP_TRUE;
24243  break;
24244 
24245  case OP_WAYPOINT_MISSED:
24246  sexp_val = sexp_waypoint_missed();
24247  break;
24248 
24249  case OP_WAYPOINT_TWICE:
24250  sexp_val = sexp_waypoint_twice();
24251  break;
24252 
24253  case OP_PATH_FLOWN:
24254  sexp_val = sexp_path_flown();
24255  break;
24256 
24257  case OP_TRAINING_MSG:
24259  sexp_val = SEXP_TRUE;
24260  break;
24261 
24262  case OP_FLASH_HUD_GAUGE:
24263  sexp_flash_hud_gauge(node);
24264  sexp_val = SEXP_TRUE;
24265  break;
24266 
24269  sexp_val = SEXP_TRUE;
24270  break;
24271 
24274  sexp_val = SEXP_TRUE;
24275  break;
24276 
24277  // Karajorma
24278  case OP_STRING_TO_INT:
24279  sexp_val = sexp_string_to_int(node);
24280  break;
24281 
24282  // Goober5000
24283  case OP_INT_TO_STRING:
24284  sexp_int_to_string(node);
24285  sexp_val = SEXP_TRUE;
24286  break;
24287 
24288  // Goober5000
24289  case OP_STRING_CONCATENATE:
24291  sexp_val = SEXP_TRUE;
24292  break;
24293 
24294  // Goober5000
24297  sexp_val = SEXP_TRUE;
24298  break;
24299 
24300  // Goober5000
24303  sexp_val = SEXP_TRUE;
24304  break;
24305 
24306  // Goober5000
24307  case OP_STRING_GET_LENGTH:
24308  sexp_val = sexp_string_get_length(node);
24309  break;
24310 
24311  // Karajorma
24312  case OP_DEBUG:
24313  sexp_debug(node);
24314  sexp_val = SEXP_TRUE;
24315  break;
24316 
24317  case 0: // zero represents a non-operator
24318  return eval_num(cur_node);
24319 
24320  case OP_NOP:
24321  sexp_val = SEXP_TRUE;
24322  break;
24323 
24324  case OP_BEAM_FIRE:
24325  case OP_BEAM_FIRE_COORDS:
24326  sexp_beam_fire(node, op_num == OP_BEAM_FIRE_COORDS);
24327  sexp_val = SEXP_TRUE;
24328  break;
24329 
24330  case OP_BEAM_FLOATING_FIRE:
24332  sexp_val = SEXP_TRUE;
24333  break;
24334 
24335  case OP_IS_TAGGED:
24336  sexp_val = sexp_is_tagged(node);
24337  break;
24338 
24339  case OP_IS_PLAYER:
24340  sexp_val = sexp_is_player(node);
24341  break;
24342 
24343  case OP_NUM_KILLS:
24344  case OP_NUM_ASSISTS:
24345  case OP_SHIP_SCORE:
24346  case OP_SHIP_DEATHS:
24347  case OP_RESPAWNS_LEFT:
24348  sexp_val = sexp_return_player_data(node, op_num);
24349  break;
24350 
24351  case OP_SET_RESPAWNS:
24352  sexp_set_respawns(node);
24353  sexp_val = SEXP_TRUE;
24354  break;
24355 
24356  case OP_REMOVE_WEAPONS:
24357  sexp_remove_weapons(node);
24358  sexp_val = SEXP_TRUE;
24359  break;
24360 
24361  case OP_NUM_TYPE_KILLS:
24362  sexp_val = sexp_num_type_kills(node);
24363  break;
24364 
24365  case OP_NUM_CLASS_KILLS:
24366  sexp_val = sexp_num_class_kills(node);
24367  break;
24368 
24369  case OP_BEAM_FREE:
24370  sexp_val = SEXP_TRUE;
24371  sexp_beam_free(node);
24372  break;
24373 
24374  case OP_BEAM_FREE_ALL:
24375  sexp_val = SEXP_TRUE;
24376  sexp_beam_free_all(node);
24377  break;
24378 
24379  case OP_BEAM_LOCK:
24380  sexp_val = SEXP_TRUE;
24381  sexp_beam_lock(node);
24382  break;
24383 
24384  case OP_BEAM_LOCK_ALL:
24385  sexp_val = SEXP_TRUE;
24386  sexp_beam_lock_all(node);
24387  break;
24388 
24389  case OP_TURRET_FREE:
24390  sexp_val = SEXP_TRUE;
24391  sexp_turret_free(node);
24392  break;
24393 
24394  case OP_TURRET_FREE_ALL:
24395  sexp_val = SEXP_TRUE;
24396  sexp_turret_free_all(node);
24397  break;
24398 
24399  case OP_TURRET_LOCK:
24400  sexp_val = SEXP_TRUE;
24401  sexp_turret_lock(node);
24402  break;
24403 
24404  case OP_TURRET_LOCK_ALL:
24405  sexp_val = SEXP_TRUE;
24406  sexp_turret_lock_all(node);
24407  break;
24408 
24410  sexp_val = SEXP_TRUE;
24412  break;
24413 
24415  sexp_val = SEXP_TRUE;
24417  break;
24418 
24420  sexp_val = SEXP_TRUE;
24422  break;
24423 
24425  sexp_val = SEXP_TRUE;
24427  break;
24428 
24430  sexp_val = SEXP_TRUE;
24432  break;
24433 
24435  sexp_val = SEXP_TRUE;
24437  break;
24438 
24439  case OP_SET_ARMOR_TYPE:
24440  sexp_val = SEXP_TRUE;
24441  sexp_set_armor_type(node);
24442  break;
24443 
24445  sexp_val = SEXP_TRUE;
24447  break;
24448 
24450  sexp_val = SEXP_TRUE;
24452  break;
24453 
24455  sexp_val = SEXP_TRUE;
24457  break;
24458 
24460  sexp_val = SEXP_TRUE;
24462  break;
24463 
24465  sexp_val = SEXP_TRUE;
24467  break;
24468 
24469  case OP_ADD_REMOVE_ESCORT:
24470  sexp_val = SEXP_TRUE;
24471  sexp_add_remove_escort(node);
24472  break;
24473 
24475  sexp_val = SEXP_TRUE;
24477  break;
24478 
24480  sexp_val = SEXP_TRUE;
24482  break;
24483 
24484  case OP_AWACS_SET_RADIUS:
24485  sexp_val = SEXP_TRUE;
24486  sexp_awacs_set_radius(node);
24487  break;
24488 
24491  sexp_val = SEXP_TRUE;
24492  break;
24493 
24494  case OP_CAP_WAYPOINT_SPEED:
24495  sexp_val = SEXP_TRUE;
24497  break;
24498 
24500  sexp_val = SEXP_TRUE;
24502  break;
24503 
24505  sexp_val = SEXP_TRUE;
24507  break;
24508 
24509  case OP_SUBSYS_SET_RANDOM:
24510  sexp_val = SEXP_TRUE;
24511  sexp_subsys_set_random(node);
24512  break;
24513 
24514  case OP_SUPERNOVA_START:
24515  sexp_val = SEXP_TRUE;
24516  sexp_supernova_start(node);
24517  break;
24518 
24519  case OP_SUPERNOVA_STOP:
24520  sexp_val = SEXP_TRUE;
24521  sexp_supernova_stop(node);
24522  break;
24523 
24524  case OP_SET_MOTION_DEBRIS:
24525  sexp_val = SEXP_TRUE;
24526  sexp_set_motion_debris(node);
24527  break;
24528 
24530  sexp_val = sexp_shield_recharge_pct(node);
24531  break;
24532 
24534  sexp_val = sexp_engine_recharge_pct(node);
24535  break;
24536 
24538  sexp_val = sexp_weapon_recharge_pct(node);
24539  break;
24540 
24541  case OP_GET_ETS_VALUE:
24542  sexp_val = sexp_get_ets_value(node);
24543  break;
24544 
24545  case OP_SET_ETS_VALUES:
24546  sexp_val = SEXP_TRUE;
24547  sexp_set_ets_values(node);
24548  break;
24549 
24550  case OP_SHIELD_QUAD_LOW:
24551  sexp_val = sexp_shield_quad_low(node);
24552  break;
24553 
24554  case OP_PRIMARY_AMMO_PCT:
24555  sexp_val = sexp_primary_ammo_pct(node);
24556  break;
24557 
24558  case OP_SECONDARY_AMMO_PCT:
24559  sexp_val = sexp_secondary_ammo_pct(node);
24560  break;
24561 
24562  // Karajorma
24563  case OP_GET_PRIMARY_AMMO:
24564  sexp_val = sexp_get_primary_ammo(node);
24565  break;
24566 
24567  // Karajorma
24568  case OP_GET_SECONDARY_AMMO:
24569  sexp_val = sexp_get_secondary_ammo(node);
24570  break;
24571 
24572  // Karajorma
24574  sexp_val = sexp_get_countermeasures(node);
24575  break;
24576 
24578  sexp_val = sexp_is_secondary_selected(node);
24579  break;
24580 
24582  sexp_val = sexp_is_primary_selected(node);
24583  break;
24584 
24585  // Goober5000
24586  case OP_SET_SUPPORT_SHIP:
24587  sexp_set_support_ship(node);
24588  sexp_val = SEXP_TRUE;
24589  break;
24590 
24591  // Goober5000
24592  case OP_SET_ARRIVAL_INFO:
24593  sexp_set_arrival_info(node);
24594  sexp_val = SEXP_TRUE;
24595  break;
24596 
24597  // Goober5000
24598  case OP_SET_DEPARTURE_INFO:
24600  sexp_val = SEXP_TRUE;
24601  break;
24602 
24603  // Goober5000
24604  case OP_CHANGE_SHIP_CLASS:
24605  sexp_change_ship_class(node);
24606  sexp_val = SEXP_TRUE;
24607  break;
24608 
24609  // Goober5000
24610  case OP_SHIP_COPY_DAMAGE:
24611  sexp_ship_copy_damage(node);
24612  sexp_val = SEXP_TRUE;
24613  break;
24614 
24615  //-Bobboau
24619  sexp_val = SEXP_TRUE;
24620  break;
24621 
24622  //-Bobboau
24623  case OP_ACTIVATE_GLOW_MAPS:
24626  sexp_val = SEXP_TRUE;
24627  break;
24628 
24629  //-Bobboau
24633  sexp_val = SEXP_TRUE;
24634  break;
24635 
24636  // taylor
24637  case OP_SET_SKYBOX_MODEL:
24638  sexp_set_skybox_model(node);
24639  sexp_val = SEXP_TRUE;
24640  break;
24641 
24642  case OP_SET_SKYBOX_ORIENT:
24644  sexp_val = SEXP_TRUE;
24645  break;
24646 
24649  sexp_val = SEXP_TRUE;
24650  break;
24651 
24654  sexp_val = SEXP_TRUE;
24655  break;
24656 
24660  sexp_val = SEXP_TRUE;
24661  break;
24662 
24665  sexp_val = SEXP_TRUE;
24666  break;
24667 
24670  sexp_val = SEXP_TRUE;
24671  break;
24672 
24675  sexp_val = SEXP_TRUE;
24676  break;
24677 
24678  // Karajorma
24679  case OP_SET_PRIMARY_AMMO:
24680  sexp_set_primary_ammo(node);
24681  sexp_val = SEXP_TRUE;
24682  break;
24683 
24684  // Karajorma
24685  case OP_SET_SECONDARY_AMMO:
24687  sexp_val = SEXP_TRUE;
24688  break;
24689 
24690  // Karajorma
24691  case OP_SET_PRIMARY_WEAPON:
24693  sexp_set_weapon(node, op_num == OP_SET_PRIMARY_WEAPON);
24694  sexp_val = SEXP_TRUE;
24695  break;
24696 
24697  // Karajorma
24700  sexp_val = SEXP_TRUE;
24701  break;
24702 
24703  // Karajorma
24707  sexp_val = SEXP_TRUE;
24708  break;
24709 
24713  sexp_val = SEXP_TRUE;
24714  break;
24715 
24716  // KeldorKatarn
24717  case OP_LOCK_AFTERBURNER:
24718  case OP_UNLOCK_AFTERBURNER:
24720  sexp_val = SEXP_TRUE;
24721  break;
24722 
24724  case OP_SET_WEAPON_ENERGY:
24725  case OP_SET_SHIELD_ENERGY:
24726  sexp_set_energy_pct(node, op_num);
24727  sexp_val = SEXP_TRUE;
24728  break;
24729 
24730  case OP_SET_AMBIENT_LIGHT:
24731  sexp_set_ambient_light(node);
24732  sexp_val = SEXP_TRUE;
24733  break;
24734 
24735  case OP_SET_POST_EFFECT:
24736  sexp_set_post_effect(node);
24737  sexp_val = SEXP_TRUE;
24738  break;
24739 
24742  sexp_val = sexp_weapon_fired_delay(node, op_num);
24743  break;
24744 
24745  case OP_HAS_PRIMARY_WEAPON:
24747  sexp_val = sexp_has_weapon(node, op_num);
24748  break;
24749 
24750  case OP_DIRECTIVE_VALUE:
24751  sexp_val = sexp_directive_value(node);
24752  break;
24753 
24756  sexp_val = SEXP_TRUE;
24757  break;
24758 
24759  case OP_NUM_SHIPS_IN_BATTLE: // phreak
24760  sexp_val = sexp_num_ships_in_battle(node);
24761  break;
24762 
24763  // Karajorma
24764  case OP_NUM_SHIPS_IN_WING:
24765  sexp_val=sexp_num_ships_in_wing(node);
24766  break;
24767 
24768  case OP_CURRENT_SPEED:
24769  sexp_val = sexp_current_speed(node);
24770  break;
24771 
24772  case OP_NAV_IS_VISITED: //kazan
24773  sexp_val = is_nav_visited(node);
24774  break;
24775 
24776  case OP_NAV_DISTANCE: //kazan
24777  sexp_val = distance_to_nav(node);
24778  break;
24779 
24780  case OP_NAV_ADD_WAYPOINT: //kazan
24781  sexp_val = SEXP_TRUE;
24782  add_nav_waypoint(node);
24783  break;
24784 
24785  case OP_NAV_ADD_SHIP: //kazan
24786  sexp_val = SEXP_TRUE;
24787  add_nav_ship(node);
24788  break;
24789 
24790  case OP_NAV_DEL: //kazan
24791  sexp_val = SEXP_TRUE;
24792  del_nav(node);
24793  break;
24794 
24795  case OP_NAV_HIDE: //kazan
24796  sexp_val = SEXP_TRUE;
24797  hide_nav(node);
24798  break;
24799 
24800  case OP_NAV_RESTRICT: //kazan
24801  sexp_val = SEXP_TRUE;
24802  restrict_nav(node);
24803  break;
24804 
24805  case OP_NAV_UNHIDE: //kazan
24806  sexp_val = SEXP_TRUE;
24807  unhide_nav(node);
24808  break;
24809 
24810  case OP_NAV_UNRESTRICT: //kazan
24811  sexp_val = SEXP_TRUE;
24812  unrestrict_nav(node);
24813  break;
24814 
24815  case OP_NAV_SET_VISITED: //kazan
24816  sexp_val = SEXP_TRUE;
24817  set_nav_visited(node);
24818  break;
24819 
24820  case OP_NAV_UNSET_VISITED: //kazan
24821  sexp_val = SEXP_TRUE;
24822  unset_nav_visited(node);
24823  break;
24824 
24825  case OP_NAV_SET_CARRY: //kazan
24826  sexp_val = SEXP_TRUE;
24827  set_nav_carry_status(node);
24828  break;
24829 
24830  case OP_NAV_UNSET_CARRY: //kazan
24831  sexp_val = SEXP_TRUE;
24832  unset_nav_carry_status(node);
24833  break;
24834 
24835  case OP_NAV_SET_NEEDSLINK:
24836  sexp_val = SEXP_TRUE;
24837  set_nav_needslink(node);
24838  break;
24839 
24841  sexp_val = SEXP_TRUE;
24842  unset_nav_needslink(node);
24843  break;
24844 
24845  case OP_NAV_ISLINKED:
24846  sexp_val = is_nav_linked(node);
24847  break;
24848 
24849  case OP_NAV_USEAP:
24850  sexp_val = SEXP_TRUE;
24851  set_use_ap(node);
24852  break;
24853 
24854  case OP_NAV_USECINEMATICS:
24855  sexp_val = SEXP_TRUE;
24856  set_use_ap_cinematics(node);
24857  break;
24858 
24859  //Talon1024
24860  case OP_NAV_SELECT:
24861  sexp_val = SEXP_TRUE;
24862  select_nav(node);
24863  break;
24864 
24865  //Talon1024
24866  case OP_NAV_UNSELECT:
24867  sexp_val = SEXP_TRUE;
24868  unselect_nav();
24869  break;
24870 
24871  case OP_SCRAMBLE_MESSAGES:
24873  sexp_scramble_messages(node, op_num == OP_SCRAMBLE_MESSAGES );
24874  sexp_val = SEXP_TRUE;
24875  break;
24876 
24879  sexp_val = SEXP_TRUE;
24881  break;
24882 
24883  case OP_CUTSCENES_FADE_IN:
24884  case OP_CUTSCENES_FADE_OUT:
24885  sexp_val = SEXP_TRUE;
24886  sexp_fade(node, op_num == OP_CUTSCENES_FADE_IN);
24887  break;
24888 
24890  sexp_val = SEXP_TRUE;
24891  sexp_set_camera(node);
24892  break;
24894  sexp_val = SEXP_TRUE;
24895  sexp_set_camera_facing(node);
24896  break;
24898  sexp_val = SEXP_TRUE;
24900  break;
24902  sexp_val = SEXP_TRUE;
24903  sexp_set_camera_fov(node);
24904  break;
24906  sexp_val = SEXP_TRUE;
24907  sexp_set_camera_host(node);
24908  break;
24910  sexp_val = SEXP_TRUE;
24912  break;
24914  sexp_val = SEXP_TRUE;
24916  break;
24918  sexp_val = SEXP_TRUE;
24919  sexp_set_camera_target(node);
24920  break;
24921  case OP_CUTSCENES_SET_FOV:
24922  sexp_val = SEXP_TRUE;
24923  sexp_set_fov(node);
24924  break;
24925  case OP_CUTSCENES_GET_FOV:
24926  sexp_val = sexp_get_fov();
24927  break;
24929  sexp_val = SEXP_TRUE;
24930  sexp_reset_fov();
24931  break;
24933  sexp_val = SEXP_TRUE;
24934  sexp_reset_camera(node);
24935  break;
24937  sexp_val = SEXP_TRUE;
24938  sexp_show_subtitle(node);
24939  break;
24941  sexp_val = SEXP_TRUE;
24943  break;
24945  sexp_val = SEXP_TRUE;
24947  break;
24949  sexp_val = SEXP_TRUE;
24951  break;
24953  sexp_val = SEXP_TRUE;
24955  break;
24957  sexp_val = SEXP_TRUE;
24958  sexp_force_perspective(node);
24959  break;
24960 
24961  case OP_SET_CAMERA_SHUDDER:
24962  sexp_val = SEXP_TRUE;
24964  break;
24965 
24966  case OP_JUMP_NODE_SET_JUMPNODE_NAME: //CommanderDJ
24967  sexp_val = SEXP_TRUE;
24968  sexp_set_jumpnode_name(node);
24969  break;
24970 
24972  sexp_val = SEXP_TRUE;
24974  break;
24976  sexp_val = SEXP_TRUE;
24978  break;
24982  sexp_val = SEXP_TRUE;
24983  break;
24984 
24985  case OP_SCRIPT_EVAL_NUM:
24986  sexp_val = sexp_script_eval(node, OPR_NUMBER);
24987  break;
24988 
24989  case OP_SCRIPT_EVAL_STRING:
24990  sexp_val = sexp_script_eval(node, OPR_STRING);
24991  break;
24992 
24993  case OP_SCRIPT_EVAL:
24994  sexp_val = sexp_script_eval(node, OPR_NULL);
24995  break;
24996 
24997  case OP_SCRIPT_EVAL_BLOCK:
24998  sexp_val = sexp_script_eval(node, OPR_NULL, true);
24999  break;
25000 
25001  case OP_SCRIPT_EVAL_MULTI:
25002  sexp_script_eval_multi(node);
25003  sexp_val = SEXP_TRUE;
25004  break;
25005 
25006  case OP_CHANGE_IFF_COLOR:
25007  sexp_change_iff_color(node);
25008  sexp_val = SEXP_TRUE;
25009  break;
25010 
25011  case OP_DISABLE_ETS:
25012  case OP_ENABLE_ETS:
25013  sexp_disable_ets(node, (op_num == OP_DISABLE_ETS));
25014  sexp_val = SEXP_TRUE;
25015  break;
25016 
25017  case OP_FORCE_GLIDE:
25018  sexp_val = SEXP_TRUE;
25019  sexp_force_glide(node);
25020  break;
25021 
25022  case OP_HUD_SET_DIRECTIVE:
25023  sexp_val = SEXP_TRUE;
25024  sexp_hud_set_directive(node);
25025  break;
25026 
25028  sexp_val = SEXP_TRUE;
25030  break;
25031 
25033  sexp_val = SEXP_TRUE;
25035  break;
25036 
25037  case OP_HUD_CLEAR_MESSAGES:
25038  sexp_val = SEXP_TRUE;
25040  break;
25041 
25043  sexp_val = SEXP_TRUE;
25045  break;
25046 
25048  sexp_val = SEXP_TRUE;
25050  break;
25051 
25052  case OP_ADD_TO_COLGROUP:
25053  sexp_val = SEXP_TRUE;
25054  sexp_manipulate_colgroup(node, true);
25055  break;
25056 
25058  sexp_val = SEXP_TRUE;
25059  sexp_manipulate_colgroup(node, false);
25060  break;
25061 
25062  case OP_GET_COLGROUP_ID:
25063  sexp_val = sexp_get_colgroup(node);
25064  break;
25065 
25066  case OP_SHIP_EFFECT:
25067  sexp_val = SEXP_TRUE;
25068  sexp_ship_effect(node);
25069  break;
25070 
25071  case OP_CLEAR_SUBTITLES:
25072  sexp_val = SEXP_TRUE;
25074  break;
25075 
25076  case OP_SET_THRUSTERS:
25077  sexp_val = SEXP_TRUE;
25078  sexp_set_thrusters(node);
25079  break;
25080 
25081  case OP_CHANGE_TEAM_COLOR:
25082  sexp_val = SEXP_TRUE;
25083  sexp_change_team_color(node);
25084  break;
25085 
25086  case OP_CALL_SSM_STRIKE:
25087  sexp_val = SEXP_TRUE;
25088  sexp_call_ssm_strike(node);
25089  break;
25090 
25092  sexp_val = sexp_player_is_cheating_bastard();
25093  break;
25094 
25096  sexp_val = sexp_get_turret_primary_ammo(node);
25097  break;
25098 
25100  sexp_val = sexp_get_turret_secondary_ammo(node);
25101  break;
25102 
25104  sexp_val = SEXP_TRUE;
25106  break;
25107 
25109  sexp_val = SEXP_TRUE;
25111  break;
25112 
25113  default:
25114  Error(LOCATION, "Looking for SEXP operator, found '%s'.\n", CTEXT(cur_node));
25115  break;
25116  }
25117 
25118  if (Log_event) {
25119  add_to_event_log_buffer(get_operator_index(cur_node), sexp_val);
25120  }
25121 
25122  Assert(!Current_sexp_operator.empty());
25123  Current_sexp_operator.pop_back();
25124 
25125  Assert(sexp_val != UNINITIALIZED);
25126 
25127  // if we haven't returned, check the sexp value of the sexpression evaluation. A special
25128  // value of known true or known false means that we should set the sexp.value field for
25129  // short circuit eval.
25130  if (sexp_val == SEXP_KNOWN_TRUE) {
25131  Sexp_nodes[cur_node].value = SEXP_KNOWN_TRUE;
25132  return SEXP_TRUE;
25133  }
25134 
25135  if (sexp_val == SEXP_KNOWN_FALSE) {
25136  Sexp_nodes[cur_node].value = SEXP_KNOWN_FALSE;
25137  return SEXP_FALSE;
25138  }
25139 
25140  if ( sexp_val == SEXP_NAN ) {
25141  Sexp_nodes[cur_node].value = SEXP_NAN; // not a number values are false I would suspect
25142  return SEXP_FALSE;
25143  }
25144 
25145  if ( sexp_val == SEXP_NAN_FOREVER ) {
25146  Sexp_nodes[cur_node].value = SEXP_NAN_FOREVER;
25147  return SEXP_FALSE; // Goober5000 changed from sexp_val to SEXP_FALSE on 2/21/2006 in accordance with above comment
25148  }
25149 
25150  if ( sexp_val == SEXP_CANT_EVAL ) {
25151  Sexp_nodes[cur_node].value = SEXP_CANT_EVAL;
25152  Sexp_useful_number = 0; // indicate sexp isn't current yet
25153  return SEXP_FALSE;
25154  }
25155 
25156  if ( Sexp_nodes[cur_node].value == SEXP_NAN ) { // if we had a nan, but now don't, reset the value
25157  Sexp_nodes[cur_node].value = SEXP_UNKNOWN;
25158  return sexp_val;
25159  }
25160 
25161  // now, reconcile positive and negative - Goober5000
25162  if (sexp_val < 0)
25163  {
25164  int parent_node = find_parent_operator(cur_node);
25165  int arg_num = find_argnum(parent_node, cur_node);
25166 
25167  // make sure everything works okay
25168  if (arg_num == -1)
25169  {
25170  SCP_string sexp_text;
25171  convert_sexp_to_string(sexp_text, cur_node, SEXP_ERROR_CHECK_MODE);
25172  Error(LOCATION, "Error finding sexp argument. Received value %d for sexp:\n%s", sexp_val, sexp_text.c_str());
25173  }
25174 
25175  // if we need a positive value, make it positive
25176  if (query_operator_argument_type(get_operator_index(parent_node), arg_num) == OPF_POSITIVE)
25177  {
25178  sexp_val *= -1;
25179  }
25180  }
25181 
25182  if ( sexp_val ){
25183  Sexp_nodes[cur_node].value = SEXP_TRUE;
25184  } else {
25185  Sexp_nodes[cur_node].value = SEXP_FALSE;
25186  }
25187 
25188  return sexp_val;
25189  }
25190 }
25191 
25197 {
25198  int op_num;
25199 
25201 
25202  while (Multi_sexp_bytes_left > 0) {
25203  op_num = multi_sexp_get_next_operator();
25204 
25206 
25207  if (op_num < 0) {
25208  Warning(LOCATION, "Received invalid operator number from host in multi_sexp_eval(). Entire packet may be corrupt. Discarding packet");
25209  Int3();
25210  return;
25211  }
25212 
25213  switch(op_num) {
25214 
25215  case OP_CHANGE_SOUNDTRACK:
25217  break;
25218 
25219  case OP_SET_PERSONA:
25221  break;
25222 
25225  break;
25226 
25229  break;
25232  break;
25235  break;
25238  break;
25242  break;
25243 
25246  break;
25247 
25248  case OP_SET_RESPAWNS:
25250  break;
25251 
25252  case OP_REMOVE_WEAPONS:
25254  break;
25255 
25256  case OP_CHANGE_SHIP_CLASS:
25258  break;
25259 
25262  break;
25263 
25266  break;
25267 
25270  break;
25271 
25274  break;
25275 
25278  case OP_SHIP_INVISIBLE:
25279  case OP_SHIP_VISIBLE:
25280  case OP_SHIP_STEALTHY:
25281  case OP_SHIP_UNSTEALTHY:
25284  case OP_LOCK_AFTERBURNER:
25285  case OP_UNLOCK_AFTERBURNER:
25290  case OP_SHIELDS_ON:
25291  case OP_SHIELDS_OFF:
25293  break;
25294 
25295  case OP_ALTER_SHIP_FLAG:
25297  break;
25298 
25301  break;
25302 
25303  case OP_SET_AMBIENT_LIGHT:
25305  break;
25306 
25307  case OP_MODIFY_VARIABLE:
25309  break;
25310 
25311  case OP_NAV_ADD_WAYPOINT:
25313  break;
25314 
25315  case OP_CUTSCENES_FADE_IN:
25316  case OP_CUTSCENES_FADE_OUT:
25318  break;
25319 
25320  case OP_NAV_ADD_SHIP:
25322  break;
25323 
25324  case OP_NAV_DEL:
25325  multi_del_nav();
25326  break;
25327 
25328  case OP_ADD_REMOVE_ESCORT:
25330  break;
25331 
25334  break;
25335 
25338  break;
25339 
25340  case OP_TRAINING_MSG:
25342  break;
25343 
25344  case OP_HUD_DISABLE:
25346  break;
25347 
25350  break;
25351 
25352  case OP_FLASH_HUD_GAUGE:
25354  break;
25355 
25356  case OP_HUD_DISPLAY_GAUGE:
25358  break;
25359 
25363  break;
25364 
25367  break;
25368 
25371  break;
25372 
25375  break;
25376 
25379  break;
25380 
25383  break;
25384 
25387  break;
25388 
25389  case OP_SET_CAMERA_SHUDDER:
25391  break;
25392 
25395  break;
25396 
25397  case OP_CUTSCENES_SET_FOV:
25399  break;
25400 
25403  break;
25404 
25407  break;
25408 
25409  case OP_IGNORE_KEY:
25411  break;
25412 
25415  break;
25416 
25419  break;
25420 
25424  break;
25425 
25426  case OP_CLEAR_SUBTITLES:
25428  break;
25429 
25430  case OP_SET_OBJECT_SPEED_X:
25431  case OP_SET_OBJECT_SPEED_Y:
25432  case OP_SET_OBJECT_SPEED_Z:
25434  break;
25437  break;
25438 
25439  case OP_CHANGE_TEAM_COLOR:
25441  break;
25442 
25445  break;
25446 
25449  break;
25450 
25453  break;
25454 
25455  case OP_SET_ETS_VALUES:
25457  break;
25458 
25459  case OP_SCRIPT_EVAL_MULTI:
25461  break;
25462 
25465  break;
25466 
25469  break;
25470 
25471  // bad sexp in the packet
25472  default:
25473  // probably just a version error where the host supports a SEXP but a client does not
25475  Warning(LOCATION, "Received invalid SEXP operator number from host. Operator number %d is not supported by this version.", op_num);
25476  }
25477  // a more major problem
25478  else {
25479  Warning(LOCATION, "Received invalid SEXP packet from host. Function involving operator %d lacks termination. Entire packet may be corrupt. Discarding remaining packet", op_num);
25480  Int3();
25481  return;
25482  }
25483  }
25484 
25486  }
25487 }
25488 
25489 // get_sexp_main reads and builds the internal representation for a
25490 // symbolic expression.
25491 // On entry:
25492 // Mp points at first character in expression.
25493 // The symbolic expression is built in Sexp_nodes beginning at node 0.
25495 {
25496  int start_node, op;
25497 
25499 
25500  if (*Mp != '(')
25501  {
25502  char buf[512];
25503  strncpy(buf, Mp, 512);
25504  if (buf[511] != '\0')
25505  strcpy(&buf[506], "[...]");
25506 
25507  Error(LOCATION, "Expected to find an open parenthesis in the following sexp:\n%s", buf);
25508  return -1;
25509  }
25510 
25511  Mp++;
25512  start_node = get_sexp();
25513 
25514  // only need to check syntax if we have a operator
25515  if (!Fred_running && (start_node >= 0))
25516  {
25517  op = get_operator_index(CTEXT(start_node));
25518  if (op < 0)
25519  {
25520  Error(LOCATION, "Can't find operator %s in operator list!\n", CTEXT(start_node));
25521  return -1;
25522  }
25523  }
25524 
25525  return start_node;
25526 }
25527 
25528 int run_sexp(const char* sexpression)
25529 {
25530  char* oldMp = Mp;
25531  int n, i, sexp_val = UNINITIALIZED;
25532  char buf[8192];
25533 
25534  strcpy_s(buf, sexpression);
25535 
25536  // HACK: ! -> "
25537  for (i = 0; i < (int)strlen(buf); i++)
25538  if (buf[i] == '!')
25539  buf[i]='\"';
25540 
25541  Mp = buf;
25542 
25543  n = get_sexp_main();
25544  if (n != -1)
25545  {
25546  sexp_val = eval_sexp(n);
25547  free_sexp2(n);
25548  }
25549  Mp = oldMp;
25550 
25551  return sexp_val;
25552 }
25553 
25554 DCF(sexpc, "Always runs the given sexp command (Warning! There is no undo for this!)")
25555 {
25558 
25559  if (dc_optional_string_either("help", "--help")) {
25560  dc_printf( "Usage: sexpc sexpression\n. Always runs the given sexp as '( when ( true ) ( sexp ) )' .\n" );
25561  return;
25562  }
25563 
25564  dc_stuff_string(sexp);
25565 
25566  sexp_always = "( when ( true ) ( " + sexp + " ) )";
25567 
25568  int sexp_val = run_sexp(sexp_always.c_str());
25569  dc_printf("SEXP '%s' run, sexp_val = %d\n", sexp_always.c_str(), sexp_val);
25570 }
25571 
25572 
25573 DCF(sexp,"Runs the given sexp")
25574 {
25575  SCP_string sexp;
25576 
25577  if (dc_optional_string_either("help", "--help")) {
25578  dc_printf( "Usage: sexp 'sexpression'\n. Runs the given sexp.\n");
25579  return;
25580  }
25581 
25582  dc_stuff_string(sexp);
25583 
25584  int sexp_val = run_sexp(sexp.c_str());
25585  dc_printf("SEXP '%s' run, sexp_val = %d\n", sexp.c_str(), sexp_val);
25586 }
25587 
25588 // returns the data type returned by an operator
25590 {
25591  if (op < FIRST_OP)
25592  {
25593  Assert(op >= 0 && op < Num_operators);
25594  op = Operators[op].value;
25595  }
25596 
25597  switch (op)
25598  {
25599  case OP_TRUE:
25600  case OP_FALSE:
25601  case OP_AND:
25602  case OP_AND_IN_SEQUENCE:
25603  case OP_OR:
25604  case OP_NOT:
25605  case OP_XOR:
25606  case OP_EQUALS:
25607  case OP_GREATER_THAN:
25608  case OP_LESS_THAN:
25609  case OP_NOT_EQUAL:
25610  case OP_GREATER_OR_EQUAL:
25611  case OP_LESS_OR_EQUAL:
25612  case OP_STRING_EQUALS:
25614  case OP_STRING_LESS_THAN:
25615  case OP_PERFORM_ACTIONS:
25616  case OP_IS_DESTROYED:
25618  case OP_IS_DISABLED:
25619  case OP_IS_DISARMED:
25620  case OP_HAS_DOCKED:
25621  case OP_HAS_UNDOCKED:
25622  case OP_HAS_ARRIVED:
25623  case OP_HAS_DEPARTED:
25624  case OP_IS_DESTROYED_DELAY:
25627  case OP_IS_DISABLED_DELAY:
25628  case OP_IS_DISARMED_DELAY:
25629  case OP_HAS_DOCKED_DELAY:
25630  case OP_HAS_UNDOCKED_DELAY:
25631  case OP_HAS_ARRIVED_DELAY:
25632  case OP_HAS_DEPARTED_DELAY:
25633  case OP_IS_IFF:
25634  case OP_IS_AI_CLASS:
25635  case OP_IS_SHIP_TYPE:
25636  case OP_IS_SHIP_CLASS:
25637  case OP_HAS_TIME_ELAPSED:
25638  case OP_GOAL_INCOMPLETE:
25639  case OP_GOAL_TRUE_DELAY:
25640  case OP_GOAL_FALSE_DELAY:
25641  case OP_EVENT_INCOMPLETE:
25642  case OP_EVENT_TRUE_DELAY:
25645  case OP_EVENT_FALSE_DELAY:
25649  case OP_PREVIOUS_GOAL_TRUE:
25652  case OP_WAYPOINTS_DONE:
25655  case OP_LAST_ORDER_TIME:
25656  case OP_KEY_PRESSED:
25657  case OP_TARGETED:
25658  case OP_NODE_TARGETED:
25659  case OP_SPEED:
25660  case OP_FACING:
25661  case OP_FACING2:
25662  case OP_ORDER:
25663  case OP_QUERY_ORDERS:
25664  case OP_WAYPOINT_MISSED:
25665  case OP_WAYPOINT_TWICE:
25666  case OP_PATH_FLOWN:
25667  case OP_EVENT_TRUE:
25668  case OP_EVENT_FALSE:
25670  case OP_IS_CARGO_KNOWN:
25673  case OP_CARGO_KNOWN_DELAY:
25675  case OP_WAS_MEDAL_GRANTED:
25681  case OP_DEPART_NODE_DELAY:
25683  case OP_SPECIAL_CHECK:
25684  case OP_IS_TAGGED:
25685  case OP_PRIMARIES_DEPLETED:
25687  case OP_SHIELD_QUAD_LOW:
25690  case OP_IS_SHIP_STEALTHY:
25692  case OP_IS_CARGO:
25693  case OP_MISSILE_LOCKED:
25694  case OP_NAV_IS_VISITED:
25695  case OP_NAV_ISLINKED:
25696  case OP_IS_PLAYER:
25699  case OP_IS_FACING:
25700  case OP_HAS_PRIMARY_WEAPON:
25702  case OP_IS_BIT_SET:
25703  case OP_DIRECTIVE_VALUE:
25704  case OP_IS_IN_BOX:
25705  case OP_IS_IN_MISSION:
25707  case OP_ARE_SHIP_FLAGS_SET:
25708  return OPR_BOOL;
25709 
25710  case OP_PLUS:
25711  case OP_MINUS:
25712  case OP_MOD:
25713  case OP_MUL:
25714  case OP_DIV:
25715  case OP_RAND:
25716  case OP_RAND_MULTIPLE:
25717  case OP_MIN:
25718  case OP_MAX:
25719  case OP_AVG:
25720  case OP_POW:
25721  case OP_SIGNUM:
25722  case OP_GET_OBJECT_X:
25723  case OP_GET_OBJECT_Y:
25724  case OP_GET_OBJECT_Z:
25725  case OP_GET_OBJECT_PITCH:
25726  case OP_GET_OBJECT_BANK:
25727  case OP_GET_OBJECT_HEADING:
25728  case OP_GET_OBJECT_SPEED_X:
25729  case OP_GET_OBJECT_SPEED_Y:
25730  case OP_GET_OBJECT_SPEED_Z:
25731  case OP_SCRIPT_EVAL_NUM:
25732  case OP_STRING_TO_INT:
25733  case OP_GET_THROTTLE_SPEED:
25735  case OP_GET_COLGROUP_ID:
25736  return OPR_NUMBER;
25737 
25738  case OP_ABS:
25739  case OP_SET_BIT:
25740  case OP_UNSET_BIT:
25741  case OP_BITWISE_AND:
25742  case OP_BITWISE_OR:
25743  case OP_BITWISE_NOT:
25744  case OP_BITWISE_XOR:
25746  case OP_TIME_SHIP_ARRIVED:
25747  case OP_TIME_SHIP_DEPARTED:
25749  case OP_TIME_WING_ARRIVED:
25750  case OP_TIME_WING_DEPARTED:
25751  case OP_MISSION_TIME:
25752  case OP_MISSION_TIME_MSECS:
25753  case OP_TIME_DOCKED:
25754  case OP_TIME_UNDOCKED:
25755  case OP_AFTERBURNER_LEFT:
25756  case OP_WEAPON_ENERGY_LEFT:
25757  case OP_SHIELDS_LEFT:
25758  case OP_HITS_LEFT:
25762  case OP_SIM_HITS_LEFT:
25763  case OP_DISTANCE:
25764  case OP_DISTANCE_SUBSYSTEM:
25765  case OP_NUM_WITHIN_BOX:
25766  case OP_NUM_PLAYERS:
25767  case OP_NUM_KILLS:
25768  case OP_NUM_ASSISTS:
25769  case OP_SHIP_DEATHS:
25770  case OP_RESPAWNS_LEFT:
25771  case OP_SHIP_SCORE:
25772  case OP_NUM_TYPE_KILLS:
25773  case OP_NUM_CLASS_KILLS:
25777  case OP_PRIMARY_AMMO_PCT:
25778  case OP_SECONDARY_AMMO_PCT:
25779  case OP_GET_PRIMARY_AMMO:
25780  case OP_GET_SECONDARY_AMMO:
25783  case OP_IS_SHIP_VISIBLE:
25784  case OP_TEAM_SCORE:
25786  case OP_NUM_SHIPS_IN_WING:
25787  case OP_CURRENT_SPEED:
25788  case OP_NAV_DISTANCE:
25789  case OP_GET_DAMAGE_CAUSED:
25790  case OP_CUTSCENES_GET_FOV:
25792  case OP_STRING_GET_LENGTH:
25793  case OP_GET_ETS_VALUE:
25796  return OPR_POSITIVE;
25797 
25798  case OP_COND:
25799  case OP_WHEN:
25800  case OP_WHEN_ARGUMENT:
25801  case OP_EVERY_TIME:
25803  case OP_IF_THEN_ELSE:
25805  case OP_VALIDATE_ARGUMENT:
25809  case OP_CHANGE_IFF:
25810  case OP_CHANGE_AI_CLASS:
25811  case OP_CLEAR_SHIP_GOALS:
25812  case OP_CLEAR_WING_GOALS:
25813  case OP_CLEAR_GOALS:
25814  case OP_ADD_SHIP_GOAL:
25815  case OP_ADD_WING_GOAL:
25816  case OP_ADD_GOAL:
25817  case OP_REMOVE_GOAL:
25818  case OP_PROTECT_SHIP:
25819  case OP_UNPROTECT_SHIP:
25820  case OP_BEAM_PROTECT_SHIP:
25824  case OP_NOP:
25825  case OP_GOALS_ID:
25826  case OP_SEND_MESSAGE:
25827  case OP_SELF_DESTRUCT:
25828  case OP_NEXT_MISSION:
25829  case OP_END_CAMPAIGN:
25830  case OP_END_OF_CAMPAIGN:
25831  case OP_SABOTAGE_SUBSYSTEM:
25832  case OP_REPAIR_SUBSYSTEM:
25833  case OP_INVALIDATE_GOAL:
25834  case OP_VALIDATE_GOAL:
25836  case OP_TRANSFER_CARGO:
25837  case OP_EXCHANGE_CARGO:
25838  case OP_SET_CARGO:
25839  case OP_JETTISON_CARGO:
25840  case OP_SET_DOCKED:
25841  case OP_CARGO_NO_DEPLETE:
25842  case OP_SET_SCANNED:
25843  case OP_SET_UNSCANNED:
25844  case OP_KEY_RESET:
25845  case OP_KEY_RESET_MULTIPLE:
25846  case OP_TRAINING_MSG:
25849  case OP_END_MISSION:
25851  case OP_FORCE_JUMP:
25854  case OP_GOOD_REARM_TIME:
25855  case OP_GRANT_PROMOTION:
25856  case OP_GRANT_MEDAL:
25857  case OP_ALLOW_SHIP:
25858  case OP_ALLOW_WEAPON:
25859  case OP_TECH_ADD_SHIP:
25860  case OP_TECH_ADD_WEAPON:
25861  case OP_TECH_ADD_INTEL:
25865  case OP_CHANGE_TEAM_SCORE:
25866  case OP_WARP_BROKEN:
25867  case OP_WARP_NOT_BROKEN:
25868  case OP_WARP_NEVER:
25869  case OP_WARP_ALLOWED:
25870  case OP_SET_SUBSPACE_DRIVE:
25871  case OP_FLASH_HUD_GAUGE:
25873  case OP_SHIP_VISIBLE:
25874  case OP_SHIP_INVISIBLE:
25875  case OP_SHIP_TAG:
25876  case OP_SHIP_UNTAG:
25877  case OP_SHIP_VULNERABLE:
25878  case OP_SHIP_INVULNERABLE:
25881  case OP_SHIP_GUARDIAN:
25882  case OP_SHIP_NO_GUARDIAN:
25885  case OP_SHIP_VANISH:
25886  case OP_DESTROY_INSTANTLY:
25887  case OP_SHIELDS_ON:
25888  case OP_SHIELDS_OFF:
25889  case OP_SHIP_STEALTHY:
25890  case OP_SHIP_UNSTEALTHY:
25899  case OP_RED_ALERT:
25900  case OP_MODIFY_VARIABLE:
25902  case OP_BEAM_FIRE:
25903  case OP_BEAM_FIRE_COORDS:
25904  case OP_BEAM_FLOATING_FIRE:
25905  case OP_BEAM_FREE:
25906  case OP_BEAM_FREE_ALL:
25907  case OP_BEAM_LOCK:
25908  case OP_BEAM_LOCK_ALL:
25909  case OP_TURRET_FREE:
25910  case OP_TURRET_FREE_ALL:
25911  case OP_TURRET_LOCK:
25912  case OP_TURRET_LOCK_ALL:
25919  case OP_SET_ARMOR_TYPE:
25927  case OP_ADD_REMOVE_ESCORT:
25930  case OP_AWACS_SET_RADIUS:
25932  case OP_SEND_MESSAGE_LIST:
25933  case OP_CAP_WAYPOINT_SPEED:
25936  case OP_SUBSYS_SET_RANDOM:
25937  case OP_SUPERNOVA_START:
25938  case OP_SUPERNOVA_STOP:
25940  case OP_SHIP_VAPORIZE:
25941  case OP_SHIP_NO_VAPORIZE:
25944  case OP_COLLIDE_INVISIBLE:
25945  case OP_SET_MOBILE:
25946  case OP_SET_IMMOBILE:
25947  case OP_IGNORE_KEY:
25948  case OP_CHANGE_SHIP_CLASS:
25949  case OP_SHIP_COPY_DAMAGE:
25953  case OP_ACTIVATE_GLOW_MAPS:
25956  case OP_SET_SKYBOX_MODEL:
25957  case OP_SET_SKYBOX_ORIENT:
25958  case OP_SET_SUPPORT_SHIP:
25959  case OP_SET_ARRIVAL_INFO:
25960  case OP_SET_DEPARTURE_INFO:
25961  case OP_CHANGE_SOUNDTRACK:
25969  case OP_EXPLOSION_EFFECT:
25970  case OP_WARP_EFFECT:
25973  case OP_SET_OBJECT_FACING:
25975  case OP_SHIP_MANEUVER:
25976  case OP_SHIP_ROT_MANEUVER:
25977  case OP_SHIP_LAT_MANEUVER:
25978  case OP_HUD_DISABLE:
25980  case OP_KAMIKAZE:
25988  case OP_PLAYER_USE_AI:
25989  case OP_PLAYER_NOT_USE_AI:
25990  case OP_ALLOW_TREASON:
25991  case OP_SET_PLAYER_ORDERS:
25992  case OP_NAV_ADD_WAYPOINT:
25993  case OP_NAV_ADD_SHIP:
25994  case OP_NAV_DEL:
25995  case OP_NAV_HIDE:
25996  case OP_NAV_RESTRICT:
25997  case OP_NAV_UNHIDE:
25998  case OP_NAV_UNRESTRICT:
25999  case OP_NAV_SET_VISITED:
26000  case OP_NAV_UNSET_VISITED:
26001  case OP_NAV_SET_CARRY:
26002  case OP_NAV_UNSET_CARRY:
26003  case OP_NAV_SET_NEEDSLINK:
26005  case OP_NAV_USECINEMATICS:
26006  case OP_NAV_USEAP:
26007  case OP_NAV_SELECT:
26008  case OP_NAV_UNSELECT:
26009  case OP_HUD_SET_TEXT:
26010  case OP_HUD_SET_TEXT_NUM:
26011  case OP_HUD_SET_MESSAGE:
26012  case OP_HUD_SET_COORDS:
26013  case OP_HUD_SET_FRAME:
26014  case OP_HUD_SET_COLOR:
26016  case OP_HUD_CLEAR_MESSAGES:
26019  case OP_SET_DEATH_MESSAGE:
26020  case OP_SCRAMBLE_MESSAGES:
26024  case OP_CUTSCENES_FADE_IN:
26025  case OP_CUTSCENES_FADE_OUT:
26034  case OP_CUTSCENES_SET_FOV:
26043  case OP_SET_CAMERA_SHUDDER:
26049  case OP_SET_OBJECT_SPEED_X:
26050  case OP_SET_OBJECT_SPEED_Y:
26051  case OP_SET_OBJECT_SPEED_Z:
26052  case OP_SHIP_CREATE:
26053  case OP_WEAPON_CREATE:
26054  case OP_MISSION_SET_NEBULA:
26057  case OP_ADD_SUN_BITMAP:
26058  case OP_REMOVE_SUN_BITMAP:
26060  case OP_NEBULA_TOGGLE_POOF:
26061  case OP_SET_PRIMARY_AMMO:
26062  case OP_SET_SECONDARY_AMMO:
26063  case OP_SET_PRIMARY_WEAPON:
26066  case OP_SCRIPT_EVAL:
26067  case OP_SCRIPT_EVAL_BLOCK:
26068  case OP_SCRIPT_EVAL_STRING:
26069  case OP_SCRIPT_EVAL_MULTI:
26076  case OP_LOCK_AFTERBURNER:
26077  case OP_UNLOCK_AFTERBURNER:
26078  case OP_RESET_ORDERS:
26079  case OP_SET_PERSONA:
26080  case OP_SET_MISSION_MOOD:
26082  case OP_SET_RESPAWNS:
26084  case OP_SET_WEAPON_ENERGY:
26085  case OP_SET_SHIELD_ENERGY:
26086  case OP_SET_AMBIENT_LIGHT:
26087  case OP_SET_POST_EFFECT:
26088  case OP_CHANGE_IFF_COLOR:
26089  case OP_REMOVE_WEAPONS:
26091  case OP_HUD_DISPLAY_GAUGE:
26092  case OP_FORCE_GLIDE:
26093  case OP_HUD_SET_DIRECTIVE:
26096  case OP_STRING_CONCATENATE:
26097  case OP_INT_TO_STRING:
26098  case OP_DISABLE_ETS:
26099  case OP_ENABLE_ETS:
26102  case OP_ADD_TO_COLGROUP:
26104  case OP_SHIP_EFFECT:
26105  case OP_CLEAR_SUBTITLES:
26106  case OP_SET_THRUSTERS:
26108  case OP_DEBUG:
26111  case OP_ALTER_SHIP_FLAG:
26112  case OP_CHANGE_TEAM_COLOR:
26116  case OP_SET_ETS_VALUES:
26117  case OP_CALL_SSM_STRIKE:
26118  case OP_SET_MOTION_DEBRIS:
26121  return OPR_NULL;
26122 
26123  case OP_AI_CHASE:
26124  case OP_AI_DOCK:
26125  case OP_AI_UNDOCK:
26126  case OP_AI_WARP: // this particular operator is obsolete
26127  case OP_AI_WARP_OUT:
26128  case OP_AI_WAYPOINTS:
26129  case OP_AI_WAYPOINTS_ONCE:
26130  case OP_AI_DESTROY_SUBSYS:
26131  case OP_AI_CHASE_WING:
26132  case OP_AI_DISABLE_SHIP:
26133  case OP_AI_DISARM_SHIP:
26134  case OP_AI_GUARD:
26135  case OP_AI_GUARD_WING:
26136  case OP_AI_CHASE_ANY:
26137  case OP_AI_EVADE_SHIP:
26138  case OP_AI_STAY_NEAR_SHIP:
26140  case OP_AI_IGNORE:
26141  case OP_AI_IGNORE_NEW:
26142  case OP_AI_STAY_STILL:
26143  case OP_AI_PLAY_DEAD:
26144  case OP_AI_FORM_ON_WING:
26145  return OPR_AI_GOAL;
26146 
26147  case OP_ANY_OF:
26148  case OP_EVERY_OF:
26149  case OP_RANDOM_OF:
26150  case OP_RANDOM_MULTIPLE_OF:
26151  case OP_NUMBER_OF:
26152  case OP_IN_SEQUENCE:
26153  case OP_FOR_COUNTER:
26154  return OPR_FLEXIBLE_ARGUMENT;
26155 
26156  default:
26157  Int3();
26158  }
26159 
26160  return 0;
26161 }
26162 
26169 int query_operator_argument_type(int op, int argnum)
26170 {
26171  int index = op;
26172 
26173  if (op < FIRST_OP)
26174  {
26175  Assert(index >= 0 && index < Num_operators);
26176  op = Operators[index].value;
26177 
26178  } else {
26179  Warning(LOCATION, "Possible unnecessary search for operator index. Trace out and see if this is necessary.\n");
26180 
26181  for (index=0; index<Num_operators; index++)
26182  if (Operators[index].value == op)
26183  break;
26184 
26185  Assert(index < Num_operators);
26186  }
26187 
26188  if (argnum >= Operators[index].max)
26189  return OPF_NONE;
26190 
26191  switch (op) {
26192  case OP_TRUE:
26193  case OP_FALSE:
26194  case OP_MISSION_TIME:
26195  case OP_MISSION_TIME_MSECS:
26196  case OP_NOP:
26197  case OP_WAYPOINT_MISSED:
26198  case OP_WAYPOINT_TWICE:
26199  case OP_PATH_FLOWN:
26200  case OP_GRANT_PROMOTION:
26202  case OP_RED_ALERT:
26203  case OP_FORCE_JUMP:
26204  case OP_RESET_ORDERS:
26208  case OP_SUPERNOVA_STOP:
26209  case OP_NAV_UNSELECT:
26211  return OPF_NONE;
26212 
26213  case OP_AND:
26214  case OP_AND_IN_SEQUENCE:
26215  case OP_OR:
26216  case OP_NOT:
26217  case OP_XOR:
26218  return OPF_BOOL;
26219 
26220  case OP_PLUS:
26221  case OP_MINUS:
26222  case OP_MOD:
26223  case OP_MUL:
26224  case OP_DIV:
26225  case OP_EQUALS:
26226  case OP_GREATER_THAN:
26227  case OP_LESS_THAN:
26228  case OP_NOT_EQUAL:
26229  case OP_GREATER_OR_EQUAL:
26230  case OP_LESS_OR_EQUAL:
26231  case OP_RAND:
26232  case OP_RAND_MULTIPLE:
26233  case OP_ABS:
26234  case OP_MIN:
26235  case OP_MAX:
26236  case OP_AVG:
26237  return OPF_NUMBER;
26238 
26239  case OP_POW:
26240  if (argnum == 0)
26241  return OPF_NUMBER;
26242  else
26243  return OPF_POSITIVE;
26244 
26245  case OP_SIGNUM:
26246  return OPF_NUMBER;
26247 
26248  case OP_STRING_EQUALS:
26250  case OP_STRING_LESS_THAN:
26251  case OP_STRING_TO_INT: // Karajorma
26252  case OP_STRING_GET_LENGTH: // Goober5000
26253  return OPF_STRING;
26254 
26255  case OP_STRING_CONCATENATE:
26256  if (argnum == 0 || argnum == 1) {
26257  return OPF_STRING;
26258  } else if (argnum == 2) {
26259  return OPF_VARIABLE_NAME;
26260  }
26261 
26262  case OP_INT_TO_STRING:
26263  if (argnum == 0) {
26264  return OPF_NUMBER;
26265  } else if (argnum == 1) {
26266  return OPF_VARIABLE_NAME;
26267  }
26268 
26270  if (argnum == 0) {
26271  return OPF_STRING;
26272  } else if (argnum == 1 || argnum == 2) {
26273  return OPF_POSITIVE;
26274  } else if (argnum == 3) {
26275  return OPF_VARIABLE_NAME;
26276  }
26277 
26279  if (argnum == 0) {
26280  return OPF_STRING;
26281  } else if (argnum == 1 || argnum == 2) {
26282  return OPF_POSITIVE;
26283  } else if (argnum == 3) {
26284  return OPF_STRING;
26285  } else if (argnum == 4) {
26286  return OPF_VARIABLE_NAME;
26287  }
26288 
26289  case OP_DEBUG:
26290  if (argnum == 0) {
26291  return OPF_BOOL;
26292  }else if (argnum == 1) {
26293  return OPF_MESSAGE;
26294  }else {
26295  return OPF_STRING;
26296  }
26297 
26298  case OP_HAS_TIME_ELAPSED:
26299  case OP_SPEED:
26301  case OP_SPECIAL_CHECK:
26302  case OP_AI_WARP_OUT:
26303  case OP_TEAM_SCORE:
26305  case OP_MISSION_SET_NEBULA: //WMC
26307  case OP_SET_BIT:
26308  case OP_UNSET_BIT:
26309  case OP_IS_BIT_SET:
26310  case OP_BITWISE_AND:
26311  case OP_BITWISE_OR:
26312  case OP_BITWISE_NOT:
26313  case OP_BITWISE_XOR:
26314  return OPF_POSITIVE;
26315 
26316  case OP_AI_WARP: // this operator is obsolete
26318  if ( !argnum )
26319  return OPF_WAYPOINT_PATH;
26320  else
26321  return OPF_NUMBER;
26322 
26323  case OP_AI_WAYPOINTS:
26324  case OP_AI_WAYPOINTS_ONCE:
26325  if ( argnum == 0 )
26326  return OPF_WAYPOINT_PATH;
26327  else
26328  return OPF_POSITIVE;
26329 
26332  if (argnum == 0)
26333  return OPF_STRING;
26334  else
26335  return OPF_SHIP;
26336 
26337  case OP_IS_DISABLED:
26338  case OP_IS_DISARMED:
26340  case OP_TIME_SHIP_ARRIVED:
26341  case OP_TIME_SHIP_DEPARTED:
26342  case OP_AFTERBURNER_LEFT:
26343  case OP_WEAPON_ENERGY_LEFT:
26344  case OP_SHIELDS_LEFT:
26345  case OP_HITS_LEFT:
26346  case OP_SIM_HITS_LEFT:
26347  case OP_CLEAR_SHIP_GOALS:
26348  case OP_PROTECT_SHIP:
26349  case OP_UNPROTECT_SHIP:
26350  case OP_BEAM_PROTECT_SHIP:
26352  case OP_TRANSFER_CARGO:
26353  case OP_EXCHANGE_CARGO:
26354  case OP_SHIP_INVISIBLE:
26355  case OP_SHIP_VISIBLE:
26356  case OP_SHIP_INVULNERABLE:
26357  case OP_SHIP_VULNERABLE:
26360  case OP_SHIP_GUARDIAN:
26361  case OP_SHIP_NO_GUARDIAN:
26362  case OP_SHIP_VANISH:
26363  case OP_DESTROY_INSTANTLY:
26364  case OP_SHIELDS_ON:
26365  case OP_SHIELDS_OFF:
26366  case OP_SHIP_STEALTHY:
26367  case OP_SHIP_UNSTEALTHY:
26370  case OP_PRIMARIES_DEPLETED:
26374  case OP_IS_SHIP_VISIBLE:
26375  case OP_IS_SHIP_STEALTHY:
26377  case OP_GET_DAMAGE_CAUSED:
26378  case OP_GET_THROTTLE_SPEED:
26379  return OPF_SHIP;
26380 
26381  case OP_ALTER_SHIP_FLAG:
26382  if(argnum == 0)
26383  return OPF_SHIP_FLAG;
26384  if(argnum == 1 || argnum == 2)
26385  return OPF_BOOL;
26386  else
26387  return OPF_SHIP_WING_WHOLETEAM;
26388 
26390  if(argnum == 0)
26391  return OPF_SHIP;
26392  else
26393  return OPF_POSITIVE;
26394 
26395  case OP_SHIP_CREATE:
26396  if(argnum == 0)
26397  return OPF_STRING;
26398  else if(argnum == 1)
26399  return OPF_SHIP_CLASS_NAME;
26400  else
26401  return OPF_NUMBER;
26402 
26403  case OP_WEAPON_CREATE:
26404  if (argnum == 0)
26405  return OPF_SHIP_OR_NONE;
26406  else if (argnum == 1)
26407  return OPF_WEAPON_NAME;
26408  else if (argnum == 8)
26409  return OPF_SHIP;
26410  else if (argnum == 9)
26411  return OPF_SUBSYSTEM;
26412  else
26413  return OPF_NUMBER;
26414 
26415  case OP_REMOVE_WEAPONS:
26416  return OPF_WEAPON_NAME;
26417 
26419  if (argnum == 0)
26420  return OPF_POSITIVE;
26421  else
26422  return OPF_SHIP;
26423 
26425  if (argnum == 0)
26426  return OPF_POSITIVE;
26427  else if (argnum == 1)
26428  return OPF_SHIP;
26429  else
26430  return OPF_SUBSYS_OR_GENERIC;
26431 
26434  if (argnum == 0)
26435  return OPF_SHIP;
26436  else
26437  return OPF_SUBSYS_OR_GENERIC;
26438 
26443  if (argnum == 0)
26444  return OPF_SHIP;
26445  else if (argnum == 1)
26446  return OPF_BOOL;
26447  else
26448  return OPF_SUBSYS_OR_GENERIC;
26449 
26450  case OP_IS_DESTROYED:
26451  case OP_HAS_ARRIVED:
26452  case OP_HAS_DEPARTED:
26453  case OP_CLEAR_GOALS:
26454  return OPF_SHIP_WING;
26455 
26456  case OP_IS_DISABLED_DELAY:
26457  case OP_IS_DISARMED_DELAY:
26458  if ( argnum == 0 )
26459  return OPF_POSITIVE;
26460  else
26461  return OPF_SHIP;
26462 
26463  case OP_SHIP_TAG:
26464  if (argnum == 0)
26465  return OPF_SHIP;
26466  else if (argnum == 3)
26467  return OPF_SSM_CLASS;
26468  else if (argnum == 7)
26469  return OPF_IFF;
26470  else if (argnum > 3) // SSM origin coordinates shouldn't be limited to positive numbers
26471  return OPF_NUMBER;
26472  else
26473  return OPF_POSITIVE;
26474 
26475  case OP_SHIP_UNTAG:
26476  return OPF_SHIP;
26477 
26478  case OP_FACING:
26479  if (argnum == 0)
26480  return OPF_SHIP;
26481  else
26482  return OPF_POSITIVE;
26483 
26484  case OP_FACING2:
26485  if (argnum == 0) {
26486  return OPF_WAYPOINT_PATH;
26487  } else {
26488  return OPF_POSITIVE;
26489  }
26490 
26491  case OP_ORDER:
26492  if (argnum == 1)
26493  return OPF_AI_ORDER;
26494  else
26495  return OPF_SHIP_WING; // arg 0 or 2
26496 
26497  case OP_QUERY_ORDERS:
26498  if (argnum == 0)
26499  return OPF_ORDER_RECIPIENT;
26500  if (argnum == 1)
26501  return OPF_AI_ORDER;
26502  if (argnum == 2)
26503  return OPF_POSITIVE;
26504  if (argnum == 5)
26505  return OPF_SUBSYSTEM;
26506  else
26507  return OPF_SHIP_WING;
26508 
26510  if (argnum == 0)
26511  return OPF_POSITIVE;
26512  else
26513  return OPF_SHIP;
26514 
26515  case OP_IS_DESTROYED_DELAY:
26516  case OP_HAS_ARRIVED_DELAY:
26517  case OP_HAS_DEPARTED_DELAY:
26518  case OP_LAST_ORDER_TIME:
26519  if ( argnum == 0 )
26520  return OPF_POSITIVE;
26521  else
26522  return OPF_SHIP_WING;
26523 
26525  if (argnum == 0)
26526  return OPF_STRING;
26527  else
26528  return OPF_SHIP_WING;
26529 
26531  if (argnum == 0)
26532  return OPF_STRING;
26533  else
26534  return OPF_SHIP;
26535 
26536  case OP_SET_DEATH_MESSAGE:
26537  return OPF_MESSAGE_OR_STRING;
26538 
26539  case OP_DISTANCE:
26541 
26542  case OP_SET_OBJECT_SPEED_X:
26543  case OP_SET_OBJECT_SPEED_Y:
26544  case OP_SET_OBJECT_SPEED_Z:
26545  if (argnum == 0)
26546  return OPF_SHIP_WING;
26547  else if (argnum == 1)
26548  return OPF_NUMBER;
26549  else
26550  return OPF_BOOL;
26551 
26552  case OP_GET_OBJECT_SPEED_X:
26553  case OP_GET_OBJECT_SPEED_Y:
26554  case OP_GET_OBJECT_SPEED_Z:
26555  if (argnum == 0)
26556  return OPF_SHIP_WING;
26557  else
26558  return OPF_BOOL;
26559 
26560  case OP_GET_OBJECT_X:
26561  case OP_GET_OBJECT_Y:
26562  case OP_GET_OBJECT_Z:
26563  if (argnum == 0)
26564  return OPF_SHIP_WING_POINT;
26565  else if (argnum == 1)
26566  return OPF_SUBSYSTEM_OR_NONE;
26567  else
26568  return OPF_NUMBER;
26569 
26570  case OP_GET_OBJECT_PITCH:
26571  case OP_GET_OBJECT_BANK:
26572  case OP_GET_OBJECT_HEADING:
26573  return OPF_SHIP_WING;
26574 
26576  if(argnum == 0)
26577  return OPF_SHIP_WING_POINT;
26578  else
26579  return OPF_NUMBER;
26580 
26582  if (argnum == 0)
26583  return OPF_SHIP_WING;
26584  else
26585  return OPF_NUMBER;
26586 
26587  case OP_SET_OBJECT_FACING:
26588  if (argnum == 0)
26589  return OPF_SHIP_WING;
26590  else if (argnum < 4)
26591  return OPF_NUMBER;
26592  else
26593  return OPF_POSITIVE;
26594 
26596  if (argnum == 0)
26597  return OPF_SHIP_WING;
26598  else if (argnum == 1)
26599  return OPF_SHIP_WING_POINT;
26600  else
26601  return OPF_POSITIVE;
26602 
26603  case OP_SHIP_MANEUVER:
26604  if (argnum == 0)
26605  return OPF_SHIP_WING;
26606  else if (argnum == 1)
26607  return OPF_POSITIVE;
26608  else if (argnum < 5)
26609  return OPF_NUMBER;
26610  else if (argnum == 5)
26611  return OPF_BOOL;
26612  else if (argnum < 9)
26613  return OPF_NUMBER;
26614  else
26615  return OPF_BOOL;
26616 
26617  case OP_SHIP_ROT_MANEUVER:
26618  case OP_SHIP_LAT_MANEUVER:
26619  if (argnum == 0)
26620  return OPF_SHIP_WING;
26621  else if (argnum == 1)
26622  return OPF_POSITIVE;
26623  else if (argnum < 5)
26624  return OPF_NUMBER;
26625  else
26626  return OPF_BOOL;
26627 
26628  case OP_MODIFY_VARIABLE:
26629  if (argnum == 0) {
26630  return OPF_VARIABLE_NAME;
26631  } else {
26632  return OPF_AMBIGUOUS;
26633  }
26634 
26637  return OPF_POSITIVE;
26638 
26640  if (argnum == 0) {
26641  return OPF_POSITIVE;
26642  } else {
26643  return OPF_VARIABLE_NAME;
26644  }
26645 
26647  if (argnum == 0) {
26648  return OPF_POSITIVE;
26649  } else {
26650  return OPF_AMBIGUOUS;
26651  }
26652 
26653  case OP_HAS_DOCKED:
26654  case OP_HAS_UNDOCKED:
26655  case OP_HAS_DOCKED_DELAY:
26656  case OP_HAS_UNDOCKED_DELAY:
26657  case OP_TIME_DOCKED:
26658  case OP_TIME_UNDOCKED:
26659  if ( argnum < 2 )
26660  return OPF_SHIP;
26661  else
26662  return OPF_POSITIVE;
26663 
26665  case OP_TIME_WING_ARRIVED:
26666  case OP_TIME_WING_DEPARTED:
26667  case OP_CLEAR_WING_GOALS:
26668  return OPF_WING;
26669 
26670  case OP_SET_SCANNED:
26671  case OP_SET_UNSCANNED:
26673  if (!argnum)
26674  return OPF_SHIP;
26675  else
26676  return OPF_SUBSYSTEM;
26677 
26679  if (argnum == 0)
26680  return OPF_SHIP;
26681  else if (argnum == 1)
26682  return OPF_SUBSYSTEM;
26683  else
26684  return OPF_BOOL;
26685 
26687  if (argnum == 0)
26688  return OPF_SHIP;
26689  else
26690  return OPF_SUBSYSTEM_TYPE;
26691 
26693  if (argnum == 0)
26694  return OPF_SHIP;
26695  else if (argnum == 1)
26696  return OPF_SUBSYSTEM;
26697 
26698  case OP_DISTANCE_SUBSYSTEM:
26699  if (argnum == 0)
26701  else if (argnum == 1)
26702  return OPF_SHIP;
26703  else if (argnum == 2)
26704  return OPF_SUBSYSTEM;
26705  else
26706  Int3(); // shouldn't happen
26707 
26708  case OP_NUM_WITHIN_BOX:
26709  if(argnum < 3)
26710  return OPF_NUMBER;
26711  else if(argnum < 6)
26712  return OPF_POSITIVE;
26713  else
26714  return OPF_SHIP_WING;
26715 
26716  case OP_IS_IN_BOX:
26717  if (argnum == 0) // First arg is a ship/wing/point
26718  return OPF_SHIP_WING_POINT;
26719  else if (argnum <= 6) // Next 6 args are coordinates
26720  return OPF_NUMBER;
26721  else // Next arg is a ship
26722  return OPF_SHIP;
26723 
26724  case OP_IS_IN_MISSION:
26725  return OPF_STRING;
26726 
26727  // Sesquipedalian
26728  case OP_MISSILE_LOCKED:
26729  if (argnum == 0)
26730  return OPF_POSITIVE;
26731  else if (argnum == 1)
26732  return OPF_SHIP;
26733  else
26734  return OPF_SUBSYSTEM;
26735 
26736  case OP_TARGETED:
26737  if (!argnum)
26738  return OPF_SHIP;
26739  else if (argnum == 1)
26740  return OPF_POSITIVE;
26741  else
26742  return OPF_SUBSYSTEM;
26743 
26744  case OP_NODE_TARGETED:
26745  if (!argnum)
26746  return OPF_JUMP_NODE_NAME;
26747  else if (argnum == 1)
26748  return OPF_POSITIVE;
26749 
26751  if ( argnum == 0 )
26752  return OPF_SHIP;
26753  else if ( argnum == 1 )
26754  return OPF_SUBSYSTEM;
26755  else
26756  return OPF_POSITIVE;
26757 
26758  case OP_IS_IFF:
26759  case OP_CHANGE_IFF:
26760  if (!argnum)
26761  return OPF_IFF;
26762  else
26763  return OPF_SHIP_WING;
26764 
26765  case OP_ADD_SHIP_GOAL:
26766  if (!argnum)
26767  return OPF_SHIP;
26768  else
26769  return OPF_AI_GOAL;
26770 
26771  case OP_ADD_WING_GOAL:
26772  if (!argnum)
26773  return OPF_WING;
26774  else
26775  return OPF_AI_GOAL;
26776 
26777  case OP_ADD_GOAL:
26778  case OP_REMOVE_GOAL:
26779  if ( argnum == 0 )
26780  return OPF_SHIP_WING;
26781  else
26782  return OPF_AI_GOAL;
26783 
26784  case OP_COND:
26785  case OP_WHEN:
26786  case OP_EVERY_TIME:
26787  case OP_IF_THEN_ELSE:
26788  case OP_PERFORM_ACTIONS:
26789  if (!argnum)
26790  return OPF_BOOL;
26791  else
26792  return OPF_NULL;
26793 
26794  case OP_WHEN_ARGUMENT:
26796  if (argnum == 0)
26797  return OPF_FLEXIBLE_ARGUMENT;
26798  else if (argnum == 1)
26799  return OPF_BOOL;
26800  else
26801  return OPF_NULL;
26802 
26804  return OPF_NULL;
26805 
26806  case OP_ANY_OF:
26807  case OP_EVERY_OF:
26808  case OP_RANDOM_OF:
26809  case OP_RANDOM_MULTIPLE_OF:
26810  case OP_IN_SEQUENCE:
26811  return OPF_ANYTHING;
26812 
26813  case OP_NUMBER_OF:
26814  if (argnum == 0)
26815  return OPF_POSITIVE;
26816  else
26817  return OPF_ANYTHING;
26818 
26819  case OP_FOR_COUNTER:
26820  return OPF_NUMBER;
26821 
26823  case OP_VALIDATE_ARGUMENT:
26824  return OPF_ANYTHING;
26825 
26826  case OP_AI_DISABLE_SHIP:
26827  case OP_AI_DISARM_SHIP:
26828  if (argnum == 0)
26829  return OPF_SHIP;
26830  else if (argnum == 1)
26831  return OPF_POSITIVE;
26832  else
26833  return OPF_BOOL;
26834 
26835  case OP_AI_EVADE_SHIP:
26836  case OP_AI_STAY_NEAR_SHIP:
26837  case OP_AI_IGNORE:
26838  case OP_AI_IGNORE_NEW:
26839  if (!argnum)
26840  return OPF_SHIP;
26841  else
26842  return OPF_POSITIVE;
26843 
26844  case OP_AI_CHASE:
26845  if (argnum == 0)
26846  return OPF_SHIP_WING;
26847  else if (argnum == 1)
26848  return OPF_POSITIVE;
26849  else
26850  return OPF_BOOL;
26851 
26852  case OP_AI_GUARD:
26853  if (!argnum)
26854  return OPF_SHIP_WING;
26855  else
26856  return OPF_POSITIVE;
26857 
26859  return OPF_POSITIVE;
26860 
26861  case OP_AI_DOCK:
26862  if (!argnum)
26863  return OPF_SHIP;
26864  else if (argnum == 1)
26865  return OPF_DOCKER_POINT;
26866  else if (argnum == 2)
26867  return OPF_DOCKEE_POINT;
26868  else
26869  return OPF_POSITIVE;
26870 
26871  case OP_AI_UNDOCK:
26872  if (argnum == 0)
26873  return OPF_POSITIVE;
26874  else
26875  return OPF_SHIP;
26876 
26877  case OP_AI_CHASE_WING:
26878  if (argnum == 0)
26879  return OPF_WING;
26880  else if (argnum == 1)
26881  return OPF_POSITIVE;
26882  else
26883  return OPF_BOOL;
26884 
26885  case OP_AI_GUARD_WING:
26886  if (!argnum)
26887  return OPF_WING;
26888  else
26889  return OPF_POSITIVE;
26890 
26891  case OP_AI_DESTROY_SUBSYS:
26892  if (!argnum)
26893  return OPF_SHIP;
26894  else if (argnum == 1)
26895  return OPF_SUBSYSTEM;
26896  else if (argnum == 2)
26897  return OPF_POSITIVE;
26898  else
26899  return OPF_BOOL;
26900 
26901  case OP_GOALS_ID:
26902  return OPF_AI_GOAL;
26903 
26904  case OP_SET_CARGO:
26905  case OP_IS_CARGO:
26906  if (argnum == 0)
26907  return OPF_CARGO;
26908  else if (argnum == 1)
26909  return OPF_SHIP;
26910  else
26911  return OPF_SUBSYSTEM;
26912 
26913  case OP_CHANGE_AI_CLASS:
26914  case OP_IS_AI_CLASS:
26915  if (argnum == 0)
26916  return OPF_AI_CLASS;
26917  else if (argnum == 1)
26918  return OPF_SHIP;
26919  else
26920  return OPF_SUBSYSTEM;
26921 
26922  case OP_IS_SHIP_TYPE:
26923  if (argnum == 0)
26924  return OPF_SHIP_TYPE;
26925  else
26926  return OPF_SHIP;
26927 
26928  case OP_IS_SHIP_CLASS:
26929  if (argnum == 0)
26930  return OPF_SHIP_CLASS_NAME;
26931  else
26932  return OPF_SHIP;
26933 
26934  case OP_CHANGE_SOUNDTRACK:
26935  return OPF_SOUNDTRACK_NAME;
26936 
26938  if (argnum == 3)
26939  return OPF_GAME_SND;
26940  else
26941  return OPF_POSITIVE;
26942 
26944  if (argnum==0)
26945  return OPF_STRING;
26946  else
26947  return OPF_POSITIVE;
26948 
26951  case OP_ALLOW_TREASON:
26952  case OP_END_MISSION:
26954  return OPF_BOOL;
26955 
26956  case OP_SET_PLAYER_ORDERS:
26957  if (argnum==0)
26958  return OPF_SHIP;
26959  if (argnum==1)
26960  return OPF_BOOL;
26961  else
26962  return OPF_AI_ORDER;
26963 
26965  if (argnum == 0)
26966  return OPF_SOUND_ENVIRONMENT;
26967 
26968  // fall through
26969  argnum--;
26970 
26972  {
26973  // every two, the value repeats
26974  int a_mod = argnum % 2;
26975 
26976  if (a_mod == 0)
26978  else
26979  return OPF_POSITIVE;
26980  }
26981 
26983  {
26984  if (argnum == 0)
26985  return OPF_AUDIO_VOLUME_OPTION;
26986  else
26987  return OPF_POSITIVE;
26988  }
26989 
26991  {
26992  // editing a ship
26993  if (argnum == 0)
26994  return OPF_SHIP;
26995 
26996  // every two, the value repeats
26997  int a_mod = (argnum - 1) % 2;
26998 
26999  if (a_mod == 0)
27000  return OPF_EXPLOSION_OPTION;
27001  else
27002  return OPF_POSITIVE;
27003  }
27004 
27005  case OP_HUD_DISABLE:
27007  return OPF_POSITIVE;
27008 
27009  case OP_HUD_SET_TEXT:
27010  return OPF_STRING;
27011 
27012  case OP_HUD_SET_MESSAGE:
27013  if(argnum == 0)
27014  return OPF_STRING;
27015  else
27016  return OPF_MESSAGE;
27017 
27018  case OP_HUD_SET_TEXT_NUM:
27019  case OP_HUD_SET_COORDS:
27020  case OP_HUD_SET_FRAME:
27021  case OP_HUD_SET_COLOR:
27022  if(argnum == 0)
27023  return OPF_STRING;
27024  else
27025  return OPF_POSITIVE;
27026 
27027  case OP_HUD_CLEAR_MESSAGES:
27028  return OPF_NONE;
27029 
27030  case OP_PLAYER_USE_AI:
27031  case OP_PLAYER_NOT_USE_AI:
27032  return OPF_NONE;
27033 
27034  case OP_EXPLOSION_EFFECT:
27035  if (argnum <= 2)
27036  return OPF_NUMBER;
27037  else if (argnum == 10)
27038  return OPF_GAME_SND;
27039  else
27040  return OPF_POSITIVE;
27041 
27042  case OP_WARP_EFFECT:
27043  if (argnum <= 5)
27044  return OPF_NUMBER;
27045  else if (argnum == 8 || argnum == 9)
27046  return OPF_GAME_SND;
27047  else
27048  return OPF_POSITIVE;
27049 
27050  case OP_SEND_MESSAGE:
27052  if ( argnum == 0 )
27053  return OPF_WHO_FROM;
27054  else if ( argnum == 1 )
27055  return OPF_PRIORITY;
27056  else
27057  return OPF_MESSAGE;
27058 
27059  case OP_SEND_MESSAGE_LIST:
27060  {
27061  // every four, the value repeats
27062  int a_mod = argnum % 4;
27063 
27064  // who from
27065  if(a_mod == 0)
27066  return OPF_WHO_FROM;
27067  else if(a_mod == 1)
27068  return OPF_PRIORITY;
27069  else if(a_mod == 2)
27070  return OPF_MESSAGE;
27071  else if(a_mod == 3)
27072  return OPF_POSITIVE;
27073  }
27074 
27075  case OP_TRAINING_MSG:
27076  if (argnum < 2)
27077  return OPF_MESSAGE;
27078  else
27079  return OPF_POSITIVE;
27080 
27081  // Karajorma
27084  return OPF_WHO_FROM;
27085 
27086  case OP_SET_PERSONA:
27087  if (argnum == 0)
27088  return OPF_PERSONA;
27089  else
27090  return OPF_SHIP;
27091 
27092  case OP_SET_MISSION_MOOD:
27093  return OPF_MISSION_MOOD;
27094 
27095  case OP_CHANGE_TEAM_COLOR:
27096  if (argnum == 0)
27097  return OPF_TEAM_COLOR;
27098  else if (argnum == 1)
27099  return OPF_NUMBER;
27100  else
27101  return OPF_SHIP;
27102 
27103  case OP_CALL_SSM_STRIKE:
27104  if (argnum == 0)
27105  return OPF_SSM_CLASS;
27106  else if (argnum == 1)
27107  return OPF_IFF;
27108  else
27109  return OPF_SHIP;
27110 
27111  case OP_SELF_DESTRUCT:
27112  return OPF_SHIP;
27113 
27114  case OP_NEXT_MISSION:
27115  return OPF_MISSION_NAME;
27116 
27117  case OP_END_CAMPAIGN:
27118  return OPF_BOOL;
27119 
27120  case OP_END_OF_CAMPAIGN:
27121  return OPF_NONE;
27122 
27123  case OP_PREVIOUS_GOAL_TRUE:
27125  if ( argnum == 0 )
27126  return OPF_MISSION_NAME;
27127  else if (argnum == 1 )
27128  return OPF_GOAL_NAME;
27129  else
27130  return OPF_BOOL;
27131 
27133  return OPF_GOAL_NAME;
27134 
27138  if (!argnum)
27139  return OPF_MISSION_NAME;
27140  else if ( argnum == 1 )
27141  return OPF_EVENT_NAME;
27142  else
27143  return OPF_BOOL;
27144 
27145  case OP_SABOTAGE_SUBSYSTEM:
27146  if (!argnum)
27147  return OPF_SHIP; // changed from OPF_SHIP_NOT_PLAYER by Goober5000: now it can be the player ship also
27148  else if (argnum == 1 )
27149  return OPF_SUBSYS_OR_GENERIC;
27150  else
27151  return OPF_POSITIVE;
27152 
27153  case OP_REPAIR_SUBSYSTEM:
27155  if (!argnum)
27156  return OPF_SHIP; // changed from OPF_SHIP_NOT_PLAYER by Goober5000: now it can be the player ship also
27157  else if (argnum == 1 )
27158  return OPF_SUBSYS_OR_GENERIC;
27159  else if (argnum == 2)
27160  return OPF_POSITIVE;
27161  else
27162  return OPF_BOOL;
27163 
27165  if (argnum == 0)
27166  return OPF_SHIP;
27167  else
27168  return OPF_SUBSYS_OR_GENERIC;
27169 
27170  case OP_WAYPOINTS_DONE:
27171  if ( argnum == 0 )
27172  return OPF_SHIP_WING;
27173  else
27174  return OPF_WAYPOINT_PATH;
27175 
27177  if ( argnum == 0 )
27178  return OPF_SHIP_WING;
27179  else if ( argnum == 1 )
27180  return OPF_WAYPOINT_PATH;
27181  else
27182  return OPF_POSITIVE;
27183 
27184  case OP_INVALIDATE_GOAL:
27185  case OP_VALIDATE_GOAL:
27186  return OPF_GOAL_NAME;
27187 
27189  if ( argnum == 0 )
27190  return OPF_POSITIVE;
27191  else
27192  return OPF_SHIP_TYPE;
27193 
27194  case OP_KEY_PRESSED:
27195  if (!argnum)
27196  return OPF_KEYPRESS;
27197  else
27198  return OPF_POSITIVE;
27199 
27200  case OP_KEY_RESET:
27201  case OP_KEY_RESET_MULTIPLE:
27202  return OPF_KEYPRESS;
27203 
27204  case OP_EVENT_TRUE:
27205  case OP_EVENT_FALSE:
27206  return OPF_EVENT_NAME;
27207 
27208  case OP_EVENT_INCOMPLETE:
27209  case OP_EVENT_TRUE_DELAY:
27210  case OP_EVENT_FALSE_DELAY:
27213  if (argnum == 0)
27214  return OPF_EVENT_NAME;
27215  else if (argnum == 1)
27216  return OPF_POSITIVE;
27217  else if (argnum == 2)
27218  return OPF_BOOL;
27219 
27220  case OP_GOAL_INCOMPLETE:
27221  case OP_GOAL_TRUE_DELAY:
27222  case OP_GOAL_FALSE_DELAY:
27223  if (!argnum)
27224  return OPF_GOAL_NAME;
27225  else
27226  return OPF_POSITIVE;
27227 
27228  case OP_AI_PLAY_DEAD:
27229  case OP_AI_CHASE_ANY:
27230  return OPF_POSITIVE;
27231 
27232  case OP_AI_STAY_STILL:
27233  if (!argnum)
27234  return OPF_SHIP_POINT;
27235  else
27236  return OPF_POSITIVE;
27237 
27238  case OP_AI_FORM_ON_WING:
27239  return OPF_SHIP;
27240 
27241  case OP_GOOD_REARM_TIME:
27242  if ( argnum == 0 )
27243  return OPF_IFF;
27244  else
27245  return OPF_POSITIVE;
27246 
27247  case OP_NUM_PLAYERS:
27248  return OPF_POSITIVE;
27249 
27251  return OPF_SKILL_LEVEL;
27252 
27253  case OP_GRANT_MEDAL:
27254  case OP_WAS_MEDAL_GRANTED:
27255  return OPF_MEDAL_NAME;
27256 
27257  case OP_IS_CARGO_KNOWN:
27258  return OPF_SHIP;
27259 
27260  case OP_CARGO_KNOWN_DELAY:
27261  if ( argnum == 0 )
27262  return OPF_POSITIVE;
27263  else
27264  return OPF_SHIP;
27265 
27267  if ( argnum == 0 ) {
27268  return OPF_POSITIVE;
27269  } else {
27270  return OPF_SHIP;
27271  }
27272 
27273  case OP_ARE_SHIP_FLAGS_SET:
27274  if (argnum == 0) {
27275  return OPF_SHIP;
27276  } else {
27277  return OPF_SHIP_FLAG;
27278  }
27279 
27281  if ( argnum == 0 ) {
27282  return OPF_POSITIVE;
27283  } else if ( argnum == 1 ) {
27284  return OPF_SHIP;
27285  } else {
27286  return OPF_SUBSYSTEM;
27287  }
27288 
27289  case OP_ALLOW_SHIP:
27290  case OP_TECH_ADD_SHIP:
27291  return OPF_SHIP_CLASS_NAME;
27292 
27293  case OP_ALLOW_WEAPON:
27294  case OP_TECH_ADD_WEAPON:
27295  return OPF_WEAPON_NAME;
27296 
27297  case OP_TECH_ADD_INTEL:
27298  return OPF_INTEL_NAME;
27299 
27301  return !(argnum % 2) ? OPF_INTEL_NAME : OPF_NUMBER;
27302 
27304  return OPF_NONE;
27305 
27307  if (argnum == 0)
27308  return OPF_NUMBER;
27309  else
27310  return OPF_SHIP;
27311 
27312  case OP_CHANGE_TEAM_SCORE:
27313  return OPF_NUMBER;
27314 
27315  case OP_SHIP_VAPORIZE:
27316  case OP_SHIP_NO_VAPORIZE:
27317  return OPF_SHIP;
27318 
27320  case OP_COLLIDE_INVISIBLE:
27321  return OPF_SHIP;
27322 
27323  case OP_SET_MOBILE:
27324  case OP_SET_IMMOBILE:
27325  return OPF_SHIP;
27326 
27327  case OP_IGNORE_KEY:
27328  if (argnum == 0)
27329  return OPF_NUMBER;
27330  else
27331  return OPF_KEYPRESS;
27332 
27333 
27334  case OP_WARP_BROKEN:
27335  case OP_WARP_NOT_BROKEN:
27336  case OP_WARP_NEVER:
27337  case OP_WARP_ALLOWED:
27338  return OPF_SHIP;
27339 
27340  case OP_SET_SUBSPACE_DRIVE:
27341  if (argnum == 0)
27342  return OPF_BOOL;
27343  else
27344  return OPF_SHIP;
27345 
27346  case OP_FLASH_HUD_GAUGE:
27347  return OPF_HUD_GAUGE_NAME;
27348 
27350  if ( argnum == 0 )
27351  return OPF_IFF;
27352  else if ( argnum == 1 )
27353  return OPF_POSITIVE;
27354  else if ( argnum == 2 )
27355  return OPF_HUGE_WEAPON;
27356  else
27357  return OPF_SHIP;
27358 
27362  if ( argnum == 0 ){
27363  return OPF_POSITIVE;
27364  } else {
27365  return OPF_SHIP_WING;
27366  }
27367  break;
27368 
27371  if ( argnum == 0 ){
27372  return OPF_POSITIVE;
27373  } else {
27374  return OPF_SHIP;
27375  }
27376  break;
27377 
27378  case OP_DEPART_NODE_DELAY:
27379  if ( argnum == 0 ){
27380  return OPF_POSITIVE;
27381  } else if ( argnum == 1 ){
27382  return OPF_JUMP_NODE_NAME;
27383  } else {
27384  return OPF_SHIP;
27385  }
27386 
27388  if ( argnum == 0 ){
27389  return OPF_POSITIVE;
27390  } else {
27391  return OPF_SHIP_WING;
27392  }
27393 
27394  case OP_JETTISON_CARGO:
27395  if(argnum == 1){
27396  return OPF_POSITIVE;
27397  } else {
27398  return OPF_SHIP;
27399  }
27400 
27401  case OP_SET_DOCKED:
27402  if (argnum == 0) {
27403  return OPF_SHIP;
27404  } else if (argnum == 1) {
27405  return OPF_DOCKER_POINT;
27406  } else if (argnum == 2) {
27407  return OPF_SHIP;
27408  } else {
27409  return OPF_DOCKEE_POINT;
27410  }
27411 
27412  case OP_CARGO_NO_DEPLETE:
27413  if (argnum == 0) {
27414  return OPF_SHIP;
27415  } else {
27416  return OPF_NUMBER;
27417  }
27418 
27419  case OP_BEAM_FIRE:
27420  switch(argnum) {
27421  case 0:
27422  return OPF_SHIP;
27423  case 1:
27424  return OPF_SUBSYSTEM;
27425  case 2:
27426  return OPF_SHIP;
27427  case 3:
27428  return OPF_SUBSYSTEM;
27429  case 4:
27430  return OPF_BOOL;
27431  }
27432 
27433  case OP_BEAM_FIRE_COORDS:
27434  switch(argnum) {
27435  case 0:
27436  return OPF_SHIP;
27437  case 1:
27438  return OPF_SUBSYSTEM;
27439  case 5:
27440  return OPF_BOOL;
27441  default:
27442  return OPF_NUMBER;
27443  }
27444 
27445  case OP_BEAM_FLOATING_FIRE:
27446  switch(argnum) {
27447  case 0:
27448  return OPF_WEAPON_NAME;
27449  case 1:
27450  case 6:
27451  return OPF_SHIP_OR_NONE;
27452  case 2:
27453  return OPF_IFF;
27454  case 7:
27455  return OPF_SUBSYSTEM_OR_NONE;
27456  default:
27457  return OPF_NUMBER;
27458  }
27459 
27460  case OP_IS_TAGGED:
27461  return OPF_SHIP;
27462 
27463  case OP_IS_PLAYER:
27464  if (argnum == 0) {
27465  return OPF_BOOL;
27466  } else {
27467  return OPF_SHIP;
27468  }
27469 
27470  case OP_NUM_KILLS:
27471  case OP_NUM_ASSISTS:
27472  case OP_SHIP_SCORE:
27473  case OP_SHIP_DEATHS:
27474  case OP_RESPAWNS_LEFT:
27475  return OPF_SHIP;
27476 
27477  case OP_SET_RESPAWNS:
27478  if (argnum == 0 ) {
27479  return OPF_POSITIVE;
27480  }
27481  else {
27482  return OPF_SHIP;
27483  }
27484 
27485  case OP_NUM_TYPE_KILLS:
27486  if(argnum == 0){
27487  return OPF_SHIP;
27488  } else {
27489  return OPF_SHIP_TYPE;
27490  }
27491 
27492  case OP_NUM_CLASS_KILLS:
27493  if(argnum == 0){
27494  return OPF_SHIP;
27495  } else {
27496  return OPF_SHIP_CLASS_NAME;
27497  }
27498 
27499  case OP_BEAM_FREE:
27500  case OP_BEAM_LOCK:
27501  case OP_TURRET_FREE:
27502  case OP_TURRET_LOCK:
27505  if(argnum == 0){
27506  return OPF_SHIP;
27507  } else {
27508  return OPF_SUBSYSTEM;
27509  }
27510 
27513  if(argnum == 0){
27514  return OPF_SHIP;
27515  } else {
27516  return OPF_SUBSYS_OR_GENERIC;
27517  }
27518 
27520  if(argnum == 0) {
27521  return OPF_SHIP;
27522  } else if(argnum == 1) {
27523  return OPF_SUBSYSTEM;
27524  } else if(argnum == 2) {
27525  return OPF_WEAPON_NAME;
27526  } else if(argnum > 2) {
27527  return OPF_POSITIVE;
27528  }
27529 
27531  if(argnum == 0) {
27532  return OPF_SHIP;
27533  } else if(argnum == 1) {
27534  return OPF_NUMBER;
27535  } else {
27536  return OPF_SUBSYSTEM;
27537  }
27538 
27540  if(argnum == 0) {
27541  return OPF_SHIP;
27542  } else if(argnum == 1) {
27543  return OPF_NUMBER;
27544  } else {
27545  return OPF_SUBSYSTEM;
27546  }
27547 
27549  if(argnum == 0) {
27550  return OPF_SHIP;
27551  } else if(argnum == 1) {
27552  return OPF_NUMBER;
27553  } else {
27554  return OPF_SUBSYSTEM;
27555  }
27556 
27558  if(argnum == 0) {
27559  return OPF_SHIP;
27560  } else if(argnum == 1) {
27561  return OPF_SUBSYSTEM;
27562  } else if(argnum == 2) {
27563  return OPF_BOOL;
27564  } else {
27565  return OPF_TARGET_PRIORITIES;
27566  }
27567 
27568  case OP_SET_ARMOR_TYPE:
27569  if(argnum == 0) {
27570  return OPF_SHIP;
27571  } else if(argnum == 1) {
27572  return OPF_BOOL;
27573  } else if(argnum == 2) {
27574  return OPF_ARMOR_TYPE;
27575  } else {
27576  return OPF_SUBSYSTEM;
27577  }
27578 
27580  if(argnum == 0) {
27581  return OPF_BOOL;
27582  } else if(argnum == 1) {
27583  return OPF_DAMAGE_TYPE;
27584  } else if(argnum == 2) {
27585  return OPF_BOOL;
27586  } else {
27587  return OPF_WEAPON_NAME;
27588  }
27589 
27591  if(argnum == 0) {
27592  return OPF_BOOL;
27593  } else if(argnum == 1) {
27594  return OPF_DAMAGE_TYPE;
27595  } else if(argnum == 2) {
27596  return OPF_BOOL;
27597  } else {
27598  return OPF_SHIP;
27599  }
27600 
27602  if(argnum == 0) {
27603  return OPF_DAMAGE_TYPE;
27604  } else if(argnum == 1) {
27605  return OPF_BOOL;
27606  } else {
27607  return OPF_SHIP_CLASS_NAME;
27608  }
27609 
27611  if(argnum == 0) {
27612  return OPF_DAMAGE_TYPE;
27613  } else {
27614  return OPF_BOOL;
27615  }
27616 
27618  if(argnum == 0) {
27619  return OPF_SHIP;
27620  } else if(argnum == 1) {
27621  return OPF_SUBSYSTEM;
27622  } else {
27623  return OPF_TURRET_TARGET_ORDER;
27624  }
27625 
27627  if(argnum == 0) {
27628  return OPF_SHIP;
27629  } else {
27630  return OPF_TURRET_TARGET_ORDER;
27631  }
27632 
27636  if (argnum == 0)
27637  return OPF_SHIP;
27638  else
27639  return OPF_ROTATING_SUBSYSTEM;
27640 
27642  if (argnum == 0)
27643  return OPF_SHIP;
27644  else if (argnum == 1)
27645  return OPF_ROTATING_SUBSYSTEM;
27646  else if (argnum == 2)
27647  return OPF_NUMBER;
27648  else
27649  return OPF_POSITIVE;
27650 
27652  if (argnum == 0)
27653  return OPF_SHIP;
27654  else if (argnum == 1)
27655  return OPF_ANIMATION_TYPE;
27656  else if (argnum == 2 || argnum == 3)
27657  return OPF_NUMBER;
27658  else if (argnum == 4)
27659  return OPF_BOOL;
27660  else if (argnum == 5)
27661  return OPF_SUBSYSTEM;
27662 
27663  case OP_BEAM_FREE_ALL:
27664  case OP_BEAM_LOCK_ALL:
27665  case OP_TURRET_FREE_ALL:
27666  case OP_TURRET_LOCK_ALL:
27669  return OPF_SHIP;
27670 
27671  case OP_ADD_REMOVE_ESCORT:
27672  if(argnum == 0){
27673  return OPF_SHIP;
27674  } else {
27675  return OPF_NUMBER;
27676  }
27677 
27678  case OP_AWACS_SET_RADIUS:
27679  if(argnum == 0){
27680  return OPF_SHIP;
27681  } else if(argnum == 1){
27682  return OPF_AWACS_SUBSYSTEM;
27683  } else {
27684  return OPF_NUMBER;
27685  }
27686 
27688  if (!argnum)
27689  return OPF_SHIP;
27690  else
27691  return OPF_NUMBER;
27692 
27693  case OP_CAP_WAYPOINT_SPEED:
27694  if (argnum == 0) {
27695  return OPF_SHIP;
27696  } else {
27697  return OPF_NUMBER;
27698  }
27699 
27700  case OP_SUBSYS_SET_RANDOM:
27701  if (argnum == 0) {
27702  return OPF_SHIP;
27703  } else if (argnum == 1 || argnum == 2) {
27704  return OPF_NUMBER;
27705  } else {
27706  return OPF_SUBSYSTEM;
27707  }
27708 
27709  case OP_SUPERNOVA_START:
27710  return OPF_POSITIVE;
27711 
27715  return OPF_SHIP;
27716 
27717  case OP_GET_ETS_VALUE:
27718  if (argnum == 0) {
27719  return OPF_STRING;
27720  } else {
27721  return OPF_SHIP;
27722  }
27723 
27724  case OP_SET_ETS_VALUES:
27725  if (argnum < 3) {
27726  return OPF_POSITIVE;
27727  } else {
27728  return OPF_SHIP;
27729  }
27730 
27731  case OP_SHIELD_QUAD_LOW:
27732  if(argnum == 0){
27733  return OPF_SHIP;
27734  } else {
27735  return OPF_NUMBER;
27736  }
27737 
27738  case OP_PRIMARY_AMMO_PCT:
27739  case OP_SECONDARY_AMMO_PCT:
27740  if(argnum == 0){
27741  return OPF_SHIP;
27742  } else {
27743  return OPF_NUMBER;
27744  }
27745 
27746  // Karajorma
27747  case OP_GET_PRIMARY_AMMO:
27748  case OP_SET_PRIMARY_AMMO:
27749  case OP_GET_SECONDARY_AMMO:
27750  case OP_SET_SECONDARY_AMMO:
27751  if(argnum == 0){
27752  return OPF_SHIP;
27753  } else {
27754  return OPF_NUMBER;
27755  }
27756 
27757  // Karajorma
27758  case OP_SET_PRIMARY_WEAPON:
27760  if(argnum == 0)
27761  {
27762  return OPF_SHIP;
27763  }
27764 
27765  else if (argnum == 2)
27766  {
27767  return OPF_WEAPON_NAME;
27768  }
27769  else
27770  {
27771  return OPF_NUMBER;
27772  }
27773 
27774  // DahBlount
27779  if (argnum == 0){
27780  return OPF_SHIP;
27781  } else if (argnum == 1){
27782  return OPF_SUBSYSTEM;
27783  } else {
27784  return OPF_NUMBER;
27785  }
27786 
27788  return OPF_SHIP;
27789 
27791  if (argnum == 0)
27792  return OPF_SHIP;
27793  else
27794  return OPF_POSITIVE;
27795 
27796  // Karajorma
27801  // KeldorKatarn
27802  case OP_LOCK_AFTERBURNER:
27803  case OP_UNLOCK_AFTERBURNER:
27804  return OPF_SHIP;
27805 
27806 
27808  case OP_SET_WEAPON_ENERGY:
27809  case OP_SET_SHIELD_ENERGY:
27810  if (argnum == 0) {
27811  return OPF_POSITIVE;
27812  }
27813  else {
27814  return OPF_SHIP;
27815  }
27816 
27817  case OP_SET_AMBIENT_LIGHT:
27818  return OPF_POSITIVE;
27819 
27820  case OP_SET_POST_EFFECT:
27821  if (argnum == 0)
27822  return OPF_POST_EFFECT;
27823  else
27824  return OPF_POSITIVE;
27825 
27827  if (argnum == 0) {
27828  return OPF_SHIP;
27829  }
27830  else if (argnum == 1) {
27831  return OPF_STRING;
27832  }
27833  else {
27834  return OPF_SUBSYSTEM;
27835  }
27836 
27839  if(argnum == 0){
27840  return OPF_SHIP;
27841  } else {
27842  return OPF_NUMBER;
27843  }
27844 
27846  if (argnum < 2)
27847  {
27848  return OPF_NUMBER;
27849  }
27850  else
27851  {
27852  return OPF_SHIP;
27853  }
27854 
27856  return OPF_POSITIVE;
27857 
27858  case OP_CHANGE_SHIP_CLASS:
27859  if (!argnum)
27860  return OPF_SHIP_CLASS_NAME;
27861  else
27862  return OPF_SHIP;
27863 
27864  case OP_SHIP_COPY_DAMAGE:
27865  return OPF_SHIP;
27866 
27867  case OP_DEACTIVATE_GLOW_POINTS: //-Bobboau
27868  case OP_ACTIVATE_GLOW_POINTS: //-Bobboau
27869  case OP_DEACTIVATE_GLOW_MAPS: //-Bobboau
27870  case OP_ACTIVATE_GLOW_MAPS: //-Bobboau
27871  return OPF_SHIP; //a list of ships that are to be activated/deactivated
27874  if (!argnum)
27875  return OPF_SHIP; //the ship
27876  else
27877  return OPF_POSITIVE; //the glow bank to disable
27878 
27879  // taylor
27880  case OP_SET_SKYBOX_MODEL:
27881  if (argnum == 0)
27882  return OPF_SKYBOX_MODEL_NAME;
27883  else if (argnum == 1)
27884  return OPF_BOOL;
27885  else
27886  return OPF_SKYBOX_FLAGS;
27887 
27888  case OP_SET_SKYBOX_ORIENT:
27889  return OPF_NUMBER;
27890 
27891  // Goober5000 - this is complicated :)
27892  case OP_SET_SUPPORT_SHIP:
27893  if ((argnum == 0) || (argnum == 2))
27894  return OPF_DEPARTURE_LOCATION; // use this for both because we don't want Near Ship or In Front of Ship
27895  if ((argnum == 1) || (argnum == 3))
27896  return OPF_SHIP_WITH_BAY; // same - we don't want to anchor around anything without a docking bay
27897  if (argnum == 4)
27898  return OPF_SUPPORT_SHIP_CLASS;
27899  if (argnum == 5)
27900  return OPF_NUMBER;
27901  if (argnum == 6)
27902  return OPF_NUMBER;
27903  break;
27904 
27905  // Goober5000
27906  case OP_SET_ARRIVAL_INFO:
27907  if (argnum == 0)
27908  return OPF_SHIP_WING;
27909  else if (argnum == 1)
27910  return OPF_ARRIVAL_LOCATION;
27911  else if (argnum == 2)
27912  return OPF_ARRIVAL_ANCHOR_ALL;
27913  else if (argnum == 3)
27914  return OPF_NUMBER;
27915  else if (argnum == 4 || argnum == 5)
27916  return OPF_POSITIVE;
27917  else if (argnum == 6)
27918  return OPF_BOOL;
27919  break;
27920 
27921  // Goober5000
27922  case OP_SET_DEPARTURE_INFO:
27923  if (argnum == 0)
27924  return OPF_SHIP_WING;
27925  else if (argnum == 1)
27926  return OPF_DEPARTURE_LOCATION;
27927  else if (argnum == 2)
27928  return OPF_SHIP_WITH_BAY;
27929  else if (argnum == 3 || argnum == 4)
27930  return OPF_NUMBER;
27931  else if (argnum == 5)
27932  return OPF_BOOL;
27933  break;
27934 
27935  case OP_KAMIKAZE:
27936  if (argnum==0)
27937  return OPF_POSITIVE;
27938  else
27939  return OPF_SHIP_WING;
27940 
27941  case OP_NUM_SHIPS_IN_BATTLE: //phreak modified by FUBAR
27942  return OPF_SHIP_WING_WHOLETEAM;
27943 
27944  case OP_NUM_SHIPS_IN_WING: // Karajorma
27945  return OPF_WING;
27946 
27947  case OP_CURRENT_SPEED:
27948  return OPF_SHIP_WING;
27949 
27952  if (argnum == 0)
27953  return OPF_SHIP;
27954  else
27955  return OPF_POSITIVE;
27956 
27957  case OP_HAS_PRIMARY_WEAPON:
27959  if (argnum == 0)
27960  return OPF_SHIP;
27961  else if (argnum == 1)
27962  return OPF_WEAPON_BANK_NUMBER;
27963  else
27964  return OPF_WEAPON_NAME;
27965 
27966  case OP_DIRECTIVE_VALUE:
27967  if (argnum == 0)
27968  return OPF_NUMBER;
27969  else
27970  return OPF_BOOL;
27971 
27972  case OP_NAV_IS_VISITED: //Kazan
27973  case OP_NAV_DISTANCE: //kazan
27974  case OP_NAV_DEL: //kazan
27975  case OP_NAV_HIDE: //kazan
27976  case OP_NAV_RESTRICT: //kazan
27977  case OP_NAV_UNHIDE: //kazan
27978  case OP_NAV_UNRESTRICT: //kazan
27979  case OP_NAV_SET_VISITED: //kazan
27980  case OP_NAV_UNSET_VISITED: //kazan
27981  case OP_NAV_SELECT: //Talon1024
27982  return OPF_STRING;
27983 
27984  case OP_NAV_SET_CARRY: //kazan
27985  case OP_NAV_UNSET_CARRY: //kazan
27986  return OPF_SHIP_WING;
27987 
27988  case OP_NAV_SET_NEEDSLINK: // kazan
27990  case OP_NAV_ISLINKED:
27991  return OPF_SHIP;
27992 
27993  case OP_NAV_USECINEMATICS:
27994  case OP_NAV_USEAP:
27995  return OPF_BOOL;
27996 
27997  case OP_NAV_ADD_WAYPOINT: //kazan
27998  if (argnum==0)
27999  return OPF_STRING;
28000  else if (argnum==1)
28001  return OPF_WAYPOINT_PATH;
28002  else if (argnum==2)
28003  return OPF_POSITIVE;
28004  else
28005  return OPF_SHIP_WING_WHOLETEAM;
28006 
28007  case OP_NAV_ADD_SHIP: //kazan
28008  if (argnum==0)
28009  return OPF_STRING;
28010  else
28011  return OPF_SHIP;
28012 
28013  //<Cutscenes>
28014  case OP_SCRAMBLE_MESSAGES:
28016  return OPF_SHIP;
28017 
28018  case OP_CUTSCENES_GET_FOV:
28019  return OPF_NONE;
28020 
28023  case OP_CUTSCENES_FADE_IN:
28024  case OP_CUTSCENES_FADE_OUT:
28026  return OPF_POSITIVE;
28027 
28028  case OP_CUTSCENES_SET_FOV:
28029  return OPF_NUMBER;
28030 
28032  return OPF_STRING;
28033 
28037  if(argnum < 3)
28038  return OPF_NUMBER;
28039  else
28040  return OPF_POSITIVE;
28041 
28043  if(argnum < 1)
28044  return OPF_SHIP_WING_POINT;
28045  else
28046  return OPF_POSITIVE;
28047 
28049  return OPF_POSITIVE;
28050 
28053  if(argnum < 1)
28055  else
28056  return OPF_SUBSYSTEM_OR_NONE;
28057 
28059  return OPF_BOOL;
28060 
28063  return OPF_NONE;
28064 
28066  if(argnum==0)
28067  return OPF_BOOL;
28068  else
28069  return OPF_POSITIVE;
28070 
28071  case OP_SET_CAMERA_SHUDDER:
28072  return OPF_POSITIVE;
28073 
28075  if(argnum < 2)
28076  return OPF_NUMBER;
28077  else if (argnum == 2)
28078  return OPF_STRING;
28079  else if (argnum == 3)
28080  return OPF_POSITIVE;
28081  else if (argnum == 4)
28082  return OPF_STRING;
28083  else if (argnum == 5)
28084  return OPF_POSITIVE;
28085  else if (argnum < 8)
28086  return OPF_BOOL;
28087  else if (argnum < 12)
28088  return OPF_POSITIVE;
28089  else if (argnum == 12 )
28090  return OPF_BOOL;
28091 
28093  if (argnum == 0)
28094  return OPF_MESSAGE_OR_STRING;
28095  else if (argnum == 1 || argnum == 2)
28096  return OPF_NUMBER;
28097  else if (argnum == 3 || argnum == 4)
28098  return OPF_BOOL;
28099  else if (argnum >= 5 && argnum <= 10)
28100  return OPF_POSITIVE;
28101  else if (argnum == 11)
28102  return OPF_FONT;
28103  else if (argnum == 12)
28104  return OPF_BOOL;
28105 
28107  if (argnum == 0)
28108  return OPF_STRING;
28109  else if (argnum == 1 || argnum == 2)
28110  return OPF_NUMBER;
28111  else if (argnum == 3 || argnum == 4)
28112  return OPF_BOOL;
28113  else if (argnum >= 5 && argnum <= 8)
28114  return OPF_POSITIVE;
28115  else if (argnum == 9)
28116  return OPF_BOOL;
28117 
28118  //</Cutscenes>
28119 
28120  case OP_JUMP_NODE_SET_JUMPNODE_NAME: //CommanderDJ
28121  if(argnum==0)
28122  return OPF_JUMP_NODE_NAME;
28123  else if (argnum==1)
28124  return OPF_STRING;
28125 
28127  if(argnum==0)
28128  return OPF_JUMP_NODE_NAME;
28129  else
28130  return OPF_POSITIVE;
28131 
28133  if(argnum==0)
28134  return OPF_JUMP_NODE_NAME;
28135  else if (argnum == 1)
28136  return OPF_STRING;
28137  else
28138  return OPF_BOOL;
28139 
28142  return OPF_JUMP_NODE_NAME;
28143 
28145  if (argnum == 0)
28146  return OPF_BACKGROUND_BITMAP;
28147  else if (argnum == 8)
28148  return OPF_VARIABLE_NAME;
28149  else
28150  return OPF_POSITIVE;
28151 
28153  return OPF_POSITIVE;
28154 
28155  case OP_ADD_SUN_BITMAP:
28156  if (argnum == 0)
28157  return OPF_SUN_BITMAP;
28158  else if (argnum == 5)
28159  return OPF_VARIABLE_NAME;
28160  else
28161  return OPF_POSITIVE;
28162 
28163  case OP_REMOVE_SUN_BITMAP:
28164  return OPF_POSITIVE;
28165 
28167  return OPF_NEBULA_STORM_TYPE;
28168 
28170  return OPF_NEBULA_PATTERN;
28171 
28172  case OP_NEBULA_TOGGLE_POOF:
28173  if (!argnum)
28174  return OPF_NEBULA_POOF;
28175  else
28176  return OPF_BOOL;
28177 
28178  case OP_SCRIPT_EVAL_NUM:
28179  case OP_SCRIPT_EVAL_BLOCK:
28180  case OP_SCRIPT_EVAL:
28181  return OPF_STRING;
28182 
28183  case OP_SCRIPT_EVAL_STRING:
28184  if (!argnum)
28185  return OPF_STRING;
28186  else
28187  return OPF_VARIABLE_NAME;
28188 
28189  case OP_SCRIPT_EVAL_MULTI:
28190  if (argnum == 0)
28191  return OPF_STRING;
28192  else if (argnum == 1)
28193  return OPF_BOOL;
28194  else
28195  return OPF_SHIP;
28196 
28197  case OP_CHANGE_IFF_COLOR:
28198  if ((argnum == 0) || (argnum == 1))
28199  return OPF_IFF;
28200  else if ((argnum >= 2) && (argnum <=4))
28201  return OPF_POSITIVE;
28202  else return OPF_SHIP_WING;
28203 
28204  case OP_HUD_DISPLAY_GAUGE:
28205  if ( argnum == 0 ) {
28206  return OPF_POSITIVE;
28207  } else {
28208  return OPF_HUD_ELEMENT;
28209  }
28210 
28211  case OP_DISABLE_ETS:
28212  case OP_ENABLE_ETS:
28213  return OPF_SHIP;
28214 
28215  case OP_IS_FACING:
28216  if (argnum == 0)
28217  return OPF_SHIP;
28218  else if (argnum == 1)
28219  return OPF_SHIP_POINT;
28220  else
28221  return OPF_POSITIVE;
28222 
28223  case OP_FORCE_GLIDE:
28224  if (argnum == 0)
28225  return OPF_SHIP;
28226  else
28227  return OPF_BOOL;
28228 
28229  case OP_HUD_SET_DIRECTIVE:
28230  return OPF_STRING;
28231 
28233  if (argnum == 0)
28234  return OPF_STRING;
28235  else
28236  return OPF_BOOL;
28237 
28239  if (argnum == 0)
28240  return OPF_HUD_GAUGE;
28241  else
28242  return OPF_BOOL;
28243 
28245  if (argnum == 0)
28246  return OPF_BOOL;
28247  else
28248  return OPF_STRING;
28249 
28251  if (argnum == 0)
28252  return OPF_BOOL;
28253  else
28254  return OPF_HUD_GAUGE;
28255 
28256  case OP_GET_COLGROUP_ID:
28257  return OPF_SHIP;
28258 
28259  case OP_ADD_TO_COLGROUP:
28260  if (argnum == 0)
28261  return OPF_SHIP;
28262  else
28263  return OPF_POSITIVE;
28264 
28266  if (argnum == 0)
28267  return OPF_SHIP;
28268  else
28269  return OPF_POSITIVE;
28270 
28271  case OP_SHIP_EFFECT:
28272  if (argnum == 0)
28273  return OPF_SHIP_EFFECT;
28274  else if (argnum == 1)
28275  return OPF_NUMBER;
28276  else
28277  return OPF_SHIP_WING;
28278 
28279  case OP_CLEAR_SUBTITLES:
28280  return OPF_NONE;
28281 
28282  case OP_SET_THRUSTERS:
28283  if (argnum == 0)
28284  return OPF_BOOL;
28285  else
28286  return OPF_SHIP;
28287 
28288  case OP_SET_MOTION_DEBRIS:
28289  return OPF_BOOL;
28290 
28291  default:
28292  Int3();
28293  }
28294 
28295  return 0;
28296 }
28297 
28298 // DA: 1/7/99 Used to rename ships and waypoints, not variables
28299 // Strictly used in FRED
28300 void update_sexp_references(const char *old_name, const char *new_name)
28301 {
28302  int i;
28303 
28304  Assert(strlen(new_name) < TOKEN_LENGTH);
28305  for (i = 0; i < Num_sexp_nodes; i++)
28306  {
28307  if ((SEXP_NODE_TYPE(i) == SEXP_ATOM) && (Sexp_nodes[i].subtype == SEXP_ATOM_STRING))
28308  if (!stricmp(CTEXT(i), old_name))
28309  strcpy(CTEXT(i), new_name);
28310  }
28311 }
28312 
28313 // DA: 1/7/99 Used to rename event names, goal names, not variables
28314 // Strictly used in FRED
28315 void update_sexp_references(const char *old_name, const char *new_name, int format)
28316 {
28317  int i;
28318  if (!strcmp(old_name, new_name)) {
28319  return;
28320  }
28321 
28322  Assert(strlen(new_name) < TOKEN_LENGTH);
28323  for (i = 0; i < Num_sexp_nodes; i++)
28324  {
28325  if (is_sexp_top_level(i))
28326  update_sexp_references(old_name, new_name, format, i);
28327  }
28328 }
28329 
28330 // DA: 1/7/99 Used to rename event names, goal names, not variables
28331 // recursive function to update references to a certain type of data
28332 void update_sexp_references(const char *old_name, const char *new_name, int format, int node)
28333 {
28334  int i, n, op;
28335 
28336  if (node < 0)
28337  return;
28338 
28339  if ((SEXP_NODE_TYPE(node) == SEXP_LIST) && (Sexp_nodes[node].subtype == SEXP_ATOM_LIST))
28340  {
28341  if (Sexp_nodes[node].first)
28342  update_sexp_references(old_name, new_name, format, Sexp_nodes[node].first);
28343 
28344  if (Sexp_nodes[node].rest)
28345  update_sexp_references(old_name, new_name, format, Sexp_nodes[node].rest);
28346 
28347  return;
28348  }
28349 
28350  if (SEXP_NODE_TYPE(node) != SEXP_ATOM)
28351  return;
28352 
28353  if (Sexp_nodes[node].subtype != SEXP_ATOM_OPERATOR)
28354  return;
28355 
28356  op = get_operator_index(CTEXT(node));
28357  Assert(Sexp_nodes[node].first < 0);
28358  n = Sexp_nodes[node].rest;
28359  i = 0;
28360  while (n >= 0)
28361  {
28362  if (SEXP_NODE_TYPE(n) == SEXP_LIST)
28363  {
28364  update_sexp_references(old_name, new_name, format, Sexp_nodes[n].first);
28365  }
28366  else
28367  {
28368  Assert((SEXP_NODE_TYPE(n) == SEXP_ATOM) && ((Sexp_nodes[n].subtype == SEXP_ATOM_NUMBER) || (Sexp_nodes[n].subtype == SEXP_ATOM_STRING)));
28369 
28370  if (query_operator_argument_type(op, i) == format)
28371  {
28372  if (!stricmp(CTEXT(n), old_name))
28373  strcpy(CTEXT(n), new_name);
28374  }
28375  }
28376 
28377  n = Sexp_nodes[n].rest;
28378  i++;
28379  }
28380 }
28381 
28382 int query_referenced_in_sexp(int mode, char *name, int *node)
28383 {
28384  int i, n, j;
28385 
28386  for (n=0; n<Num_sexp_nodes; n++){
28387  if ((SEXP_NODE_TYPE(n) == SEXP_ATOM) && (Sexp_nodes[n].subtype == SEXP_ATOM_STRING)){
28388  if (!stricmp(CTEXT(n), name)){
28389  break;
28390  }
28391  }
28392  }
28393 
28394  if (n == Num_sexp_nodes){
28395  return 0;
28396  }
28397 
28398  if (node){
28399  *node = n;
28400  }
28401 
28402  // so we know it's being used somewhere.. Time to find out where..
28403  for (i=0; i<MAX_SHIPS; i++)
28404  if (Ships[i].objnum >= 0) {
28405  if (query_node_in_sexp(n, Ships[i].arrival_cue)){
28406  return i | SRC_SHIP_ARRIVAL;
28407  }
28408  if (query_node_in_sexp(n, Ships[i].departure_cue)){
28409  return i | SRC_SHIP_DEPARTURE;
28410  }
28411  }
28412 
28413  for (i=0; i<MAX_WINGS; i++){
28414  if (Wings[i].wave_count) {
28415  if (query_node_in_sexp(n, Wings[i].arrival_cue)){
28416  return i | SRC_WING_ARRIVAL;
28417  }
28418  if (query_node_in_sexp(n, Wings[i].departure_cue)){
28419  return i | SRC_WING_DEPARTURE;
28420  }
28421  }
28422  }
28423 
28424  for (i=0; i<Num_mission_events; i++){
28425  if (query_node_in_sexp(n, Mission_events[i].formula)){
28426  return i | SRC_EVENT;
28427  }
28428  }
28429 
28430  for (i=0; i<Num_goals; i++){
28431  if (query_node_in_sexp(n, Mission_goals[i].formula)){
28432  return i | SRC_MISSION_GOAL;
28433  }
28434  }
28435 
28436  for (j=0; j<Num_teams; j++) {
28437  for (i=0; i<Debriefings[j].num_stages; i++) {
28438  if (query_node_in_sexp(n, Debriefings[j].stages[i].formula)){
28439  return i | SRC_DEBRIEFING;
28440  }
28441  }
28442  }
28443 
28444  for (j=0; j<Num_teams; j++) {
28445  for (i=0; i<Briefings[j].num_stages; i++) {
28446  if (query_node_in_sexp(n, Briefings[j].stages[i].formula)){
28447  return i | SRC_BRIEFING;
28448  }
28449  }
28450  }
28451 
28452  return SRC_UNKNOWN;
28453 }
28454 
28455 int verify_vector(char *text)
28456 {
28457  char *str;
28458  int len = 0;
28459 
28460  if (text == NULL)
28461  return -1;
28462 
28463  len = strlen(text);
28464  if (text[0] != '(' || text[len - 1] != ')'){
28465  return -1;
28466  }
28467 
28468  str = &text[0];
28469  skip_white(&str);
28470  if (*str != '('){
28471  return -1;
28472  }
28473 
28474  str++;
28475  skip_white(&str);
28476  if (validate_float(&str)){
28477  return -1;
28478  }
28479 
28480  skip_white(&str);
28481  if (validate_float(&str)){
28482  return -1;
28483  }
28484 
28485  skip_white(&str);
28486  if (validate_float(&str)){
28487  return -1;
28488  }
28489 
28490  skip_white(&str);
28491  if (*str != ')'){
28492  return -1;
28493  }
28494 
28495  str++;
28496  skip_white(&str);
28497  if (*str){
28498  return -1;
28499  }
28500 
28501  return 0;
28502 }
28503 
28504 void skip_white(char **str)
28505 {
28506  if ((**str == ' ') || (**str == '\t')){
28507  (*str)++;
28508  }
28509 }
28510 
28511 int validate_float(char **str)
28512 {
28513  int count = 0, dot = 0;
28514 
28515  while (isdigit(**str) || **str == '.') {
28516  if (**str == '.') {
28517  if (dot){
28518  return -1;
28519  }
28520 
28521  dot = 1;
28522  }
28523 
28524  (*str)++;
28525  count++;
28526  }
28527 
28528  if (!count){
28529  return -1;
28530  }
28531 
28532  return 0;
28533 }
28534 
28538 int sexp_query_type_match(int opf, int opr)
28539 {
28540  switch (opf) {
28541  case OPF_NUMBER:
28542  return ((opr == OPR_NUMBER) || (opr == OPR_POSITIVE));
28543 
28544  case OPF_POSITIVE:
28545  // Goober5000's number hack
28546  return ((opr == OPR_POSITIVE) || (opr == OPR_NUMBER));
28547 
28548  case OPF_BOOL:
28549  return (opr == OPR_BOOL);
28550 
28551  case OPF_NULL:
28552  return (opr == OPR_NULL);
28553 
28554  // Goober5000
28555  case OPF_FLEXIBLE_ARGUMENT:
28556  return (opr == OPR_FLEXIBLE_ARGUMENT);
28557 
28558  // Goober5000
28559  case OPF_ANYTHING:
28560  // don't match any operators, only data
28561  return 0;
28562 
28563  case OPF_AI_GOAL:
28564  return (opr == OPR_AI_GOAL);
28565  }
28566 
28567  return 0;
28568 }
28569 
28571 {
28572  switch (num) {
28573  case SEXP_CHECK_NONOP_ARGS:
28574  return "Data shouldn't have arguments";
28575 
28577  return "Operator expected instead of data";
28578 
28579  case SEXP_CHECK_UNKNOWN_OP:
28580  return "Unrecognized operator";
28581 
28583  return "Argument type mismatch";
28584 
28586  return "Argument count is illegal";
28587 
28589  return "Unknown operator argument type";
28590 
28592  return "Not a number";
28593 
28595  return "Invalid ship name";
28596 
28598  return "Invalid wing name";
28599 
28601  return "Invalid subsystem name";
28602 
28604  return "Invalid subsystem type";
28605 
28607  return "Invalid team name";
28608 
28610  return "Invalid AI class name";
28611 
28613  return "Invalid point";
28614 
28616  return "Negative number not allowed";
28617 
28619  return "Invalid ship/wing name";
28620 
28622  return "Invalid ship type";
28623 
28625  return "Invalid message name";
28626 
28628  return "Invalid priority";
28629 
28631  return "Invalid mission filename";
28632 
28634  return "Invalid goal name";
28635 
28637  return "Mission level too low in tree";
28638 
28640  return "Invalid message source";
28641 
28643  return "Invalid docker point";
28644 
28646  return "Invalid dockee point";
28647 
28649  return "Ship not allowed to have this order";
28650 
28652  return "Ship can't dock with target ship";
28653 
28655  return "Number is out of range";
28656 
28658  return "Event name is invalid (not known)";
28659 
28661  return "Skill level name is invalid (not known)";
28662 
28664  return "Invalid medal name";
28665 
28667  return "Invalid weapon name";
28668 
28670  return "Invalid intel name";
28671 
28673  return "Invalid ship class name";
28674 
28676  return "Invalid HUD gauges name";
28677 
28679  return "Invalid Jump Node name";
28680 
28682  return "Unknown error";
28683 
28685  return "Invalid support ship class";
28686 
28688  return "Ship does not have a fighter bay";
28689 
28691  return "Invalid arrival location";
28692 
28694  return "Invalid departure location";
28695 
28697  return "Invalid universal arrival anchor";
28698 
28700  return "Invalid soundtrack name";
28701 
28703  return "Invalid persona name";
28704 
28706  return "Invalid variable name";
28707 
28709  return "Invalid variable type";
28710 
28712  return "Invalid font";
28713 
28715  return "Invalid hud element magic name";
28716 
28718  return "Invalid sound environment";
28719 
28721  return "Invalid sound environment option";
28722 
28724  return "Invalid audio volume option";
28725 
28727  return "Invalid explosion option";
28728 
28730  return "Invalid ship effect name";
28731 
28733  return "Invalid turret target order";
28734 
28736  return "Invalid armor type";
28737 
28739  return "Invalid damage type";
28740 
28742  return "Invalid hud gauge";
28743 
28745  return "Invalid target priorities";
28746 
28748  return "Invalid animation type";
28749 
28751  return "Invalid mission mood";
28752 
28754  return "Invalid ship flag";
28755 
28757  return "Not a valid Team Color setting";
28758 
28760  return "Invalid game sound";
28761 
28763  return "Invalid SSM class";
28764 
28765  default:
28766  Warning(LOCATION, "Unhandled sexp error code %d!", num);
28767  return "Unhandled sexp error code!";
28768  }
28769 }
28770 
28771 int query_sexp_ai_goal_valid(int sexp_ai_goal, int ship_num)
28772 {
28773  int i, op;
28774 
28775  for (op=0; op<Num_operators; op++)
28776  if (Operators[op].value == sexp_ai_goal)
28777  break;
28778 
28779  Assert(op < Num_operators);
28780  for (i=0; i<Num_sexp_ai_goal_links; i++)
28781  if (Sexp_ai_goal_links[i].op_code == sexp_ai_goal)
28782  break;
28783 
28784  Assert(i < Num_sexp_ai_goal_links);
28785  return ai_query_goal_valid(ship_num, Sexp_ai_goal_links[i].ai_goal);
28786 }
28787 
28788 // Takes an Sexp_node.text pointing to a variable (of form "Sexp_variables[xx]=string" or "Sexp_variables[xx]=number")
28789 // and returns the index into the Sexp_variables array of the actual value
28791 {
28792  char *text = Sexp_nodes[node].text;
28793  char char_index[8];
28794  char *start_index;
28795  int variable_index;
28796 
28797  // get past the '['
28798  start_index = text + 15;
28799  Assert(isdigit(*start_index));
28800 
28801  int len = 0;
28802 
28803  while ( *start_index != ']' ) {
28804  char_index[len++] = *(start_index++);
28805  Assert(len < 3);
28806  }
28807 
28808  Assert(len > 0);
28809  char_index[len] = 0; // append null termination to string
28810 
28811  variable_index = atoi(char_index);
28812  Assert( (variable_index >= 0) && (variable_index < MAX_SEXP_VARIABLES) );
28813 
28814  return variable_index;
28815 }
28816 
28817 
28821 char *CTEXT(int n)
28822 {
28823  int sexp_variable_index = -1;
28824  char variable_name[TOKEN_LENGTH];
28825  char *current_argument;
28826 
28827  Assertion(n >= 0 && n < Num_sexp_nodes, "Passed an out-of-range node index (%d) to CTEXT!", n);
28828  if ( n < 0 ) {
28829  return NULL;
28830  }
28831 
28832  // Goober5000 - MWAHAHAHAHAHAHAHA! Thank you, Volition programmers! Without
28833  // the CTEXT wrapper, when-argument would probably be infeasibly difficult to code.
28834  if (!strcmp(Sexp_nodes[n].text, SEXP_ARGUMENT_STRING))
28835  {
28836  if (Fred_running)
28837  {
28838  // CTEXT is used when writing sexps to savefiles, so don't translate the argument
28839  return Sexp_nodes[n].text;
28840  }
28841  else
28842  {
28843  // make sure we have an argument to replace it with
28844  if (Sexp_replacement_arguments.empty())
28845  return Sexp_nodes[n].text;
28846  }
28847 
28848  // if the replacement argument is a variable name, get the variable index
28849  sexp_variable_index = get_index_sexp_variable_name(Sexp_replacement_arguments.back());
28850 
28851  current_argument = Sexp_replacement_arguments.back();
28852 
28853  // if the replacement argument is a formatted variable name, get the variable index
28854  if (current_argument[0] == SEXP_VARIABLE_CHAR)
28855  {
28856  get_unformatted_sexp_variable_name(variable_name, current_argument);
28857  sexp_variable_index = get_index_sexp_variable_name(variable_name);
28858  }
28859 
28860  // if we have a variable, return the variable value, else return the regular argument
28861  if (sexp_variable_index != -1)
28862  return Sexp_variables[sexp_variable_index].text;
28863  else
28864  return Sexp_replacement_arguments.back();
28865  }
28866 
28867  // Goober5000 - if not special argument, proceed as normal
28868  if (Sexp_nodes[n].type & SEXP_FLAG_VARIABLE)
28869  {
28870  if (Fred_running)
28871  {
28872  sexp_variable_index = get_index_sexp_variable_name(Sexp_nodes[n].text);
28873  Assert(sexp_variable_index != -1);
28874  }
28875  else
28876  {
28877  sexp_variable_index = atoi(Sexp_nodes[n].text);
28878  }
28879  // Reference a Sexp_variable
28880  // string format -- "Sexp_variables[xx]=number" or "Sexp_variables[xx]=string", where xx is the index
28881 
28882  Assert( !(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NOT_USED) );
28883  Assert(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET);
28884 
28885  if (Log_event) {
28886  Current_event_log_variable_buffer->push_back(Sexp_variables[sexp_variable_index].text);
28887  Current_event_log_variable_buffer->push_back(Sexp_variables[sexp_variable_index].variable_name);
28888  }
28889 
28890  return Sexp_variables[sexp_variable_index].text;
28891  }
28892  else
28893  {
28894  return Sexp_nodes[n].text;
28895  }
28896 }
28897 
28898 
28903 {
28904  for (int i=0; i<MAX_SEXP_VARIABLES; i++) {
28905  Sexp_variables[i].type = SEXP_VARIABLE_NOT_USED;
28906  Block_variables[i].type = SEXP_VARIABLE_NOT_USED;
28907  }
28908 }
28909 
28913 void add_block_variable(const char *text, const char *var_name, int type, int index)
28914 {
28915  Assert( (index >= 0) && (index < MAX_SEXP_VARIABLES) );
28916 
28917  strcpy_s(Block_variables[index].text, text);
28918  strcpy_s(Block_variables[index].variable_name, var_name);
28919  Block_variables[index].type &= ~SEXP_VARIABLE_NOT_USED;
28920  Block_variables[index].type = (type | SEXP_VARIABLE_SET);
28921 
28922 }
28923 
28929 int sexp_add_variable(const char *text, const char *var_name, int type, int index)
28930 {
28931  // if index == -1, find next open slot
28932  if (index == -1) {
28933  for (int i=0; i<MAX_SEXP_VARIABLES; i++) {
28934  if (Sexp_variables[i].type == SEXP_VARIABLE_NOT_USED) {
28935  index = i;
28936  break;
28937  }
28938  }
28939  } else {
28940  Assert( (index >= 0) && (index < MAX_SEXP_VARIABLES) );
28941  }
28942 
28943  if (index >= 0) {
28944  strcpy_s(Sexp_variables[index].text, text);
28945  strcpy_s(Sexp_variables[index].variable_name, var_name);
28946  Sexp_variables[index].type &= ~SEXP_VARIABLE_NOT_USED;
28947  Sexp_variables[index].type = (type | SEXP_VARIABLE_SET);
28948  }
28949 
28950  return index;
28951 }
28952 
28953 // Goober5000 - minor variant of the above that is now required for variable arrays
28954 void sexp_add_array_block_variable(int index, bool is_numeric)
28955 {
28956  Assert(index >= 0 && index < MAX_SEXP_VARIABLES);
28957 
28958  strcpy_s(Sexp_variables[index].text, "");
28959  strcpy_s(Sexp_variables[index].variable_name, "variable array block");
28960 
28961  if (is_numeric)
28962  Sexp_variables[index].type = SEXP_VARIABLE_NUMBER | SEXP_VARIABLE_SET;
28963  else
28964  Sexp_variables[index].type = SEXP_VARIABLE_STRING | SEXP_VARIABLE_SET;
28965 }
28966 
28972 void sexp_modify_variable(char *text, int index, bool sexp_callback)
28973 {
28974  Assert(index >= 0 && index < MAX_SEXP_VARIABLES);
28975  Assert(Sexp_variables[index].type & SEXP_VARIABLE_SET);
28977 
28978  if (strchr(text, '$') != NULL)
28979  {
28980  // we want to use the same variable substitution that's in messages etc.
28981  SCP_string temp_text = text;
28983 
28984  // copy to original buffer
28985  int len = temp_text.copy(Sexp_variables[index].text, TOKEN_LENGTH);
28986  text[len] = 0;
28987  }
28988  else
28989  {
28990  // no variables, so no substitution
28991  strcpy_s(Sexp_variables[index].text, text);
28992  }
28993  Sexp_variables[index].type |= SEXP_VARIABLE_MODIFIED;
28994 
28995  // do multi_callback_here
28996  // if we're called from the sexp code send a SEXP packet (more efficient)
28997  if( MULTIPLAYER_MASTER && (Sexp_variables[index].type & SEXP_VARIABLE_NETWORK) && sexp_callback) {
28999  multi_send_int(index);
29000  multi_send_string(Sexp_variables[index].text);
29002  }
29003  // otherwise send a SEXP variable packet
29004  else if ( (Game_mode & GM_MULTIPLAYER) && (Sexp_variables[index].type & SEXP_VARIABLE_NETWORK) ) {
29005  send_variable_update_packet(index, Sexp_variables[index].text);
29006  }
29007 }
29008 
29010 {
29011  char value[TOKEN_LENGTH];
29012  int variable_index = -1;
29013 
29014  // get the data
29015  multi_get_int(variable_index);
29016  if (!multi_get_string(value)) {
29017  return;
29018  }
29019 
29020  // set the sexp_variable
29021  if ( (variable_index >= 0) && (variable_index < MAX_SEXP_VARIABLES) ) {
29022  // maybe create it first
29023  if (!(Sexp_variables[variable_index].type & SEXP_VARIABLE_SET)) {
29024  mprintf(("Warning; received multi packet for variable index which is not set! Assuming this should be an array block variable...\n"));
29026  }
29027 
29028  strcpy_s(Sexp_variables[variable_index].text, value);
29029  }
29030 }
29031 
29033 {
29034  int sexp_variable_index;
29035  int new_number;
29036  char *new_text;
29037  char number_as_str[TOKEN_LENGTH];
29038 
29039  Assert(n >= 0);
29040 
29041  // Only do single player or multi host
29042  if ( MULTIPLAYER_CLIENT )
29043  return;
29044 
29045  // get sexp_variable index
29046  Assert(Sexp_nodes[n].first == -1);
29047  sexp_variable_index = atoi(Sexp_nodes[n].text);
29048 
29049  // verify variable set
29050  Assert(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET);
29051 
29052  if (Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NUMBER)
29053  {
29054  // get new numerical value
29055  new_number = eval_sexp(CDR(n));
29056  sprintf(number_as_str, "%d", new_number);
29057 
29058  // assign to variable
29059  sexp_modify_variable(number_as_str, sexp_variable_index);
29060  }
29061  else if (Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_STRING)
29062  {
29063  // get new string
29064  new_text = CTEXT(CDR(n));
29065 
29066  // assign to variable
29067  sexp_modify_variable(new_text, sexp_variable_index);
29068  }
29069  else
29070  {
29071  Error(LOCATION, "Invalid variable type.\n");
29072  }
29073 }
29074 
29075 bool is_sexp_node_numeric(int node)
29076 {
29077  Assert(node >= 0);
29078 
29079  // make the common case fast: if the node has a CAR node, that means it uses an operator;
29080  // and operators cannot currently return strings
29081  if (Sexp_nodes[node].first >= 0)
29082  return true;
29083 
29084  // if the node text is numeric, the node is too
29085  if (can_construe_as_integer(Sexp_nodes[node].text))
29086  return true;
29087 
29088  // otherwise it's gotta be text
29089  return false;
29090 }
29091 
29092 // By Goober5000. Very similar to sexp_modify_variable(). Even uses the same multi code! :)
29094 {
29095  int sexp_variable_index;
29096  int new_number;
29097  char *new_text;
29098  char number_as_str[TOKEN_LENGTH];
29099 
29100  Assert(node >= 0);
29101 
29102  // Only do single player or multi host
29103  if ( MULTIPLAYER_CLIENT )
29104  return;
29105 
29106  // get sexp_variable index
29107  sexp_variable_index = eval_num(node);
29108 
29109  // check range
29110  if (sexp_variable_index < 0 || sexp_variable_index >= MAX_SEXP_VARIABLES)
29111  {
29112  Warning(LOCATION, "set-variable-by-index: sexp variable index %d out of range! min is 0; max is %d", sexp_variable_index, MAX_SEXP_VARIABLES - 1);
29113  return;
29114  }
29115 
29116  // verify variable set
29117  if (!(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET))
29118  {
29119  // well phooey. go ahead and create it
29120  sexp_add_array_block_variable(sexp_variable_index, is_sexp_node_numeric(CDR(node)));
29121  }
29122 
29123  if (Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NUMBER)
29124  {
29125  // get new numerical value
29126  new_number = eval_sexp(CDR(node));
29127  sprintf(number_as_str, "%d", new_number);
29128 
29129  // assign to variable
29130  sexp_modify_variable(number_as_str, sexp_variable_index);
29131  }
29132  else if (Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_STRING)
29133  {
29134  // get new string
29135  new_text = CTEXT(CDR(node));
29136 
29137  // assign to variable
29138  sexp_modify_variable(new_text, sexp_variable_index);
29139  }
29140  else
29141  {
29142  Error(LOCATION, "Invalid variable type.\n");
29143  }
29144 }
29145 
29146 // Goober5000
29148 {
29149  int sexp_variable_index;
29150 
29151  Assert(node >= 0);
29152 
29153  // get sexp_variable index
29154  sexp_variable_index = eval_num(node);
29155 
29156  // check range
29157  if (sexp_variable_index < 0 || sexp_variable_index >= MAX_SEXP_VARIABLES)
29158  {
29159  Warning(LOCATION, "get-variable-by-index: sexp variable index %d out of range! min is 0; max is %d", sexp_variable_index, MAX_SEXP_VARIABLES - 1);
29160  return 0;
29161  }
29162 
29163  if (Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NOT_USED)
29164  {
29165  mprintf(("warning: retrieving a value from a sexp variable which is not in use!\n"));
29166  }
29167  else if (!(Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SET))
29168  {
29169  mprintf(("warning: retrieving a value from a sexp variable which is not set!\n"));
29170  }
29171 
29172  if (Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_STRING)
29173  {
29174  mprintf(("warning: variable %d is a string but it is not possible to return a string value through a sexp!\n", sexp_variable_index));
29175  return SEXP_NAN_FOREVER;
29176  }
29177 
29178  return atoi(Sexp_variables[sexp_variable_index].text);
29179 }
29180 
29181 // Goober5000
29182 // (yes, this reuses a lot of code, but it's a major pain to consolidate it)
29184 {
29185  int from_index;
29186  int to_index;
29187 
29188  Assert(node >= 0);
29189 
29190  // Only do single player or multi host
29191  if ( MULTIPLAYER_CLIENT )
29192  return;
29193 
29194  // get sexp_variable index
29195  from_index = eval_num(node);
29196 
29197  // check range
29198  if (from_index < 0 || from_index >= MAX_SEXP_VARIABLES)
29199  {
29200  Warning(LOCATION, "copy-variable-from-index: sexp variable index %d out of range! min is 0; max is %d", from_index, MAX_SEXP_VARIABLES - 1);
29201  return;
29202  }
29203 
29204  if (Sexp_variables[from_index].type & SEXP_VARIABLE_NOT_USED)
29205  {
29206  mprintf(("warning: retrieving a value from a sexp variable which is not in use!\n"));
29207  }
29208  else if (!(Sexp_variables[from_index].type & SEXP_VARIABLE_SET))
29209  {
29210  mprintf(("warning: retrieving a value from a sexp variable which is not set!\n"));
29211  }
29212 
29213  // now get the variable we are modifying
29214  to_index = atoi(Sexp_nodes[CDR(node)].text);
29215 
29216  // verify variable set
29217  Assert(Sexp_variables[to_index].type & SEXP_VARIABLE_SET);
29218 
29219  // verify matching types
29220  if ( ((Sexp_variables[from_index].type & SEXP_VARIABLE_NUMBER) && !(Sexp_variables[to_index].type & SEXP_VARIABLE_NUMBER))
29221  || ((Sexp_variables[from_index].type & SEXP_VARIABLE_STRING) && !(Sexp_variables[to_index].type & SEXP_VARIABLE_STRING)) )
29222  {
29223  Warning(LOCATION, "copy-variable-from-index: cannot copy variables of different types! source = '%s', destination = '%s'", Sexp_variables[from_index].variable_name, Sexp_variables[to_index].variable_name);
29224  return;
29225  }
29226 
29227  // assign to variable
29228  sexp_modify_variable(Sexp_variables[from_index].text, to_index);
29229 }
29230 
29231 // Goober5000
29232 // (yes, this reuses a lot of code, but it's a major pain to consolidate it)
29233 // (and yes, that reused a comment :p)
29235 {
29236  int from_index;
29237  int to_index;
29238 
29239  Assert(node >= 0);
29240 
29241  // Only do single player or multi host
29242  if ( MULTIPLAYER_CLIENT )
29243  return;
29244 
29245  // get sexp_variable indexes
29246  from_index = eval_num(node);
29247  to_index = eval_num(CDR(node));
29248 
29249  // check ranges
29250  if (from_index < 0 || from_index >= MAX_SEXP_VARIABLES)
29251  {
29252  Warning(LOCATION, "copy-variable-between-indexes: sexp variable index %d out of range! min is 0; max is %d", from_index, MAX_SEXP_VARIABLES - 1);
29253  return;
29254  }
29255  if (to_index < 0 || to_index >= MAX_SEXP_VARIABLES)
29256  {
29257  Warning(LOCATION, "copy-variable-between-indexes: sexp variable index %d out of range! min is 0; max is %d", to_index, MAX_SEXP_VARIABLES - 1);
29258  return;
29259  }
29260 
29261  if (Sexp_variables[from_index].type & SEXP_VARIABLE_NOT_USED)
29262  {
29263  mprintf(("warning: retrieving a value from a sexp variable which is not in use!\n"));
29264  }
29265  else if (!(Sexp_variables[from_index].type & SEXP_VARIABLE_SET))
29266  {
29267  mprintf(("warning: retrieving a value from a sexp variable which is not set!\n"));
29268  }
29269 
29270  if (!(Sexp_variables[to_index].type & SEXP_VARIABLE_SET))
29271  {
29272  // well phooey. go ahead and create it
29273  sexp_add_array_block_variable(to_index, (Sexp_variables[from_index].type & SEXP_VARIABLE_NUMBER) != 0);
29274  }
29275 
29276  // verify matching types
29277  if ( ((Sexp_variables[from_index].type & SEXP_VARIABLE_NUMBER) && !(Sexp_variables[to_index].type & SEXP_VARIABLE_NUMBER))
29278  || ((Sexp_variables[from_index].type & SEXP_VARIABLE_STRING) && !(Sexp_variables[to_index].type & SEXP_VARIABLE_STRING)) )
29279  {
29280  Warning(LOCATION, "copy-variable-between-indexes: cannot copy variables of different types! source = '%s', destination = '%s'", Sexp_variables[from_index].variable_name, Sexp_variables[to_index].variable_name);
29281  return;
29282  }
29283 
29284  // assign to variable
29285  sexp_modify_variable(Sexp_variables[from_index].text, to_index);
29286 }
29287 
29288 // Different type needed for Fred (1) allow modification of type (2) no callback required
29289 void sexp_fred_modify_variable(const char *text, const char *var_name, int index, int type)
29290 {
29291  Assert(index >= 0 && index < MAX_SEXP_VARIABLES);
29292  Assert(Sexp_variables[index].type & SEXP_VARIABLE_SET);
29293  Assert( (type & SEXP_VARIABLE_NUMBER) || (type & SEXP_VARIABLE_STRING) );
29294 
29295  strcpy_s(Sexp_variables[index].text, text);
29296  strcpy_s(Sexp_variables[index].variable_name, var_name);
29297  Sexp_variables[index].type = (SEXP_VARIABLE_SET | SEXP_VARIABLE_MODIFIED | type);
29298 }
29299 
29304 {
29305  int var_index;
29306 
29307  if (!(Sexp_nodes[node].type & SEXP_FLAG_VARIABLE)) {
29308  return -1;
29309  }
29310 
29311  if (Fred_running) {
29312  var_index = get_index_sexp_variable_name(Sexp_nodes[node].text);
29313  }
29314  else {
29315  var_index = atoi(Sexp_nodes[node].text);
29316  }
29317 
29318  return var_index;
29319 }
29320 
29324 int get_index_sexp_variable_name(const char *text)
29325 {
29326  for (int i=0; i<MAX_SEXP_VARIABLES; i++) {
29327  if (Sexp_variables[i].type & SEXP_VARIABLE_SET) {
29328  // check case sensitive
29329  if ( !strcmp(Sexp_variables[i].variable_name, text) ) {
29330  return i;
29331  }
29332  }
29333  }
29334 
29335  // not found
29336  return -1;
29337 }
29338 
29343 {
29344  for (int i=0; i<MAX_SEXP_VARIABLES; i++) {
29345  if (Sexp_variables[i].type & SEXP_VARIABLE_SET) {
29346  // check case sensitive
29347  if ( text == Sexp_variables[i].variable_name ) {
29348  return i;
29349  }
29350  }
29351  }
29352 
29353  // not found
29354  return -1;
29355 }
29356 
29357 // Goober5000 - tests whether a variable name starts here
29358 // return index of sexp_variable_name, -1 if not found
29359 int get_index_sexp_variable_name_special(const char *startpos)
29360 {
29361  for (int i = MAX_SEXP_VARIABLES - 1; i >= 0; i--) {
29362  if (Sexp_variables[i].type & SEXP_VARIABLE_SET) {
29363  // check case sensitive
29364  // check number of chars in variable name
29365  if ( !strncmp(startpos, Sexp_variables[i].variable_name, strlen(Sexp_variables[i].variable_name)) ) {
29366  return i;
29367  }
29368  }
29369  }
29370 
29371  // not found
29372  return -1;
29373 }
29374 
29375 // Goober5000 - tests whether a variable name starts here
29376 // return index of sexp_variable_name, -1 if not found
29378 {
29379  for (int i = MAX_SEXP_VARIABLES - 1; i >= 0; i--) {
29380  if (Sexp_variables[i].type & SEXP_VARIABLE_SET) {
29381  // check case sensitive
29382  // check that the variable name starts here, as opposed to farther down the string
29383  size_t pos = text.find(Sexp_variables[i].variable_name, startpos);
29384  if (pos != SCP_string::npos && pos == startpos) {
29385  return i;
29386  }
29387  }
29388  }
29389 
29390  // not found
29391  return -1;
29392 }
29393 
29394 // Goober5000
29395 bool sexp_replace_variable_names_with_values(char *text, int max_len)
29396 {
29397  Assert(text != NULL);
29398  Assert(max_len >= 0);
29399 
29400  bool replaced_anything = false;
29401  char *pos = text;
29402  do {
29403  // look for the meta-character
29404  pos = strchr(pos, '$');
29405 
29406  // found?
29407  if (pos != NULL)
29408  {
29409  // see if a variable starts at the next char
29410  int var_index = get_index_sexp_variable_name_special(pos+1);
29411  if (var_index >= 0)
29412  {
29413  // get the replacement string ($variable)
29414  char what_to_replace[TOKEN_LENGTH+1];
29415  memset(what_to_replace, 0, TOKEN_LENGTH+1);
29416  strncpy(what_to_replace, pos, strlen(Sexp_variables[var_index].variable_name) + 1);
29417 
29418  // replace it
29419  pos = text + replace_one(text, what_to_replace, Sexp_variables[var_index].text, max_len);
29420  replaced_anything = true;
29421  }
29422  // no match... so keep iterating along the string
29423  else
29424  {
29425  pos++;
29426  }
29427  }
29428  } while (pos != NULL);
29429 
29430  return replaced_anything;
29431 }
29432 
29433 // Goober5000
29435 {
29436  bool replaced_anything = false;
29437 
29438  size_t lookHere = 0;
29439  size_t foundHere;
29440 
29441  do {
29442  // look for the meta-character
29443  foundHere = text.find('$', lookHere);
29444 
29445  // found?
29446  if (foundHere != SCP_string::npos)
29447  {
29448  // see if a variable starts at the next char
29449  int var_index = get_index_sexp_variable_name_special(text, foundHere+1);
29450  if (var_index >= 0)
29451  {
29452  // replace $variable with the value
29453  text.replace(foundHere, strlen(Sexp_variables[var_index].variable_name)+1, Sexp_variables[var_index].text);
29454  replaced_anything = true;
29455 
29456  lookHere = foundHere + strlen(Sexp_variables[var_index].text);
29457  }
29458  // no match... so keep iterating along the string
29459  else
29460  {
29461  lookHere = foundHere + 1;
29462  }
29463  }
29464  } while (foundHere != SCP_string::npos);
29465 
29466  return replaced_anything;
29467 }
29468 
29469 // returns the index of the nth variable of the type given or -1 if there aren't that many
29470 // NOTE : Not 0th order. If you want the 4th string variable call it as get_nth_variable_index(4, SEXP_VARIABLE_STRING)
29471 int get_nth_variable_index(int nth, int variable_type)
29472 {
29473  // Loop through Sexp_variables until we have found the one corresponding to the argument
29474  Assert ((nth > 0) && (nth < MAX_SEXP_VARIABLES));
29475  for (int i=0; i < MAX_SEXP_VARIABLES; i++) {
29476  if ((Sexp_variables[i].type & variable_type)) {
29477  nth--;
29478  }
29479 
29480  if (!nth) {
29481  return i;
29482  }
29483  }
29484  return -1;
29485 }
29486 
29491 {
29492  int count = 0;
29493 
29494  for (int i=0; i<MAX_SEXP_VARIABLES; i++) {
29495  if ( Sexp_variables[i].type & SEXP_VARIABLE_SET) {
29496  count++;
29497  }
29498  }
29499 
29500  return count;
29501 }
29502 
29507 {
29508  int count = 0;
29509 
29510  for (int i=0; i<MAX_SEXP_VARIABLES; i++) {
29511  if ( (Sexp_variables[i].type & SEXP_VARIABLE_SET) && (Sexp_variables[i].type & SEXP_VARIABLE_CAMPAIGN_PERSISTENT) ) {
29512  count++;
29513  }
29514  }
29515 
29516  return count;
29517 }
29518 
29522 int sexp_variable_typed_count(int sexp_variables_index, int variable_type)
29523 {
29524  Assert ((sexp_variables_index >= 0) && (sexp_variables_index < MAX_SEXP_VARIABLES));
29525  // Loop through Sexp_variables until we have found the one corresponding to the argument
29526  int count = 0;
29527  for (int i=0; i < MAX_SEXP_VARIABLES; i++) {
29528  if (!(Sexp_variables[i].type & variable_type)) {
29529  continue;
29530  }
29531 
29532  if (i == sexp_variables_index) {
29533  return count ;
29534  }
29535  count++;
29536  }
29537  // shouldn't ever get here
29538  Int3();
29539  return -1;
29540 }
29541 
29546 {
29547  Assert(Sexp_variables[index].type & SEXP_VARIABLE_SET);
29548 
29549  Sexp_variables[index].type = SEXP_VARIABLE_NOT_USED;
29550 }
29551 
29552 int sexp_var_compare(const void *var1, const void *var2)
29553 {
29554  int set1, set2;
29555  sexp_variable *sexp_var1, *sexp_var2;
29556 
29557  sexp_var1 = (sexp_variable*) var1;
29558  sexp_var2 = (sexp_variable*) var2;
29559 
29560  set1 = sexp_var1->type & SEXP_VARIABLE_SET;
29561  set2 = sexp_var2->type & SEXP_VARIABLE_SET;
29562 
29563  if (!set1 && !set2) {
29564  return 0;
29565  } else if (set1 && !set2) {
29566  return -1;
29567  } else if (!set1 && set2) {
29568  return 1;
29569  } else {
29570  return stricmp( sexp_var1->variable_name, sexp_var2->variable_name);
29571  }
29572 }
29573 
29578 {
29579  insertion_sort( (void *)Sexp_variables, (size_t)(MAX_SEXP_VARIABLES), sizeof(sexp_variable), sexp_var_compare );
29580 }
29581 
29585 int eval_num(int n)
29586 {
29587  if (n < 0)
29588  {
29589  Int3();
29590  return 0;
29591  }
29592 
29593  if (CAR(n) != -1) // if argument is a sexp
29594  return eval_sexp(CAR(n));
29595  else
29596  return atoi(CTEXT(n)); // otherwise, just get the number
29597 }
29598 
29599 // Goober5000
29600 int get_sexp_id(char *sexp_name)
29601 {
29602  for (int i = 0; i < Num_operators; i++)
29603  {
29604  if (!stricmp(sexp_name, Operators[i].text))
29605  return Operators[i].value;
29606  }
29607  return -1;
29608 }
29609 
29610 // Goober5000
29611 int get_category(int sexp_id)
29612 {
29613  int category = (sexp_id & OP_CATEGORY_MASK);
29614 
29615  // hack so that CHANGE and CHANGE2 show up in the same menu
29616  if (category == OP_CATEGORY_CHANGE2)
29617  category = OP_CATEGORY_CHANGE;
29618 
29619  return category;
29620 }
29621 
29622 // Goober5000
29623 int category_of_subcategory(int subcategory_id)
29624 {
29625  int category = (subcategory_id & OP_CATEGORY_MASK);
29626 
29627  // hack so that CHANGE and CHANGE2 show up in the same menu
29628  if (category == OP_CATEGORY_CHANGE2)
29629  category = OP_CATEGORY_CHANGE;
29630 
29631  return category;
29632 }
29633 
29634 // Goober5000 - for FRED2 menu subcategories
29635 int get_subcategory(int sexp_id)
29636 {
29637  switch(sexp_id)
29638  {
29639  case OP_SEND_MESSAGE_LIST:
29640  case OP_SEND_MESSAGE:
29642  case OP_SCRAMBLE_MESSAGES:
29646  case OP_SET_DEATH_MESSAGE:
29647  case OP_SET_PERSONA:
29648  case OP_SET_MISSION_MOOD:
29650 
29651  case OP_ADD_GOAL:
29652  case OP_REMOVE_GOAL:
29653  case OP_CLEAR_GOALS:
29654  case OP_GOOD_REARM_TIME:
29656  case OP_CHANGE_AI_CLASS:
29657  case OP_PLAYER_USE_AI:
29658  case OP_PLAYER_NOT_USE_AI:
29659  case OP_SET_PLAYER_ORDERS:
29660  case OP_CAP_WAYPOINT_SPEED:
29662 
29663  case OP_ALTER_SHIP_FLAG:
29664  case OP_PROTECT_SHIP:
29665  case OP_UNPROTECT_SHIP:
29666  case OP_BEAM_PROTECT_SHIP:
29670  case OP_SHIP_INVISIBLE:
29671  case OP_SHIP_VISIBLE:
29672  case OP_SHIP_STEALTHY:
29673  case OP_SHIP_UNSTEALTHY:
29679  case OP_KAMIKAZE:
29680  case OP_CHANGE_IFF:
29681  case OP_CHANGE_IFF_COLOR:
29682  case OP_ADD_REMOVE_ESCORT:
29685  case OP_SHIP_TAG:
29686  case OP_SHIP_UNTAG:
29687  case OP_SET_ARRIVAL_INFO:
29688  case OP_SET_DEPARTURE_INFO:
29690 
29691  case OP_SET_WEAPON_ENERGY:
29692  case OP_SET_SHIELD_ENERGY:
29695  case OP_SET_SUBSPACE_DRIVE:
29697  case OP_SET_PRIMARY_WEAPON: // Karajorma
29698  case OP_SET_SECONDARY_WEAPON: // Karajorma
29699  case OP_SET_PRIMARY_AMMO: // Karajorma
29700  case OP_SET_SECONDARY_AMMO: // Karajorma
29701  case OP_SET_NUM_COUNTERMEASURES: // Karajorma
29706  case OP_LOCK_AFTERBURNER: // KeldorKatarn
29707  case OP_UNLOCK_AFTERBURNER: // KeldorKatarn
29708  case OP_SHIELDS_ON:
29709  case OP_SHIELDS_OFF:
29710  case OP_FORCE_GLIDE:
29711  case OP_DISABLE_ETS:
29712  case OP_ENABLE_ETS:
29713  case OP_WARP_BROKEN:
29714  case OP_WARP_NOT_BROKEN:
29715  case OP_WARP_NEVER:
29716  case OP_WARP_ALLOWED:
29717  case OP_SET_ETS_VALUES:
29719 
29720  case OP_SHIP_INVULNERABLE:
29721  case OP_SHIP_VULNERABLE:
29722  case OP_SHIP_GUARDIAN:
29723  case OP_SHIP_NO_GUARDIAN:
29726  case OP_SELF_DESTRUCT:
29727  case OP_DESTROY_INSTANTLY:
29729  case OP_SABOTAGE_SUBSYSTEM:
29730  case OP_REPAIR_SUBSYSTEM:
29731  case OP_SHIP_COPY_DAMAGE:
29733  case OP_SUBSYS_SET_RANDOM:
29746  case OP_AWACS_SET_RADIUS:
29748 
29749  case OP_TRANSFER_CARGO:
29750  case OP_EXCHANGE_CARGO:
29751  case OP_SET_CARGO:
29752  case OP_JETTISON_CARGO:
29753  case OP_SET_DOCKED:
29754  case OP_CARGO_NO_DEPLETE:
29755  case OP_SET_SCANNED:
29756  case OP_SET_UNSCANNED:
29757  return CHANGE_SUBCATEGORY_CARGO;
29758 
29759  case OP_SET_ARMOR_TYPE:
29765 
29766  case OP_BEAM_FIRE:
29767  case OP_BEAM_FIRE_COORDS:
29768  case OP_BEAM_FLOATING_FIRE:
29769  case OP_BEAM_FREE:
29770  case OP_BEAM_FREE_ALL:
29771  case OP_BEAM_LOCK:
29772  case OP_BEAM_LOCK_ALL:
29773  case OP_TURRET_FREE:
29774  case OP_TURRET_FREE_ALL:
29775  case OP_TURRET_LOCK:
29776  case OP_TURRET_LOCK_ALL:
29795 
29796  case OP_CHANGE_SHIP_CLASS:
29798  case OP_ACTIVATE_GLOW_MAPS:
29803  case OP_SET_THRUSTERS:
29805  case OP_COLLIDE_INVISIBLE:
29806  case OP_ADD_TO_COLGROUP:
29808  case OP_GET_COLGROUP_ID:
29809  case OP_CHANGE_TEAM_COLOR:
29811 
29814  case OP_SET_OBJECT_FACING:
29816  case OP_SET_OBJECT_SPEED_X:
29817  case OP_SET_OBJECT_SPEED_Y:
29818  case OP_SET_OBJECT_SPEED_Z:
29819  case OP_SHIP_MANEUVER:
29820  case OP_SHIP_ROT_MANEUVER:
29821  case OP_SHIP_LAT_MANEUVER:
29822  case OP_SET_MOBILE:
29823  case OP_SET_IMMOBILE:
29825 
29826  case OP_INVALIDATE_GOAL:
29827  case OP_VALIDATE_GOAL:
29828  case OP_RED_ALERT:
29829  case OP_END_MISSION:
29830  case OP_FORCE_JUMP:
29831  case OP_END_CAMPAIGN:
29833  case OP_ALLOW_TREASON:
29834  case OP_GRANT_PROMOTION:
29835  case OP_GRANT_MEDAL:
29836  case OP_ALLOW_SHIP:
29837  case OP_ALLOW_WEAPON:
29838  case OP_TECH_ADD_SHIP:
29839  case OP_TECH_ADD_WEAPON:
29840  case OP_TECH_ADD_INTEL:
29844  case OP_CHANGE_TEAM_SCORE:
29845  case OP_SET_RESPAWNS:
29847 
29848  case OP_CHANGE_SOUNDTRACK:
29857 
29858  case OP_HUD_DISABLE:
29862  case OP_HUD_SET_TEXT:
29863  case OP_HUD_SET_TEXT_NUM:
29864  case OP_HUD_SET_MESSAGE:
29865  case OP_HUD_SET_DIRECTIVE:
29866  case OP_HUD_SET_FRAME:
29867  case OP_HUD_SET_COLOR:
29868  case OP_HUD_SET_COORDS:
29869  case OP_HUD_DISPLAY_GAUGE:
29872  case OP_HUD_CLEAR_MESSAGES:
29874  return CHANGE_SUBCATEGORY_HUD;
29875 
29876  case OP_NAV_ADD_WAYPOINT:
29877  case OP_NAV_ADD_SHIP:
29878  case OP_NAV_DEL:
29879  case OP_NAV_HIDE:
29880  case OP_NAV_RESTRICT:
29881  case OP_NAV_UNHIDE:
29882  case OP_NAV_UNRESTRICT:
29883  case OP_NAV_SET_VISITED:
29884  case OP_NAV_SET_CARRY:
29885  case OP_NAV_UNSET_CARRY:
29886  case OP_NAV_UNSET_VISITED:
29887  case OP_NAV_SET_NEEDSLINK:
29889  case OP_NAV_USECINEMATICS:
29890  case OP_NAV_USEAP:
29891  case OP_NAV_SELECT:
29892  case OP_NAV_UNSELECT:
29893  return CHANGE_SUBCATEGORY_NAV;
29894 
29897  case OP_CUTSCENES_FADE_IN:
29898  case OP_CUTSCENES_FADE_OUT:
29907  case OP_CUTSCENES_SET_FOV:
29908  case OP_CUTSCENES_GET_FOV:
29914  case OP_CLEAR_SUBTITLES:
29916  case OP_SET_CAMERA_SHUDDER:
29917  case OP_SUPERNOVA_START:
29918  case OP_SUPERNOVA_STOP:
29919  case OP_SET_MOTION_DEBRIS:
29921 
29922  case OP_SET_SKYBOX_MODEL:
29923  case OP_SET_SKYBOX_ORIENT:
29924  case OP_MISSION_SET_NEBULA:
29928  case OP_ADD_SUN_BITMAP:
29929  case OP_REMOVE_SUN_BITMAP:
29931  case OP_NEBULA_TOGGLE_POOF:
29933  case OP_SET_AMBIENT_LIGHT:
29935 
29936  case OP_JUMP_NODE_SET_JUMPNODE_NAME: //CommanderDJ
29942 
29943  case OP_SET_POST_EFFECT:
29944  case OP_SHIP_EFFECT:
29945  case OP_SHIP_CREATE:
29946  case OP_WEAPON_CREATE:
29947  case OP_SHIP_VANISH:
29948  case OP_SHIP_VAPORIZE:
29949  case OP_SHIP_NO_VAPORIZE:
29951  case OP_EXPLOSION_EFFECT:
29952  case OP_WARP_EFFECT:
29953  case OP_REMOVE_WEAPONS:
29956  case OP_CALL_SSM_STRIKE:
29958 
29959  case OP_MODIFY_VARIABLE:
29964  case OP_INT_TO_STRING:
29965  case OP_STRING_CONCATENATE:
29969 
29972  case OP_SET_SUPPORT_SHIP:
29973  case OP_SCRIPT_EVAL_STRING:
29974  case OP_SCRIPT_EVAL_BLOCK:
29975  case OP_SCRIPT_EVAL:
29976  case OP_SCRIPT_EVAL_MULTI:
29977  return CHANGE_SUBCATEGORY_OTHER;
29978 
29980  case OP_NUM_SHIPS_IN_WING:
29981  case OP_DIRECTIVE_VALUE:
29983 
29985  case OP_WAS_MEDAL_GRANTED:
29987  case OP_NUM_KILLS:
29988  case OP_NUM_ASSISTS:
29989  case OP_NUM_TYPE_KILLS:
29990  case OP_NUM_CLASS_KILLS:
29991  case OP_SHIP_SCORE:
29992  case OP_LAST_ORDER_TIME:
29995 
29996  case OP_NUM_PLAYERS:
29997  case OP_TEAM_SCORE:
29998  case OP_SHIP_DEATHS:
29999  case OP_RESPAWNS_LEFT:
30000  case OP_IS_PLAYER:
30002 
30004  case OP_IS_TAGGED:
30005  case OP_IS_SHIP_VISIBLE:
30006  case OP_IS_SHIP_STEALTHY:
30008  case OP_IS_IFF:
30009  case OP_IS_AI_CLASS:
30010  case OP_IS_SHIP_CLASS:
30011  case OP_IS_SHIP_TYPE:
30012  case OP_CURRENT_SPEED:
30013  case OP_GET_THROTTLE_SPEED:
30014  case OP_IS_FACING:
30015  case OP_IS_IN_MISSION:
30016  case OP_NAV_ISLINKED:
30017  case OP_ARE_SHIP_FLAGS_SET:
30019 
30023  case OP_SHIELD_QUAD_LOW:
30024  case OP_PRIMARY_AMMO_PCT:
30025  case OP_SECONDARY_AMMO_PCT:
30028  case OP_GET_PRIMARY_AMMO:
30029  case OP_GET_SECONDARY_AMMO:
30031  case OP_AFTERBURNER_LEFT:
30032  case OP_WEAPON_ENERGY_LEFT:
30035  case OP_HAS_PRIMARY_WEAPON:
30037  case OP_GET_ETS_VALUE:
30039 
30040  case OP_CARGO_KNOWN_DELAY:
30042  case OP_IS_CARGO:
30043  return STATUS_SUBCATEGORY_CARGO;
30044 
30045  case OP_SHIELDS_LEFT:
30046  case OP_HITS_LEFT:
30050  case OP_SIM_HITS_LEFT:
30051  case OP_GET_DAMAGE_CAUSED:
30053 
30054  case OP_DISTANCE:
30055  case OP_DISTANCE_SUBSYSTEM:
30056  case OP_NAV_DISTANCE:
30057  case OP_GET_OBJECT_X:
30058  case OP_GET_OBJECT_Y:
30059  case OP_GET_OBJECT_Z:
30060  case OP_GET_OBJECT_PITCH:
30061  case OP_GET_OBJECT_BANK:
30062  case OP_GET_OBJECT_HEADING:
30063  case OP_GET_OBJECT_SPEED_X:
30064  case OP_GET_OBJECT_SPEED_Y:
30065  case OP_GET_OBJECT_SPEED_Z:
30066  case OP_NUM_WITHIN_BOX:
30068  case OP_IS_IN_BOX:
30070 
30071  case OP_STRING_TO_INT:
30072  case OP_STRING_GET_LENGTH:
30074 
30075  case OP_SCRIPT_EVAL_NUM:
30076  return STATUS_SUBCATEGORY_OTHER;
30077 
30078  default:
30079  return -1; // sexp doesn't have a subcategory
30080  }
30081 }
30082 
30084  { OP_PLUS, "Plus (Arithmetic operator)\r\n"
30085  "\tAdds numbers and returns results.\r\n\r\n"
30086  "Returns a number. Takes 2 or more numeric arguments." },
30087 
30088  { OP_MINUS, "Minus (Arithmetic operator)\r\n"
30089  "\tSubtracts numbers and returns results.\r\n\r\n"
30090  "Returns a number. Takes 2 or more numeric arguments." },
30091 
30092  { OP_MOD, "Mod (Arithmetic operator)\r\n"
30093  "\tDivides numbers and returns the remainer.\r\n\r\n"
30094  "Returns a number. Takes 2 or more numeric arguments." },
30095 
30096  { OP_MUL, "Multiply (Arithmetic operator)\r\n"
30097  "\tMultiplies numbers and returns results.\r\n\r\n"
30098  "Returns a number. Takes 2 or more numeric arguments." },
30099 
30100  { OP_DIV, "Divide (Arithmetic operator)\r\n"
30101  "\tDivides numbers and returns results.\r\n\r\n"
30102  "Returns a number. Takes 2 or more numeric arguments." },
30103 
30104  { OP_RAND, "Rand (Arithmetic operator)\r\n"
30105  "\tGets a random number. This number will not change on successive calls to this sexp.\r\n\r\n"
30106  "Returns a number. Takes 2 or 3 numeric arguments...\r\n"
30107  "\t1:\tLow range of random number.\r\n"
30108  "\t2:\tHigh range of random number.\r\n"
30109  "\t3:\t(optional) A seed to use when generating numbers. (Setting this to 0 is the same as having no seed at all)" },
30110 
30111  // Goober5000
30112  { OP_RAND_MULTIPLE, "Rand-multiple (Arithmetic operator)\r\n"
30113  "\tGets a random number. This number can and will change between successive calls to this sexp.\r\n\r\n"
30114  "Returns a number. Takes 2 or 3 numeric arguments...\r\n"
30115  "\t1:\tLow range of random number.\r\n"
30116  "\t2:\tHigh range of random number.\r\n"
30117  "\t3:\t(optional) A seed to use when generating numbers. (Setting this to 0 is the same as having no seed at all)" },
30118 
30119  // -------------------------- Nav Points --- Kazan --------------------------
30120  { OP_NAV_IS_VISITED, "is-nav-visited\r\n"
30121  "Returns true when the player has visited the given navpoint (Has closed to within 1000m of it). Takes 1 argument...\r\n"
30122  "\t1:\tThe name of the navpoint" },
30123 
30124  { OP_NAV_DISTANCE, "distance-to-nav\r\n"
30125  "Returns the distance from the player ship to that nav point. Takes 1 argument..."
30126  "\t1:\tThe name of the navpoint" },
30127 
30128  { OP_NAV_ADD_WAYPOINT, "add-nav-waypoint\r\n"
30129  "Adds a Navpoint to a navpoint path. Takes 3 or 4 Arguments...\r\n"
30130  "\t1:\tName of the new navpoint.\r\n"
30131  "\t2:\tName of the navpoint path the new navpoint should be added to.\r\n"
30132  "\t3:\tPosition where the new navpoint will be inserted. Note: This is 1-indexed, so the first waypoint in a path has position 1.\r\n"
30133  "\t4:\t(Optional Argument) Controls the visibility of the new navpoint. Only entities belonging to the chosen category will be able to see it.\r\n" },
30134 
30135  { OP_NAV_ADD_SHIP, "add-nav-ship\r\n"
30136  "Binds the named navpoint to the named ship - when the ship moves, the waypoint moves with it. Takes 2 Arguments...\r\n"
30137  "\t1:\tThe NavPoint's Name\r\n"
30138  "\t2:\tThe Ship's Name\r\n" },
30139 
30140  { OP_NAV_DEL, "del-nav\r\n"
30141  "Deletes a nav point. Takes 1 Argument...\r\n"
30142  "\t1:\tNavPoint Name" },
30143 
30144  { OP_NAV_HIDE, "hide-nav\r\n"
30145  "Hides a nav point. Takes 1 Argument...\r\n"
30146  "\t1:\tNavPoint Name, it then 'hides' that Nav Point\r\n" },
30147 
30148  { OP_NAV_RESTRICT, "restrict-nav\r\n"
30149  "This causes the nav point to be unselectable. Takes 1 Argument...\r\n"
30150  "\t1:\tThe Navpoint name\r\n" },
30151 
30152  { OP_NAV_UNHIDE, "unhide-nav\r\n"
30153  "Restores a hidden navpoint. Takes 1 Argument...\r\n"
30154  "\t1:\tThe Navpoint Name\r\n" },
30155 
30156  { OP_NAV_UNRESTRICT, "unrestrict-nav\r\n"
30157  "Removes restrictions from a Navpoint. Takes 1 Argument...\r\n"
30158  "\t1:\tThe Navpoint Name\r\n" },
30159 
30160  { OP_NAV_SET_VISITED, "set-nav-visited\r\n"
30161  "Sets the status of the given Navpoint to \"visited\". Takes 1 Argument...\r\n"
30162  "\t1:\tThe Navpoint Name\r\n" },
30163 
30164  { OP_NAV_UNSET_VISITED, "unset-nav-visited\r\n"
30165  "Removes the \"visited\" status from a Navpoint. Takes 1 Argument...\r\n"
30166  "\t1:\tThe Navpoint Name\r\n" },
30167 
30168  { OP_NAV_SET_CARRY, "nav-set-carry\r\n"
30169  "Sets the Nav Carry flag for all listed ships. Vessels with this flag will follow the player into and out of autopilot.\r\n"
30170  "Takes 1 or more arguments...\r\n"
30171  "\t1:\tShips and Wings that should receive the Nav Carry flag.\r\n" },
30172 
30173  { OP_NAV_UNSET_CARRY, "unset-nav-carry\r\n"
30174  "Removes the Nav Carry flag from all listed ships and wings. Takes 1 or more arguments...\r\n"
30175  "\t1:\tShips and Wings to remove the Nav Carry flag from\r\n" },
30176 
30177  { OP_NAV_SET_NEEDSLINK, "set-nav-needslink\r\n"
30178  "Marks all listed ships as needing to link up before entering autopilot.\r\n"
30179  "Takes 1 or more arguments...\r\n"
30180  "\t1:\tShips to mark\r\n" },
30181 
30182  { OP_NAV_UNSET_NEEDSLINK, "unset-nav-needslink\r\n"
30183  "Removes the requirement for the listed ships to link up before entering autopilot.\r\n"
30184  "Takes 1 or more arguments...\r\n"
30185  "\t1:\tShips to mark\r\n" },
30186 
30187  { OP_NAV_ISLINKED, "is-nav-linked\r\n"
30188  "Determines if a ship is linked for autopilot (\"set-nav-carry\" or \"set-nav-needslink\" + linked)"
30189  "Takes 1 argument...\r\n"
30190  "\t1:\tShip to check\r\n"},
30191 
30192  { OP_NAV_USECINEMATICS, "use-nav-cinematics\r\n"
30193  "Controls the use of the cinematic autopilot camera. Takes 1 Argument..."
30194  "\t1:\tSet to true to enable automatic cinematics, set to false to disable automatic cinematics." },
30195 
30196  { OP_NAV_USEAP, "use-autopilot\r\n"
30197  "Takes 1 boolean argument.\r\n"
30198  "\t1:\tSet to true to enable autopilot, set to false to disable autopilot." },
30199 
30200  { OP_NAV_SELECT, "nav-select (Action operator)\r\n"
30201  "\tSelects a nav point.\r\n\r\n"
30202  "Takes 1 argument...\r\n"
30203  "\t1:\tName of the nav point." },
30204 
30205  { OP_NAV_UNSELECT, "nav-deselect (Action operator)\r\n"
30206  "\tDeselects any navpoint selected.\r\n\r\n"
30207  "Takes no arguments..." },
30208 
30209  // -------------------------- -------------------------- --------------------------
30210 
30211  // Goober5000
30212  { OP_ABS, "Absolute value (Arithmetic operator)\r\n"
30213  "\tReturns the absolute value of a number. Takes 1 numeric argument.\r\n" },
30214 
30215  // Goober5000
30216  { OP_MIN, "Minimum value (Arithmetic operator)\r\n"
30217  "\tReturns the minimum of a set of numbers. Takes 1 or more numeric arguments.\r\n" },
30218 
30219  // Goober5000
30220  { OP_MAX, "Maximum value (Arithmetic operator)\r\n"
30221  "\tReturns the maximum of a set of numbers. Takes 1 or more numeric arguments.\r\n" },
30222 
30223  // Goober5000
30224  { OP_AVG, "Average value (Arithmetic operator)\r\n"
30225  "\tReturns the average (rounded to the nearest integer) of a set of numbers. Takes 1 or more numeric arguments.\r\n" },
30226 
30227  // Goober5000
30228  { OP_POW, "Power (Arithmetic operator)\r\n"
30229  "\tRaises one number to the power of the next number. If the result will be larger than INT_MAX or smaller than INT_MIN, the appropriate limit will be returned. Takes 2 numeric arguments.\r\n" },
30230 
30231  // Goober5000
30232  { OP_SIGNUM, "Signum (Arithmetic operator)\r\n"
30233  "\tReturns the sign of a number: -1 if it is negative, 0 if it is 0, and 1 if it is positive. Takes one argument.\r\n" },
30234 
30235  // Goober5000
30236  { OP_SET_BIT, "set-bit\r\n"
30237  "\tTurns on (sets to 1) a certain bit in the provided number, returning the result. This allows numbers to store up to 32 boolean flags, from 2^0 to 2^31. Takes 2 numeric arguments...\r\n"
30238  "\t1: The number whose bit should be set\r\n"
30239  "\t2: The index of the bit to set. Valid indexes are between 0 and 31, inclusive.\r\n" },
30240 
30241  // Goober5000
30242  { OP_UNSET_BIT, "unset-bit\r\n"
30243  "\tTurns off (sets to 0) a certain bit in the provided number, returning the result. This allows numbers to store up to 32 boolean flags, from 2^0 to 2^31. Takes 2 numeric arguments...\r\n"
30244  "\t1: The number whose bit should be unset\r\n"
30245  "\t2: The index of the bit to unset. Valid indexes are between 0 and 31, inclusive.\r\n" },
30246 
30247  // Goober5000
30248  { OP_IS_BIT_SET, "is-bit-set\r\n"
30249  "\tReturns true if the specified bit is set (equal to 1) in the provided number. Takes 2 numeric arguments...\r\n"
30250  "\t1: The number whose bit should be tested\r\n"
30251  "\t2: The index of the bit to test. Valid indexes are between 0 and 31, inclusive.\r\n" },
30252 
30253  // Goober5000
30254  { OP_BITWISE_AND, "bitwise-and\r\n"
30255  "\tPerforms the bitwise AND operator on its arguments. This is the same as if the logical AND operator was performed on each successive bit. Takes 2 or more numeric arguments.\r\n" },
30256 
30257  // Goober5000
30258  { OP_BITWISE_OR, "bitwise-or\r\n"
30259  "\tPerforms the bitwise OR operator on its arguments. This is the same as if the logical OR operator was performed on each successive bit. Takes 2 or more numeric arguments.\r\n" },
30260 
30261  // Goober5000
30262  { OP_BITWISE_NOT, "bitwise-not\r\n"
30263  "\tPerforms the bitwise NOT operator on its argument. This is the same as if the logical NOT operator was performed on each successive bit.\r\n\r\n"
30264  "Note that the operation is performed as if on an unsigned integer whose maximum value is INT_MAX. In other words, there is no need to worry about the sign bit.\r\n\r\n"
30265  "Takes only 1 argument.\r\n" },
30266 
30267  // Goober5000
30268  { OP_BITWISE_XOR, "bitwise-xor\r\n"
30269  "\tPerforms the bitwise XOR operator on its arguments. This is the same as if the logical XOR operator was performed on each successive bit. Takes 2 or more numeric arguments.\r\n" },
30270 
30271  { OP_SET_OBJECT_SPEED_X, "set-object-speed-x\r\n"
30272  "\tSets the X speed of a ship or wing."
30273  "Takes 2 or 3 arguments...\r\n"
30274  "\t1: The name of the object.\r\n"
30275  "\t2: The speed to set.\r\n"
30276  "\t3: Whether the speed on the axis should be set according to the universe grid (when false) or according to the object's facing (when true); You almost always want to set this to true; (optional; defaults to false).\r\n" },
30277 
30278  { OP_SET_OBJECT_SPEED_Y, "set-object-speed-y\r\n"
30279  "\tSets the Y speed of a ship or wing."
30280  "Takes 2 or 3 arguments...\r\n"
30281  "\t1: The name of the object.\r\n"
30282  "\t2: The speed to set.\r\n"
30283  "\t3: Whether the speed on the axis should be set according to the universe grid (when false) or according to the object's facing (when true); You almost always want to set this to true; (optional; defaults to false).\r\n" },
30284 
30285  { OP_SET_OBJECT_SPEED_Z, "set-object-speed-z\r\n"
30286  "\tSets the Z speed of a ship or wing."
30287  "Takes 2 or 3 arguments...\r\n"
30288  "\t1: The name of the object.\r\n"
30289  "\t2: The speed to set.\r\n"
30290  "\t3: Whether the speed on the axis should be set according to the universe grid (when false) or according to the object's facing (when true); You almost always want to set this to true; (optional; defaults to false).\r\n" },
30291 
30292  { OP_GET_OBJECT_SPEED_X, "get-object-speed-x\r\n"
30293  "\tReturns the X speed of a ship or wing as an integer."
30294  "Takes 2 or 3 arguments...\r\n"
30295  "\t1: The name of the object.\r\n"
30296  "\t2: Whether the speed on the axis should be set according to the universe grid (when false) or according to the object's facing (when true); You almost always want to set this to true; (optional; defaults to false).\r\n" },
30297 
30298  { OP_GET_OBJECT_SPEED_Y, "get-object-speed-y\r\n"
30299  "\tReturns the Y speed of a ship or wing as an integer."
30300  "Takes 2 or 3 arguments...\r\n"
30301  "\t1: The name of the object.\r\n"
30302  "\t2: Whether the speed on the axis should be set according to the universe grid (when false) or according to the object's facing (when true); You almost always want to set this to true; (optional; defaults to false).\r\n" },
30303 
30304  { OP_GET_OBJECT_SPEED_Z, "get-object-speed-z\r\n"
30305  "\tReturns the Z speed of a ship or wing as an integer."
30306  "Takes 2 or 3 arguments...\r\n"
30307  "\t1: The name of the object.\r\n"
30308  "\t2: Whether the speed on the axis should be set according to the universe grid (when false) or according to the object's facing (when true); You almost always want to set this to true; (optional; defaults to false).\r\n" },
30309 
30310  // Goober5000
30311  { OP_GET_OBJECT_X, "get-object-x\r\n"
30312  "\tReturns the absolute X coordinate of a set of coordinates relative to a particular object (or object's "
30313  "subsystem). The input coordinates are the coordinates relative to the object's position and orientation. "
30314  "If no input coordinates are specified, the coordinate returned is the coordinate of the object (or object's "
30315  "subsystem) itself. Takes 1 to 5 arguments...\r\n"
30316  "\t1: The name of a ship, wing, or waypoint.\r\n"
30317  "\t2: A ship subsystem (or \"" SEXP_NONE_STRING "\" if the first argument is not a ship - optional).\r\n"
30318  "\t3: The relative X coordinate (optional).\r\n"
30319  "\t4: The relative Y coordinate (optional).\r\n"
30320  "\t5: The relative Z coordinate (optional).\r\n" },
30321 
30322  // Goober5000
30323  { OP_GET_OBJECT_Y, "get-object-y\r\n"
30324  "\tReturns the absolute Y coordinate of a set of coordinates relative to a particular object (or object's "
30325  "subsystem). The input coordinates are the coordinates relative to the object's position and orientation. "
30326  "If no input coordinates are specified, the coordinate returned is the coordinate of the object (or object's "
30327  "subsystem) itself. Takes 1 to 5 arguments...\r\n"
30328  "\t1: The name of a ship, wing, or waypoint.\r\n"
30329  "\t2: A ship subsystem (or \"" SEXP_NONE_STRING "\" if the first argument is not a ship - optional).\r\n"
30330  "\t3: The relative X coordinate (optional).\r\n"
30331  "\t4: The relative Y coordinate (optional).\r\n"
30332  "\t5: The relative Z coordinate (optional).\r\n" },
30333 
30334  // Goober5000
30335  { OP_GET_OBJECT_Z, "get-object-z\r\n"
30336  "\tReturns the absolute Z coordinate of a set of coordinates relative to a particular object (or object's "
30337  "subsystem). The input coordinates are the coordinates relative to the object's position and orientation. "
30338  "If no input coordinates are specified, the coordinate returned is the coordinate of the object (or object's "
30339  "subsystem) itself. Takes 1 to 5 arguments...\r\n"
30340  "\t1: The name of a ship, wing, or waypoint.\r\n"
30341  "\t2: A ship subsystem (or \"" SEXP_NONE_STRING "\" if the first argument is not a ship - optional).\r\n"
30342  "\t3: The relative X coordinate (optional).\r\n"
30343  "\t4: The relative Y coordinate (optional).\r\n"
30344  "\t5: The relative Z coordinate (optional).\r\n" },
30345 
30346  // Goober5000
30347  { OP_SET_OBJECT_POSITION, "set-object-position\r\n"
30348  "\tInstantaneously sets an object's spatial coordinates."
30349  "Takes 4 arguments...\r\n"
30350  "\t1: The name of a ship, wing, or waypoint.\r\n"
30351  "\t2: The new X coordinate.\r\n"
30352  "\t3: The new Y coordinate.\r\n"
30353  "\t4: The new Z coordinate." },
30354 
30355  // Goober5000
30356  { OP_GET_OBJECT_PITCH, "get-object-pitch\r\n"
30357  "\tReturns the pitch angle, in degrees, of a particular object. The returned value will be between 0 and 360. Takes 1 argument...\r\n"
30358  "\t1: The name of a ship or wing.\r\n" },
30359 
30360  // Goober5000
30361  { OP_GET_OBJECT_BANK, "get-object-bank\r\n"
30362  "\tReturns the bank angle, in degrees, of a particular object. The returned value will be between 0 and 360. Takes 1 argument...\r\n"
30363  "\t1: The name of a ship or wing.\r\n" },
30364 
30365  // Goober5000
30366  { OP_GET_OBJECT_HEADING, "get-object-heading\r\n"
30367  "\tReturns the heading angle, in degrees, of a particular object. The returned value will be between 0 and 360. Takes 1 argument...\r\n"
30368  "\t1: The name of a ship or wing.\r\n" },
30369 
30370  // Goober5000
30371  { OP_SET_OBJECT_ORIENTATION, "set-object-orientation\r\n"
30372  "\tInstantaneously sets an object's spatial orientation."
30373  "Takes 4 arguments...\r\n"
30374  "\t1: The name of a ship or wing.\r\n"
30375  "\t2: The new pitch angle, in degrees. The angle can be any number; it does not have to be between 0 and 360.\r\n"
30376  "\t3: The new bank angle, in degrees. The angle can be any can be any number; it does not have to be between 0 and 360.\r\n"
30377  "\t4: The new heading angle, in degrees. The angle can be any number; it does not have to be between 0 and 360." },
30378 
30379  { OP_TRUE, "True (Boolean operator)\r\n"
30380  "\tA true boolean state\r\n\r\n"
30381  "Returns a boolean value." },
30382 
30383  { OP_FALSE, "False (Boolean operator)\r\n"
30384  "\tA false boolean state\r\n\r\n"
30385  "Returns a boolean value." },
30386 
30387  { OP_AND, "And (Boolean operator)\r\n"
30388  "\tAnd is true if all of its arguments are true.\r\n\r\n"
30389  "Returns a boolean value. Takes 2 or more boolean arguments." },
30390 
30391  { OP_OR, "Or (Boolean operator)\r\n"
30392  "\tOr is true if any of its arguments are true.\r\n\r\n"
30393  "Returns a boolean value. Takes 2 or more boolean arguments." },
30394 
30395  { OP_XOR, "Xor (Boolean operator)\r\n"
30396  "\tXor is true if exactly one of its arguments is true.\r\n\r\n"
30397  "Returns a boolean value. Takes 2 or more boolean arguments." },
30398 
30399  { OP_EQUALS, "Equals (Boolean operator)\r\n"
30400  "\tIs true if all of its arguments are equal.\r\n\r\n"
30401  "Returns a boolean value. Takes 2 or more numeric arguments." },
30402 
30403  { OP_GREATER_THAN, "Greater Than (Boolean operator)\r\n"
30404  "\tTrue if the first argument is greater than the subsequent argument(s).\r\n\r\n"
30405  "Returns a boolean value. Takes 2 numeric arguments." },
30406 
30407  { OP_LESS_THAN, "Less Than (Boolean operator)\r\n"
30408  "\tTrue if the first argument is less than the subsequent argument(s).\r\n\r\n"
30409  "Returns a boolean value. Takes 2 numeric arguments." },
30410 
30411  { OP_NOT_EQUAL, "Not Equal To (Boolean operator)\r\n"
30412  "\tIs true if the first argument is not equal to any of the subsequent arguments.\r\n\r\n"
30413  "Returns a boolean value. Takes 2 or more numeric arguments." },
30414 
30415  { OP_GREATER_OR_EQUAL, "Greater Than Or Equal To (Boolean operator)\r\n"
30416  "\tTrue if the first argument is greater than or equal to the subsequent argument(s).\r\n\r\n"
30417  "Returns a boolean value. Takes 2 numeric arguments." },
30418 
30419  { OP_LESS_OR_EQUAL, "Less Than Or Equal To (Boolean operator)\r\n"
30420  "\tTrue if the first argument is less than or equal to the subsequent argument(s).\r\n\r\n"
30421  "Returns a boolean value. Takes 2 numeric arguments." },
30422 
30423  // Goober5000
30424  { OP_PERFORM_ACTIONS, "perform-actions\r\n"
30425  "\tThis sexp allows actions to be performed as part of a conditional test. It is most useful for assigning variables or performing some sort of pre-test action within the conditional part of \"when\", etc. "
30426  "It works well as the first branch of an \"and\" sexp, provided it returns true so as to not affect the return value of the \"and\".\r\n\r\n"
30427  "Returns a boolean value. Takes 2 or more arguments.\r\n"
30428  "\t1:\tA boolean value to return after all successive actions have been performed.\r\n"
30429  "\tRest:\tActions to perform, which would normally appear in a \"when\" sexp.\r\n" },
30430 
30431  // Goober5000
30432  { OP_STRING_EQUALS, "String Equals (Boolean operator)\r\n"
30433  "\tIs true if all of its arguments are equal.\r\n\r\n"
30434  "Returns a boolean value. Takes 2 or more string arguments." },
30435 
30436  // Goober5000
30437  { OP_STRING_GREATER_THAN, "String Greater Than (Boolean operator)\r\n"
30438  "\tTrue if the first argument is greater than the second argument.\r\n\r\n"
30439  "Returns a boolean value. Takes 2 string arguments." },
30440 
30441  // Goober5000
30442  { OP_STRING_LESS_THAN, "String Less Than (Boolean operator)\r\n"
30443  "\tTrue if the first argument is less than the second argument.\r\n\r\n"
30444  "Returns a boolean value. Takes 2 string arguments." },
30445 
30446  // Goober5000 - added wing capability
30447  { OP_IS_IFF, "Is IFF (Boolean operator)\r\n"
30448  "\tTrue if ship(s) or wing(s) are all of the specified team.\r\n\r\n"
30449  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30450  "\t1:\tTeam (\"friendly\", \"hostile\", \"neutral\", or \"unknown\").\r\n"
30451  "\tRest:\tName of ship or wing to check." },
30452 
30453  // Goober5000
30454  { OP_IS_AI_CLASS, "Is AI Class (Boolean operator)\r\n"
30455  "\tTrue if ship or ship subsystem(s) is/are all of the specified AI class.\r\n\r\n"
30456  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30457  "\t1:\tAI class (\"None\", \"Coward\", \"Lieutenant\", etc.)\r\n"
30458  "\t2:\tName of ship to check.\r\n"
30459  "\tRest:\tName of ship subsystem(s) to check (optional)" },
30460 
30461  // Goober5000
30462  { OP_IS_SHIP_TYPE, "Is Ship Type (Boolean operator)\r\n"
30463  "\tTrue if ship or ships is/are all of the specified ship type.\r\n\r\n"
30464  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30465  "\t1:\tShip type (\"fighter\", \"bomber\", etc.)\r\n"
30466  "\t2:\tName of ship to check.\r\n" },
30467 
30468  // Goober5000
30469  { OP_IS_SHIP_CLASS, "Is Ship Class (Boolean operator)\r\n"
30470  "\tTrue if ship or ships is/are all of the specified ship class.\r\n\r\n"
30471  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30472  "\t1:\tShip class\r\n"
30473  "\t2:\tName of ship to check.\r\n" },
30474 
30475  { OP_HAS_TIME_ELAPSED, "Has time elapsed (Boolean operator)\r\n"
30476  "\tBecomes true when the specified amount of time has elapsed (Mission time "
30477  "becomes greater than the specified time).\r\n"
30478  "Returns a boolean value. Takes 1 numeric argument...\r\n"
30479  "\t1:\tThe amount of time in seconds." },
30480 
30481  { OP_NOT, "Not (Boolean operator)\r\n"
30482  "\tReturns opposite boolean value of argument (True becomes false, and "
30483  "false becomes true).\r\n\r\n"
30484  "Returns a boolean value. Takes 1 boolean argument." },
30485 
30486  { OP_PREVIOUS_GOAL_TRUE, "Previous Mission Goal True (Boolean operator)\r\n"
30487  "\tReturns true if the specified goal in the specified mission is true "
30488  "(or succeeded). It returns false otherwise.\r\n\r\n"
30489  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30490  "\t1:\tName of the mission.\r\n"
30491  "\t2:\tName of the goal in the mission.\r\n"
30492  "\t3:\t(Optional) True/False which signifies what this sexpression should return when "
30493  "this mission is played as a single mission." },
30494 
30495  { OP_PREVIOUS_GOAL_FALSE, "Previous Mission Goal False (Boolean operator)\r\n"
30496  "\tReturns true if the specified goal in the specified mission "
30497  "is false (or failed). It returns false otherwise.\r\n\r\n"
30498  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30499  "\t1:\tName of the mission.\r\n"
30500  "\t2:\tName of the goal in the mission.\r\n"
30501  "\t3:\t(Optional) True/False which signifies what this sexpression should return when "
30502  "this mission is played as a single mission." },
30503 
30504  { OP_PREVIOUS_GOAL_INCOMPLETE, "Previous Mission Goal Incomplete (Boolean operator)\r\n"
30505  "\tReturns true if the specified goal in the specified mission "
30506  "is incomplete (not true or false). It returns false otherwise.\r\n\r\n"
30507  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30508  "\t1:\tName of the mission.\r\n"
30509  "\t2:\tName of the goal in the mission.\r\n"
30510  "\t3:\t(Optional) True/False which signifies what this sexpression should return when "
30511  "this mission is played as a single mission." },
30512 
30513  { OP_PREVIOUS_EVENT_TRUE, "Previous Mission Event True (Boolean operator)\r\n"
30514  "\tReturns true if the specified event in the specified mission is true "
30515  "(or succeeded). It returns false otherwise.\r\n\r\n"
30516  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30517  "\t1:\tName of the mission.\r\n"
30518  "\t2:\tName of the event in the mission.\r\n"
30519  "\t3:\t(Optional) True/False which signifies what this sexpression should return when "
30520  "this mission is played as a single mission." },
30521 
30522  { OP_PREVIOUS_EVENT_FALSE, "Previous Mission Event False (Boolean operator)\r\n"
30523  "\tReturns true if the specified event in the specified mission "
30524  "is false (or failed). It returns false otherwise.\r\n\r\n"
30525  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30526  "\t1:\tName of the mission.\r\n"
30527  "\t2:\tName of the event in the mission.\r\n"
30528  "\t3:\t(Optional) True/False which signifies what this sexpression should return when "
30529  "this mission is played as a single mission." },
30530 
30531  { OP_PREVIOUS_EVENT_INCOMPLETE, "Previous Mission Event Incomplete (Boolean operator)\r\n"
30532  "\tReturns true if the specified event in the specified mission "
30533  "is incomplete (not true or false). It returns false otherwise.\r\n\r\n"
30534  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30535  "\t1:\tName of the mission.\r\n"
30536  "\t2:\tName of the event in the mission.\r\n"
30537  "\t3:\t(Optional) True/False which signifies what this sexpression should return when "
30538  "this mission is played as a single mission." },
30539 
30540  { OP_GOAL_TRUE_DELAY, "Mission Goal True (Boolean operator)\r\n"
30541  "\tReturns true N seconds after the specified goal in the this mission is true "
30542  "(or succeeded). It returns false otherwise.\r\n\r\n"
30543  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30544  "\t1:\tName of the event in the mission.\r\n"
30545  "\t2:\tNumber of seconds to delay before returning true."},
30546 
30547  { OP_GOAL_FALSE_DELAY, "Mission Goal False (Boolean operator)\r\n"
30548  "\tReturns true N seconds after the specified goal in the this mission is false "
30549  "(or failed). It returns false otherwise.\r\n\r\n"
30550  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30551  "\t1:\tName of the event in the mission.\r\n"
30552  "\t2:\tNumber of seconds to delay before returning true."},
30553 
30554  { OP_GOAL_INCOMPLETE, "Mission Goal Incomplete (Boolean operator)\r\n"
30555  "\tReturns true if the specified goal in the this mission is incomplete. This "
30556  "sexpression will only be useful in conjunction with another sexpression like"
30557  "has-time-elapsed. Used alone, it will return true upon misison startup."
30558  "Returns a boolean value. Takes 1 argument...\r\n"
30559  "\t1:\tName of the event in the mission."},
30560 
30561  { OP_EVENT_TRUE_DELAY, "Mission Event True (Boolean operator)\r\n"
30562  "\tReturns true N seconds after the specified event in the this mission is true "
30563  "(or succeeded). It returns false otherwise.\r\n\r\n"
30564  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30565  "\t1:\tName of the event in the mission.\r\n"
30566  "\t2:\tNumber of seconds to delay before returning true.\r\n"
30567  "\t3:\t(Optional) Defaults to False. When set to false, directives will only appear as soon as the specified event is true.\r\n"
30568  "\t\tWhen set to true, the event only affects whether the directive succeeds/fails, and has no effect on when it appears"},
30569 
30570  { OP_EVENT_FALSE_DELAY, "Mission Event False (Boolean operator)\r\n"
30571  "\tReturns true N seconds after the specified event in the this mission is false "
30572  "(or failed). It returns false otherwise.\r\n\r\n"
30573  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30574  "\t1:\tName of the event in the mission.\r\n"
30575  "\t2:\tNumber of seconds to delay before returning true.\r\n"
30576  "\t3:\t(Optional) Defaults to False. When set to false, directives will only appear as soon as the specified event is true.\r\n"
30577  "\t\tWhen set to true, the event only affects whether the directive succeeds/fails, and has no effect on when it appears"},
30578 
30579  { OP_EVENT_TRUE_MSECS_DELAY, "Mission Event True (Boolean operator)\r\n"
30580  "\tReturns true N milliseconds after the specified event in the this mission is true "
30581  "(or succeeded). It returns false otherwise.\r\n\r\n"
30582  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30583  "\t1:\tName of the event in the mission.\r\n"
30584  "\t2:\tNumber of milliseconds to delay before returning true.\r\n"
30585  "\t3:\t(Optional) Defaults to False. When set to false, directives will only appear as soon as the specified event is true.\r\n"
30586  "\t\tWhen set to true, the event only affects whether the directive succeeds/fails, and has no effect on when it appears"},
30587 
30588  { OP_EVENT_FALSE_MSECS_DELAY, "Mission Event False (Boolean operator)\r\n"
30589  "\tReturns true N milliseconds after the specified event in the this mission is false "
30590  "(or failed). It returns false otherwise.\r\n\r\n"
30591  "Returns a boolean value. Takes 2 required arguments and 1 optional argument...\r\n"
30592  "\t1:\tName of the event in the mission.\r\n"
30593  "\t2:\tNumber of milliseconds to delay before returning true.\r\n"
30594  "\t3:\t(Optional) Defaults to False. When set to false, directives will only appear as soon as the specified event is true.\r\n"
30595  "\t\tWhen set to true, the event only affects whether the directive succeeds/fails, and has no effect on when it appears"},
30596 
30597  { OP_EVENT_INCOMPLETE, "Mission Event Incomplete (Boolean operator)\r\n"
30598  "\tReturns true if the specified event in the this mission is incomplete. This "
30599  "sexpression will only be useful in conjunction with another sexpression like"
30600  "has-time-elapsed. Used alone, it will return true upon misison startup."
30601  "Returns a boolean value. Takes 1 argument...\r\n"
30602  "\t1:\tName of the event in the mission."},
30603 
30604  { OP_IS_DESTROYED_DELAY, "Is destroyed delay (Boolean operator)\r\n"
30605  "\tBecomes true <delay> seconds after all specified ships have been destroyed.\r\n\r\n"
30606  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30607  "\t1:\tTime delay in seconds (see above).\r\n"
30608  "\tRest:\tName of ship (or wing) to check status of." },
30609 
30610  { OP_WAS_DESTROYED_BY_DELAY, "Was destroyed by delay (Boolean operator)\r\n"
30611  "\tBecomes true <delay> seconds after all specified ships have been destroyed by the specified first ship.\r\n\r\n"
30612  "Returns a boolean value. Takes 3 or more arguments...\r\n"
30613  "\t1:\tTime delay in seconds (see above).\r\n"
30614  "\t2:\tShip that should have destroyed the other ships (see below).\r\n"
30615  "\tRest:\tName of ships to check status of." },
30616 
30617  { OP_IS_SUBSYSTEM_DESTROYED_DELAY, "Is subsystem destroyed delay (Boolean operator)\r\n"
30618  "\tBecomes true <delay> seconds after the specified subsystem of the specified "
30619  "ship is destroyed.\r\n\r\n"
30620  "Returns a boolean value. Takes 3 arguments...\r\n"
30621  "\t1:\tName of ship the subsystem we are checking is on.\r\n"
30622  "\t2:\tThe name of the subsystem we are checking status of.\r\n"
30623  "\t3:\tTime delay in seconds (see above)." },
30624 
30625  { OP_IS_DISABLED_DELAY, "Is disabled delay (Boolean operator)\r\n"
30626  "\tBecomes true <delay> seconds after the specified ship(s) are disabled. A "
30627  "ship is disabled when all of its engine subsystems are destroyed. All "
30628  "ships must be diabled for this function to return true.\r\n\r\n"
30629  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30630  "\t1:\tTime delay is seconds (see above).\r\n"
30631  "\tRest:\tNames of ships to check disabled status of." },
30632 
30633  { OP_IS_DISARMED_DELAY, "Is disarmed delay (Boolean operator)\r\n"
30634  "\tBecomes true <delay> seconds after the specified ship(s) are disarmed. A "
30635  "ship is disarmed when all of its turret subsystems are destroyed. All "
30636  "ships must be disarmed for this function to return true.\r\n\r\n"
30637  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30638  "\t1:\tTime delay is seconds (see above).\r\n"
30639  "\tRest:\tNames of ships to check disarmed status of." },
30640 
30641  { OP_HAS_DOCKED_DELAY, "Has docked delay (Boolean operator)\r\n"
30642  "\tBecomes true <delay> seconds after the specified ships have docked the "
30643  "specified number of times.\r\n\r\n"
30644  "Returns a boolean value. Takes 4 arguments...\r\n"
30645  "\t1:\tThe name of the docker ship\r\n"
30646  "\t2:\tThe name of the dockee ship\r\n"
30647  "\t3:\tThe number of times they have to have docked\r\n"
30648  "\t4:\tTime delay in seconds (see above)." },
30649 
30650  { OP_HAS_UNDOCKED_DELAY, "Has undocked delay (Boolean operator)\r\n"
30651  "\tBecomes true <delay> seconds after the specified ships have undocked the "
30652  "specified number of times.\r\n\r\n"
30653  "Returns a boolean value. Takes 4 arguments...\r\n"
30654  "\t1:\tThe name of the docker ship\r\n"
30655  "\t2:\tThe name of the dockee ship\r\n"
30656  "\t3:\tThe number of times they have to have undocked\r\n"
30657  "\t4:\tTime delay in seconds (see above)." },
30658 
30659  { OP_HAS_ARRIVED_DELAY, "Has arrived delay (Boolean operator)\r\n"
30660  "\tBecomes true <delay> seconds after the specified ship(s) have arrived into the mission\r\n\r\n"
30661  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30662  "\t1:\tTime delay in seconds (see above).\r\n"
30663  "\tRest:\tName of ship (or wing) we want to check has arrived." },
30664 
30665  { OP_HAS_DEPARTED_DELAY, "Has departed delay (Boolean operator)\r\n"
30666  "\tBecomes true <delay> seconds after the specified ship(s) or wing(s) have departed "
30667  "from the mission by warping out. If any ship was destroyed, this operator will "
30668  "never be true.\r\n\r\n"
30669  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30670  "\t1:\tTime delay in seconds (see above).\r\n"
30671  "\tRest:\tName of ship (or wing) we want to check has departed." },
30672 
30673  { OP_WAYPOINTS_DONE_DELAY, "Waypoints done delay (Boolean operator)\r\n"
30674  "\tBecomes true <delay> seconds after the specified ship has completed flying the "
30675  "specified waypoint path.\r\n\r\n"
30676  "Returns a boolean value. Takes 3 or 4 arguments...\r\n"
30677  "\t1:\tName of ship we are checking.\r\n"
30678  "\t2:\tWaypoint path we want to check if ship has flown.\r\n"
30679  "\t3:\tTime delay in seconds (see above).\r\n"
30680  "\t4:\tHow many times the ship has completed the waypoint path (optional)." },
30681 
30682  { OP_SHIP_TYPE_DESTROYED, "Ship Type Destroyed (Boolean operator)\r\n"
30683  "\tBecomes true when the specified percentage of ship types in this mission "
30684  "have been destroyed. The ship type is a generic type such as fighter/bomber, "
30685  "transport, etc. Fighters and bombers count as the same type.\r\n\r\n"
30686  "Returns a boolean value. Takes 2 arguments...\r\n"
30687  "\t1:\tPercentage of ships that must be destroyed.\r\n"
30688  "\t2:\tShip type to check for." },
30689 
30690  { OP_TIME_SHIP_DESTROYED, "Time ship destroyed (Time operator)\r\n"
30691  "\tReturns the time the specified ship was destroy.\r\n\r\n"
30692  "Returns a numeric value. Takes 1 argument...\r\n"
30693  "\t1:\tName of ship we want to check." },
30694 
30695  { OP_TIME_SHIP_ARRIVED, "Time ship arrived (Time operator)\r\n"
30696  "\tReturns the time the specified ship arrived into the mission.\r\n\r\n"
30697  "Returns a numeric value. Takes 1 argument...\r\n"
30698  "\t1:\tName of ship we want to check." },
30699 
30700  { OP_TIME_SHIP_DEPARTED, "Time ship departed (Time operator)\r\n"
30701  "\tReturns the time the specified ship departed the mission by warping out. Being "
30702  "destroyed doesn't count departed.\r\n\r\n"
30703  "Returns a numeric value. Takes 1 argument...\r\n"
30704  "\t1:\tName of ship we want to check." },
30705 
30706  { OP_TIME_WING_DESTROYED, "Time wing destroyed (Time operator)\r\n"
30707  "\tReturns the time the specified wing was destroy.\r\n\r\n"
30708  "Returns a numeric value. Takes 1 argument...\r\n"
30709  "\t1:\tName of wing we want to check." },
30710 
30711  { OP_TIME_WING_ARRIVED, "Time wing arrived (Time operator)\r\n"
30712  "\tReturns the time the specified wing arrived into the mission.\r\n\r\n"
30713  "Returns a numeric value. Takes 1 argument...\r\n"
30714  "\t1:\tName of wing we want to check." },
30715 
30716  { OP_TIME_WING_DEPARTED, "Time wing departed (Time operator)\r\n"
30717  "\tReturns the time the specified wing departed the mission by warping out. All "
30718  "ships in the wing have to have warped out. If any are destroyed, the wing can "
30719  "never be considered departed.\r\n\r\n"
30720  "Returns a numeric value. Takes 1 argument...\r\n"
30721  "\t1:\tName of ship we want to check." },
30722 
30723  { OP_MISSION_TIME, "Mission time (Time operator)\r\n"
30724  "\tReturns the current time into the mission.\r\n\r\n"
30725  "Returns a numeric value. Takes no arguments." },
30726 
30727  { OP_MISSION_TIME_MSECS, "Mission time, in milliseconds (Time operator)\r\n"
30728  "\tReturns the current time into the mission, in milliseconds. Useful for more fine-grained timing than possible with normal second-based sexps. (Tip: when an event occurs, assign the result of mission-time-msecs to a variable. Then, in another event, wait until mission-time-msecs is greater than the value of that variable plus some delay amount. This second event should be chained or coupled with additional conditions so that it doesn't accidentally fire on an uninitialized variable!)\r\n\r\n"
30729  "Returns a numeric value. Takes no arguments." },
30730 
30731  { OP_TIME_DOCKED, "Time docked (Time operator)\r\n"
30732  "\tReturns the time the specified ships docked.\r\n\r\n"
30733  "Returns a numeric value. Takes 3 arguments...\r\n"
30734  "\t1:\tThe name of the docker ship.\r\n"
30735  "\t2:\tThe name of the dockee ship.\r\n"
30736  "\t3:\tThe number of times they must have docked to be true." },
30737 
30738  { OP_TIME_UNDOCKED, "Time undocked (Time operator)\r\n"
30739  "\tReturns the time the specified ships undocked.\r\n\r\n"
30740  "Returns a numeric value. Takes 3 arguments...\r\n"
30741  "\t1:\tThe name of the docker ship.\r\n"
30742  "\t2:\tThe name of the dockee ship.\r\n"
30743  "\t3:\tThe number of times they must have undocked to be true." },
30744 
30745  { OP_AFTERBURNER_LEFT, "Afterburner left\r\n"
30746  "\tReturns a ship's current engine energy as a percentage.\r\n"
30747  "\t1: Ship name\r\n" },
30748 
30749  { OP_WEAPON_ENERGY_LEFT, "Weapon energy left\r\n"
30750  "\tReturns a ship's current weapon energy as a percentage.\r\n"
30751  "\t1: Ship name\r\n" },
30752 
30753  { OP_SHIELDS_LEFT, "Shields left (Status operator)\r\n"
30754  "\tReturns the current level of the specified ship's shields as a percentage.\r\n\r\n"
30755  "Returns a numeric value. Takes 1 argument...\r\n"
30756  "\t1:\tName of ship to check." },
30757 
30758  { OP_HITS_LEFT, "Hits left (Status operator)\r\n"
30759  "\tReturns the current level of the specified ship's hull as a percentage.\r\n\r\n"
30760  "Returns a numeric value. Takes 1 argument...\r\n"
30761  "\t1:\tName of ship to check." },
30762 
30763  { OP_HITS_LEFT_SUBSYSTEM, "Hits left subsystem (status operator, deprecated)\r\n"
30764  "\tReturns the current level of the specified ship's subsystem integrity as a percentage of the damage done to *all "
30765  "subsystems of the same type*. This operator provides the same functionality as the new hits-left-subsystem-generic "
30766  "operator, except that it gets the subsystem type in a very misleading way. Common consensus among SCP programmers is "
30767  "that this operator was intended to behave like hits-left-subsystem-specific but was programmed incorrectly. As such, "
30768  "this operator is deprecated. Mission designers are strongly encouraged to use hits-left-subsystem-specific rather than "
30769  "the optional boolean parameter.\r\n\r\n"
30770  "Returns a numeric value. Takes 2 or 3 arguments...\r\n"
30771  "\t1:\tName of ship to check.\r\n"
30772  "\t2:\tName of subsystem on ship to check.\r\n"
30773  "\t3:\t(Optional) True/False. When set to true only the subsystem supplied will be tested; when set to false (the default), "
30774  "all subsystems of that type will be tested." },
30775 
30776  { OP_HITS_LEFT_SUBSYSTEM_GENERIC, "hits-left-subsystem-generic (status operator)\r\n"
30777  "\tReturns the current level of integrity of a generic subsystem type, as a percentage. A \"generic subsystem type\" "
30778  "is a subsystem *category*, (for example, Engines), that includes one or more *individual* subsystems (for example, engine01, "
30779  "engine02, and engine03) on a ship.\r\n\r\nThis is the way FreeSpace tests certain subsystem thresholds internally; for "
30780  "example, if the integrity of all engine subsystems (that is, the combined strength of all engines divided by the maximum "
30781  "total strength of all engines) is less than 30%, the player cannot warp out.\r\n\r\n"
30782  "Returns a numeric value. Takes 2 arguments...\r\n"
30783  "\t1:\tName of ship to check\r\n"
30784  "\t2:\tName of subsystem type to check\r\n" },
30785 
30786  { OP_HITS_LEFT_SUBSYSTEM_SPECIFIC, "hits-left-subsystem-specific (status operator)\r\n"
30787  "\tReturns the current level of integrity of a specific subsystem, as a percentage.\r\n\r\n(If you were looking for the old "
30788  "hits-left-subsystem operator, this is almost certainly the operator you want. The hits-left-subsystem operator "
30789  "suffers from a serious design flaw that causes it to behave like hits-left-subsystem-generic. As such it has been deprecated "
30790  "and will not appear in the operator list; it can only be used if you type it in manually. Old missions using hits-left-subsystem "
30791  "will still work, but mission designers are strongly encouraged to use the new operators instead.)\r\n\r\n"
30792  "Returns a numeric value. Takes 2 arguments...\r\n"
30793  "\t1:\tName of ship to check\r\n"
30794  "\t2:\tName of subsystem to check\r\n" },
30795 
30796  { OP_SIM_HITS_LEFT, "Simulated Hits left (Status operator)\r\n"
30797  "\tReturns the current level of the specified ship's simulated hull as a percentage.\r\n\r\n"
30798  "Returns a numeric value. Takes 1 argument...\r\n"
30799  "\t1:\tName of ship to check." },
30800 
30801  { OP_DISTANCE, "Distance (Status operator)\r\n"
30802  "\tReturns the distance between two objects. These objects can be either a ship, "
30803  "a wing, or a waypoint.\r\n"
30804  "When a wing or team is given (for either argument) the answer will be the shortest distance. \r\n\r\n"
30805  "Returns a numeric value. Takes 2 arguments...\r\n"
30806  "\t1:\tThe name of one of the objects.\r\n"
30807  "\t2:\tThe name of the other object." },
30808 
30809  { OP_DISTANCE_SUBSYSTEM, "Distance from ship subsystem (Status operator)\r\n"
30810  "\tReturns the distance between an object and a ship subsystem. The object can be either a ship, "
30811  "a wing, or a waypoint.\r\n\r\n"
30812  "Returns a numeric value. Takes 3 arguments...\r\n"
30813  "\t1:\tThe name of the object.\r\n"
30814  "\t2:\tThe name of the ship which houses the subsystem.\r\n"
30815  "\t3:\tThe name of the subsystem." },
30816 
30817  { OP_NUM_WITHIN_BOX, "Number of specified objects in the box specified\r\n"
30818  "\t1: Box center (X)\r\n"
30819  "\t2: Box center (Y)\r\n"
30820  "\t3: Box center (Z)\r\n"
30821  "\t4: Box width\r\n"
30822  "\t5: Box height\r\n"
30823  "\t6: Box depth\r\n"
30824  "\tRest:\tShips or wings to check" },
30825 
30826  { OP_IS_IN_BOX, "Whether an object is in the box specified. If a second ship is specified, "
30827  "the box is relative to that ship's reference frame. \r\n"
30828  "\t1: Ships, wings, or points to check\r\n"
30829  "\t2: Min X\r\n"
30830  "\t3: Max X\r\n"
30831  "\t4: Min Y\r\n"
30832  "\t5: Max Y\r\n"
30833  "\t6: Min Z\r\n"
30834  "\t7: Max Z\r\n"
30835  "\t8: Ship to use as reference frame (optional)." },
30836 
30837  { OP_IS_IN_MISSION, "Checks whether a given ship is presently in the mission. This sexp doesn't check the arrival list or exited status; it only tests to see if the "
30838  "ship is active. This means that internally the sexp only returns SEXP_TRUE or SEXP_FALSE and does not use any of the special shortcut values. This is useful "
30839  "for ships created with ship-create, as those ships will not have used the conventional ship arrival list.\r\n\r\n"
30840  "Takes 1 or more string arguments, which are checked against the ship list." },
30841 
30842  { OP_GET_DAMAGE_CAUSED, "Get damage caused (Status operator)\r\n"
30843  "\tReturns the amount of damage one or more ships have done to a ship.\r\n\r\n"
30844  "Takes 2 or more arguments...\r\n"
30845  "\t1:\tShip that has been damaged.\r\n"
30846  "\t2:\tName of ships that may have damaged it." },
30847 
30848  { OP_LAST_ORDER_TIME, "Last order time (Status operator)\r\n"
30849  "\tReturns true if <count> seconds have elapsed since one or more ships have received "
30850  "a meaningful order from the player. A meaningful order is currently any order that "
30851  "is not the warp out order.\r\n\r\n"
30852  "Returns a boolean value. Takes 2 or more arguments...\r\n"
30853  "\t1:\tTime in seconds that must elapse.\r\n"
30854  "\tRest:\tName of ship or wing to check for having received orders." },
30855 
30856  { OP_WHEN, "When (Conditional operator)\r\n"
30857  "\tPerforms specified actions when a condition becomes true\r\n\r\n"
30858  "Takes 2 or more arguments...\r\n"
30859  "\t1:\tBoolean expression that must be true for actions to take place.\r\n"
30860  "\tRest:\tActions to take when boolean expression becomes true." },
30861 
30862  { OP_COND, "Blah" },
30863 
30864  // Goober5000
30865  { OP_WHEN_ARGUMENT, "When-argument (Conditional operator)\r\n"
30866  "\tPerforms specified actions when a condition, given a set of arguments, becomes true.\r\n\r\n"
30867  "Takes 3 or more arguments...\r\n"
30868  "\t1:\tThe arguments to evaluate (see any-of, every-of, random-of, etc.).\r\n"
30869  "\t2:\tBoolean expression that must be true for actions to take place.\r\n"
30870  "\tRest:\tActions to take when the boolean expression becomes true." },
30871 
30872  // Goober5000
30873  { OP_EVERY_TIME, "Every-time (Conditional operator)\r\n"
30874  "\tThis is a version of \"when\" that will always evaluate its arguments. It's useful "
30875  "in situations where you need to repeatedly check things that may become true more than "
30876  "once. Since this sexp will execute every time it's evaluated, you may need to use it as "
30877  "an argument to \"when\" if you want to impose restrictions on how it's called.\r\n\r\n"
30878  "Takes 2 or more arguments...\r\n"
30879  "\t1:\tBoolean expression that must be true for actions to take place.\r\n"
30880  "\tRest:\tActions to take when boolean expression is true." },
30881 
30882  // Goober5000
30883  { OP_EVERY_TIME_ARGUMENT, "Every-time-argument (Conditional operator)\r\n"
30884  "\tThis is a version of \"when-argument\" that will always evaluate its arguments. It's useful "
30885  "in situations where you need to repeatedly check things that may become true more than "
30886  "once. Since this sexp will execute every time it's evaluated, you may need to use it as "
30887  "an argument to \"when\" (not \"when-argument\") if you want to impose restrictions on how it's called.\r\n\r\n"
30888  "Takes 3 or more arguments...\r\n"
30889  "\t1:\tThe arguments to evaluate (see any-of, all-of, random-of, etc.).\r\n"
30890  "\t2:\tBoolean expression that must be true for actions to take place.\r\n"
30891  "\tRest:\tActions to take when the boolean expression becomes true." },
30892 
30893  // Goober5000
30894  { OP_IF_THEN_ELSE, "If-then-else (Conditional operator)\r\n"
30895  "\tPerforms one action if a condition is true (like \"when\"), or another action (or set of actions) if the condition is false. "
30896  "Note that this sexp only completes one of its branches once the condition has been determined; "
30897  "it does not come back later and evaluate the other branch if the condition happens to switch truth values.\r\n\r\n"
30898  "Takes 3 or more arguments...\r\n"
30899  "\t1:\tBoolean expression to evaluate.\r\n"
30900  "\t2:\tActions to take if that expression becomes true.\r\n"
30901  "\tRest:\tActions to take if that expression becomes false.\r\n" },
30902 
30903  // Karajorma
30904  { OP_DO_FOR_VALID_ARGUMENTS, "Do-for-valid-arguments (Conditional operator)\r\n"
30905  "\tPerforms specified actions once for each valid " SEXP_ARGUMENT_STRING " in the parent conditional.\r\n"
30906  "\tMust not be used for any SEXP that actually contains " SEXP_ARGUMENT_STRING " as these are already being executed\r\n"
30907  "\tmultiple times without using Do-for-valid-arguments. Any use of " SEXP_ARGUMENT_STRING " and will \r\n"
30908  "\tprevent execution of the entire SEXP unless it is nested inside another when(or every-time)-argument SEXP.\r\n\r\n"
30909  "Takes 1 or more arguments...\r\n"
30910  "\tAll:\tActions to take." },
30911 
30912  // Karajorma
30913  { OP_NUM_VALID_ARGUMENTS, "num-valid-arguments (Conditional operator)\r\n"
30914  "\tReturns the number of valid arguments in the argument list.\r\n\r\n"
30915  "Takes no arguments...\r\n"},
30916 
30917  // Goober5000
30918  { OP_ANY_OF, "Any-of (Conditional operator)\r\n"
30919  "\tSupplies arguments for the " SEXP_ARGUMENT_STRING " special data item. Any of the supplied arguments can satisfy the expression(s) "
30920  "in which " SEXP_ARGUMENT_STRING " is used.\r\n\r\n"
30921  "In practice, this will behave like a standard \"for-each\" statement, evaluating the action operators for each argument that satisfies the condition.\r\n\r\n"
30922  "Takes 1 or more arguments...\r\n"
30923  "\tAll:\tAnything that could be used in place of " SEXP_ARGUMENT_STRING "." },
30924 
30925  // Goober5000
30926  { OP_EVERY_OF, "Every-of (Conditional operator)\r\n"
30927  "\tSupplies arguments for the " SEXP_ARGUMENT_STRING " special data item. Every one of the supplied arguments will be evaluated to satisfy the expression(s) "
30928  "in which " SEXP_ARGUMENT_STRING " is used.\r\n\r\n"
30929  "Takes 1 or more arguments...\r\n"
30930  "\tAll:\tAnything that could be used in place of " SEXP_ARGUMENT_STRING "." },
30931 
30932  // Goober5000
30933  { OP_RANDOM_OF, "Random-of (Conditional operator)\r\n"
30934  "\tSupplies arguments for the " SEXP_ARGUMENT_STRING " special data item. A random supplied argument will be selected to satisfy the expression(s) "
30935  "in which " SEXP_ARGUMENT_STRING " is used. The same argument will be returned by all subsequent calls\r\n\r\n"
30936  "Takes 1 or more arguments...\r\n"
30937  "\tAll:\tAnything that could be used in place of " SEXP_ARGUMENT_STRING "." },
30938 
30939  // Karajorma
30940  { OP_RANDOM_MULTIPLE_OF, "Random-multiple-of (Conditional operator)\r\n"
30941  "\tSupplies arguments for the " SEXP_ARGUMENT_STRING " special data item. A random supplied argument will be selected to satisfy the expression(s) "
30942  "in which " SEXP_ARGUMENT_STRING " is used.\r\n\r\n"
30943  "Takes 1 or more arguments...\r\n"
30944  "\tAll:\tAnything that could be used in place of " SEXP_ARGUMENT_STRING "." },
30945 
30946  // Goober5000
30947  { OP_NUMBER_OF, "Number-of (Conditional operator)\r\n"
30948  "\tSupplies arguments for the " SEXP_ARGUMENT_STRING " special data item. Any [number] of the supplied arguments can satisfy the expression(s) "
30949  "in which " SEXP_ARGUMENT_STRING " is used.\r\n\r\n"
30950  "Takes 2 or more arguments...\r\n"
30951  "\t1:\tNumber of arguments, as above\r\n"
30952  "\tRest:\tAnything that could be used in place of " SEXP_ARGUMENT_STRING "." },
30953 
30954  // Karajorma
30955  { OP_IN_SEQUENCE, "In-Sequence (Conditional operator)\r\n"
30956  "\tSupplies arguments for the " SEXP_ARGUMENT_STRING " special data item. The first argument in the list will be selected to satisfy the expression(s) "
30957  "in which " SEXP_ARGUMENT_STRING " is used. The same argument will be returned by all subsequent calls\r\n\r\n"
30958  "Takes 1 or more arguments...\r\n"
30959  "\tAll:\tAnything that could be used in place of " SEXP_ARGUMENT_STRING "." },
30960 
30961  // Goober5000
30962  { OP_FOR_COUNTER, "For-Counter (Conditional operator)\r\n"
30963  "\tSupplies counter values for the " SEXP_ARGUMENT_STRING " special data item. This sexp will count up from the start value to the stop value, and each value will be provided as an argument to the action operators. "
30964  "The default increment is 1, but if the optional increment parameter is provided, the counter will increment by that number. The stop value will be supplied if appropriate; e.g. counting from 0 to 10 by 2 will supply 0, 2, 4, 6, 8, and 10; "
30965  "but counting by 3 will supply 0, 3, 6, and 9.\r\n\r\n"
30966  "Note that the counter values are all treated as valid arguments, and it is impossible to invalidate a counter argument. If you want to invalidate a counter value, use Any-of and list the values explicitly.\r\n\r\n"
30967  "This sexp will usually need to be accompanied by the string-to-int sexp, as the counter variables are provided in string format but are most useful in integer format.\r\n\r\n"
30968  "Takes 2 or 3 arguments...\r\n"
30969  "\t1:\tCounter start value\r\n"
30970  "\t2:\tCounter stop value\r\n"
30971  "\t3:\tCounter increment (optional)" },
30972 
30973  // Goober5000
30974  { OP_INVALIDATE_ARGUMENT, "Invalidate-argument (Conditional operator)\r\n"
30975  "\tRemoves an argument from future consideration as a " SEXP_ARGUMENT_STRING " special data item.\r\n"
30976  "Takes 1 or more arguments...\r\n"
30977  "\tAll:\tThe argument to remove from the preceding argument list." },
30978 
30979  // Karajorma
30980  { OP_VALIDATE_ARGUMENT, "Validate-argument (Conditional operator)\r\n"
30981  "\tRestores an argument for future consideration as a " SEXP_ARGUMENT_STRING " special data item.\r\n"
30982  "\tIf the argument hasn't been previously invalidated, it will do nothing.\r\n"
30983  "Takes 1 or more arguments...\r\n"
30984  "\tAll:\tThe argument to restore to the preceding argument list." },
30985 
30986  // Karajorma
30987  { OP_INVALIDATE_ALL_ARGUMENTS, "Invalidate-all-arguments (Conditional operator)\r\n"
30988  "\tRemoves all argument from future consideration as " SEXP_ARGUMENT_STRING " special data items.\r\n"
30989  "Takes no arguments." },
30990 
30991  // Karajorma
30992  { OP_VALIDATE_ALL_ARGUMENTS, "Validate-all-arguments (Conditional operator)\r\n"
30993  "\tRestores all arguments for future consideration as " SEXP_ARGUMENT_STRING " special data items.\r\n"
30994  "\tIf the argument hasn't been previously invalidated, it will do nothing.\r\n"
30995  "Takes no arguments." },
30996 
30997  // Goober5000 - added wing capability
30998  { OP_CHANGE_IFF, "Change IFF (Action operator)\r\n"
30999  "\tSets the specified ship(s) or wing(s) to the specified team.\r\n"
31000  "Takes 2 or more arguments...\r\n"
31001  "\t1:\tTeam to change to (\"friendly\", \"hostile\" or \"unknown\").\r\n"
31002  "\tRest:\tName of ship or wing to change team status of." },
31003 
31004  // Wanderer
31005  { OP_CHANGE_IFF_COLOR, "Change IFF Color (Action operator)\r\n"
31006  "\tSets the specified ship(s) or wing(s) apparent color.\r\n"
31007  "Takes 6 or more arguments...\r\n"
31008  "\t1:\tName of the team from which target is observed from.\r\n"
31009  "\t2:\tName of the team of the observed target to receive the alternate color.\r\n"
31010  "\t3:\tRed color (value from 0 to 255).\r\n"
31011  "\t4:\tGreen color (value from 0 to 255).\r\n"
31012  "\t5:\tBlue color (value from 0 to 255).\r\n"
31013  "\tRest:\tName of ship or wing to change team status of." },
31014 
31015  // Goober5000
31016  { OP_CHANGE_AI_CLASS, "Change AI Class (Action operator)\r\n"
31017  "\tSets the specified ship or ship subsystem(s) to the specified ai class.\r\n"
31018  "Takes 2 or more arguments...\r\n"
31019  "\t1:\tAI Class to change to (\"None\", \"Coward\", \"Lieutenant\", etc.)\r\n"
31020  "\t2:\tName of ship to change AI class of\r\n"
31021  "\tRest:\tName of subsystem to change AI class of (optional)" },
31022 
31023  { OP_MODIFY_VARIABLE, "Modify-variable (Misc. operator)\r\n"
31024  "\tModifies variable to specified value\r\n\r\n"
31025  "Takes 2 arguments...\r\n"
31026  "\t1:\tName of Variable.\r\n"
31027  "\t2:\tValue to be set." },
31028 
31029  { OP_GET_VARIABLE_BY_INDEX, "get-variable-by-index (originally variable-array-get)\r\n"
31030  "\tGets the value of the variable specified by the given index. This is an alternate way "
31031  "to access variables rather than by their names, and it enables cool features such as "
31032  "arrays and pointers.\r\n\r\nPlease note that only numeric variables are supported. Any "
31033  "attempt to access a string variable will result in a value of SEXP_NAN_FOREVER being returned.\r\n\r\n"
31034  "Takes 1 argument...\r\n"
31035  "\t1:\tIndex of variable, from 0 to MAX_SEXP_VARIABLES - 1." },
31036 
31037  { OP_SET_VARIABLE_BY_INDEX, "set-variable-by-index (originally variable-array-set)\r\n"
31038  "\tSets the value of the variable specified by the given index. This is an alternate way "
31039  "to modify variables rather than by their names, and it enables cool features such as "
31040  "arrays and pointers.\r\n\r\nIn contrast to get-variable-by-index, note that this sexp "
31041  "*does* allow the modification of string variables.\r\n\r\n"
31042  "Takes 2 arguments...\r\n"
31043  "\t1:\tIndex of variable, from 0 to MAX_SEXP_VARIABLES - 1.\r\n"
31044  "\t2:\tValue to be set." },
31045 
31046  { OP_COPY_VARIABLE_FROM_INDEX, "copy-variable-from-index\r\n"
31047  "\tRetrieves the value of the variable specified by the given index and stores it in another variable. "
31048  "This is very similar to variable-array-get, except the result is stored in a new variable rather than "
31049  "being returned by value. One important difference is that this sexp can be used to copy string variables as well as numeric variables.\r\n\r\n"
31050  "Takes 2 arguments...\r\n"
31051  "\t1:\tIndex of source variable, from 0 to MAX_SEXP_VARIABLES - 1.\r\n"
31052  "\t2:\tDestination variable. The type of this variable must match the type of the variable referenced by the index." },
31053 
31054  { OP_COPY_VARIABLE_BETWEEN_INDEXES, "copy-variable-between-indexes\r\n"
31055  "\tRetrieves the value of the variable specified by the first index and stores it in the variable specified by the second index. The first variable is not modified.\r\n\r\n"
31056  "Takes 2 arguments...\r\n"
31057  "\t1:\tIndex of source variable, from 0 to MAX_SEXP_VARIABLES - 1.\r\n"
31058  "\t2:\tIndex of destination variable, from 0 to MAX_SEXP_VARIABLES - 1. The types of both variables must match." },
31059 
31060  { OP_PROTECT_SHIP, "Protect ship (Action operator)\r\n"
31061  "\tProtects a ship from being attacked by any enemy ship. Any ship "
31062  "that is protected will not come under enemy fire.\r\n\r\n"
31063  "Takes 1 or more arguments...\r\n"
31064  "\tAll:\tName of ship(s) to protect." },
31065 
31066  { OP_UNPROTECT_SHIP, "Unprotect ship (Action operator)\r\n"
31067  "\tUnprotects a ship from being attacked by any enemy ship. Any ship "
31068  "that is not protected can come under enemy fire. This function is the opposite "
31069  "of protect-ship.\r\n\r\n"
31070  "Takes 1 or more arguments...\r\n"
31071  "\tAll:\tName of ship(s) to unprotect." },
31072 
31073  { OP_BEAM_PROTECT_SHIP, "Beam Protect ship (Action operator)\r\n"
31074  "\tProtects a ship from being attacked with beam weapon. Any ship "
31075  "that is beam protected will not come under enemy beam fire.\r\n\r\n"
31076  "Takes 1 or more arguments...\r\n"
31077  "\tAll:\tName of ship(s) to protect." },
31078 
31079  { OP_BEAM_UNPROTECT_SHIP, "Beam Unprotect ship (Action operator)\r\n"
31080  "\tUnprotects a ship from being attacked with beam weapon. Any ship "
31081  "that is not beam protected can come under enemy beam fire. This function is the opposite "
31082  "of beam-protect-ship.\r\n\r\n"
31083  "Takes 1 or more arguments...\r\n"
31084  "\tAll:\tName of ship(s) to unprotect." },
31085 
31086  // Goober5000
31087  { OP_TURRET_PROTECT_SHIP, "Turret Protect ship (Action operator)\r\n"
31088  "\tProtects a ship from being attacked with a turret weapon of a given type. Any ship "
31089  "that is turret protected will not come under enemy fire from that type of turret, though it may come under fire by other turrets.\r\n\r\n"
31090  "Takes 2 or more arguments...\r\n"
31091  "\t1:\tType of turret (currently supported types are \"beam\", \"flak\", \"laser\", and \"missile\")\r\n"
31092  "\tRest:\tName of ship(s) to protect." },
31093 
31094  // Goober5000
31095  { OP_TURRET_UNPROTECT_SHIP, "Turret Unprotect ship (Action operator)\r\n"
31096  "\tUnprotects a ship from being attacked with a turret weapon of a given type. Any ship "
31097  "that is not turret protected can come under enemy fire from that type of turret. This function is the opposite "
31098  "of turret-protect-ship.\r\n\r\n"
31099  "Takes 2 or more arguments...\r\n"
31100  "\t1:\tType of turret (currently supported types are \"beam\", \"flak\", \"laser\", and \"missile\")\r\n"
31101  "\tRest:\tName of ship(s) to unprotect." },
31102 
31103  { OP_SEND_MESSAGE, "Send message (Action operator)\r\n"
31104  "\tSends a message to the player. Can be send by a ship, wing, or special "
31105  "source. To send it from a special source, make the first character of the first "
31106  "argument a \"#\".\r\n\r\n"
31107  "Takes 3 arguments...\r\n"
31108  "\t1:\tName of who the message is from.\r\n"
31109  "\t2:\tPriority of message (\"Low\", \"Normal\" or \"High\").\r\n"
31110  "\t3:\tName of message (from message editor)." },
31111 
31112  // Karajorma
31113  { OP_ENABLE_BUILTIN_MESSAGES, "Enable builtin messages (Action operator)\r\n"
31114  "\tTurns the built in messages sent by command or pilots on\r\n"
31115  "Takes 0 or more arguments...\r\n"
31116  "If no arguments are supplied any ships not given individual silence orders will be able\r\n"
31117  "to send built in messages. Command will also be unsilenced\r\n"
31118  "Using the Any Wingman option cancels radio silence for all ships in wings.\r\n"
31119  "\tAll:\tName of ship to allow to talk." },
31120 
31121  // Karajorma
31122  { OP_DISABLE_BUILTIN_MESSAGES, "Disable builtin messages (Action operator)\r\n"
31123  "\tTurns the built in messages sent by command or pilots off\r\n"
31124  "Takes 0 or more arguments....\r\n"
31125  "If no arguments are supplied all built in messages are disabled.\r\n"
31126  "Using the Any Wingman option silences for all ships in wings.\r\n"
31127  "\tAll:\tName of ship to be silenced." },
31128 
31129  // Karajorma
31130  { OP_SET_MISSION_MOOD, "set Mission Mood (Action operator)\r\n"
31131  "\tSets the mood of the mission, this affects the choice of builtin messages sent by wingmen\r\n"
31132  "Takes 1 argument...\r\n"
31133  "\t1:\tMission mood (from messages.tbl) to use." },
31134 
31135  // Karajorma
31136  { OP_SET_PERSONA, "Set Persona (Action operator)\r\n"
31137  "\tSets the persona of the supplied ship to the persona supplied\r\n"
31138  "Takes 2 or more arguments...\r\n"
31139  "\t1:\tPersona to use."
31140  "\tRest:\tName of the ship." },
31141 
31142  { OP_SELF_DESTRUCT, "Self destruct (Action operator)\r\n"
31143  "\tCauses the specified ship(s) to self destruct.\r\n\r\n"
31144  "Takes 1 or more arguments...\r\n"
31145  "\tAll:\tName of ship to self destruct." },
31146 
31147  { OP_NEXT_MISSION, "Next Mission (Action operator)\r\n"
31148  "\tThe next mission operator is used for campaign branching in the campaign editor. "
31149  "It specifies which mission should played be next in the campaign. This operator "
31150  "generally follows a 'when' or 'cond' statment in the campaign file.\r\n\r\n"
31151  "Takes 1 argument...\r\n"
31152  "\t1:\tName of mission (filename) to proceed to." },
31153 
31154  { OP_CLEAR_GOALS, "Clear goals (Action operator)\r\n"
31155  "\tClears the goals for the specified ships and/or wings.\r\n\r\n"
31156  "Takes 1 or more arguments...\r\n"
31157  "\tAll:\tName of ship or wing." },
31158 
31159  { OP_ADD_GOAL, "Add goal (Action operator)\r\n"
31160  "\tAdds a goal to a ship or wing.\r\n\r\n"
31161  "Takes 2 arguments...\r\n"
31162  "\t1:\tName of ship or wing to add goal to.\r\n"
31163  "\t2:\tGoal to add." },
31164 
31165  // Goober5000
31166  { OP_REMOVE_GOAL, "Remove goal (Action operator)\r\n"
31167  "\tRemoves a goal from a ship or wing.\r\n\r\n"
31168  "Takes 2 arguments...\r\n"
31169  "\t1:\tName of ship or wing to remove goal from.\r\n"
31170  "\t2:\tGoal to remove." },
31171 
31172  { OP_SABOTAGE_SUBSYSTEM, "Sabotage subystem (Action operator)\r\n"
31173  "\tReduces the specified subsystem integrity by the specified percentage."
31174  "If the percntage strength of the subsystem (after completion) is less than 0%,"
31175  "subsystem strength is set to 0%.\r\n\r\n"
31176  "Takes 3 arguments...\r\n"
31177  "\t1:\tName of ship subsystem is on.\r\n"
31178  "\t2:\tName of subsystem to sabotage.\r\n"
31179  "\t3:\tPercentage to reduce subsystem integrity by." },
31180 
31181  { OP_REPAIR_SUBSYSTEM, "Repair Subystem (Action operator)\r\n"
31182  "\tIncreases the specified subsystem integrity by the specified percentage."
31183  "If the percntage strength of the subsystem (after completion) is greater than 100%,"
31184  "subsystem strength is set to 100%.\r\n\r\n"
31185  "Takes 4 arguments...\r\n"
31186  "\t1:\tName of ship subsystem is on.\r\n"
31187  "\t2:\tName of subsystem to repair.\r\n"
31188  "\t3:\tPercentage to increase subsystem integrity by.\r\n"
31189  "\t4:\tRepair turret submodel. Optional argument that defaults to true."},
31190 
31191  { OP_SET_SUBSYSTEM_STRNGTH, "Set Subsystem Strength (Action operator)\r\n"
31192  "\tSets the specified subsystem to the the specified percentage."
31193  "If the percentage specified is < 0, strength is set to 0. If the percentage is "
31194  "> 100 % the subsystem strength is set to 100%.\r\n\r\n"
31195  "Takes 3 arguments...\r\n"
31196  "\t1:\tName of ship subsystem is on.\r\n"
31197  "\t2:\tName of subsystem to set strength.\r\n"
31198  "\t3:\tPercentage to set subsystem integrity to.\r\n"
31199  "\t4:\tRepair turret submodel. Optional argument that defaults to true."},
31200 
31201  { OP_DESTROY_SUBSYS_INSTANTLY, "destroy-subsys-instantly\r\n"
31202  "\tDetroys the specified subsystems without effects."
31203  "\tSingle player only!"
31204  "Takes 2 or more arguments...\r\n"
31205  "\t1:\tName of ship subsystem is on.\r\n"
31206  "\tRest:\tName of subsystem to destroy.\r\n"},
31207 
31208  { OP_INVALIDATE_GOAL, "Invalidate goal (Action operator)\r\n"
31209  "\tMakes a mission goal invalid, which causes it to not show up on mission goals "
31210  "screen, or be evaluated.\r\n"
31211  "Takes 1 or more arguments...\r\n"
31212  "\tAll:\tName of mission goal to invalidate." },
31213 
31214  { OP_VALIDATE_GOAL, "Validate goal (Action operator)\r\n"
31215  "\tMakes a mission goal valid again, so it shows up on mission goals screen.\r\n"
31216  "Takes 1 or more arguments...\r\n"
31217  "\tAll:\tName of mission goal to validate." },
31218 
31219  { OP_SEND_RANDOM_MESSAGE, "Send random message (Action operator)\r\n"
31220  "\tSends a random message to the player from those supplied. Can be send by a "
31221  "ship, wing, or special source. To send it from a special source, make the first "
31222  "character of the first argument a \"#\".\r\n\r\n"
31223  "Takes 3 or more arguments...\r\n"
31224  "\t1:\tName of who the message is from.\r\n"
31225  "\t2:\tPriority of message (\"Low\", \"Normal\" or \"High\")."
31226  "\tRest:\tName of message (from message editor)." },
31227 
31228  { OP_TRANSFER_CARGO, "Transfer Cargo (Action operator)\r\n"
31229  "\tTransfers the cargo from one ship to another ship.\r\n\r\n"
31230  "Takes 2 arguments...\r\n"
31231  "\t1:\tName of ship that cargo is being transferred from.\r\n"
31232  "\t2:\tName of ship that cargo is being transferred to." },
31233 
31234  { OP_EXCHANGE_CARGO, "Exchange Cargo (Action operator)\r\n"
31235  "\tExchanges the cargos of two ships. If one of the two ships contains no cargo, "
31236  "the cargo is transferred instead.\r\n"
31237  "Takes 2 arguments...\r\n"
31238  "\t1:\tName of one of the ships.\r\n"
31239  "\t2:\tName of the other ship." },
31240 
31241  // Goober5000
31242  { OP_SET_CARGO, "Set Cargo (Action operator)\r\n"
31243  "\tSets the cargo on a ship or ship subsystem. The cargo-no-deplete flag status is carried through to the new cargo.\r\n"
31244  "Takes 2 or 3 arguments...\r\n"
31245  "\t1:\tName of the cargo\r\n"
31246  "\t2:\tName of the ship\r\n"
31247  "\t3:\tName of the ship subsystem (optional)" },
31248 
31249  // Goober5000
31250  { OP_IS_CARGO, "Is Cargo (Status operator)\r\n"
31251  "\tChecks whether the specified ship or ship subsystem contains a particular cargo.\r\n"
31252  "Takes 2 or 3 arguments...\r\n"
31253  "\t1:\tName of the cargo\r\n"
31254  "\t2:\tName of the ship\r\n"
31255  "\t3:\tName of the ship subsystem (optional)" },
31256 
31257  // Goober5000
31258  { OP_CHANGE_SOUNDTRACK, "change-soundtrack\r\n"
31259  "\tChanges the mission music. Takes 1 argument...\r\n"
31260  "\t1: Name of the music selection (taken from music.tbl)" },
31261 
31262  // Goober5000
31263  { OP_PLAY_SOUND_FROM_TABLE, "play-sound-from-table\r\n"
31264  "\tPlays a sound listed in the Game Sounds section of sounds.tbl. Note that if the sound is a non-3D sound (if the min and max radius are 0, or unspecified), the sound will just play without being fixed at a particular position in space. "
31265  "In this case, the origin coordinates will be ignored. (A better design would have put the sound index first and made the origin arguments optional, but the difference between 2D and 3D sounds was not understood at the time. C'est la vie.)\r\n\r\n"
31266  "Takes 4 arguments...\r\n"
31267  "\t1: Origin X\r\n"
31268  "\t2: Origin Y\r\n"
31269  "\t3: Origin Z\r\n"
31270  "\t4: Sound (index into sounds.tbl or name of the sound entry)" },
31271 
31272  // Goober5000
31273  { OP_PLAY_SOUND_FROM_FILE, "play-sound-from-file\r\n"
31274  "\tPlays a sound, such as a music soundtrack, from a file. Important: Only one sound at a time can be played with this sexp!\r\n"
31275  "Takes 1 to 3 arguments...\r\n"
31276  "\t1: Sound (file name)\r\n"
31277  "\t2: Enter a non-zero number to loop. default is off (optional).\r\n"
31278  "\t3: Enter a non-zero number to use environment effects. default is off (optional)."
31279  },
31280 
31281  // Goober5000
31282  { OP_CLOSE_SOUND_FROM_FILE, "close-sound-from-file\r\n"
31283  "\tCloses the currently playing sound started by play-sound-from-file, if there is any. Takes 1 argument...\r\n"
31284  "\t1: Fade (default is true)" },
31285 
31286  // Goober5000
31287  { OP_PAUSE_SOUND_FROM_FILE, "pause-sound-from-file\r\n"
31288  "\tPauses or unpauses the currently playing sound started by play-sound-from-file, if there is any. Takes 1 argument...\r\n"
31289  "\t1: Boolean - True to pause, False to unpause" },
31290 
31291  // Taylor
31292  { OP_SET_SOUND_ENVIRONMENT, "set-sound-environment\r\n"
31293  "Sets the EAX environment for all sound effects. Optionally sets one or more parameters specific to the environment. Takes 1 or more arguments...\r\n"
31294  "\t1:\tSound environment name (a value of \"" SEXP_NONE_STRING "\" will disable the effects)\r\n"
31295  "\t2:\tEnvironment option (optional)\r\n"
31296  "\t3:\tEnvironment value x 1000, e.g. 10 is 0.01 (optional)\r\n"
31297  "Use Add-Data to specify additional environment options in repeating option-value pairs, just like Send-Message-List can have additional messages in source-priority-message-delay groups.\r\n\r\n"
31298  "IMPORTANT: each additional option in the list MUST HAVE two entries; any option without the two proper fields will be ignored, as will any successive options." },
31299 
31300  // Taylor
31301  { OP_UPDATE_SOUND_ENVIRONMENT, "update-sound-environment\r\n"
31302  "Updates the current EAX environment with new values. Takes 2 or more arguments...\r\n"
31303  "\t1:\tEnvironment option\r\n"
31304  "\t2:\tEnvironment value x 1000, e.g. 10 is 0.01\r\n"
31305  "Use Add-Data to specify additional environment options in repeating option-value pairs, just like Send-Message-List can have additional messages in source-priority-message-delay groups.\r\n\r\n"
31306  "IMPORTANT: Each additional option in the list MUST HAVE two entries; any option without the two proper fields will be ignored, as will any successive options." },
31307 
31308  //The E
31309  { OP_ADJUST_AUDIO_VOLUME, "adjust-audio-volume\r\n"
31310  "Adjusts the relative volume of one sound type. Takes 1 to 3 arguments....\r\n"
31311  "\t1:\tSound Type to adjust, either Music, Voice or Effects. Will act as a reset for the given category, if no other argument present\r\n"
31312  "\t2:\tPercentage of the users' settings to adjust to (optional), 0 will be silence, 100 means the maximum volume as set by the user\r\n"
31313  "\t3:\tFade time (optional), time in milliseconds to adjust the volume"},
31314 
31315  // Goober5000
31316  { OP_SET_EXPLOSION_OPTION, "set-explosion-option\r\n"
31317  "Sets an explosion option on a particular ship. Takes 3 or more arguments...\r\n"
31318  "\t1:\tShip name\r\n"
31319  "\t2:\tExplosion option\r\n"
31320  "\t3:\tExplosion value (for shockwave speed, 0 will produce no shockwave; for death roll time, 0 will use the default time)\r\n"
31321  "Use Add-Data to specify additional explosion options in repeating option-value pairs, just like Send-Message-List can have additional messages in source-priority-message-delay groups.\r\n\r\n"
31322  "IMPORTANT: Each additional option in the list MUST HAVE two entries; any option without the two proper fields will be ignored, as will any successive options." },
31323 
31324  // Goober5000
31325  { OP_EXPLOSION_EFFECT, "explosion-effect\r\n"
31326  "\tCauses an explosion at a given origin, with the given parameters. "
31327  "Takes 11 or 13 arguments...\r\n"
31328  "\t1: Origin X\r\n"
31329  "\t2: Origin Y\r\n"
31330  "\t3: Origin Z\r\n"
31331  "\t4: Damage\r\n"
31332  "\t5: Blast force\r\n"
31333  "\t6: Size of explosion (if 0, explosion will not be visible)\r\n"
31334  "\t7: Inner radius to apply damage (if 0, explosion will not be visible)\r\n"
31335  "\t8: Outer radius to apply damage (if 0, explosion will not be visible)\r\n"
31336  "\t9: Shockwave speed (if 0, there will be no shockwave)\r\n"
31337  "\t10: Type - For backward compatibility 0 = medium, 1 = large1 (4th in table), 2 = large2 (5th in table)\r\n"
31338  " 3 or greater link to respctive entry in fireball.tbl\r\n"
31339  "\t11: Sound (index into sounds.tbl or name of the sound entry)\r\n"
31340  "\t12: EMP intensity (optional)\r\n"
31341  "\t13: EMP duration in seconds (optional)" },
31342 
31343  // Goober5000
31344  { OP_WARP_EFFECT, "warp-effect\r\n"
31345  "\tCauses a subspace warp effect at a given origin, facing toward a given location, with the given parameters.\r\n"
31346  "Takes 12 arguments...\r\n"
31347  "\t1: Origin X\r\n"
31348  "\t2: Origin Y\r\n"
31349  "\t3: Origin Z\r\n"
31350  "\t4: Location X\r\n"
31351  "\t5: Location Y\r\n"
31352  "\t6: Location Z\r\n"
31353  "\t7: Radius\r\n"
31354  "\t8: Duration in seconds (values smaller than 4 are ignored)\r\n"
31355  "\t9: Warp opening sound (index into sounds.tbl or name of the sound entry)\r\n"
31356  "\t10: Warp closing sound (index into sounds.tbl or name of the sound entry)\r\n"
31357  "\t11: Type (0 for standard blue [default], 1 for Knossos green)\r\n"
31358  "\t12: Shape (0 for 2-D [default], 1 for 3-D)" },
31359 
31360  // Goober5000
31361  { OP_SET_OBJECT_FACING, "set-object-facing\r\n"
31362  "\tSets an object's orientation to face the specified coordinates. "
31363  "Takes 4 arguments...\r\n"
31364  "\t1: The name of a ship or wing.\r\n"
31365  "\t2: The X coordinate to face.\r\n"
31366  "\t3: The Y coordinate to face.\r\n"
31367  "\t4: The Z coordinate to face.\r\n"
31368  "\t5: Turn time in milliseconds (optional)\r\n"
31369  "\t6: Bank (optional). Enter a non-zero value to enable banking." },
31370 
31371  // Goober5000
31372  { OP_SET_OBJECT_FACING_OBJECT, "set-object-facing-object\r\n"
31373  "\tSets an object's orientation to face the specified object. "
31374  "Takes 2 arguments...\r\n"
31375  "\t1: The name of a ship or wing.\r\n"
31376  "\t2: The object to face.\r\n"
31377  "\t3: Turn time in milliseconds (optional)\r\n"
31378  "\t4: Bank (optional). Enter a non-zero value to enable banking." },
31379 
31380  // Wanderer
31381  { OP_SHIP_MANEUVER, "ship-maneuver\r\n"
31382  "\tCombines the effects of the ship-rot-maneuver and ship-lat-maneuver sexps. Takes 10 arguments:\r\n"
31383  "\t1: The name of a ship or wing\r\n"
31384  "\t2: Duration of the maneuver, in milliseconds\r\n"
31385  "\t3: Heading movement velocity, as a percentage (-100 to 100) of the tabled maximum heading velocity, or 0 to not modify the ship's current value\r\n"
31386  "\t4: Pitch movement velocity, as a percentage (-100 to 100) of the tabled maximum pitch velocity, or 0 to not modify the ship's current value\r\n"
31387  "\t5: Bank movement velocity, as a percentage (-100 to 100) of the tabled maximum bank velocity, or 0 to not modify the ship's current value\r\n"
31388  "\t6: Whether to apply all of the rotational velocity values even if any of them are 0\r\n"
31389  "\t7: Vertical movement velocity, as a percentage (-100 to 100) of the tabled maximum vertical velocity, or 0 to not modify the ship's current value\r\n"
31390  "\t8: Sideways movement velocity, as a percentage (-100 to 100) of the tabled maximum sideways velocity, or 0 to not modify the ship's current value\r\n"
31391  "\t9: Forward movement velocity, as a percentage (-100 to 100) of the tabled maximum forward velocity, or 0 to not modify the ship's current value\r\n"
31392  "\t10: Whether to apply all of the lateral velocity values even if any of them are 0\r\n" },
31393 
31394  // Wanderer
31395  { OP_SHIP_ROT_MANEUVER, "ship-rot-maneuver\r\n"
31396  "\tCauses a ship to move in a rotational direction. For the purposes of this sexp, this means the ship rotates along its own heading, pitch, or bank axis (or a combination of axes) without regard to normal ship rotation rules. "
31397  "You may find it necessary to disable the ship AI (e.g. by issuing a play-dead order) before running this sexp.\r\n\r\n"
31398  "Takes 6 arguments:\r\n"
31399  "\t1: The name of a ship or wing\r\n"
31400  "\t2: Duration of the maneuver, in milliseconds\r\n"
31401  "\t3: Heading movement velocity, as a percentage (-100 to 100) of the tabled maximum heading velocity, or 0 to not modify the ship's current value\r\n"
31402  "\t4: Pitch movement velocity, as a percentage (-100 to 100) of the tabled maximum pitch velocity, or 0 to not modify the ship's current value\r\n"
31403  "\t5: Bank movement velocity, as a percentage (-100 to 100) of the tabled maximum bank velocity, or 0 to not modify the ship's current value\r\n"
31404  "\t6: Whether to apply all of the above velocity values even if any of them are 0\r\n" },
31405 
31406  // Wanderer
31407  { OP_SHIP_LAT_MANEUVER, "ship-lat-maneuver\r\n"
31408  "\tCauses a ship to move in a lateral direction. For the purposes of this sexp, this means the ship translates along its own X, Y, or Z axis (or a combination of axes) without regard to normal ship movement rules. "
31409  "You may find it necessary to disable the ship AI (e.g. by issuing a play-dead order) before running this sexp.\r\n\r\n"
31410  "Takes 6 arguments:\r\n"
31411  "\t1: The name of a ship or wing\r\n"
31412  "\t2: Duration of the maneuver, in milliseconds\r\n"
31413  "\t3: Vertical movement velocity, as a percentage (-100 to 100) of the tabled maximum vertical velocity, or 0 to not modify the ship's current value\r\n"
31414  "\t4: Sideways movement velocity, as a percentage (-100 to 100) of the tabled maximum sideways velocity, or 0 to not modify the ship's current value\r\n"
31415  "\t5: Forward movement velocity, as a percentage (-100 to 100) of the tabled maximum forward velocity, or 0 to not modify the ship's current value\r\n"
31416  "\t6: Whether to apply all of the above velocity values even if any of them are 0\r\n" },
31417 
31418  // Goober5000
31419  { OP_SHIP_TAG, "ship-tag\r\n"
31420  "\tTags a ship. Takes 3 or 8 arguments...\r\n"
31421  "\t1: The name of a ship.\r\n"
31422  "\t2: The tag level (currently 1, 2, or 3).\r\n"
31423  "\t3: The tag time (in seconds).\r\n"
31424  "\t4: A SSM missile (optional - used only for TAG-C).\r\n"
31425  "\t5: The X origin of the SSM missile (optional - used only for TAG-C).\r\n"
31426  "\t6: The Y origin of the SSM missile (optional - used only for TAG-C).\r\n"
31427  "\t7: The Z origin of the SSM missile (optional - used only for TAG-C).\r\n"
31428  "\t8: The team the SSM missile belongs to (optional - used only for TAG-C).\r\n" },
31429 
31430 /* made obsolete by Goober5000 - it only works in debug builds anyway
31431  { OP_INT3, "Error (Debug directive)\r\n"
31432  "Causes the game to halt with an error." },
31433 */
31434 
31435  { OP_AI_CHASE, "Ai-chase (Ship goal)\r\n"
31436  "\tCauses the specified ship to chase and attack the specified target.\r\n\r\n"
31437  "Takes 2 or 3 arguments...\r\n"
31438  "\t1:\tName of ship to chase.\r\n"
31439  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
31440  "\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
31441  },
31442 
31443  { OP_AI_DOCK, "Ai-dock (Ship goal)\r\n"
31444  "\tCauses one ship to dock with another ship.\r\n\r\n"
31445  "Takes 4 arguments...\r\n"
31446  "\t1:\tName of dockee ship (The ship that \"docker\" will dock with).\r\n"
31447  "\t2:\tDocker's docking point - Which dock point docker uses to dock.\r\n"
31448  "\t3:\tDockee's docking point - Which dock point on dockee docker will move to.\r\n"
31449  "\t4:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
31450 
31451  { OP_AI_UNDOCK, "Ai-undock (Ship goal)\r\n"
31452  "\tCauses the specified ship to undock from who it is currently docked with.\r\n\r\n"
31453  "Takes 1 or 2 arguments...\r\n"
31454  "\t1:\tGoal priority (number between 0 and 89).\r\n"
31455  "\t2 (optional):\tShip to undock from. If none is specified, the code will pick the first docked ship." },
31456 
31457  { OP_AI_WARP_OUT, "Ai-warp-out (Ship/Wing Goal)\r\n"
31458  "\tCauses the specified ship/wing to immediately warp out of the mission, from its current location. "
31459  "It will warp even if its departure cue is specified as a hangar bay.\r\n\r\n"
31460  "Takes 2 arguments...\r\n"
31461  "\t1:\tName of waypoint path to follow to warp out (not used).\r\n"
31462  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
31463 
31464  { OP_AI_WAYPOINTS, "Ai-waypoints (Ship goal)\r\n"
31465  "\tCauses the specified ship to fly a waypoint path continuously.\r\n\r\n"
31466  "Takes 2 arguments...\r\n"
31467  "\t1:\tName of waypoint path to fly.\r\n"
31468  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
31469 
31470  { OP_AI_WAYPOINTS_ONCE, "Ai-waypoints once (Ship goal)\r\n"
31471  "\tCauses the specified ship to fly a waypoint path.\r\n\r\n"
31472  "Takes 2 arguments...\r\n"
31473  "\t1:\tName of waypoint path to fly.\r\n"
31474  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
31475 
31476  { OP_AI_DESTROY_SUBSYS, "Ai-destroy subsys (Ship goal)\r\n"
31477  "\tCauses the specified ship to attack and try and destroy the specified subsystem "
31478  "on the specified ship.\r\n\r\n"
31479  "Takes 3 or 4 arguments...\r\n"
31480  "\t1:\tName of ship subsystem is on.\r\n"
31481  "\t2:\tName of subsystem on the ship to attack and destroy.\r\n"
31482  "\t3:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
31483  "\t4 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
31484  },
31485 
31486  { OP_AI_CHASE_WING, "Ai-chase wing (Ship goal)\r\n"
31487  "\tCauses the specified ship to chase and attack the specified target.\r\n\r\n"
31488  "Takes 2 or 3 arguments...\r\n"
31489  "\t1:\tName of wing to chase.\r\n"
31490  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
31491  "\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
31492  },
31493 
31494  { OP_AI_DISABLE_SHIP, "Ai-disable-ship (Ship/wing goal)\r\n"
31495  "\tThis AI goal causes a ship/wing to destroy all of the engine subsystems on "
31496  "the specified ship. This goal is different than ai-destroy-subsystem since a ship "
31497  "may have multiple engine subsystems requiring the use of > 1 ai-destroy-subsystem "
31498  "goals.\r\n"
31499  "Please note that this goal may call \"protect-ship\" on the target "
31500  "to prevent overzealous AI ships from destroying it in the process of disabling it. "
31501  "If the ship must be destroyed later on, be sure to call an \"unprotect-ship\" sexp.\r\n\r\n"
31502  "Takes 2 or 3 arguments...\r\n"
31503  "\t1:\tName of ship whose engine subsystems should be destroyed\r\n"
31504  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
31505  "\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
31506  },
31507 
31508  { OP_AI_DISARM_SHIP, "Ai-disarm-ship (Ship/wing goal)\r\n"
31509  "\tThis AI goal causes a ship/wing to destroy all of the turret subsystems on "
31510  "the specified ship. This goal is different than ai-destroy-subsystem since a ship "
31511  "may have multiple turret subsystems requiring the use of > 1 ai-destroy-subsystem "
31512  "goals.\r\n"
31513  "Please note that this goal may call \"protect-ship\" on the target "
31514  "to prevent overzealous AI ships from destroying it in the process of disarming it. "
31515  "If the ship must be destroyed later on, be sure to call an \"unprotect-ship\" sexp.\r\n\r\n"
31516  "Takes 2 arguments...\r\n"
31517  "\t1:\tName of ship whose turret subsystems should be destroyed\r\n"
31518  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
31519  "\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
31520  },
31521 
31522  { OP_AI_GUARD, "Ai-guard (Ship goal)\r\n"
31523  "\tCauses the specified ship to guard a ship from other ships not on the same team.\r\n\r\n"
31524  "Takes 2 arguments...\r\n"
31525  "\t1:\tName of ship to guard.\r\n"
31526  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
31527 
31528  { OP_AI_CHASE_ANY, "Ai-chase-any (Ship goal)\r\n"
31529  "\tCauses the specified ship to chase and attack any ship on the opposite team.\r\n\r\n"
31530  "Takes 1 argument...\r\n"
31531  "\t1:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
31532 
31533  { OP_AI_GUARD_WING, "Ai-guard wing (Ship goal)\r\n"
31534  "\tCauses the specified ship to guard a wing of ships from other ships not on the "
31535  "same team.\r\n\r\n"
31536  "Takes 2 arguments...\r\n"
31537  "\t1:\tName of wing to guard.\r\n"
31538  "\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
31539 
31540  { OP_NOP, "Do-nothing (Action operator)\r\n"
31541  "\tDoes nothing. This is used as the default for any required action arguments "
31542  "of an operator." },
31543 
31544  { OP_KEY_PRESSED, "Key-pressed (Boolean training operator)\r\n"
31545  "\tBecomes true when the specified default key has been pressed. Default key "
31546  "refers to the what the key normally is when not remapped. FreeSpace will "
31547  "automatically account for any keys that have been remapped. If the optional "
31548  "delay is specified, becomes true that many seconds after the key has been pressed.\r\n\r\n"
31549  "Returns a boolean value. Takes 1 or 2 arguments...\r\n"
31550  "\t1:\tDefault key to check for.\r\n"
31551  "\t2:\tDelay before operator registers as true (optional).\r\n" },
31552 
31553  { OP_KEY_RESET, "Key-reset (Training operator)\r\n"
31554  "\tMarks the specified default key as having not been pressed, so key-pressed will be false "
31555  "until the player presses it again. See key-pressed help for more information about "
31556  "what a default key is.\r\n\r\n"
31557  "\tNote that this sexp will not work properly in repeating events. Use key-reset-multiple "
31558  "if this is to be called multiple times in one event.\r\n\r\n"
31559  "Returns a boolean value. Takes 1 or more arguments...\r\n"
31560  "\tAll:\tDefault key to reset." },
31561 
31562  // Goober5000
31563  { OP_KEY_RESET_MULTIPLE, "Key-reset-multiple (Training operator)\r\n"
31564  "\tMarks the specified default key as having not been pressed, so key-pressed will be false "
31565  "until the player presses it again. See key-pressed help for more information about "
31566  "what a default key is.\r\n\r\n"
31567  "\tThis sexp, unlike key-reset, will work properly if called multiple times in one event.\r\n\r\n"
31568  "Returns a boolean value. Takes 1 or more arguments...\r\n"
31569  "\tAll:\tDefault key to reset." },
31570 
31571  { OP_TARGETED, "Targeted (Boolean training operator)\r\n"
31572  "\tIs true as long as the player has the specified ship (or ship's subsystem) targeted, "
31573  "or has been targeted for the specified amount of time.\r\n\r\n"
31574  "Returns a boolean value. Takes 1 to 3 arguments (first required, rest optional):\r\n"
31575  "\t1:\tName of ship to check if targeted by player.\r\n"
31576  "\t2:\tLength of time target should have been kept for (optional).\r\n"
31577  "\t3:\tName of subsystem on ship to check if targeted (optional)." },
31578 
31579  { OP_NODE_TARGETED, "Node-Targeted (Boolean training operator)\r\n"
31580  "\tIs true as long as the player has the specified jump node targeted, "
31581  "or has been targeted for the specified amount of time.\r\n\r\n"
31582  "Returns a boolean value. Takes 1 to 2 arguments (first required, rest optional):\r\n"
31583  "\t1:\tName of Jump Node to check if targeted by player.\r\n"
31584  "\t2:\tLength of time target should have been kept for (optional)."},
31585 
31586  // Sesquipedalian
31587  { OP_MISSILE_LOCKED, "Missile-locked (Boolean training operator)\r\n"
31588  "\tIs true as long as the player has had a missile lock for the specified amount of time. "
31589  "Optional arguments require lock to be maintained on a specified ship (or ship's subsystem).\r\n\r\n"
31590  "Returns a boolean value. Takes 1 to 3 arguments (first required, rest optional):\r\n"
31591  "\t1:\tLength of time missile lock should have been kept for.\r\n"
31592  "\t2:\tName of ship to check if locked onto by player (optional).\r\n"
31593  "\t3:\tName of subsystem on ship to check if locked onto (optional)." },
31594 
31595  { OP_SPEED, "Speed (Boolean training operator)\r\n"
31596  "\tBecomes true when the player has been within the specified speed range set by "
31597  "set-training-context-speed for the specified amount of time.\r\n\r\n"
31598  "Returns a boolean value. Takes 1 argument...\r\n"
31599  "\t1:\tTime in seconds." },
31600 
31601  { OP_GET_THROTTLE_SPEED, "Get-Throttle-Speed (Training operator)\r\n"
31602  "\tReturns the current throttle speed that the ship has been set to. Reverse speeds are returned as a negative value. "
31603  "Takes 1 argument...\r\n"
31604  "\t1:\tName of the player ship to check the throttle value for." },
31605 
31606  { OP_FACING, "Facing (Boolean training operator)\r\n"
31607  "\tIs true as long as the specified ship is within the player's specified "
31608  "forward cone. A forward cone is defined as any point that the angle between the "
31609  "vector of the point and the player, and the forward facing vector is within the "
31610  "given angle.\r\n\r\n"
31611  "Returns a boolean value. Takes 2 argument...\r\n"
31612  "\t1:\tShip to check is withing forward cone.\r\n"
31613  "\t2:\tAngle in degrees of the forward cone." },
31614 
31615  { OP_IS_FACING, "Is Facing (Boolean training operator)\r\n"
31616  "\tIs true as long as the second object is within the first ship's specified "
31617  "forward cone. A forward cone is defined as any point that the angle between the "
31618  "vector of the ship and point, and the forward facing vector is within the "
31619  "given angle. If the distance between the two is greater than the fourth"
31620  "parameter, this will return false.\r\n\r\n"
31621  "Returns a boolean value. Takes 3 or 4 argument...\r\n"
31622  "\t1:\tShip to check from.\r\n"
31623  "\t2:\tObject to check is within forward cone.\r\n"
31624  "\t3:\tAngle in degrees of the forward cone.\r\n"
31625  "\t4:\tRange in meters (optional)."},
31626 
31627  { OP_FACING2, "Facing Waypoint(Boolean training operator)\r\n"
31628  "\tIs true as long as the specified first waypoint is within the player's specified "
31629  "forward cone. A forward cone is defined as any point that the angle between the "
31630  "vector of the point and the player, and the forward facing vector is within the "
31631  "given angle.\r\n\r\n"
31632  "Returns a boolean value. Takes 2 argument...\r\n"
31633  "\t1:\tName of waypoint path whose first point is within forward cone.\r\n"
31634  "\t2:\tAngle in degrees of the forward cone." },
31635 
31636  // fixed by Goober5000 and then deprecated by Karajorma
31637  { OP_ORDER, "Order (Boolean training operator)\r\n"
31638  "\tDeprecated - Use Query-Orders in any new mission.\r\n\r\n"
31639  "\tBecomes true when the player had given the specified ship or wing the specified order.\r\n\r\n"
31640  "Returns a boolean value. Takes 2 or 3 arguments...\r\n"
31641  "\t1:\tName of ship or wing to check if given order to.\r\n"
31642  "\t2:\tName of order to check if player has given.\r\n"
31643  "\t3:\tName of the target of the order (optional)." },
31644 
31645  { OP_QUERY_ORDERS, "Query-Orders (Boolean training operator)\r\n"
31646  "\tBecomes true when the player had given the specified ship or wing the specified order.\r\n\r\n"
31647  "Returns a boolean value. Takes 2 or more arguments...\r\n"
31648  "\t1:\tName of ship or wing to check if given order to.\r\n"
31649  "\t2:\tName of order to check if player has given.\r\n"
31650  "\t3:\tMaximum length of time since order was given. Use 0 for any time in the mission.\r\n"
31651  "\t4:\tName of the target of the order (optional).\r\n"
31652  "\t5:\tName of player ship giving the order(optional).\r\n"
31653  "\t6:\tName of the subsystem for Destroy Subsystem orders.(optional)" },
31654 
31655  // Karajorma
31656  { OP_RESET_ORDERS, "Reset-Orders (Action training operator)\r\n"
31657  "\tResets the list of orders the player has given.\r\n"
31658  "Takes no arguments." },
31659 
31660  { OP_WAYPOINT_MISSED, "Waypoint-missed (Boolean training operator)\r\n"
31661  "\tBecomes true when a waypoint is flown, but the waypoint is ahead of the one "
31662  "they are supposed to be flying. The one they are supposed to be flying is the "
31663  "next one in sequence in the path after the last one they have hit.\r\n\r\n"
31664  "Returns a boolean value. Takes no arguments." },
31665 
31666  { OP_PATH_FLOWN, "Path-flown (Boolean training operator)\r\n"
31667  "\tBecomes true when all the waypoints in the path have been flown, in sequence.\r\n\r\n"
31668  "Returns a boolean value. Takes no arguments." },
31669 
31670  { OP_WAYPOINT_TWICE, "Waypoint-twice (Boolean training operator)\r\n"
31671  "\tBecomes true when a waypoint is hit that is before the last one hit, which "
31672  "indicates they have flown a waypoint twice.\r\n\r\n"
31673  "Returns a boolean value. Takes no arguments." },
31674 
31675  { OP_TRAINING_MSG, "Training-msg (Action training operator)\r\n"
31676  "\tSends the player a training message. Uses the same messages as normal messages, "
31677  "only they get displayed differently using this operator. If a secondary message "
31678  "is specified, it is sent the last time, while the primary message is sent all other "
31679  "times (event should have a repeat count greater than 1).\r\n\r\n"
31680  "Takes 1-3 arguments...\r\n"
31681  "\t1:\tName of primary message to send.\r\n"
31682  "\t2:\tName of secondary message to send (optional).\r\n"
31683  "\t3:\tDelay (in seconds) to wait before sending message. (optional)\r\n"
31684  "\t4:\tAmount of Time (in seconds) to display message (optional)." },
31685 
31686  { OP_SET_TRAINING_CONTEXT_FLY_PATH, "Set-training-context-fly-path (Training context operator)\r\n"
31687  "\tTells FreeSpace that the player is expected to fly a waypoint path. This must be "
31688  "executed before waypoint-missed, waypoint-twice and path-flown operators become valid.\r\n\r\n"
31689  "Takes 2 arguments...\r\n"
31690  "\t1:\tName of waypoint path player should fly.\r\n"
31691  "\t2:\tDistance away a player needs to be from a waypoint for it to be registered as flown." },
31692 
31693  { OP_SET_TRAINING_CONTEXT_SPEED, "Set-training-context-speed (Training context operator)\r\n"
31694  "\tTells FreeSpace that the player is expected to fly within a certain speed range. Once "
31695  "this operator has been executed, you can measure how long they have been within this "
31696  "speed range with the speed operator.\r\n\r\n"
31697  "Takes 2 arguments...\r\n"
31698  "\t1:\tMinimum speed of range player is to fly between.\r\n"
31699  "\t2:\tMaximum speed of range player is to fly between." },
31700 
31701  // Karajorma
31702  { OP_STRING_TO_INT, "string-to-int\r\n"
31703  "\tConverts a string into an integer. All non-numeric characters (except for the negative sign) will be ignored, as will any fractional part of a decimal number. This behavior is somewhat different than the atoi() function in C or C++, which will abort if it encounters any non-numeric character. For a string like \"turret31\", this sexp will return 31, but atoi() will return 0.\r\n\r\n"
31704  "Takes 1 argument...\r\n"
31705  "\t1:\tString to convert" },
31706 
31707  // Goober5000
31708  { OP_STRING_GET_LENGTH, "string-get-length\r\n"
31709  "\tReturns the length of the specified string. Takes 1 argument." },
31710 
31711  // Goober5000
31712  { OP_INT_TO_STRING, "int-to-string\r\n"
31713  "\tConverts an integer into a string. The destination must be a string variable.\r\n"
31714  "Takes 2 argument...\r\n"
31715  "\t1:\tInteger to convert\r\n"
31716  "\t2:\tString variable to contain the result\r\n" },
31717 
31718  // Goober5000
31719  { OP_STRING_CONCATENATE, "string-concatenate\r\n"
31720  "\tConcatenates two strings, putting the result into a string variable. If the length of the string will "
31721  "exceed the sexp variable token limit (currently 32), it will be truncated.\r\n\r\n"
31722  "Takes 3 arguments...\r\n"
31723  "\t1: First string\r\n"
31724  "\t2: Second string\r\n"
31725  "\t3: String variable to hold the result\r\n" },
31726 
31727  // Goober5000
31728  { OP_STRING_GET_SUBSTRING, "string-get-substring\r\n"
31729  "\tExtracts a substring from a parent string, putting the result into a string variable. If the length of the string will "
31730  "exceed the sexp variable token limit (currently 32), it will be truncated.\r\n\r\n"
31731  "Takes 3 arguments...\r\n"
31732  "\t1: Parent string\r\n"
31733  "\t2: Index at which the substring begins (0-based)\r\n"
31734  "\t3: Length of the substring\r\n"
31735  "\t4: String variable to hold the result\r\n" },
31736 
31737  // Goober5000
31738  { OP_STRING_SET_SUBSTRING, "string-set-substring\r\n"
31739  "\tReplaces a substring from a parent string with a new string, putting the result into a string variable. If the length of the string will "
31740  "exceed the sexp variable token limit (currently 32), it will be truncated.\r\n\r\n"
31741  "Takes 3 arguments...\r\n"
31742  "\t1: Parent string\r\n"
31743  "\t2: Index at which the substring begins (0-based)\r\n"
31744  "\t3: Length of the substring\r\n"
31745  "\t4: New substring (which can be a different length than the old substring)\r\n"
31746  "\t5: String variable to hold the result\r\n" },
31747 
31748  // Karajorma
31749  { OP_DEBUG, "debug\r\n"
31750  "\tPops up a warning on debug builds (and optionally on release builds)\r\n"
31751  "Takes 1 or more arguments...\r\n"
31752  "\t1:\t If false, popup messages in release builds too. Defaults to true.\r\n"
31753  "\t2:\tName of a message which will appear in the warning (optional)\r\n"},
31754 
31755  { OP_GRANT_PROMOTION, "Grant promotion (Action operator)\r\n"
31756  "\tIn a single player game, this function grants a player an automatic promotion to the "
31757  "next rank which the player can obtain. If he is already at the highest rank, this "
31758  "operator has no effect. It takes no arguments." },
31759 
31760  { OP_GRANT_MEDAL, "Grant medal (Action operator)\r\n"
31761  "\tIn single player missions, this function grants the given medal to the player. "
31762  "Currently, only 1 medal will be allowed to be given per mission.\r\n\r\n"
31763  "Takes 1 argument...\r\n"
31764  "\t1:\tName of medal to grant to player." },
31765 
31766  { OP_GOOD_SECONDARY_TIME, "Set preferred secondary weapons\r\n"
31767  "\tThis sexpression is used to inform the AI about preferred secondary weapons to "
31768  "fire during combat. When this expression is evaluated, any AI ships of the given "
31769  "team prefer to fire the given weapon at the given ship. (Preferred over other "
31770  "secondary weapons)\r\n\r\n"
31771  "Takes 4 argument...\r\n"
31772  "\t1:\tTeam name which will prefer firing given weapon\r\n"
31773  "\t2:\tMaximum number of this type of weapon above team can fire.\r\n"
31774  "\t3:\tWeapon name (list includes only the valid weapons for this expression\r\n"
31775  "\t4:\tShip name at which the above named team should fire the above named weapon." },
31776 
31777  { OP_AND_IN_SEQUENCE, "And in sequence (Boolean operator)\r\n"
31778  "\tReturns true if all of its arguments have become true in the order they are "
31779  "listed in.\r\n\r\n"
31780  "Returns a boolean value. Takes 2 or more boolean arguments." },
31781 
31782  { OP_SKILL_LEVEL_AT_LEAST, "Skill level at least (Boolean operator)\r\n"
31783  "\tReturns true if the player has selected the given skill level or higher.\r\n\r\n"
31784  "Returns a boolean value. Takes 1 argument...\r\n"
31785  "\t1:\tName of the skill level to check." },
31786 
31787  { OP_NUM_PLAYERS, "Num players (Status operator)\r\n"
31788  "\tReturns the current number of players (multiplayer) playing in the current mission.\r\n\r\n"
31789  "Returns a numeric value. Takes no arguments." },
31790 
31791  { OP_IS_CARGO_KNOWN, "Is cargo known (Boolean operator)\r\n"
31792  "\tReturns true if all of the specified objects' cargo is known by the player (i.e. they "
31793  "have scanned each one.\r\n\r\n"
31794  "Returns a boolean value. Takes 1 or more arguments...\r\n"
31795  "\tAll:\tName of ship to check if its cargo is known." },
31796 
31797  { OP_HAS_BEEN_TAGGED_DELAY, "Has ship been tagged (delay) (Boolean operator)\r\n"
31798  "\tReturns true if all of the specified ships have been tagged.\r\n\r\n"
31799  "Returns a boolean value after <delay> seconds when all ships have been tagged. Takes 2 or more arguments...\r\n"
31800  "\t1:\tDelay in seconds after which sexpression will return true when all cargo scanned."
31801  "\tRest:\tNames of ships to check if tagged.." },
31802 
31803  { OP_ARE_SHIP_FLAGS_SET, "Are ship flags set (Boolean operator)\r\n"
31804  "\tReturns true if all of the specified flags have been set for this particular ship.\r\n\r\n"
31805  "Takes 2 or more arguments...\r\n"
31806  "\t1:\tName of the ship."
31807  "\tRest:\tShip, object or ai flags which might be set for this ship.." },
31808 
31809  { OP_CAP_SUBSYS_CARGO_KNOWN_DELAY, "Is capital ship subsystem cargo known (delay) (Boolean operator)\r\n"
31810  "\tReturns true if all of the specified subsystem cargo is known by the player.\r\n"
31811  "\tNote: Cargo must be explicitly named.\r\n\r\n"
31812  "Returns a boolean value after <delay> seconds when all cargo is known. Takes 3 or more arguments...\r\n"
31813  "\t1:\tDelay in seconds after which sexpression will return true when all cargo scanned.\r\n"
31814  "\t2:\tName of capital ship\r\n"
31815  "\tRest:\tNames of subsystems to check for cargo known.." },
31816 
31817  { OP_CARGO_KNOWN_DELAY, "Is cargo known (delay) (Boolean operator)\r\n"
31818  "\tReturns true if all of the specified objects' cargo is known by the player (i.e. they "
31819  "have scanned each one.\r\n\r\n"
31820  "Returns a boolean value after <delay> seconds when all cargo is known. Takes 2 or more arguments...\r\n"
31821  "\t1:\tDelay in seconds after which sexpression will return true when all cargo scanned."
31822  "\tRest:\tNames of ships/cargo to check for cargo known.." },
31823 
31824  { OP_WAS_PROMOTION_GRANTED, "Was promotion granted (Boolean operator)\r\n"
31825  "\tReturns true if a promotion was granted via the 'Grant promotion' operator in the mission.\r\n\r\n"
31826  "Returns a boolean value. Takes no arguments." },
31827 
31828  { OP_WAS_MEDAL_GRANTED, "Was medal granted (Boolean operator)\r\n"
31829  "\tReturns true if a medal was granted via via the 'Grant medal' operator in the mission. "
31830  "If you provide the optional argument to this operator, then true is only returned if the "
31831  "specified medal was granted.\r\n\r\n"
31832  "Returns a boolean value. Takes 0 or 1 arguments...\r\n"
31833  "\t1:\tName of medal to specifically check for (optional)." },
31834 
31835  { OP_GOOD_REARM_TIME, "Good rearm time (Action operator)\r\n"
31836  "\tInforms the game logic that right now is a good time for a given team to attempt to "
31837  "rearm their ships. The time parameter specified how long the \"good time\" will last.\r\n\r\n"
31838  "Takes 2 arguments...\r\n"
31839  "\t1:\tTeam Name\r\n"
31840  "\t2:\tTime in seconds rearm window should last" },
31841 
31842  { OP_ALLOW_SHIP, "Allow ship (Action operator)\r\n"
31843  "\tThis operator makes the given ship type available to the Terran team. Players will be "
31844  "able to have ships of this type in their starting wings in all future missions of this "
31845  "campaign.\r\n\r\n"
31846  "Takes 1 argument...\r\n"
31847  "\t1:\tName of ship type (or ship class) to allow." },
31848 
31849  { OP_ALLOW_WEAPON, "Allow weapon (Action operator)\r\n"
31850  "\tThis operator makes the given weapon available to the Terran team. Players will be "
31851  "able to equip ships with in all future missions of this campaign.\r\n\r\n"
31852  "Takes 1 argument...\r\n"
31853  "\t1:\tName of weapon (primary or secondary) to allow." },
31854 
31855  { OP_TECH_ADD_SHIP, "Tech add ship (Action operator)\r\n"
31856  "\tThis operator makes the given ship type available in the techroom database. Players will "
31857  "then be able to view this ship's specs there.\r\n\r\n"
31858  "Takes 1 or more arguments...\r\n"
31859  "\tAll:\tName of ship type (or ship class) to add." },
31860 
31861  { OP_TECH_ADD_WEAPON, "Tech add weapon (Action operator)\r\n"
31862  "\tThis operator makes the given weapon available in the techroom database. Players will "
31863  "then be able to view this weapon's specs there.\r\n\r\n"
31864  "Takes 1 or more arguments...\r\n"
31865  "\tAll:\tName of weapon (primary or secondary) to add." },
31866 
31867  { OP_TECH_ADD_INTEL, "Tech add intel (Action operator, deprecated in favor of tech-add-intel-xstr)\r\n"
31868  "\tThis operator makes the given intel entry available in the techroom database. Players will "
31869  "then be able to view this intel entry there.\r\n\r\n"
31870  "Takes 1 or more arguments...\r\n"
31871  "\tAll:\tName of intel entry to add." },
31872 
31873  { OP_TECH_ADD_INTEL_XSTR, "Tech add intel XSTR (Action operator)\r\n"
31874  "\tThis operator makes the given intel entry available in the techroom database. Players will "
31875  "then be able to view this intel entry there.\r\n\r\n"
31876  "Takes 2 or more arguments...\r\n"
31877  "\t1:\tName of intel entry to add.\r\n"
31878  "\t2:\tXSTR ID of intel entry, or -1 if there is no XSTR entry.\r\n"
31879  "Use Add-Data for multiple entries.\r\n\r\n"
31880  "IMPORTANT: Each additional entry in the list MUST HAVE two fields; "
31881  "any entry without both fields will be ignored, as will any successive entries." },
31882 
31883  { OP_TECH_RESET_TO_DEFAULT, "Tech reset to default (Action operator)\r\n"
31884  "\tThis operator resets the tech room to the default represented in the tables. This is "
31885  "useful for starting new campaigns, so that the player will not see tech entries carried over "
31886  "from previous campaigns.\r\n\r\n"
31887  "Takes no arguments." },
31888 
31889  { OP_CHANGE_PLAYER_SCORE, "Change Player Score (Action operator)\r\n"
31890  "\tThis operator allows direct alteration of the player's score for this mission.\r\n\r\n"
31891  "Takes 2 or more arguments."
31892  "\t1:\tAmount to alter the player's score by.\r\n"
31893  "\tRest:\tName of ship the player is flying."},
31894 
31895  { OP_CHANGE_TEAM_SCORE, "Change Team Score (Action operator)\r\n"
31896  "\tThis operator allows direct alteration of the team's score for a TvT mission (Does nothing otherwise).\r\n\r\n"
31897  "Takes 2 arguments."
31898  "\t1:\tAmount to alter the team's score by.\r\n"
31899  "\t2:\tThe team to alter the score for. (0 will add the score to all teams!)"},
31900 
31901  { OP_AI_EVADE_SHIP, "Ai-evade ship (Ship goal)\r\n"
31902  "\tCauses the specified ship to go into evade mode and run away like the weak "
31903  "sally-boy it is.\r\n\r\n"
31904  "Takes 2 arguments...\r\n"
31905  "\t1:\tName of ship to evade from.\r\n"
31906  "\t2:\tGoal priority (number between 0 and 89)." },
31907 
31908  { OP_AI_STAY_NEAR_SHIP, "Ai-stay near ship (Ship goal)\r\n"
31909  "\tCauses the specified ship to keep itself near the given ship and not stray too far "
31910  "away from it.\r\n\r\n"
31911  "Takes 2 arguments...\r\n"
31912  "\t1:\tName of ship to stay near.\r\n"
31913  "\t2:\tGoal priority (number between 0 and 89)." },
31914 
31915  { OP_AI_KEEP_SAFE_DISTANCE, "Ai-keep safe distance (Ship goal)\r\n"
31916  "\tTells the specified ship to stay a safe distance away from any ship that isn't on the "
31917  "same team as it.\r\n\r\n"
31918  "Takes 1 argument...\r\n"
31919  "\t1:\tGoal priority (number between 0 and 89)." },
31920 
31921  { OP_AI_IGNORE, "Ai-ignore (Ship goal)\r\n"
31922  "\tTells all ships to ignore the given ship and not consider it as a valid "
31923  "target to attack.\r\n\r\n"
31924  "Takes 2 arguments...\r\n"
31925  "\t1:\tName of ship to ignore.\r\n"
31926  "\t2:\tGoal priority (number between 0 and 89)." },
31927 
31928  // Goober5000
31929  { OP_AI_IGNORE_NEW, "Ai-ignore-new (Ship goal)\r\n"
31930  "\tTells the specified ship to ignore the given ship and not consider it as a valid "
31931  "target to attack.\r\n\r\n"
31932  "Takes 2 arguments...\r\n"
31933  "\t1:\tName of ship to ignore.\r\n"
31934  "\t2:\tGoal priority (number between 0 and 89)." },
31935 
31936  { OP_AI_STAY_STILL, "Ai-stay still (Ship goal)\r\n"
31937  "\tCauses the specified ship to stay still. The ship will do nothing until attacked at "
31938  "which time the ship will come to life and defend itself.\r\n\r\n"
31939  "Takes 2 arguments...\r\n"
31940  "\t1:\tShip or waypoint the ship staying still will directly face (currently not implemented)\r\n"
31941  "\t2:\tGoal priority (number between 0 and 89)." },
31942 
31943  { OP_AI_PLAY_DEAD, "Ai-play dead (Ship goal)\r\n"
31944  "\tCauses the specified ship to pretend that it is dead and not do anything. This "
31945  "expression should be used to indicate that a ship has no pilot and cannot respond "
31946  "to any enemy threats. A ship playing dead will not respond to any attack. This "
31947  "should really be named ai-is-dead\r\n\r\n"
31948  "Takes 1 argument...\r\n"
31949  "\t1:\tGoal priority (number between 0 and 89)." },
31950 
31951  { OP_AI_FORM_ON_WING, "Ai-form-on-wing (Ship Goal)\r\n"
31952  "\tCauses the ship to form on the specified ship's wing. This works analogous to the "
31953  "player order, and will cause all other goals specified for the ship to be purged.\r\n\r\n"
31954  "Takes 1 argument...\r\n"
31955  "\t1:\tShip to form on." },
31956 
31957  { OP_FLASH_HUD_GAUGE, "Ai-flash hud gauge (Training goal)\r\n"
31958  "\tCauses the specified hud gauge to flash to draw the player's attention to it.\r\n\r\n"
31959  "Takes 1 argument...\r\n"
31960  "\t1:\tName of hud gauge to flash." },
31961 
31962  { OP_ALTER_SHIP_FLAG, "alter-ship-flag\r\n"
31963  "\tSets a ships flag and/or parse flag.\r\n\r\n"
31964  "Takes 4 or more arguments...\r\n"
31965  "\t1:\tShip flag name\r\n"
31966  "\t2:\tTrue if turning on, false if turning off\r\n"
31967  "\t3:\tTrue\\False - Apply this flag to future waves of this wing. Apply to ship if not present\r\n"
31968  "\tRest:\t (optional) Name of ships, wings, or entire teams. If not supplied, will work on all ships in the mission\r\n\r\n"
31969  "Ship Flags:\r\n"
31970  "invulnerable - Stops ship from taking any damage\r\n"
31971  "protect-ship - Ship and Turret AI will ignore and not attack ship\r\n"
31972  "beam-protect-ship - Turrets with beam weapons will ignore and not attack ship\r\n"
31973  "no-shields - Ship will have no shields (ETS will be rebalanced if shields were off and are enabled)\r\n"
31974  "targetable-as-bomb - Allows ship to be targetted with the bomb targetting key\r\n"
31975  "flak-protect-ship - Turrets with flak weapons will ignore and not attack ship\r\n"
31976  "laser-protect-ship - Turrets with laser weapons will ignore and not attack ship\r\n"
31977  "missile-protect-ship - Turrets with missile weapons will ignore and not attack ship\r\n"
31978  "immobile - Will not let a ship move or rotate in any fashion\r\n"
31979  "vaporize - Causes a ship to vanish (no deathroll, no debris, no explosion) when destroyed\r\n"
31980  "break-warp - Causes a ship's subspace drive to break. Can be repaired by a support ship\r\n"
31981  "never-warp - Causes a ship's subspace drive to never work. Cannot be repaired by a support ship\r\n"
31982  "afterburner-locked - Will stop a ship from firing their afterburner\r\n"
31983  "primaries-locked - Will stop a ship from firing their primary weapons\r\n"
31984  "secondaries-locked - Will stop a ship from firing their secondary weapons\r\n"
31985  "no-subspace-drive - Will not allow a ship to jump into subspace\r\n"
31986  "don't-collide-invisible - Will cause polygons with an invisible texture to stop colliding with objects\r\n"
31987  "no-ets - Will not allow a ship to alter its ETS system\r\n"
31988  "toggle-subsystem-scanning - Switches between being able to scan a whole ship or individual subsystems\r\n"
31989  "scannable - Whether or not the ship can be scanned\r\n"
31990  "cargo-known - If set, the ships cargo can be seen without scanning the ship\r\n"
31991  "stealth - If set, the ship can't be targeted, is invisible on radar, and is ignored by AI unless firing\r\n"
31992  "friendly-stealth-invisible - If set, the ship can't be targeted even by ships on the same team\r\n"
31993  "hide-ship-name - If set, the ship name can't be seen when the ship is targeted\r\n"
31994  "hidden-from-sensors - If set, the ship can't be targeted and appears on radar as a blinking dot\r\n"
31995  "no-dynamic - Will stop allowing the AI to persue dynamic goals (eg: chasing ships it was not ordered to)\r\n"
31996  "no-secondary-lock-on - Will disable target acquisition for secondaries of all types (does not affect turrets)\r\n"},
31997 
31998  { OP_SHIP_VISIBLE, "ship-visible\r\n"
31999  "\tCauses the ships listed in this sexpression to be visible with player sensors.\r\n\r\n"
32000  "Takes 1 or more arguments...\r\n"
32001  "\t1+:\tName of ships to make visible to sensors." },
32002 
32003  { OP_SHIP_INVISIBLE, "ship-invisible\r\n"
32004  "\tCauses the ships listed in this sexpression to be invisible to player sensors.\r\n\r\n"
32005  "Takes 1 or more arguments...\r\n"
32006  "\t1+:\tName of ships to make invisible to sensors." },
32007 
32008  { OP_SHIP_VULNERABLE, "ship-vulnerable\r\n"
32009  "\tCauses the ship listed in this sexpression to be vulnerable to weapons.\r\n\r\n"
32010  "Takes 1 or more arguments...\r\n"
32011  "\t1+:\tName of ships to make vulnerable to weapons." },
32012 
32013  { OP_SHIP_INVULNERABLE, "ship-invulnerable\r\n"
32014  "\tCauses the ships listed in this sexpression to be invulnerable to weapons. Use with caution!!!!\r\n\r\n"
32015  "Takes 1 or more arguments...\r\n"
32016  "\t1+:\tName of ships to make invulnerable to weapons." },
32017 
32018  { OP_SHIP_BOMB_TARGETABLE, "ship-targetable-as-bomb\r\n"
32019  "\tCauses the ships listed in this sexpression to be targetable with bomb targeting key.\r\n\r\n"
32020  "Takes 1 or more arguments...\r\n"
32021  "\t1+:\tName of ships to make targetable with bomb targeting key." },
32022 
32023  { OP_SHIP_BOMB_UNTARGETABLE, "ship-untargetable-as-bomb\r\n"
32024  "\tCauses the ships listed in this sexpression to not be targetable with bomb targeting key.\r\n\r\n"
32025  "Takes 1 or more arguments...\r\n"
32026  "\t1+:\tName of ships to make nontargetable with bomb targeting key." },
32027 
32028  { OP_SHIELDS_ON, "shields-on\r\n" //-Sesquipedalian
32029  "\tCauses the ship listed in this sexpression to have their shields activated.\r\n"
32030  "If the ship had no-shields prior to the sexp being called, the ETS will be rebalanced to default.\r\n"
32031  "Takes 1 or more arguments...\r\n"
32032  "\t1+:\tName of ships to activate shields on." },
32033 
32034  { OP_SHIELDS_OFF, "shields-off\r\n" //-Sesquipedalian
32035  "\tCauses the ships listed in this sexpression to have their shields deactivated. \r\n\r\n"
32036  "Takes 1 or more arguments...\r\n"
32037  "\t1+:\tName of ships to deactivate shields on." },
32038 
32039  { OP_SHIP_GUARDIAN, "ship-guardian\r\n"
32040  "\tCauses the ships listed in this sexpression to not be killable by weapons. Use with caution!!!!\r\n\r\n"
32041  "Takes 1 or more arguments...\r\n"
32042  "\t1+:\tName of ships to make unkillable." },
32043 
32044  { OP_SHIP_NO_GUARDIAN, "ship-no-guardian\r\n"
32045  "\tCauses the ships listed in this sexpression to be killable by weapons, if not invulnerable.\r\n\r\n"
32046  "Takes 1 or more arguments...\r\n"
32047  "\t1+:\tName of ships to make killable." },
32048 
32049  // Goober5000
32050  { OP_SHIP_GUARDIAN_THRESHOLD, "ship-guardian-threshold\r\n"
32051  "\tSame as ship-guardian, except the lowest possible hull value is specified by the sexp rather than defaulting to 1.\r\n"
32052  "Call with a threshold of 0 (or use ship-no-guardian) to deactivate.\r\n\r\n"
32053  "Takes 2 or more arguments...\r\n"
32054  "\t1:\tThreshold value.\r\n"
32055  "\t2+:\tName of ships to make unkillable." },
32056 
32057  // Goober5000
32058  { OP_SHIP_SUBSYS_GUARDIAN_THRESHOLD, "ship-subsys-guardian-threshold\r\n"
32059  "\tSame as ship-guardian-threshold, but works on subsystems.\r\n"
32060  "Call with a threshold of 0 to deactivate.\r\n\r\n"
32061  "Takes 3 or more arguments...\r\n"
32062  "\t1:\tThreshold value.\r\n"
32063  "\t2:\tShip housing the subsystem(s).\r\n"
32064  "\t3+:\tSubsystems to make unkillable." },
32065 
32066  // Goober5000
32067  { OP_SHIP_STEALTHY, "ship-stealthy\r\n"
32068  "\tCauses the ships listed in this sexpression to become stealth ships (i.e. invisible to radar).\r\n\r\n"
32069  "Takes 1 or more arguments...\r\n"
32070  "\tAll:\tName of ships to make stealthy." },
32071 
32072  // Goober5000
32073  { OP_SHIP_UNSTEALTHY, "ship-unstealthy\r\n"
32074  "\tCauses the ships listed in this sexpression to become non-stealth ships (i.e. visible to radar).\r\n\r\n"
32075  "Takes 1 or more arguments...\r\n"
32076  "\tAll:\tName of ships to make non-stealthy." },
32077 
32078  // Goober5000
32079  { OP_FRIENDLY_STEALTH_INVISIBLE, "friendly-stealth-invisible\r\n"
32080  "\tCauses the friendly ships listed in this sexpression to be invisible to radar, just like hostile stealth ships."
32081  "It doesn't matter if the ship is friendly at the time this sexp executes: as long as it is a stealth ship, it will"
32082  "be invisible to radar both as hostile and as friendly.\r\n\r\n"
32083  "Takes 1 or more arguments...\r\n"
32084  "\tAll:\tName of ships" },
32085 
32086  // Goober5000
32087  { OP_FRIENDLY_STEALTH_VISIBLE, "friendly-stealth-visible\r\n"
32088  "\tCauses the friendly ships listed in this sexpression to resume their normal behavior of being visible to radar as"
32089  "stealth friendlies. Does not affect their visibility as stealth hostiles.\r\n\r\n"
32090  "Takes 1 or more arguments...\r\n"
32091  "\tAll:\tName of ships" },
32092 
32093  // Goober5000
32094  { OP_SHIP_SUBSYS_TARGETABLE, "ship-subsys-targetable\r\n"
32095  "\tCauses the specified ship subsystem(s) to be targetable on radar.\r\n"
32096  "Takes 2 or more arguments...\r\n"
32097  "\t1:\tName of a ship\r\n"
32098  "\tRest: Name of the ship's subsystem(s)" },
32099 
32100  // Goober5000
32101  { OP_SHIP_SUBSYS_UNTARGETABLE, "ship-subsys-untargetable\r\n"
32102  "\tCauses the specified ship subsystem(s) to not be targetable on radar.\r\n"
32103  "Takes 2 or more arguments...\r\n"
32104  "\t1:\tName of a ship\r\n"
32105  "\tRest: Name of the ship's subsystem(s)" },
32106 
32107  // FUBAR
32108  { OP_SHIP_SUBSYS_NO_REPLACE, "ship-subsys-no-replace\r\n"
32109  "\tCauses the -destroyed version of specified ship subsystem(s) to not render when it's destroyed.\r\n"
32110  "Takes 3 or more arguments...\r\n"
32111  "\t1:\tName of a ship\r\n"
32112  "\t2:\tTrue = Do not render or False = render if exists\r\n"
32113  "\tRest: Name of the ship's subsystem(s)"
32114  "\tNote: If subsystem is already dead it will vanish or reappear out of thin air" },
32115 
32116 
32117  // FUBAR
32118  { OP_SHIP_SUBSYS_NO_LIVE_DEBRIS, "ship-subsys-no-live-debris\r\n"
32119  "\tCauses the specified ship subsystem(s) to not render live debris when it's destroyed.\r\n"
32120  "Takes 3 or more arguments...\r\n"
32121  "\t1:\tName of a ship\r\n"
32122  "\t2:\tTrue = Do not render or False = render if exists\r\n"
32123  "\tRest: Name of the ship's subsystem(s)" },
32124 
32125  // FUBAR
32126  { OP_SHIP_SUBSYS_VANISHED, "ship-subsys-vanish\r\n"
32127  "\tCauses the subsystem to vanish without a trace - no fanfare, notification, or special effects. See also ship-vanish.\r\n"
32128  "\tSingle Player Only! Warning: This will cause subsystem destruction not to be logged, so 'has-departed', etc. will not work\r\n"
32129  "Takes 3 or more arguments...\r\n"
32130  "\t1:\tName of a ship\r\n"
32131  "\t2:\tTrue = vanish or False = don't vanish\r\n"
32132  "\tRest: Name of the ship's subsystem(s)"
32133  "\tNote: Useful for replacing subsystems with actual docked models." },
32134 
32135  // FUBAR
32136  { OP_SHIP_SUBSYS_IGNORE_IF_DEAD, "ship-subsys-ignore-if-dead\r\n"
32137  "\tCauses secondary weapons to ignore dead ship subsystem(s)and home on hull instead.\r\n"
32138  "Takes 3 or more arguments...\r\n"
32139  "\t1:\tName of a ship\r\n"
32140  "\t2:\tTrue = Ignore dead or False = don't ignore\r\n"
32141  "\tRest: Name of the ship's subsystem(s)" },
32142 
32143  // Goober5000
32144  { OP_SHIP_CHANGE_ALT_NAME, "ship-change-alt-name\r\n"
32145  "\tChanges the alternate ship class name displayed in the HUD target window. Takes 2 or more arguments...\r\n"
32146  "\t1:\tThe ship class name to display\r\n"
32147  "\tRest:\tThe ships to display the new class name" },
32148 
32149  // FUBAR
32150  { OP_SHIP_CHANGE_CALLSIGN, "ship-change-callsign\r\n"
32151  "\tChanges the callsign of a ship. Takes 2 or more arguments...\r\n"
32152  "\t1:\tThe callsign to display or empty to remove\r\n"
32153  "\tRest:\tThe ships to display the new callsign" },
32154 
32155  // Goober5000
32156  { OP_SET_DEATH_MESSAGE, "set-death-message\r\n"
32157  "\tSets the message displayed when the specified players are killed. Takes 1 or more arguments...\r\n"
32158  "\t1:\tThe message\r\n"
32159  "\tRest:\tThe players for whom this message is displayed (optional) (currently not implemented)" },
32160 
32161  { OP_PERCENT_SHIPS_ARRIVED, "percent-ships-arrived\r\n"
32162  "\tBoolean function which returns true if the percentage of ships in the listed ships and wings "
32163  "which have arrived is greater or equal to the given percentage. For wings, all ships of all waves "
32164  "are used for calculation for the total possible ships to arrive.\r\n\r\n"
32165  "Takes 2 or more arguments...\r\n"
32166  "\t1:\tPercentge of arriving ships at which this function will return true.\r\n"
32167  "\t2+:\tList of ships/wings whose arrival status should be determined." },
32168 
32169  { OP_PERCENT_SHIPS_DEPARTED, "percent-ships-departed\r\n"
32170  "\tBoolean function which returns true if the percentage of ships in the listed ships and wings "
32171  "which have departed is greater or equal to the given percentage. For wings, all ships of all waves "
32172  "are used for calculation for the total possible ships to depart.\r\n\r\n"
32173  "Takes 2 or more arguments...\r\n"
32174  "\t1:\tPercentge of departed ships at which this function will return true.\r\n"
32175  "\t2+:\tList of ships/wings whose departure status should be determined." },
32176 
32177  { OP_PERCENT_SHIPS_DESTROYED, "percent-ships-destroyed\r\n"
32178  "\tBoolean function which returns true if the percentage of ships in the listed ships and wings "
32179  "which have been destroyed is greater or equal to the given percentage. For wings, all ships of all waves "
32180  "are used for calculation for the total possible ships to be destroyed.\r\n\r\n"
32181  "Takes 2 or more arguments...\r\n"
32182  "\t1:\tPercentge of destroyed ships at which this function will return true.\r\n"
32183  "\t2+:\tList of ships/wings whose destroyed status should be determined." },
32184 
32185  // Goober5000
32186  { OP_PERCENT_SHIPS_DISARMED, "percent-ships-disarmed\r\n"
32187  "\tBoolean function which returns true if the percentage of ships in the listed ships "
32188  "which have been disarmed is greater or equal to the given percentage.\r\n\r\n"
32189  "Takes 2 or more arguments...\r\n"
32190  "\t1:\tPercentge of disarmed ships at which this function will return true.\r\n"
32191  "\t2+:\tList of ships whose disarmed status should be determined." },
32192 
32193  // Goober5000
32194  { OP_PERCENT_SHIPS_DISABLED, "percent-ships-disabled\r\n"
32195  "\tBoolean function which returns true if the percentage of ships in the listed ships "
32196  "which have been disabled is greater or equal to the given percentage.\r\n\r\n"
32197  "Takes 2 or more arguments...\r\n"
32198  "\t1:\tPercentge of disabled ships at which this function will return true.\r\n"
32199  "\t2+:\tList of ships whose disabled status should be determined." },
32200 
32201  { OP_RED_ALERT, "red-alert\r\n"
32202  "\tCauses Red Alert status in a mission. This function ends the current mission, and moves to "
32203  "the next mission in the campaign under red alert status. There should only be one branch from "
32204  "a mission that uses this expression\r\n\r\n"
32205  "Takes no arguments."},
32206 
32207  { OP_MISSION_SET_NEBULA, "mission-set-nebula\r\n"
32208  "\tTurns nebula on/off\r\n"
32209  "\tTakes1 argument...\r\n"
32210  "\t1:\t0 for nebula off, 1 for nebula on" },
32211 
32212  { OP_MISSION_SET_SUBSPACE, "mission-set-subspace\r\n"
32213  "\tTurns subspace on/off\r\n"
32214  "\tTakes 1 argument...\r\n"
32215  "\r1:\t0 for subspace off, 1 for subspace on" },
32216 
32217  //-Sesquipedalian
32218  { OP_END_MISSION, "end-mission\r\n"
32219  "\tEnds the mission as if the player had engaged his subspace drive, but without him doing so. Dumps the player back into a normal debriefing. Does not invoke red-alert status.\r\n"
32220  "\t1:\tEnd Mission even if the player is dead (optional; defaults to true)\r\n"
32221  "\t2:\tBoot the player out into the main hall instead of going to the debriefing (optional; defaults to false; not supported in multi)\r\n"
32222  "\t3:\tGo to the mainhall instead of starting the next mission (optional; defaults to false; not yet tested in multi)"
32223  },
32224 
32225  // Goober5000
32226  { OP_SET_DEBRIEFING_TOGGLED, "set-debriefing-toggled\r\n"
32227  "\tSets or clears the \"toggle debriefing\" mission flag. If set, the mission will have its debriefing turned off, unless it is a multiplayer dogfight mission, in which case its debriefing will be turned on. Takes 1 argument.\r\n"
32228  },
32229 
32230  // Goober5000
32231  { OP_FORCE_JUMP, "force-jump\r\n"
32232  "\tForces activation of the player's subspace drive, thus ending the mission. Takes no arguments."
32233  },
32234 
32235  // Goober5000
32236  { OP_SET_SCANNED, "set-scanned\r\n"
32237  "\tSets the cargo on the specified ship or ship subsystem as known or scanned. Takes 1 or more arguments...\r\n"
32238  "\t1:\tName of a ship\r\n"
32239  "\tRest:\tName of a subsystem on that ship (optional)\r\n" },
32240 
32241  // Goober5000
32242  { OP_SET_UNSCANNED, "set-unscanned\r\n"
32243  "\tSets the cargo on the specified ship or ship subsystem as unknown or unscanned. Takes 1 or more arguments...\r\n"
32244  "\t1:\tName of a ship\r\n"
32245  "\tRest:\tName of a subsystem on that ship (optional)\r\n" },
32246 
32247  { OP_DEPART_NODE_DELAY, "depart-node-delay\r\n"
32248  "\tReturns true N seconds after the listed ships depart, if those ships depart within the "
32249  "radius of the given jump node. The delay value is given in seconds.\r\n\r\n"
32250  "Takes 3 or more arguments...r\n"
32251  "\t1:\tDelay in seconds after the last ship listed departed before this expression can return true.\r\n"
32252  "\t2:\tName of a jump node\r\n"
32253  "\t3+:\tList of ships to check for departure within radius of the jump node." },
32254 
32255  { OP_DESTROYED_DEPARTED_DELAY, "destroyed-or-departed-delay\r\n"
32256  "\tReturns true N seconds after all the listed ships or wings have been destroyed or have "
32257  "departed.\r\n\r\n"
32258  "Takes 2 or more arguments...\r\n"
32259  "\t1:\tDelay in seconds after the last ship/wing is destroyed or departed before this expression can return true.\r\n"
32260  "\t2+:\tName of a ship or wing" },
32261 
32262  // description added by Goober5000
32263  { OP_SPECIAL_CHECK, "Special-check\r\n"
32264  "\tMike K.'s special training sexp. Returns a boolean value. Takes 1 argument as follows:\r\n"
32265  "\t0: Ship \"Freighter 1\" is aspect locked by the player\r\n"
32266  "\t1: Player has fired Interceptor#Weak at Freighter 1\r\n"
32267  "\t2: Ship \"Freighter 1\", subsystem \"Weapons\" is aspect locked by the player\r\n"
32268  "\t3: Apply 10 points of damage to player's forward shields (action operator)\r\n"
32269  "\t4: Player's front shields are nearly gone\r\n"
32270  "\t5: Quickly recharge player's front shields (action operator)\r\n"
32271  "\t6: Reduce all shield quadrants except front to 0 (action operator)\r\n"
32272  "\t7: Front shield quadrant is near maximum strength\r\n"
32273  "\t8: Rear shield quadrant is near maximum strength\r\n"
32274  "\t9: Reduce left and right shield quadrants to 0 (action operator)\r\n"
32275  "\t10: Player has fewer than 8 missiles left\r\n"
32276  "\t11: Player has 8 or more missiles left\r\n"
32277  "\t12: Player has fewer than 4 missiles left\r\n"
32278  "\t13: Reduce front shield quadrant to 0 (action operator)\r\n"
32279  "\t100: Player is out of countermeasures\r\n"
32280  "\t2000: Training failed"
32281  },
32282 
32283  { OP_END_CAMPAIGN, "end-campaign\r\n"
32284  "\tEnds the builtin campaign. Should only be used by the main FreeSpace campaign\r\n"
32285  "\t1:\tEnd Campaign even if the player is dead (optional; defaults to true)\r\n" },
32286 
32287  { OP_SHIP_VAPORIZE, "ship-vaporize\r\n"
32288  "\tSets the ship to vaporize when it is destroyed. Does not actually destroy the ship - use self-destruct for that.\r\n"
32289  "Takes 1 or more arguments...\r\n"
32290  "\tAll:\tList of ships on which to set the vaporize flag" },
32291 
32292  { OP_SHIP_NO_VAPORIZE, "ship-no-vaporize\r\n"
32293  "\tSets the ship to not vaporize when it is destroyed. Does not actually destroy the ship - use self-destruct for that.\r\n"
32294  "Takes 1 or more arguments...\r\n"
32295  "\tAll:\tList of ships on which to unset the vaporize flag" },
32296 
32297  { OP_DONT_COLLIDE_INVISIBLE, "don't-collide-invisible\r\n"
32298  "\tSets the \"don't collide invisible\" flag on a list of ships.\r\n"
32299  "Takes 1 or more arguments...\r\n"
32300  "\tAll:\tList of ships on which to set the \"don't collide invisible\" flag" },
32301 
32302  { OP_COLLIDE_INVISIBLE, "collide-invisible\r\n"
32303  "\tUnsets the \"don't collide invisible\" flag on a list of ships.\r\n"
32304  "Takes 1 or more arguments...\r\n"
32305  "\tAll:\tList of ships on which to unset the \"don't collide invisible\" flag" },
32306 
32307  { OP_SET_MOBILE, "set-mobile\r\n"
32308  "\tAllows the specified ship(s) to move. Opposite of set-immobile.\r\n"
32309  "Takes 1 or more arguments...\r\n"
32310  "\tAll:\tList of ships on which to unset the \"immobile\" flag" },
32311 
32312  { OP_SET_IMMOBILE, "set-immobile\r\n"
32313  "\tPrevents the specified ship(s) from moving in any way.\r\n"
32314  "Takes 1 or more arguments...\r\n"
32315  "\tAll:\tList of ships on which to set the \"immobile\" flag" },
32316 
32317  { OP_IGNORE_KEY, "ignore-key\r\n"
32318  "\tCauses the game to ignore (or stop ignoring) a certain key.\r\n"
32319  "Takes 2 or more arguments...\r\n"
32320  "\t1: Number of times to ignore this key (-1 = forever, 0 = stop ignoring). \r\n"
32321  "\tRest: Which key(s) to ignore.\r\n"
32322  },
32323 
32324  { OP_WARP_BROKEN, "break-warp\r\n"
32325  "\tBreak the warp drive on the specified ship. A broken warp drive can be repaired by "
32326  "a repair ship. Takes 1 or more arguments...\r\n"
32327  "\tAll:\tList of ships to break the warp drive on" },
32328 
32329  { OP_WARP_NOT_BROKEN, "fix-warp\r\n"
32330  "\tFixes a broken warp drive instantaneously. This option applies to warp drives broken with "
32331  "the break-warp sepxression. Takes 1 or more arguments...\r\n"
32332  "\tAll:\tList of ships whose warp drive should be fixed"},
32333 
32334  { OP_WARP_NEVER, "never-warp\r\n"
32335  "\tNever allows a ship to warp out. When this sexpression is used, the given ships will "
32336  "never be able to warp out. The warp drive cannot be repaired. Takes 1 or more arguments...\r\n"
32337  "\tAll:\tList of ships whose are not allowed to warp out under any condition"},
32338 
32339  { OP_WARP_ALLOWED, "allow-warp\r\n"
32340  "\tAllows a ship which was previously not allowed to warp out to do so. When this sexpression is "
32341  "used, the given ships will be able to warp out again. Takes 1 or more arguments...\r\n"
32342  "\tAll:\tList of ships whose are allowed to warp out"},
32343 
32344  { OP_SET_SUBSPACE_DRIVE, "set-subspace-drive\r\n"
32345  "\tTurns on or off the subspace edrive for the given ships. A ship with no subspace drive will act "
32346  "as though it doesn't even occur to him to depart via subspace, and if ordered to do so, he will look "
32347  "for a friendly ship with a hangar bay. If the ship is the player, pressing Alt-J will not not initiate "
32348  "a jump, nor give any indication that a jump failed. Takes 2 or more arguments...\r\n"
32349  "\t1:\tTrue if the ship should have a drive; false otherwise\r\n"
32350  "\tRest:\tList of ships" },
32351 
32352  { OP_JETTISON_CARGO, "jettison-cargo-delay\r\n"
32353  "\tCauses a cargo carrying ship to jettison its cargo without the undocking procedure. Takes 2 or more arguments...\r\n"
32354  "\t1: Ship to jettison cargo\r\n"
32355  "\t2: Delay after which to jettison cargo (note that this isn't actually used)\r\n"
32356  "\tRest (optional): Cargo to jettison. If no optional arguments are specified, the ship jettisons all cargo.\r\n"
32357  },
32358 
32359  { OP_SET_DOCKED, "set-docked\r\n"
32360  "\tCauses one ship to become instantly docked to another at the specified docking ports. Takes 4 arguments...\r\n"
32361  "\t1: Docker ship\r\n"
32362  "\t1: Docker point\r\n"
32363  "\t1: Dockee ship\r\n"
32364  "\t1: Dockee point\r\n"
32365  },
32366 
32367  { OP_BEAM_FIRE, "fire-beam\r\n"
32368  "\tFire a beam weapon from a specified subsystem\r\n"
32369  "\t1:\tShip which will be firing\r\n"
32370  "\t2:\tTurret which will fire the beam (note, this turret must have at least 1 beam weapon on it)\r\n"
32371  "\t3:\tShip which will be targeted\r\n"
32372  "\t4:\tSubsystem to target (optional)\r\n"
32373  "\t5:\tWhether to force the beam to fire (disregarding FOV and subsystem status) (optional)\r\n" },
32374 
32375  { OP_BEAM_FIRE_COORDS, "fire-beam-at-coordinates\r\n"
32376  "\tFire a beam weapon from a specified subsystem at a set of coordinates. Not compatible with multiplayer.\r\n"
32377  "\t1:\tShip which will be firing\r\n"
32378  "\t2:\tTurret which will fire the beam (note, this turret must have at least 1 beam weapon on it)\r\n"
32379  "\t3:\tx coordinate to be targeted\r\n"
32380  "\t4:\ty coordinate to be targeted\r\n"
32381  "\t5:\tz coordinate to be targeted\r\n"
32382  "\t6:\t(Optional Operator) Whether to force the beam to fire (disregarding FOV and subsystem status). Defaults to False\r\n"
32383  "\t7:\tsecond x coordinate to be targeted (optional; only used for slash beams)\r\n"
32384  "\t8:\tsecond y coordinate to be targeted (optional; only used for slash beams)\r\n"
32385  "\t9:\tsecond z coordinate to be targeted (optional; only used for slash beams)\r\n" },
32386 
32387  { OP_BEAM_FLOATING_FIRE, "beam-create\r\n"
32388  "\tFire a beam weapon from the specified coordinates to the specified target. Not compatible with multiplayer.\r\n"
32389  "\t1:\tBeam weapon to fire\r\n"
32390  "\t2:\tParent ship (for kill credit, if applicable; can be none)\r\n"
32391  "\t3:\tTeam for this beam to be on (related to difficulty-based damage)\r\n"
32392  "\t4:\tX coordinate to fire from\r\n"
32393  "\t5:\tY coordinate to fire from\r\n"
32394  "\t6:\tZ coordinate to fire from\r\n"
32395  "\t7:\tTarget ship (can be none)\r\n"
32396  "\t8:\tTarget subsystem (optional, can be none)\r\n"
32397  "\t9:\tX coordinate to fire at (optional)\r\n"
32398  "\t10:\tY coordinate to fire at (optional)\r\n"
32399  "\t11:\tZ coordinate to fire at (optional)\r\n"
32400  "\t12:\tSecond X coordinate to fire at (optional; used for slash beams)\r\n"
32401  "\t13:\tSecond Y coordinate to fire at (optional; used for slash beams)\r\n"
32402  "\t14:\tSecond Z coordinate to fire at (optional; used for slash beams)\r\n" },
32403 
32404  { OP_IS_TAGGED, "is-tagged\r\n"
32405  "\tReturns whether a given ship is tagged or not\r\n"},
32406 
32407  { OP_IS_PLAYER, "is-player\r\n"
32408  "\tReturns true if all the ships specified are currently under control of a player.\r\n"
32409  "\t1 \t(SinglePlayer) When true ships under AI control return false even if they are the player ship\r\n"
32410  "\t \t(Multiplayer) When true ships that are respawning return true if the player is still connected\r\n"
32411  "\tRest \tList of ships to test"},
32412 
32413  { OP_NUM_KILLS, "num-kills\r\n"
32414  "\tReturns the # of kills a player has. The ship specified in the first field should be the ship the player is in.\r\n"
32415  "\tSo, for single player, this would be Alpha 1. For multiplayer, it can be any ship with a player in it. If, at any\r\n"
32416  "\ttime there is no player in a given ship, this sexpression will return 0"},
32417 
32418  { OP_NUM_ASSISTS, "num-assists\r\n"
32419  "\tReturns the # of assists a player has. The ship specified in the first field should be the ship the player is in.\r\n"
32420  "\tSo, for single player, this would be Alpha 1. For multiplayer, it can be any ship with a player in it. If, at any\r\n"
32421  "\ttime there is no player in a given ship, this sexpression will return 0"},
32422 
32423  { OP_SHIP_SCORE, "ship-score\r\n"
32424  "\tReturns the score a player has. The ship specified in the first field should be the ship the player is in.\r\n"
32425  "\tSo, for single player, this would be Alpha 1. For multiplayer, it can be any ship with a player in it. If, at any\r\n"
32426  "\ttime there is no player in a given ship, this sexpression will return 0"},
32427 
32428  { OP_SHIP_DEATHS, "ship-deaths\r\n"
32429  "\tReturns the # times a ship that is a player start has died.\r\n"
32430  "\tThe ship specified in the first field should be the ship that could have a player in.it\r\n"
32431  "\tOnly really useful for multiplayer."},
32432 
32433  { OP_RESPAWNS_LEFT, "respawns-left\r\n"
32434  "\tReturns the # respawns a player (or AI that could have been a player) has remaining.\r\n"
32435  "\tThe ship specified in the first field should be the player start.\r\n"
32436  "\tOnly really useful for multiplayer."},
32437 
32438  { OP_REMOVE_WEAPONS, "remove-weapons\r\n"
32439  "\tRemoves all live weapons currently in the game"
32440  "\t1: (Optional) Remove only this specific weapon\r\n"},
32441 
32442  { OP_SET_RESPAWNS, "set-respawns\r\n"
32443  "\tSet the # respawns a player (or AI that could have been a player) has used.\r\n"
32444  "\t1: Number of respawns used up\r\n"
32445  "\tRest: The player start ship to operate on.\r\n"
32446  "\tOnly really useful for multiplayer."},
32447 
32448  { OP_NUM_TYPE_KILLS, "num-type-kills\r\n"
32449  "\tReturns the # of kills a player has on a given ship type (fighter, bomber, cruiser, etc).\r\n"
32450  "The ship specified in the first field should be the ship the player is in.\r\n"
32451  "\tSo, for single player, this would be Alpha 1. For multiplayer, it can be any ship with a player in it. If, at any\r\n"
32452  "\ttime there is no player in a given ship, this sexpression will return 0"},
32453 
32454  { OP_NUM_CLASS_KILLS, "num-class-kills\r\n"
32455  "\tReturns the # of kills a player has on a specific ship class (Ulysses, Hercules, etc).\r\n"
32456  "The ship specified in the first field should be the ship the player is in.\r\n"
32457  "\tSo, for single player, this would be Alpha 1. For multiplayer, it can be any ship with a player in it. If, at any\r\n"
32458  "\ttime there is no player in a given ship, this sexpression will return 0"},
32459 
32460  { OP_BEAM_FREE, "beam-free\r\n"
32461  "\tSets one or more beam weapons to allow firing for a given ship\r\n"
32462  "\t1: Ship to be operated on\r\n"
32463  "\t2, 3, etc : List of turrets to activate\r\n"},
32464 
32465  { OP_BEAM_FREE_ALL, "beam-free-all\r\n"
32466  "\tSets all beam weapons on the specified ship to be active\r\n"},
32467 
32468  { OP_BEAM_LOCK, "beam-lock\r\n"
32469  "\tSets one or more beam weapons to NOT allow firing for a given ship\r\n"
32470  "\t1: Ship to be operated on\r\n"
32471  "\t2, 3, etc : List of turrets to deactivate\r\n"},
32472 
32473  { OP_BEAM_LOCK_ALL, "beam-lock-all\r\n"
32474  "\tSets all beam weapons on the specified ship to be deactivated\r\n"},
32475 
32476  { OP_TURRET_FREE, "turret-free\r\n"
32477  "\tSets one or more turret weapons to allow firing for a given ship\r\n"
32478  "\t1: Ship to be operated on\r\n"
32479  "\t2, 3, etc : List of turrets to activate\r\n"},
32480 
32481  { OP_TURRET_FREE_ALL, "turret-free-all\r\n"
32482  "\tSets all turret weapons on the specified ship to be active\r\n"},
32483 
32484  { OP_TURRET_LOCK, "turret-lock\r\n"
32485  "\tSets one or more turret weapons to NOT allow firing for a given ship\r\n"
32486  "\t1: Ship to be operated on\r\n"
32487  "\t2, 3, etc : List of turrets to deactivate\r\n"},
32488 
32489  { OP_TURRET_LOCK_ALL, "turret-lock-all\r\n"
32490  "\tSets all turret weapons on the specified ship to be deactivated\r\n"},
32491 
32492  { OP_TURRET_CHANGE_WEAPON, "turret-change-weapon\r\n"
32493  "\tSets a given turret weapon slot to the specified weapon\r\n"
32494  "\t1: Ship turret is on\r\n"
32495  "\t2: Turret\r\n"
32496  "\t3: Weapon to set slot to\r\n"
32497  "\t4: Primary slot (or 0 to use secondary)\r\n"
32498  "\t5: Secondary slot (or 0 to use primary)"},
32499 
32500  { OP_TURRET_SET_DIRECTION_PREFERENCE, "turret-set-direction-preference\r\n"
32501  "\tSets specified ship turrets direction preference to the specified value\r\n"
32502  "\t1: Ship turrets are on\r\n"
32503  "\t2: Preference to set, 0 to disable, or negative to reset to default\r\n"
32504  "\trest: Turrets to set\r\n"},
32505 
32506  { OP_TURRET_SET_RATE_OF_FIRE, "turret-set-rate-of-fire\r\n"
32507  "\tSets specified ship turrets rate of fire to the specified value\r\n"
32508  "\t1: Ship turrets are on\r\n"
32509  "\t2: Rate to set in percentage format (200 = 2x, 50 = .5x), 0 to set to number of fire points, or negative to reset to default\r\n"
32510  "\trest: Turrets to set\r\n"},
32511 
32512  { OP_TURRET_SET_OPTIMUM_RANGE, "turret-set-optimum-range\r\n"
32513  "\tSets specified ship turrets optimum range to the specified value\r\n"
32514  "\t1: Ship turrets are on\r\n"
32515  "\t2: Priority to set, 0 to disable, or negative to reset to default\r\n"
32516  "\trest: Turrets to set\r\n"},
32517 
32518  { OP_TURRET_SET_TARGET_PRIORITIES, "turret-set-target-priorities\r\n"
32519  "\tSets target priorities for the specified ship turret\r\n"
32520  "\t1: Ship turret is on\r\n"
32521  "\t2: Turret to set\r\n"
32522  "\t3: True = Set new list, False = Reset to turret default\r\n"
32523  "\trest: Priorities to set (max 32) or blank for no priorities\r\n"},
32524 
32525  { OP_TURRET_GET_PRIMARY_AMMO, "turret-get-primary-ammo\r\n"
32526  "\tGets the turret's primary bank ammo, only works with ballistic weapons\r\n"
32527  "\t1: Ship turret is on\r\n"
32528  "\t2: Turret the bank is on\r\n"
32529  "\t3: Bank to check ammo\r\n"},
32530 
32531  { OP_TURRET_GET_SECONDARY_AMMO, "turret-get-secondary-ammo\r\n"
32532  "\tGets the turret's secondary bank ammo\r\n"
32533  "\t1: Ship turret is on\r\n"
32534  "\t2: Turret to check ammo\r\n"
32535  "\t3: Bank to check ammo\r\n" },
32536 
32537  { OP_TURRET_SET_PRIMARY_AMMO, "turret-set-primary-ammo\r\n"
32538  "\tSets the turret's primary bank ammo, only works with ballistic weapons\r\n"
32539  "\t1: Ship turret is on\r\n"
32540  "\t2: Turret the bank is on\r\n"
32541  "\t3: Bank to add ammo to\r\n"
32542  "\t4: Amount to add" },
32543 
32544  { OP_TURRET_SET_SECONDARY_AMMO, "turret-set-secondary-ammo\r\n"
32545  "\tSets the turret's secondary bank ammo\r\n"
32546  "\t1: Ship turret is on\r\n"
32547  "\t2: Turret the bank is on\r\n"
32548  "\t3: Bank to add ammo to\r\n"
32549  "\t4: Amount to add" },
32550 
32551  { OP_SET_ARMOR_TYPE, "set-armor-type\r\n"
32552  "\tSets the armor type for a ship or subsystem\r\n"
32553  "\t1: Ship subsystem is on\r\n"
32554  "\t2: Set = true/Reset to defualt = false\r\n"
32555  "\t3: Armor type to set or <none>\r\n"
32556  "\trest: Subsystems to set (hull for ship, shield for shields)\r\n"},
32557 
32558  { OP_WEAPON_SET_DAMAGE_TYPE, "weapon-set-damage-type\r\n"
32559  "\tSets the damage type for weapons or their shockwaves\r\n"
32560  "\t1: True = set weapon, False = set shockwave\r\n"
32561  "\t2: damage type to set or <none>\r\n"
32562  "\t3: Set = true/Reset to defualt = false\r\n"
32563  "\trest: Weapons to set\r\n"},
32564 
32565  { OP_SHIP_SET_DAMAGE_TYPE, "ship-set-damage-type\r\n"
32566  "\tSets the damage type for ships collision or debris\r\n"
32567  "\t1: true = set collision, False = set debris\r\n"
32568  "\t2: Damage type to set or <none>\r\n"
32569  "\t3: Set = true/Reset to defualt = false\r\n"
32570  "\trest: Ships to set\r\n"},
32571 
32572  { OP_SHIP_SHOCKWAVE_SET_DAMAGE_TYPE, "ship-set-shockwave-damage-type\r\n"
32573  "\tSets the shockwave damage type for a class of ship. All ships of that class are changed.\r\n"
32574  "\t1: Damage type to set or <none>\r\n"
32575  "\t2: Set = true/Reset to defualt = false\r\n"
32576  "\trest: Ship classes to set\r\n"},
32577 
32578  { OP_FIELD_SET_DAMAGE_TYPE, "field-set-damage-type\r\n"
32579  "\tSets the damage type for asteroid/debris fields\r\n"
32580  "\t1: Damage type to set or <none>\r\n"
32581  "\t2: Set = true/Reset to defualt = false\r\n"},
32582 
32583  { OP_TURRET_SET_TARGET_ORDER, "turret-set-target-order\r\n"
32584  "\tSets targeting order of a given turret\r\n"
32585  "\t1: Ship turret is on\r\n"
32586  "\t2: Turret\r\n"
32587  "\trest: Target order type (Bombs,ships,asteroids)"},
32588 
32589  { OP_SHIP_TURRET_TARGET_ORDER, "ship-turret-target-order\r\n"
32590  "\tSets targeting order of all turrets on a given ship\r\n"
32591  "\t1: Ship turrets are on\r\n"
32592  "\trest: Target order type (Bombs,ships,asteroids)"},
32593 
32594  { OP_TURRET_SUBSYS_TARGET_DISABLE, "turret-subsys-target-disable\r\n"
32595  "\tPrevents turrets from targeting only the subsystems when targeting large targets\r\n"
32596  "\t1: Ship to be operated on\r\n"
32597  "\trest: List of turrets that are affected\r\n"},
32598 
32599  { OP_TURRET_SUBSYS_TARGET_ENABLE, "turret-subsys-target-enable\r\n"
32600  "\tSets turret to target the subsystems when targeting large targets\r\n"
32601  "\t1: Ship to be operated on\r\n"
32602  "\trest: List of turrets that are affected\r\n"},
32603 
32604  { OP_ADD_REMOVE_ESCORT, "add-remove-escort\r\n"
32605  "\tAdds or removes a ship from an escort list.\r\n"
32606  "\t1: Ship to be added or removed\r\n"
32607  "\t2: 0 to remove from the list, any positive value will be used as the escort priority\r\n"
32608  "NOTE : it _IS_ safe to add a ship which may already be on the list or remove\r\n"
32609  "a ship which is not on the list\r\n"},
32610 
32611  { OP_AWACS_SET_RADIUS, "awacs-set-radius\r\n"
32612  "\tSets the awacs radius for a given ship subsystem. NOTE : does not work properly in multiplayer\r\n"
32613  "\t1: Ship which has the awacs subsystem\r\n"
32614  "\t2: Awacs subsystem\r\n"
32615  "\t3: New radius\r\n"},
32616 
32617  // Goober5000
32618  { OP_PRIMITIVE_SENSORS_SET_RANGE, "primitive-sensors-set-range\r\n"
32619  "\tSets the range of the primitive sensors on a ship. Ships outside of this range will not appear on "
32620  "sensors. Has no effect on ships that do not have the \"primitive-sensors\" flag2 set. Takes 2 arguments...\r\n"
32621  "\t1: Ship on which to set range\r\n"
32622  "\t2: Range, in meters\r\n" },
32623 
32624  { OP_SEND_MESSAGE_LIST, "send-message-list\r\n"
32625  "\tSends a series of delayed messages. All times are accumulated.\r\n"
32626  "\t1:\tName of who the message is from.\r\n"
32627  "\t2:\tPriority of message (\"Low\", \"Normal\" or \"High\").\r\n"
32628  "\t3:\tName of message (from message editor).\r\n"
32629  "\t4:\tDelay from previous message in list (if any) in ms\r\n"
32630  "Use Add-Data for multiple messages.\r\n\r\n"
32631  "IMPORTANT: Each additional message in the list MUST HAVE four entries; "
32632  "any message without the four proper fields will be ignored, as will any "
32633  "successive messages."},
32634 
32635  { OP_CAP_WAYPOINT_SPEED, "cap-waypoint-speed\r\n"
32636  "\tSets the maximum speed of a ship while flying waypoints.\r\n"
32637  "\t1: Ship name\r\n"
32638  "\t2: Maximum speed while flying waypoints\r\n"
32639  "\tNOTE: This will only work if the ship is already in the game\r\n"
32640  "\tNOTE: Set to -1 to reset\r\n"},
32641 
32642  { OP_TURRET_TAGGED_ONLY_ALL, "turret-tagged-only\r\n"
32643  "\tMakes turrets target and hence fire strictly at tagged objects\r\n"
32644  "\t1: Ship name\r\n"
32645  "\tNOTE: Will not stop a turret already firing at an untagged ship\r\n"},
32646 
32647  { OP_TURRET_TAGGED_CLEAR_ALL, "turret-tagged-clear\r\n"
32648  "\tRelaxes restriction on turrets targeting only tagged ships\r\n"
32649  "\t1: Ship name\r\n"},
32650 
32651  { OP_PRIMARIES_DEPLETED, "primaries-depleted\r\n"
32652  "\tReturns true if ship is out of primary weapons\r\n"
32653  "\t1: Ship name\r\n"},
32654 
32655  { OP_SECONDARIES_DEPLETED, "secondaries-depleted\r\n"
32656  "\tReturns true if ship is out of secondary weapons\r\n"
32657  "\t1: Ship name\r\n"},
32658 
32659  { OP_SUBSYS_SET_RANDOM, "subsys-set-random\r\n"
32660  "\tSets ship subsystem strength in a given range\r\n"
32661  "\t1: Ship name\r\n"
32662  "\t2: Low range\r\n"
32663  "\t3: High range\r\n"
32664  "\t4: List of subsys names not to be randomized\r\n"},
32665 
32666  { OP_SUPERNOVA_START, "supernova-start\r\n"
32667  "\t1: Time in seconds until the supernova shockwave hits the player\r\n"},
32668 
32669  { OP_SUPERNOVA_STOP, "supernova-stop\r\n"
32670  "\t Stops a supernova in progress.\r\n"
32671  "\t Note this only works if the camera hasn't cut to the player's death animation yet.\r\n"},
32672 
32673  { OP_WEAPON_RECHARGE_PCT, "weapon-recharge-pct\r\n"
32674  "\tReturns a percentage from 0 to 100\r\n"
32675  "\t1: Ship name\r\n" },
32676 
32677  { OP_SHIELD_RECHARGE_PCT, "shield-recharge-pct\r\n"
32678  "\tReturns a percentage from 0 to 100\r\n"
32679  "\t1: Ship name\r\n" },
32680 
32681  { OP_ENGINE_RECHARGE_PCT, "engine-recharge-pct\r\n"
32682  "\tReturns a percentage from 0 to 100\r\n"
32683  "\t1: Ship name\r\n" },
32684 
32685  { OP_GET_ETS_VALUE, "get-ets-value\r\n"
32686  "\tGets one ETS index for a ship\r\n"
32687  "\t1: ETS index to get, Engine|Shield|Weapon\r\n"
32688  "\t2: Ship name\r\n"},
32689 
32690  { OP_SET_ETS_VALUES, "set-ets-values\r\n"
32691  "\tSets ETS indexes for a ship\r\n"
32692  "\tUse values retrieved with get-ets-value\r\n"
32693  "\tIf you use your own values, make sure they add up to 12\r\n"
32694  "\t1: Engine percent\r\n"
32695  "\t2: Shields percent\r\n"
32696  "\t3: Weapons percent\r\n"
32697  "\t4: Ship name\r\n"},
32698 
32699  { OP_CARGO_NO_DEPLETE, "cargo-no-deplete\r\n"
32700  "\tCauses the named ship to have unlimited cargo.\r\n"
32701  "\tNote: only applies to BIG or HUGE ships\r\n"
32702  "Takes 1 or more arguments...\r\n"
32703  "\t1:\tName of one of the ships.\r\n"
32704  "\t2:\toptional: 1 disallow depletion, 0 allow depletion." },
32705 
32706  { OP_SHIELD_QUAD_LOW, "shield-quad-low\r\n"
32707  "\tReturns true if the specified ship has a shield quadrant below\r\n"
32708  "\tthe specified threshold percentage\r\n"
32709  "\t1: Ship name\r\n"
32710  "\t2: Percentage\r\n" },
32711 
32712  { OP_PRIMARY_AMMO_PCT, "primary-ammo-pct\r\n"
32713  "\tReturns the percentage of ammo remaining in the specified ballistic primary bank (0 to 100). Non-ballistic primary banks return as 100%.\r\n"
32714  "\t1: Ship name\r\n"
32715  "\t2: Bank to check (from 0 to N-1, where N is the number of primary banks in the ship; N or higher will return the cumulative average for all banks)" },
32716 
32717  // Karajorma
32718  { OP_GET_PRIMARY_AMMO, "get-primary-ammo\r\n"
32719  "\tReturns the amount of ammo remaining in the specified bank\r\n"
32720  "\t1: Ship name\r\n"
32721  "\t2: Bank to check (from 0 to N-1, where N is the number of primary banks in the ship; N or higher will return the cumulative total for all banks)" },
32722 
32723 
32724  { OP_SECONDARY_AMMO_PCT, "secondary-ammo-pct\r\n"
32725  "\tReturns the percentage of ammo remaining in the specified bank (0 to 100)\r\n"
32726  "\t1: Ship name\r\n"
32727  "\t2: Bank to check (from 0 to N-1, where N is the number of secondary banks in the ship; N or higher will return the cumulative average for all banks)" },
32728 
32729  // Karajorma
32730  { OP_GET_SECONDARY_AMMO, "get-secondary-ammo\r\n"
32731  "\tReturns the amount of ammo remaining in the specified bank\r\n"
32732  "\t1: Ship name\r\n"
32733  "\t2: Bank to check (from 0 to N-1, where N is the number of secondary banks in the ship; N or higher will return the cumulative total for all banks)" },
32734 
32735  // Karajorma
32736  { OP_GET_NUM_COUNTERMEASURES, "get-num-countermeasures\r\n"
32737  "\tReturns the amount of countermeasures remaining\r\n"
32738  "\t1: Ship name\r\n" },
32739 
32740  { OP_IS_SECONDARY_SELECTED, "is-secondary-selected\r\n"
32741  "\tReturns true if the specified bank is selected\r\n"
32742  "\t1: Ship name\r\n"
32743  "\t2: Bank to check (This is a zero-based index. The first bank is numbered 0.)\r\n"},
32744 
32745  { OP_IS_PRIMARY_SELECTED, "is-primary-selected\r\n"
32746  "\tReturns true if the specified bank is selected\r\n"
32747  "\t1: Ship name\r\n"
32748  "\t2: Bank to check (This is a zero-based index. The first bank is numbered 0.)\r\n"},
32749 
32750  { OP_SPECIAL_WARP_DISTANCE, "special-warp-dist\r\n"
32751  "\tReturns distance to the plane of the knossos device in percent length of ship\r\n"
32752  "\t(ie, 100 means front of ship is 1 ship length from plane of knossos device)\r\n"
32753  "\t1: Ship name\r\n"},
32754 
32755  { OP_SET_SPECIAL_WARPOUT_NAME, "special-warpout-name\r\n"
32756  "\tSets the name of the knossos device to be used for warpout\r\n"
32757  "\t1: Ship name to exit\r\n"
32758  "\t2: Name of knossos device\r\n"},
32759 
32760  { OP_SHIP_VANISH, "ship-vanish\r\n"
32761  "\tMakes the named ship vanish (no log and vanish)\r\n"
32762  "\tSingle Player Only! Warning: This will cause ship exit not to be logged, so 'has-departed', etc. will not work\r\n"
32763  "\t1: List of ship names to vanish\r\n"},
32764 
32765  { OP_DESTROY_INSTANTLY, "destroy-instantly\r\n"
32766  "\tSelf-destructs the named ship without explosion, death roll, or debris. That is, the ship is instantly gone from the mission and the only indication of what happened is a mission log entry.\r\n"
32767  "\tSingle Player Only! Non-player ship only!\r\n"
32768  "\tAll: List of ship names to destroy.\r\n"},
32769 
32770  { OP_SHIP_CREATE, "ship-create\r\n"
32771  "\tCreates a new ship\r\n"
32772  "\tTakes 5 to 8 arguments...\r\n"
32773  "\t1: Name of new ship (use \"" SEXP_NONE_STRING "\" for a default name)\r\n"
32774  "\t2: Class of new ship\r\n"
32775  "\t3: X position\r\n"
32776  "\t4: Y position\r\n"
32777  "\t5: Z position\r\n"
32778  "\t6: Pitch (optional)\r\n"
32779  "\t7: Bank (optional)\r\n"
32780  "\t8: Heading (optional)\r\n"
32781  },
32782 
32783  // Goober5000
32784  { OP_WEAPON_CREATE, "weapon-create\r\n"
32785  "\tCreates a new weapon\r\n"
32786  "\tTakes 5 to 10 arguments...\r\n"
32787  "\t 1: Name of parent ship (or \"" SEXP_NONE_STRING "\" for no parent)\r\n"
32788  "\t 2: Class of new weapon\r\n"
32789  "\t 3: X position\r\n"
32790  "\t 4: Y position\r\n"
32791  "\t 5: Z position\r\n"
32792  "\t 6: Pitch (optional)\r\n"
32793  "\t 7: Bank (optional)\r\n"
32794  "\t 8: Heading (optional)\r\n"
32795  "\t 9: Targeted ship (optional)\r\n"
32796  "\t10: Targeted subsystem (optional)\r\n"
32797  },
32798 
32799  { OP_IS_SHIP_VISIBLE, "is-ship-visible\r\n"
32800  "\tCheck whether ship is visible on Player's radar\r\n"
32801  "\tSingle Player Only! Returns 0 - not visible, 1 - partially visible, 2 - fully visible.\r\n"
32802  "\t1: Name of ship to check\r\n"},
32803 
32804  // Goober5000
32805  { OP_IS_SHIP_STEALTHY, "is-ship-stealthy\r\n"
32806  "\tCheck whether ship is currently stealthy.\r\n"
32807  "\tTrue if stealth flag set, false otherwise. Takes 1 argument...\r\n"
32808  "\t1: Name of ship to check\r\n"},
32809 
32810  // Goober5000
32811  { OP_IS_FRIENDLY_STEALTH_VISIBLE, "is-friendly-stealth-visible\r\n"
32812  "\tCheck whether ship will be visible to radar as a stealth friendly.\r\n"
32813  "\tTakes 1 argument...\r\n"
32814  "\t1: Name of ship to check\r\n"},
32815 
32816  { OP_TEAM_SCORE, "team-score\r\n"
32817  "\tGet the score of a multi team vs team game.\r\n"
32818  "\t1: Team index (1 for team 1 and 2 for team 2)\r\n"},
32819 
32820  // phreak
32821  { OP_DAMAGED_ESCORT_LIST, "damaged-escort-list\r\n"
32822  "\tSets the most damaged ship in <ship list> to <priority1>, sets the others to <priority2>. Don't use this sexp in the same mission as damaged-escort-list-all, or strange results might occur.\r\n"
32823  "\t1: Priority1\r\n"
32824  "\t2: Priority2\r\n"
32825  "\tRest: <ship_list>\r\n\r\n"
32826  },
32827 
32828  // Goober5000
32829  { OP_DAMAGED_ESCORT_LIST_ALL, "damaged-escort-list-all\r\n"
32830  "\tSets the most damaged ship in the entire existing escort list (even what's not shown onscreen) to <priority1>, the next most damaged to <priority2>, and so on. "
32831  "If there are more ships than priorities, the least most damaged ships are all set to the last priority in the list. Don't use this sexp in the same mission as damaged-escort-list, or strange results might occur.\r\n"
32832  "\tTakes between 1 and MAX_COMPLETE_ESCORT_LIST (currently 20) arguments...\r\n"
32833  "\t1: Priority 1\r\n"
32834  "\tRest: Priorities 2 through 20 (optional)\r\n\r\n"
32835  },
32836 
32837  // Goober5000
32838  { OP_CHANGE_SHIP_CLASS, "change-ship-class\r\n"
32839  "\tCauses the listed ships' classes to be changed to the specified ship class. Takes 2 or more arguments...\r\n"
32840  "\t1: The name of the new ship class\r\n"
32841  "\tRest: The list of ships to change the classes of"
32842  },
32843 
32844  // Goober5000
32845  { OP_SHIP_COPY_DAMAGE, "ship-copy-damage\r\n"
32846  "\tCopies the damage (hull, shields, and subsystems) from the first ship in the list to the rest. The initial ship must be currently "
32847  "present in the mission, but the target ships may be either in-mission or on the arrival list. Takes 2 or more arguments...\r\n"
32848  "\t1: The name of the ship that supplies the damage stats\r\n"
32849  "\tRest: The list of ships to be modified"
32850  },
32851 
32852  // Goober5000
32853  { OP_SET_SUPPORT_SHIP, "set-support-ship\r\n"
32854  "\tSets information for all support ships in a mission. Takes 6 or 7 arguments...\r\n"
32855  "\t1: Arrival location\r\n"
32856  "\t2: Arrival anchor\r\n"
32857  "\t3: Departure location\r\n"
32858  "\t4: Departure anchor\r\n"
32859  "\t5: Ship class\r\n"
32860  "\t6: Maximum number of support ships consecutively in this mission (use a negative number for infinity)\r\n"
32861  "\t7: Maximum number of support ships concurrently in this mission (optional, default 1)\r\n"
32862  "\r\n"
32863  "Note: The support ship will emerge from or depart into hyperspace if the location is set as hyperspace *or* the anchor is set as <no anchor>."
32864  },
32865 
32866  // Goober5000
32867  { OP_SET_ARRIVAL_INFO, "set-arrival-info\r\n"
32868  "\tSets arrival information for a ship or wing. Takes 2 to 7 arguments...\r\n"
32869  "\t1: Ship or wing name\r\n"
32870  "\t2: Arrival location\r\n"
32871  "\t3: Arrival anchor (optional; only required for certain locations)\r\n"
32872  "\t4: Arrival path mask (optional; this is a bitfield where the bits set to 1 correspond to the paths to use; defaults to 0 which is a special case that means all paths can be used)\r\n"
32873  "\t5: Arrival distance (optional; defaults to 0)\r\n"
32874  "\t6: Arrival delay (optional; defaults to 0)\r\n"
32875  "\t7: Whether to show a jump effect if arriving from subspace (optional; defaults to true)\r\n"
32876  },
32877 
32878  // Goober5000
32879  { OP_SET_DEPARTURE_INFO, "set-departure-info\r\n"
32880  "\tSets departure information for a ship or wing. Takes 2 to 6 arguments...\r\n"
32881  "\t1: Ship or wing name\r\n"
32882  "\t2: Departure location\r\n"
32883  "\t3: Departure anchor (optional; only required for certain locations)\r\n"
32884  "\t4: Departure path mask (optional; this is a bitfield where the bits set to 1 correspond to the paths to use; defaults to 0 which is a special case that means all paths can be used)\r\n"
32885  "\t5: Departure delay (optional; defaults to 0)\r\n"
32886  "\t6: Whether to show a jump effect if departing to subspace (optional; defaults to true)\r\n"
32887  },
32888 
32889  // Bobboau
32890  { OP_DEACTIVATE_GLOW_POINTS, "deactivate-glow-points\r\n"
32891  "\tDeactivates all glow points on a ship. Takes 1 or more arguments...\r\n"
32892  "\tAll: Name of ship on which to deactivate glow points\r\n"
32893  },
32894 
32895  // Bobboau
32896  { OP_ACTIVATE_GLOW_POINTS, "activate-glow-points\r\n"
32897  "\tActivates all glow points on a ship. Takes 1 or more arguments...\r\n"
32898  "\tAll: Name of ship on which to activate glow points\r\n"
32899  },
32900 
32901  // Bobboau
32902  { OP_DEACTIVATE_GLOW_MAPS, "deactivate-glow-maps\r\n"
32903  "\tDeactivates the glow maps for a ship. Takes 1 or more arguments...\r\n"
32904  "\tAll: Name of ship on which to deactivate glow maps\r\n"
32905  },
32906 
32907  // Bobboau
32908  { OP_ACTIVATE_GLOW_MAPS, "activate-glow-maps\r\n"
32909  "\tActivates the glow maps for a ship. Takes 1 or more arguments...\r\n"
32910  "\tAll: Name of ship on which to activate glow maps\r\n"
32911  },
32912 
32913  // Bobboau
32914  { OP_DEACTIVATE_GLOW_POINT_BANK, "deactivate-glow-point-bank\r\n"
32915  "\tDeactivates one or more glow point bank(s) on a ship. Takes 2 or more arguments...\r\n"
32916  "\t1: Name of ship on which to deactivate glow point bank(s)\r\n"
32917  "\tRest: Name of glow point bank to deactivate\r\n"
32918  },
32919 
32920  // Bobboau
32921  { OP_ACTIVATE_GLOW_POINT_BANK, "activate-glow-point-bank\r\n"
32922  "\tActivates one or more glow point bank(s) on a ship. Takes 2 or more arguments...\r\n"
32923  "\t1: Name of ship on which to activate glow point bank(s)\r\n"
32924  "\tRest: Name of glow point bank to activate\r\n"
32925  },
32926 
32927  //-Sesquipedalian
32928  { OP_KAMIKAZE, "kamikaze\r\n"
32929  "\tTells ships to perform a kamikaze on its current target. Takes 2 or more arguments...\r\n"
32930  "\t1: Damage dealt when kamikaze is done\r\n"
32931  "\tRest: Names of ships to perform kamikaze\r\n"
32932  },
32933 
32934  //phreak
32935  { OP_TURRET_TAGGED_SPECIFIC, "turret-tagged-specific\r\n"
32936  "\tSpecific turrets on a ship only fire at tagged targets, as opposed to all turrets doing this using turret-tagged-only\r\n"
32937  "\tIt is safe to slave turrets already slaved\r\n"
32938  "\tTakes 2 or more arguments...\r\n"
32939  "\t1: Name of ship to slave some turrets to target only tagged ships\r\n"
32940  "\tRest: Turrets to slave\r\n"
32941  },
32942 
32943  //phreak
32944  { OP_TURRET_TAGGED_CLEAR_SPECIFIC, "turret-tagged-clear-specific\r\n"
32945  "\tSpecific turrets on a ship are free to fire on untagged ships, as opposed to all turrets doing this using turret-tagged-clear\r\n"
32946  "\tIt is safe to unslave turrets already free\r\n"
32947  "\tTakes 2 or more arguments...\r\n"
32948  "\t1: Name of ship to unslave some turrets to target any hostile ship\r\n"
32949  "\tRest: Turrets to unslave\r\n"
32950  },
32951 
32952  // Goober5000
32953  { OP_LOCK_ROTATING_SUBSYSTEM, "lock-rotating-subsystem\r\n"
32954  "\tInstantaneously locks a rotating subsystem so that it cannot rotate unless freed by free-rotating-subsystem. "
32955  "Takes 2 or more arguments...\r\n"
32956  "\t1:\tName of the ship housing the subsystem\r\n"
32957  "\tRest:\tName of the rotating subsystem to lock"
32958  },
32959 
32960  // Goober5000
32961  { OP_FREE_ROTATING_SUBSYSTEM, "free-rotating-subsystem\r\n"
32962  "\tInstantaneously frees a rotating subsystem previously locked by lock-rotating-subsystem. "
32963  "Takes 2 or more arguments...\r\n"
32964  "\t1:\tName of the ship housing the subsystem\r\n"
32965  "\tRest:\tName of the rotating subsystem to free"
32966  },
32967 
32968  // Goober5000
32969  { OP_REVERSE_ROTATING_SUBSYSTEM, "reverse-rotating-subsystem\r\n"
32970  "\tInstantaneously reverses the rotation direction of a rotating subsystem. "
32971  "Takes 2 or more arguments...\r\n"
32972  "\t1:\tName of the ship housing the subsystem\r\n"
32973  "\tRest:\tName of the rotating subsystem to reverse"
32974  },
32975 
32976  // Goober5000
32977  { OP_ROTATING_SUBSYS_SET_TURN_TIME, "rotating-subsys-set-turn-time\r\n"
32978  "\tSets the turn time of a rotating subsystem. "
32979  "Takes 3 or 4 arguments...\r\n"
32980  "\t1:\tName of the ship housing the subsystem\r\n"
32981  "\t2:\tName of the rotating subsystem to configure\r\n"
32982  "\t3:\tThe time for one complete rotation, in milliseconds (positive is counterclockwise, negative is clockwise)\r\n"
32983  "\t4:\tThe acceleration (x1000, just as #3 is seconds x1000) to change from the current turn rate to the desired turn rate. "
32984  "This is actually the time to complete one rotation that changes in one second, or the reciprocal of what you might expect, "
32985  "meaning that larger numbers cause slower acceleration. (FS2 defaults to 2pi/0.5, or about 12.566, which would be 12566 in this sexp.) "
32986  "The advantage of this method is so that this argument can be directly compared to the previous argument using a ratio, without worrying about pi. "
32987  "Omit this argument if you want an instantaneous change."
32988  },
32989 
32990  // Goober5000
32991  { OP_TRIGGER_SUBMODEL_ANIMATION, "trigger-submodel-animation\r\n"
32992  "\tActivates a submodel animation trigger for a given ship. Takes 4 to 6 arguments...\r\n"
32993  "\t1: The ship on which the animation should run\r\n"
32994  "\t2: The type of animation (named as one would see them in ships.tbl)\r\n"
32995  "\t3: The subtype of animation, which is type-dependent. For docking animations this is the dock index.\r\n"
32996  "\t4: The animation direction: 1 for forward, or -1 for reverse\r\n"
32997  "\t5: (Optional) Whether the animation should instantly snap to its final position\r\n"
32998  "\t6: (Optional) A subsystem, if the animation should trigger on only a specific subsystem as opposed to all applicable subsystems\r\n"
32999  },
33000 
33001  // Karajorma
33002  { OP_SET_PRIMARY_AMMO, "set-primary-ammo\r\n"
33003  "\tSets the amount of ammo for the specified ballistic bank\r\n"
33004  "\t1: Ship name\r\n"
33005  "\t2: Bank to check (0, 1, and 2 are legal banks)\r\n"
33006  "\t3: Number to set this bank to (If this is larger than the maximum, bank will be set to maximum).\r\n"
33007  "\t4: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
33008  },
33009 
33010  // Karajorma
33011  { OP_SET_SECONDARY_AMMO, "set-secondary-ammo\r\n"
33012  "\tSets the amount of ammo for the specified bank\r\n"
33013  "\t1: Ship name\r\n"
33014  "\t2: Bank to check (0, 1, 2 and 3 are legal banks)\r\n"
33015  "\t3: Number to set this bank to (If this is larger than the maximum, bank will be set to maximum).\r\n"
33016  "\t4: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
33017  },
33018 
33019  // Karajorma
33020  { OP_SET_PRIMARY_WEAPON, "set-primary-weapon\r\n"
33021  "\tSets the weapon for the specified bank\r\n"
33022  "\t1: Ship name\r\n"
33023  "\t2: Bank to check (0, 1 and 2 are legal banks)\r\n"
33024  "\t3: Name of the primary weapon \r\n"
33025  "\t4: Number to set ammo of this bank to (If this is larger than the maximum, bank will be set to maximum)\r\n"
33026  "\t5: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
33027  },
33028 
33029  // Karajorma
33030  { OP_SET_SECONDARY_WEAPON, "set-secondary-weapon\r\n"
33031  "\tSets the weapon for the specified bank\r\n"
33032  "\t1: Ship name\r\n"
33033  "\t2: Bank to check (0, 1, 2 and 3 are legal banks)\r\n"
33034  "\t3: Name of the secondary weapon \r\n"
33035  "\t4: Number to set ammo of this bank to (If this is larger than the maximum, bank will be set to maximum)\r\n"
33036  "\t5: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
33037  },
33038 
33039 
33040 
33041  // Karajorma
33042  { OP_SET_NUM_COUNTERMEASURES, "set-num-countermeasures\r\n"
33043  "\tSets the number of countermeasures the ship has\r\n"
33044  "\tValues greater than the maximum a ship can carry are set to the maximum\r\n"
33045  "\t1: Ship name\r\n"
33046  "\t2: Number to set"
33047  },
33048 
33049  // Karajorma
33050  { OP_LOCK_PRIMARY_WEAPON, "lock-primary-weapon\r\n"
33051  "\tLocks the primary banks for the specified ship(s)\r\n"
33052  "\tTakes 1 or more arguments\r\n"
33053  "\t(all): Name(s) of ship(s) to lock"
33054  },
33055 
33056  // Karajorma
33057  { OP_UNLOCK_PRIMARY_WEAPON, "unlock-primary-weapon\r\n"
33058  "\tUnlocks the primary banks for the specified ship(s)\r\n"
33059  "\tTakes 1 or more arguments\r\n"
33060  "\t(all): Name(s) of ship(s) to lock"
33061  },
33062 
33063  // Karajorma
33064  { OP_LOCK_SECONDARY_WEAPON, "lock-secondary-weapon\r\n"
33065  "\tLocks the secondary banks for the specified ship(s)\r\n"
33066  "\tTakes 1 or more arguments\r\n"
33067  "\t(all): Name(s) of ship(s) to lock"
33068  },
33069 
33070  // Karajorma
33071  { OP_UNLOCK_SECONDARY_WEAPON, "unlock-secondary-weapon\r\n"
33072  "\tUnlocks the secondary banks for the specified ship(s)\r\n"
33073  "\tTakes 1 or more arguments\r\n"
33074  "\t(all): Name(s) of ship(s) to lock"
33075  },
33076 
33077  // KeldorKatarn
33078  { OP_LOCK_AFTERBURNER, "lock-afterburner\r\n"
33079  "\tLocks the afterburners on the specified ship(s)\r\n"
33080  "\tTakes 1 or more arguments\r\n"
33081  "\t(all): Name(s) of ship(s) to lock"
33082  },
33083 
33084  // KeldorKatarn
33085  { OP_UNLOCK_AFTERBURNER, "unlock-afterburner\r\n"
33086  "\tUnlocks the afterburners on the specified ship(s)\r\n"
33087  "\tTakes 1 or more arguments\r\n"
33088  "\t(all): Name(s) of ship(s) to lock"
33089  },
33090 
33091  // Karajorma
33092  { OP_SET_AFTERBURNER_ENERGY, "set-afterburner-energy\r\n"
33093  "\tSets the afterburner energy for the specified ship(s)\r\n"
33094  "\tTakes 2 or more arguments\r\n"
33095  "\t1: percentage of maximum afterburner energy.\r\n"
33096  "\t(rest): Name(s) of ship(s)"
33097  },
33098 
33099  { OP_SET_WEAPON_ENERGY, "set-weapon-energy\r\n"
33100  "\tSets the weapon energy for the specified ship(s)\r\n"
33101  "\tTakes 2 or more arguments\r\n"
33102  "\t1: percentage of maximum weapon energy.\r\n"
33103  "\t(rest): Name(s) of ship(s)"
33104  },
33105 
33106  { OP_SET_SHIELD_ENERGY, "set-shield-energy\r\n"
33107  "\tSets the shield energy for the specified ship(s)\r\n"
33108  "\tTakes 2 or more arguments\r\n"
33109  "\t1: percentage of maximum shield energy.\r\n"
33110  "\t(rest): Name(s) of ship(s)"
33111  },
33112 
33113  { OP_SET_AMBIENT_LIGHT, "set-ambient-light\r\n"
33114  "\tSets the ambient light level for the mission\r\n"
33115  "\tTakes 3 arguments\r\n"
33116  "\t1: Red (0 - 255).\r\n"
33117  "\t2: Green (0 - 255).\r\n"
33118  "\t3: Blue (0 - 255)."
33119  },
33120 
33121  { OP_SET_POST_EFFECT, "set-post-effect\r\n"
33122  "\tConfigures post-processing effect\r\n"
33123  "\tTakes 2 arguments\r\n"
33124  "\t1: Effect type\r\n"
33125  "\t2: Effect intensity (0 - 100)."
33126  },
33127 
33128  { OP_CHANGE_SUBSYSTEM_NAME, "change-subsystem-name\r\n"
33129  "\tChanges the name of the specified subsystem on the specified ship\r\n"
33130  "\tTakes 3 or more arguments\r\n"
33131  "\t1: Name of the ship.\r\n"
33132  "\t2: New name for the subsystem (names larger than the maximum display size will be truncated\r\n"
33133  "\t3: Name(s) of subsystem(s) to rename\r\n"
33134  },
33135 
33136  //phreak
33137  { OP_NUM_SHIPS_IN_BATTLE, "num-ships-in-battle\r\n"
33138  "\tReturns the number of ships in battle or the number of ships in battle out of a list of teams, wings, and ships. Takes 1 or more arguments...\r\n"
33139  "\t(all):\tTeams, Wings, and Ships to query (optional)"
33140  },
33141 
33142  // Karajorma
33143  { OP_NUM_SHIPS_IN_WING, "num-ships-in-wing\r\n"
33144  "\tReturns the number of ships in battle which belong to a given wing. Takes 1 or more arguments...\r\n"
33145  "\t(all):\tName of wing(s) to check"
33146  },
33147 
33148  // Goober5000
33149  { OP_HUD_DISABLE, "hud-disable\r\n"
33150  "\tSets whether the hud is disabled. Takes 1 argument...\r\n"
33151  "\t1: Flag (1 to disable, 0 to re-enable)"
33152  },
33153 
33154  // Goober5000
33155  { OP_HUD_DISABLE_EXCEPT_MESSAGES, "hud-disable-except-messages\r\n"
33156  "\tSets whether the hud (except for messages) is disabled. Takes 1 argument...\r\n"
33157  "\t1: Flag (1 to disable, 0 to re-enable)"
33158  },
33159 
33160  // Goober5000
33161  { OP_HUD_SET_MAX_TARGETING_RANGE, "hud-set-max-targeting-range\r\n"
33162  "\tSets the farthest distance at which an object can be targeted. Takes 1 argument...\r\n"
33163  "\1: Maximum targeting distance (0 for infinite)\r\n"
33164  },
33165 
33166  { OP_HUD_DISPLAY_GAUGE, "hud-display-gauge <milliseconds> <gauge>\r\n"
33167  "\tCauses specified hud gauge to appear or disappear for so many milliseconds. Takes 1 argument...\r\n"
33168  "\t1: Number of milliseconds that the warpout gauge should appear on the HUD."
33169  " 0 will immediately cause the gauge to disappear.\r\n"
33170  "\t2: Name of HUD element. Must be one of:\r\n"
33171  "\t\t" SEXP_HUD_GAUGE_WARPOUT " - the \"Subspace drive active\" box that appears above the viewscreen.\r\n"
33172  },
33173 
33174  // Goober5000
33175  { OP_PLAYER_USE_AI, "player-use-ai\r\n"
33176  "\tCauses the player's ship to be controlled by the FreeSpace AI. Takes 0 arguments.\r\n"
33177  },
33178 
33179  // Goober5000
33180  { OP_PLAYER_NOT_USE_AI, "player-not-use-ai\r\n"
33181  "\tCauses the player's ship to not be controlled by the FreeSpace AI. Takes 0 arguments.\r\n"
33182  },
33183 
33184  // Karajorma
33185  { OP_ALLOW_TREASON, "allow-treason\r\n"
33186  "\tTurns the Allow Traitor switch on or off in mission. Takes 0 arguments.\r\n"
33187  "\t1:\tTrue/False."
33188  },
33189 
33190  // Karajorma
33191  { OP_SET_PLAYER_ORDERS, "set-player-orders\r\n"
33192  "\tChanges the orders friendly AI will accept. Takes 3 or more arguments.\r\n"
33193  "\t1:\tShip Name\r\n"
33194  "\t2:\tTrue/False as to whether this order is allowed or not\r\n"
33195  "\tRest:\tOrder"
33196  },
33197 
33198  //WMC
33199  { OP_HUD_SET_TEXT, "hud-set-text\r\n"
33200  "\tSets the text value of a given HUD gauge. Works for custom and certain retail gauges. Takes 2 arguments...\r\n"
33201  "\t1:\tHUD gauge to be modified\r\n"
33202  "\t2:\tText to be set"
33203  },
33204 
33205  { OP_HUD_SET_TEXT_NUM, "hud-set-text-num\r\n"
33206  "\tSets the text value of a given HUD gauge to a number. Works for custom and certain retail gauges. Takes 2 arguments...\r\n"
33207  "\t1:\tHUD gauge to be modified\r\n"
33208  "\t2:\tNumber to be set"
33209  },
33210 
33211  { OP_HUD_SET_MESSAGE, "hud-set-message\r\n"
33212  "\tSets the text value of a given HUD gauge to a message from the mission's message list. Works for custom and certain retail gauges. Takes 2 arguments...\r\n"
33213  "\t1:\tHUD gauge to be modified\r\n"
33214  "\t2:\tMessage"
33215  },
33216 
33217  //WMC
33218  { OP_HUD_SET_COORDS, "hud-set-coord\r\n"
33219  "\tSets the coordinates of a given HUD gauge. Works for custom and retail gauges. Takes 3 arguments...\r\n"
33220  "\t1:\tHUD gauge to be modified\r\n"
33221  "\t2:\tCoordinate X component\r\n"
33222  "\t2:\tCoordinate Y component"
33223  },
33224 
33225  //WMC
33226  { OP_HUD_SET_FRAME, "hud-set-frame\r\n"
33227  "\tSets the frame of a given HUD gauge's associated image. Works for custom and certain retail gauges. Takes 2 arguments...\r\n"
33228  "\t1:\tHUD gauge to be modified\r\n"
33229  "\t2:\tFrame number to be changed to"
33230  },
33231 
33232  //WMC
33233  { OP_HUD_SET_COLOR, "hud-set-color\r\n"
33234  "\tSets the color of a given HUD gauge. Works only for custom gauges Takes 4 arguments...\r\n"
33235  "\t1:\tHUD gauge to be modified\r\n"
33236  "\t2:\tRed component (0-255)\r\n"
33237  "\t3:\tGreen component (0-255)\r\n"
33238  "\t4:\tBlue component (0-255)"
33239  },
33240 
33241  //WMC
33242  { OP_CURRENT_SPEED, "current-speed\r\n"
33243  "\tReturns the speed of the given object. Takes 1 argument...\r\n"
33244  "\t1:\tName of the object"
33245  },
33246 
33247  // Karajora
33248  { OP_PRIMARY_FIRED_SINCE, "primary-fired-since\r\n"
33249  "\tReturns true if the primary weapon bank specified has been fired within the supplied window of time. Takes 3 arguments...\r\n\r\n"
33250  "\t1:\tShip name\r\n"
33251  "\t2:\tWeapon bank number (This is a zero-based index. The first bank is numbered 0.)\r\n"
33252  "\t3:\tTime period to check if the weapon was fired (in millieconds)\r\n"
33253  },
33254 
33255  // Karajora
33256  { OP_SECONDARY_FIRED_SINCE, "secondary-fired-since\r\n"
33257  "\tReturns true if the secondary weapon bank specified has been fired within the supplied window of time. Takes 3 arguments...\r\n\r\n"
33258  "\t1:\tShip name\r\n"
33259  "\t2:\tWeapon bank number (This is a zero-based index. The first bank is numbered 0.)\r\n"
33260  "\t3:\tTime period to check if the weapon was fired (in millieconds)\r\n"
33261  },
33262 
33263  // Karajora
33264  { OP_HAS_PRIMARY_WEAPON, "has-primary-weapon\r\n"
33265  "\tReturns true if the primary weapon bank specified has any of the weapons listed. Takes 3 or more arguments...\r\n\r\n"
33266  "\t1:\tShip name\r\n"
33267  "\t2:\tWeapon bank number (This is a zero-based index. The first bank is numbered 0.)\r\n"
33268  "\tRest:\tWeapon name\r\n"
33269  },
33270 
33271  // Karajora
33272  { OP_HAS_SECONDARY_WEAPON, "has-secondary-weapon\r\n"
33273  "\tReturns true if the secondary weapon bank specified has any of the weapons listed. Takes 3 or more arguments...\r\n\r\n"
33274  "\t1:\tShip name\r\n"
33275  "\t2:\tWeapon bank number (This is a zero-based index. The first bank is numbered 0.)\r\n"
33276  "\tRest:\tWeapon name\r\n"
33277  },
33278 
33279  // Karajora
33280  { OP_DIRECTIVE_VALUE, "directive-value\r\n"
33281  "\tCauses a value to appear in the directive count\r\n"
33282  "\tAlways returns true. Takes 1 or more arguments...\r\n\r\n"
33283  "\t1:\tValue\r\n"
33284  "\t2:\t(Optional) Ignore the directive count set by any earlier SEXPs in the event. If set to false it will add instead\r\n"
33285  },
33286 
33287  //phreak
33288  { OP_SCRAMBLE_MESSAGES, "scramble-messages\r\n"
33289  "\tCauses messages to be sent as if the player has sustained communications subsystem or EMP damage. This effect can be reversed using unscramble-messages. Takes zero or more arguments.\r\n"
33290  "\tAll (Optional):\tName of the ship for which to scramble messages. If no ships are specified, message scrambling will be turned on for all messages the player receives.\r\n"
33291  },
33292 
33293  //phreak
33294  { OP_UNSCRAMBLE_MESSAGES, "unscramble-messages\r\n"
33295  "\tUndoes the effects of scramble-messages, causing messages to be sent clearly. Takes zero or more arguments.\r\n"
33296  "\tAll (Optional):\tName of the ship for which to scramble messages. If no ships are specified, message scrambling will be turned on for all messages the player receives.\r\n"
33297  },
33298 
33299  { OP_CUTSCENES_SET_CUTSCENE_BARS, "set-cutscene-bars\r\n"
33300  "\tShows bars at the top and bottom of screen. "
33301  "Takes 0 or 1 arguments...\r\n"
33302  "\t1:\tMilliseconds for bars to slide in\r\n"
33303  },
33304 
33305  { OP_CUTSCENES_UNSET_CUTSCENE_BARS, "unset-cutscene-bars\r\n"
33306  "\tRemoves cutscene bars. "
33307  "Takes 0 or 1 arguments...\r\n"
33308  "\t1:\tMilliseconds for bars to slide out\r\n"
33309  },
33310 
33311  { OP_CUTSCENES_FADE_IN, "fade-in\r\n"
33312  "\tFades in. "
33313  "Takes 0 to 4 arguments...\r\n"
33314  "\t1:\tTime to fade in (in milliseconds)\r\n"
33315  "\t2:\tColor to fade to (optional). If arguments 3 and 4 are specified, this is the R component of an RGB color. Otherwise it is 1 for white, 2 for red, and any other number for black.\r\n"
33316  "\t3:\tG component of an RGB color (optional)\r\n"
33317  "\t4:\tB component of an RGB color (optional)\r\n"
33318  },
33319 
33320  { OP_CUTSCENES_FADE_OUT, "fade-out\r\n"
33321  "\tFades out. "
33322  "Takes 0 to 4 arguments...\r\n"
33323  "\t1:\tTime to fade in (in milliseconds)\r\n"
33324  "\t2:\tColor to fade to (optional). If arguments 3 and 4 are specified, this is the R component of an RGB color. Otherwise it is 1 for white, 2 for red, and any other number for black.\r\n"
33325  "\t3:\tG component of an RGB color (optional)\r\n"
33326  "\t4:\tB component of an RGB color (optional)\r\n"
33327  },
33328 
33329  { OP_CUTSCENES_SET_CAMERA, "set-camera\r\n"
33330  "\tSets SEXP camera, or another specified cutscene camera. "
33331  "Takes 0 to 1 arguments...\r\n"
33332  "\t(optional)\r\n"
33333  "\t1:\tCamera name (created if nonexistent)\r\n"
33334  },
33335 
33336  { OP_CUTSCENES_SET_CAMERA_FACING, "set-camera-facing\r\n"
33337  "\tMakes the camera face the given point. "
33338  "Takes 3 to 6 arguments...\r\n"
33339  "\t1:\tX position to face\r\n"
33340  "\t2:\tY position to face\r\n"
33341  "\t3:\tZ position to face\r\n"
33342  "\t(optional)\r\n"
33343  "\t4:\tTotal turn time (milliseconds)\r\n"
33344  "\t5:\tTime to spend accelerating/decelerating (milliseconds)\r\n"
33345  "\t6:\tTime to spend decelerating (milliseconds)\r\n"
33346  },
33347 
33348  { OP_CUTSCENES_SET_CAMERA_FACING_OBJECT, "set-camera-facing-object\r\n"
33349  "\tMakes the camera face the given object. "
33350  "Takes 1 to 4 arguments...\r\n"
33351  "\t1:\tObject to face\r\n"
33352  "\t(optional)\r\n"
33353  "\t2:\tTotal turn time (milliseconds)\r\n"
33354  "\t3:\tTime to spend accelerating/decelerating (milliseconds)\r\n"
33355  "\t4:\tTime to spend decelerating (milliseconds)\r\n"
33356  },
33357 
33358  { OP_CUTSCENES_SET_CAMERA_FOV, "set-camera-fov\r\n"
33359  "\tSets the camera field of view. "
33360  "Takes 1 to 4 arguments...\r\n"
33361  "\t1:\tNew FOV (degrees)\r\n"
33362  "\t(optional)\r\n"
33363  "\t2:\tTotal zoom time (milliseconds)\r\n"
33364  "\t3:\tTime to spend accelerating/decelerating (milliseconds)\r\n"
33365  "\t4:\tTime to spend decelerating (milliseconds)\r\n"
33366  },
33367 
33368  { OP_CUTSCENES_SET_CAMERA_HOST, "set-camera-host\r\n"
33369  "\tSets the object and subystem camera should view from. Camera position is offset from the host. "
33370  "If the selected subsystem or one of its children has an eyepoint bound to it it will be used for the camera position and orientation."
33371  "If the selected subsystem is a turret and has no eyepoint the camera will be at the first firing point and look along the firing direction."
33372  "If a valid camera target is set the direction to the target will override any other orientation."
33373  "Takes 1 to 2 arguments...\r\n"
33374  "\t1:\tShip to mount camera on\r\n"
33375  "\t(optional)\r\n"
33376  "\t2:\tSubystem to mount camera on\r\n"
33377  },
33378 
33379  { OP_CUTSCENES_SET_CAMERA_POSITION, "set-camera-position\r\n"
33380  "\tSets the camera position to a spot in mission space. "
33381  "Takes 3 to 6 arguments...\r\n"
33382  "\t1:\tX position\r\n"
33383  "\t2:\tY position\r\n"
33384  "\t3:\tZ position\r\n"
33385  "\t(optional)\r\n"
33386  "\t4:\tTotal turn time (milliseconds)\r\n"
33387  "\t5:\tTime to spend accelerating/decelerating (milliseconds)\r\n"
33388  "\t6:\tTime to spend decelerating (milliseconds)\r\n"
33389  },
33390 
33391  { OP_CUTSCENES_SET_CAMERA_ROTATION, "set-camera-rotation\r\n"
33392  "\tSets the camera rotation. "
33393  "Takes 3 to 6 arguments...\r\n"
33394  "\t1:\tPitch (degrees)\r\n"
33395  "\t2:\tBank (degrees)\r\n"
33396  "\t3:\tHeading (degrees)\r\n"
33397  "\t(optional)\r\n"
33398  "\t4:\tTotal turn time (milliseconds)\r\n"
33399  "\t5:\tTime to spend accelerating/decelerating (milliseconds)\r\n"
33400  "\t6:\tTime to spend decelerating (milliseconds)\r\n"
33401  },
33402 
33403  { OP_CUTSCENES_SET_CAMERA_TARGET, "set-camera-target\r\n"
33404  "\tSets the object and subystem camera should track. Camera orientation is offset from the target. "
33405  "Takes 1 to 2 arguments...\r\n"
33406  "\t1:\tShip to track\r\n"
33407  "\t(optional)\r\n"
33408  "\t2:\tSubystem to track\r\n"
33409  },
33410 
33411  { OP_CUTSCENES_SET_FOV, "set-fov\r\n"
33412  "\tSets the field of view - overrides all camera settings. "
33413  "Takes 1 argument...\r\n"
33414  "\t1:\tNew FOV (degrees)\r\n"
33415  },
33416 
33417  // Echelon9
33418  { OP_CUTSCENES_GET_FOV, "get-fov\r\n"
33419  "\tReturns the current field of view (in degrees) from the Main camera.\r\n\r\n"
33420  "Returns a numeric value. Takes no arguments."
33421  },
33422 
33423  { OP_CUTSCENES_RESET_FOV, "reset-fov\r\n"
33424  "\tResets the field of view. "
33425  },
33426 
33427  { OP_CUTSCENES_RESET_CAMERA, "reset-camera\r\n"
33428  "\tReleases cutscene camera control. "
33429  "Takes 1 optional argument...\r\n"
33430  "\t(optional)\r\n"
33431  "\t1:\tReset camera data (Position, facing, FOV...) (default: false)"
33432  },
33433 
33434  { OP_CUTSCENES_SHOW_SUBTITLE, "show-subtitle (deprecated)\r\n"
33435  "\tDisplays a subtitle, either an image or a string of text. As this operator tries to combine two functions into one and does not adjust coordinates for screen formats, it has been deprecated.\r\n"
33436  "Takes 4 to 13 arguments...\r\n"
33437  "\t1:\tX position (negative value to be from right of screen)\r\n"
33438  "\t2:\tY position (negative value to be from bottom of screen)\r\n"
33439  "\t3:\tText to display\r\n"
33440  "\t4:\tTime to be displayed, not including fadein/out\r\n"
33441  "\t5:\tImage name (optional)\r\n"
33442  "\t6:\tFade in time (optional)\r\n"
33443  "\t7:\tCenter horizontally? (optional)\r\n"
33444  "\t8:\tCenter vertically? (optional)\r\n"
33445  "\t9:\tWidth (optional)\r\n"
33446  "\t10:\tText red component (0-255) (optional)\r\n"
33447  "\t11:\tText green component (0-255) (optional)\r\n"
33448  "\t12:\tText blue component (0-255) (optional)\r\n"
33449  "\t13:\tDrawn after shading? (optional)"
33450  },
33451 
33452  { OP_CUTSCENES_SHOW_SUBTITLE_TEXT, "show-subtitle-text\r\n"
33453  "\tDisplays a subtitle in the form of text. Note that because of the constraints of the subtitle system, textual subtitles are currently limited to 255 characters or fewer.\r\n"
33454  "Takes 6 to 13 arguments...\r\n"
33455  "\t1:\tText to display, or the name of a message containing text\r\n"
33456  "\t2:\tX position, from 0 to 100% (positive measures from the left; negative measures from the right)\r\n"
33457  "\t3:\tY position, from 0 to 100% (positive measures from the top; negative measures from the bottom)\r\n"
33458  "\t4:\tCenter horizontally? (if true, overrides argument #2)\r\n"
33459  "\t5:\tCenter vertically? (if true, overrides argument #3)\r\n"
33460  "\t6:\tTime (in milliseconds) to be displayed, not including fade-in/fade-out\r\n"
33461  "\t7:\tFade time (in milliseconds) to be used for both fade-in and fade-out (optional)\r\n"
33462  "\t8:\tParagraph width, from 1 to 100% (optional; 0 uses default 200 pixels)\r\n"
33463  "\t9:\tText red component (0-255) (optional)\r\n"
33464  "\t10:\tText green component (0-255) (optional)\r\n"
33465  "\t11:\tText blue component (0-255) (optional)\r\n"
33466  "\t12:\tText font (optional)\r\n"
33467  "\t13:\tDrawn after shading? (optional)"
33468  },
33469 
33470  { OP_CUTSCENES_SHOW_SUBTITLE_IMAGE, "show-subtitle-image\r\n"
33471  "\tDisplays a subtitle in the form of an image.\r\n"
33472  "Takes 8 to 10 arguments...\r\n"
33473  "\t1:\tImage to display\r\n"
33474  "\t2:\tX position, from 0 to 100% (positive measures from the left; negative measures from the right)\r\n"
33475  "\t3:\tY position, from 0 to 100% (positive measures from the top; negative measures from the bottom)\r\n"
33476  "\t4:\tCenter horizontally? (if true, overrides argument #2)\r\n"
33477  "\t5:\tCenter vertically? (if true, overrides argument #3)\r\n"
33478  "\t6:\tImage width, from 1 to 100% (0 uses original width)\r\n"
33479  "\t7:\tImage height, from 1 to 100% (0 uses original height)\r\n"
33480  "\t8:\tTime (in milliseconds) to be displayed, not including fade-in/fade-out\r\n"
33481  "\t9:\tFade time (in milliseconds) to be used for both fade-in and fade-out (optional)\r\n"
33482  "\t10:\tDrawn after shading? (optional)"
33483  },
33484 
33485  { OP_CUTSCENES_SET_TIME_COMPRESSION, "set-time-compression\r\n"
33486  "\tSets the time compression and prevents it from being changed by the user. "
33487  "Takes 1 to 3 arguments...\r\n"
33488  "\t1:\tNew time compression (% of 1x)\r\n"
33489  "\t2:\tTime in ms for change to take\r\n"
33490  "\t3:\tTime compression to start from\r\n"
33491  },
33492 
33493  { OP_CUTSCENES_RESET_TIME_COMPRESSION, "reset-time-compression\r\n"
33494  "\tResets the time compression - that is to say, time compression is set back to 1x, "
33495  "and the time compression controls are unlocked. Always call this when done with set-time-compression. "
33496  },
33497 
33498  { OP_CUTSCENES_FORCE_PERSPECTIVE, "lock-perspective\r\n"
33499  "\tPrevents or allows the player from changing the view mode. "
33500  "Takes 1 or 2 arguments...\r\n"
33501  "\t1:\tTrue to lock the view mode, false to unlock it\r\n"
33502  "\t2:\tWhat view mode to lock; 0 for first-person, 1 for chase, 2 for external, 3 for top-down"
33503  },
33504 
33505  { OP_SET_CAMERA_SHUDDER, "set-camera-shudder\r\n"
33506  "\tCauses the camera to shudder. Currently this will only work if the camera is showing the player's viewpoint (i.e. the HUD).\r\n\r\n"
33507  "Takes 2 arguments...\r\n"
33508  "\t1: Time (in milliseconds)\r\n"
33509  "\t2: Intensity. For comparison, the Maxim has an intensity of 1440."
33510  },
33511 
33512  { OP_JUMP_NODE_SET_JUMPNODE_NAME, "set-jumpnode-name\r\n"
33513  "\tSets the name of a jump node. Takes 2 arguments...\r\n"
33514  "\t1: Name of jump node to change name for\r\n"
33515  "\t2: New name for jump node\r\n\r\n"
33516  "\tNote: SEXPs referencing the old name will not work after the name change.\r\n"
33517  },
33518 
33519  { OP_JUMP_NODE_SET_JUMPNODE_COLOR, "set-jumpnode-color\r\n"
33520  "\tSets the color of a jump node. "
33521  "Takes 5 arguments...\r\n"
33522  "\t1:\tJump node to change color for\r\n"
33523  "\t2:\tRed value\r\n"
33524  "\t3:\tGreen value\r\n"
33525  "\t4:\tBlue value\r\n"
33526  "\t5:\tAlpha value\r\n"
33527  },
33528 
33529  { OP_JUMP_NODE_SET_JUMPNODE_MODEL, "set-jumpnode-model\r\n"
33530  "\tSets the model of a jump node. "
33531  "Takes 3 arguments...\r\n"
33532  "\t1:\tJump node to change model for\r\n"
33533  "\t2:\tModel filename\r\n"
33534  "\t3:\tShow as normal model. When this is true, the jumpnode will be rendered like a normal model.\r\n"
33535  },
33536 
33537  { OP_JUMP_NODE_SHOW_JUMPNODE, "show-jumpnode\r\n"
33538  "\tSets a jump node to display on the screen.\r\n"
33539  "\tAny:\tJump node to show\r\n"
33540  },
33541 
33542  { OP_JUMP_NODE_HIDE_JUMPNODE, "hide-jumpnode\r\n"
33543  "\tSets a jump node to not display on the screen.\r\n"
33544  "\tAny:\tJump node to hide\r\n"
33545  },
33546 
33547  // taylor, with modifications by niffiwan and MageKing17
33548  { OP_SET_SKYBOX_MODEL, "set-skybox-model\r\n"
33549  "\tSets the current skybox model. Takes 1-7 arguments\r\n"
33550  "\t1:\tModel filename (with .pof extension) to switch to\r\n"
33551  "\t2:\tRestart animated textures, if they exist (optional, defaults to true)\r\n"
33552  "\t3-8:\tSet or unset the following skyboxes flags (optional)\r\n"
33553  "\t\t\tadd-lighting, no-transparency, add-zbuffer\r\n"
33554  "\t\t\tadd-culling, no-glowmaps, force-clamp\r\n\r\n"
33555  "Note: If the model filename is set to \"default\" with no extension then it will switch to the mission supplied default skybox."
33556  },
33557 
33558  // Goober5000
33559  { OP_SET_SKYBOX_ORIENT, "set-skybox-orientation\r\n"
33560  "\tSets the current skybox orientation. Takes 3 arguments...\r\n"
33561  "\t1:\tPitch\r\n"
33562  "\t2:\tBank\r\n"
33563  "\t3:\tHeading\r\n"
33564  },
33565 
33566  { OP_ADD_BACKGROUND_BITMAP, "add-background-bitmap\r\n"
33567  "\tAdds a background bitmap to the sky. Returns an integer that is stored in a variable so it can be deleted using remove-background-bitmap\r\n\r\n"
33568  "Takes 8 to 9 arguments...\r\n"
33569  "\t1:\tBackground bitmap name\r\n"
33570  "\t2:\tPitch\r\n"
33571  "\t3:\tBank\r\n"
33572  "\t4:\tHeading\r\n"
33573  "\t5:\tX scale (expressed as a percentage of the original size of the bitmap)\r\n"
33574  "\t6:\tY scale (expressed as a percentage of the original size of the bitmap)\r\n"
33575  "\t7:\tX divisions.\r\n"
33576  "\t8:\tY divisions.\r\n"
33577  "\t9:\tVariable in which to store result (optional)\r\n"
33578  },
33579 
33580  { OP_REMOVE_BACKGROUND_BITMAP, "remove-background-bitmap\r\n"
33581  "\tRemoves the nth background bitmap from the mission\r\n\r\n"
33582  "Takes 1 argument...\r\n"
33583  "\t1:\tZero based bitmap index from the \'Bitmap\' box in the background editor\r\n"
33584  "\t\t\tYou can also use the result of a previous call to add-background-bitmap to remove that added bitmap\r\n"
33585  },
33586 
33587  { OP_ADD_SUN_BITMAP, "add-sun-bitmap\r\n"
33588  "\tAdds a sun bitmap to the sky. Returns an integer that is stored in a variable so it can be deleted using remove-sun-bitmap\r\n\r\n"
33589  "Takes 5 to 6 arguments...\r\n"
33590  "\t1:\tSun bitmap name\r\n"
33591  "\t2:\tPitch\r\n"
33592  "\t3:\tBank\r\n"
33593  "\t4:\tHeading\r\n"
33594  "\t5:\tScale (expressed as a percentage of the original size of the bitmap)\r\n"
33595  "\t6:\tVariable in which to store result (optional)\r\n"
33596  },
33597 
33598  { OP_REMOVE_SUN_BITMAP, "remove-sun-bitmap\r\n"
33599  "\tRemoves the nth sun from the mission\r\n\r\n"
33600  "Takes 1 argument...\r\n"
33601  "\t1:\tZero based sun index from the \'Suns\' box in the background editor\r\n"
33602  "\t\t\tYou can also use the result of a previous call to add-sun-bitmap to remove that added sun\r\n"
33603  },
33604 
33605  { OP_NEBULA_CHANGE_STORM, "nebula-change-storm\r\n"
33606  "\tChanges the current nebula storm\r\n\r\n"
33607  "Takes 1 argument...\r\n"
33608  "\t1:\tNebula storm to change to\r\n"
33609  },
33610 
33611  { OP_NEBULA_TOGGLE_POOF, "nebula-toggle-poof\r\n"
33612  "\tToggles the state of a nebula poof\r\n\r\n"
33613  "Takes 2 arguments...\r\n"
33614  "\t1:\tName of nebula poof to toggle\r\n"
33615  "\t2:\tA True boolean expression will toggle this poof on. A false one will do the opposite."
33616  },
33617 
33618  { OP_NEBULA_CHANGE_PATTERN, "nebula-change-pattern\r\n"
33619  "\tChanges the current nebula background pattern (as defined in nebula.tbl)\r\n\r\n"
33620  "Takes 1 argument...\r\n"
33621  "\t1:\tNebula background pattern to change to\r\n"
33622  },
33623 
33624  {OP_SCRIPT_EVAL_NUM, "script-eval-num\r\n"
33625  "\tEvaluates script to return a number"
33626  "Takes 1 argument...\r\n"
33627  "\t1:\tScript\r\n"
33628  },
33629 
33630  { OP_DISABLE_ETS, "disable-ets\r\n"
33631  "\tSwitches a ships' ETS system off\r\n\r\n"
33632  "Takes at least 1 argument...\r\n"
33633  "\tAll:\tList of ships this sexp applies to\r\n"
33634  },
33635 
33636  { OP_ENABLE_ETS, "enable-ets\r\n"
33637  "\tSwitches a ships' ETS system on\r\n\r\n"
33638  "Takes at least 1 argument...\r\n"
33639  "\tAll:\tList of ships this sexp applies to\r\n"
33640  },
33641 
33642  {OP_SCRIPT_EVAL_STRING, "script-eval-string\r\n"
33643  "\tEvaluates script to return a string\r\n\r\n"
33644  "Takes a multiple of 2 arguments...\r\n"
33645  "\t1:\tScript (Without a leading 'return')\r\n"
33646  "\t2:\tDestination variable\r\n"
33647  },
33648 
33649  {OP_SCRIPT_EVAL, "script-eval\r\n"
33650  "\tEvaluates the given script\r\n"
33651  "Takes at least 1 argument...\r\n"
33652  "\t1:\tScript to evaluate\r\n"
33653  },
33654 
33655  {OP_SCRIPT_EVAL_BLOCK, "script-eval-block\r\n"
33656  "\tEvaluates the concatenation of all arguments as a script\r\n"
33657  "Takes at least 1 argument...\r\n"
33658  "\tAll:\tScript to evaluate\r\n"
33659  },
33660 
33661  {OP_SCRIPT_EVAL_MULTI, "multi-eval\r\n"
33662  "\tEvaluates script\r\n\r\n"
33663  "Takes at least 2 arguments...\r\n"
33664  "\t1:\tScript to evaluate\r\n"
33665  "\t2:\tTrue/False - Should the script evaluate on the server?\r\n"
33666  "\t(rest):\tList of players who should evaluate this script. If no player is given, all clients will execute the script\r\n"
33667  },
33668 
33669  {OP_FORCE_GLIDE, "force-glide\r\n"
33670  "\tForces a given ship into glide mode, provided it is capable of gliding. Note that the player will not be able to leave glide mode on his own,, and that a ship in glide mode cannot warp out or enter autopilot."
33671  "Takes 2 Arguments...\r\n"
33672  "\t1:\tShip to force\r\n"
33673  "\t2:\tTrue to activate glide, False to deactivate\r\n"
33674  },
33675 
33676  {OP_HUD_SET_DIRECTIVE, "hud-set-directive\r\n"
33677  "\tSets the text of a given custom hud gauge to the provided text."
33678  "Takes 2 Arguments...\r\n"
33679  "\t1:\tHUD Gauge name\r\n"
33680  "\t2:\tText that will be displayed. This text will be treated as directive text, meaning that references to mapped keys will be replaced with the user's preferences.\r\n"
33681  },
33682 
33683  {OP_HUD_GAUGE_SET_ACTIVE, "hud-gauge-set-active (deprecated)\r\n"
33684  "\tActivates or deactivates a given custom gauge."
33685  "Takes 2 Arguments...\r\n"
33686  "\t1:\tHUD Gauge name\r\n"
33687  "\t2:\tBoolean, whether or not to display this gauge\r\n"
33688  },
33689 
33690  {OP_HUD_CLEAR_MESSAGES, "hud-clear-messages\r\n"
33691  "\tClears active messages displayed on the HUD."
33692  "Takes no arguments\r\n"
33693  },
33694 
33695  {OP_HUD_ACTIVATE_GAUGE_TYPE, "hud-activate-gauge-type (deprecated)\r\n"
33696  "\tActivates or deactivates all hud gauges of a given type."
33697  "Takes 2 Arguments...\r\n"
33698  "\t1:\tGauge Type\r\n"
33699  "\t2:\tBoolean, whether or not to display this gauge\r\n"
33700  },
33701 
33702  {OP_HUD_SET_CUSTOM_GAUGE_ACTIVE, "hud-set-custom-gauge-active\r\n"
33703  "\tActivates or deactivates a custom hud gauge defined in hud_gauges.tbl."
33704  "Takes 2 Arguments...\r\n"
33705  "\t1:\tBoolean, whether or not to display this gauge\r\n"
33706  "\tRest:\tHUD Gauge name\r\n"
33707  },
33708 
33709  {OP_HUD_SET_RETAIL_GAUGE_ACTIVE, "hud-set-custom-gauge-active\r\n"
33710  "\tActivates or deactivates a retail hud gauge grouping."
33711  "Takes 2 Arguments...\r\n"
33712  "\t1:\tBoolean, whether or not to display this gauge\r\n"
33713  "\tRest:\tHUD Gauge Group name\r\n"
33714  },
33715 
33716  {OP_ADD_TO_COLGROUP, "add-to-collision-group\r\n"
33717  "\tAdds a ship to the specified collision group(s). Note that there are 32 collision groups,\r"
33718  "\tand that an object may be in several collision groups at the same time\r\n"
33719  "Takes 2 or more Arguments...\r\n"
33720  "\t1:\tObject to add\r\n"
33721  "\t2+:\tGroup IDs. Valid IDs are 0 through 31 inclusive.\r\n"
33722  },
33723 
33724  {OP_REMOVE_FROM_COLGROUP, "remove-from-collision-group\r\n"
33725  "\tRemoves a ship from the specified collision group(s). Note that there are 32 collision groups,\n"
33726  "\tand that an object may be in several collision groups at the same time\r\n"
33727  "Takes 2 or more Arguments...\r\n"
33728  "\t1:\tObject to add\r\n"
33729  "\t2+:\tGroup IDs. Valid IDs are 0 through 31 inclusive.\r\n"
33730  },
33731 
33732  {OP_GET_COLGROUP_ID, "get-collision-group\r\n"
33733  "\tReturns an objects' collision group ID. Note that this ID is a bitfield.\r\n"
33734  "Takes 1 Argument...\r\n"
33735  "\t1:\tObject name\r\n"
33736  },
33737 
33738  //Valathil
33739  {OP_SHIP_EFFECT, "ship-effect\r\n"
33740  "\tPlays an animated shader effect on the ship(s) or wing(s).\r\n"
33741  "Takes 3 or more arguments...\r\n"
33742  "\t1:\tEffect name (as defined in post_processing.tbl)\r\n"
33743  "\t2:\tHow long the effect should take in milliseconds\r\n"
33744  "\tRest:\tShip or wing name\r\n"
33745  },
33746 
33747  {OP_CLEAR_SUBTITLES, "clear-subtitles\r\n"
33748  "\tClears the subtitle queue completely.\r\n"
33749  },
33750 
33751  {OP_SET_THRUSTERS, "set-thrusters-status\r\n"
33752  "\tManipulates the thrusters on a ship.\r\n"
33753  "Takes 2 or more arguments...\r\n"
33754  "\t1:\tBoolean, true sets thrusters to visible, false deactivates them.\r\n"
33755  "\t2:\tRest: List of ships this sexp will work on.\r\n"
33756  },
33757 
33758  {OP_SET_PLAYER_THROTTLE_SPEED, "set-player-throttle-speed\r\n"
33759  "\tSets a player's throttle to a percentage of their maximum speed.\r\n"
33760  "\tThis SEXP has no effect if used on an AI ship, however it will still work on an AI-controlled player ship.\r\n"
33761  "Takes 2 arguments...\r\n"
33762  "\t1:\tThe player ship to set the throttle of.\r\n"
33763  "\t2:\tThe percentage of the player's maximum speed to set their throttle to.\r\n"
33764  "\t\tThis is capped to either 0 or 100 if outside the valid range."
33765  },
33766 
33767  {OP_CHANGE_TEAM_COLOR, "change-team-color\r\n"
33768  "\tChanges the team color setting for one or several ships.\r\n"
33769  "\tThis sexp has no effect on ships that don't have team colors enabled for them.\r\n"
33770  "\tTakes 3 or more arguments...\r\n"
33771  "\t1:\tThe new team color name. Name must be defined in colors.tbl.\r\n"
33772  "\t2:\tCrossfade time in milliseconds. During this time, colors will be mixed.\r\n"
33773  "\t3:\tRest: List of ships this sexp will operate on."
33774  },
33775 
33776  {OP_CALL_SSM_STRIKE, "call-ssm-strike\r\n"
33777  "\tCalls a subspace missile strike on the specified ship.\r\n"
33778  "\tRequires a ssm table (ssm.tbl).\r\n"
33779  "Takes 3 arguments...\r\n"
33780  "\t1:\tStrike name.\r\n"
33781  "\t2:\tCalling team.\r\n"
33782  "\tRest:\tList of ships the strike will be called on."
33783  },
33784 
33785  {OP_PLAYER_IS_CHEATING_BASTARD, "player-is-cheating\r\n"
33786  "\tReturns true if the player is or has been cheating in this mission.\r\n"
33787  },
33788 
33789  { OP_SET_MOTION_DEBRIS, "set-motion-debris-override\r\n"
33790  "\tControls whether or not motion debris should be active.\r\n"
33791  "\tThis overrides any choice made by the user through the -nomotiondebris commandline flag."
33792  "Takes 1 argument...\r\n"
33793  "\t1:\tBoolean: True will disable motion debris, False reenable it.\r\n"
33794  }
33795 };
33796 
33797 
33798 
33800 {
33801  { "Objectives", OP_CATEGORY_OBJECTIVE },
33802  { "Time", OP_CATEGORY_TIME },
33803  { "Logical", OP_CATEGORY_LOGICAL },
33804  { "Arithmetic", OP_CATEGORY_ARITHMETIC },
33805  { "Status", OP_CATEGORY_STATUS },
33806  { "Change", OP_CATEGORY_CHANGE },
33807  { "Conditionals", OP_CATEGORY_CONDITIONAL },
33808  { "Ai goals", OP_CATEGORY_AI },
33809  { "Event/Goals", OP_CATEGORY_GOAL_EVENT },
33810  { "Training", OP_CATEGORY_TRAINING },
33811 };
33812 
33813 // Goober5000's subcategorization of the Change menu (and possibly other menus in the future,
33814 // if people so choose - see sexp.h)
33816 {
33817  { "Messages and Personas", CHANGE_SUBCATEGORY_MESSAGING },
33818  { "AI Control", CHANGE_SUBCATEGORY_AI_CONTROL },
33819  { "Ship Status", CHANGE_SUBCATEGORY_SHIP_STATUS },
33820  { "Weapons, Shields, and Engines", CHANGE_SUBCATEGORY_SHIELDS_ENGINES_AND_WEAPONS },
33821  { "Subsystems and Health", CHANGE_SUBCATEGORY_SUBSYSTEMS },
33822  { "Cargo", CHANGE_SUBCATEGORY_CARGO },
33823  { "Armor and Damage Types", CHANGE_SUBCATEGORY_ARMOR_AND_DAMAGE_TYPES },
33824  { "Beams and Turrets", CHANGE_SUBCATEGORY_BEAMS_AND_TURRETS },
33825  { "Models and Textures", CHANGE_SUBCATEGORY_MODELS_AND_TEXTURES },
33826  { "Coordinate Manipulation", CHANGE_SUBCATEGORY_COORDINATE_MANIPULATION },
33827  { "Mission and Campaign", CHANGE_SUBCATEGORY_MISSION_AND_CAMPAIGN },
33828  { "Music and Sound", CHANGE_SUBCATEGORY_MUSIC_AND_SOUND },
33829  { "HUD", CHANGE_SUBCATEGORY_HUD },
33830  { "Nav Points", CHANGE_SUBCATEGORY_NAV },
33831  { "Cutscenes", CHANGE_SUBCATEGORY_CUTSCENES },
33832  { "Backgrounds and Nebulae", CHANGE_SUBCATEGORY_BACKGROUND_AND_NEBULA },
33833  { "Jump Nodes", CHANGE_SUBCATEGORY_JUMP_NODES },
33834  { "Special Effects", CHANGE_SUBCATEGORY_SPECIAL_EFFECTS },
33835  { "Variables", CHANGE_SUBCATEGORY_VARIABLES },
33836  { "Other", CHANGE_SUBCATEGORY_OTHER },
33837  { "Mission", STATUS_SUBCATEGORY_MISSION },
33838  { "Player", STATUS_SUBCATEGORY_PLAYER },
33839  { "Multiplayer", STATUS_SUBCATEGORY_MULTIPLAYER },
33840  { "Ship Status", STATUS_SUBCATEGORY_SHIP_STATUS },
33841  { "Weapons, Shields, and Engines", STATUS_SUBCATEGORY_SHIELDS_ENGINES_AND_WEAPONS },
33842  { "Cargo", STATUS_SUBCATEGORY_CARGO },
33843  { "Damage", STATUS_SUBCATEGORY_DAMAGE },
33844  { "Distance and Coordinates", STATUS_SUBCATEGORY_DISTANCE_AND_COORDINATES },
33845  { "Variables", STATUS_SUBCATEGORY_VARIABLES },
33846  { "Other", STATUS_SUBCATEGORY_OTHER },
33847 
33848 
33849 };
33850 int Num_sexp_help = sizeof(Sexp_help) / sizeof(sexp_help_struct);
33851 int Num_op_menus = sizeof(op_menu) / sizeof(op_menu_struct);
33852 int Num_submenus = sizeof(op_submenu) / sizeof(op_menu_struct);
33853 
33857 static void output_sexp_html(int sexp_idx, FILE *fp)
33858 {
33859  if(sexp_idx < 0 || sexp_idx > Num_operators)
33860  return;
33861 
33862  bool printed=false;
33863 
33864  for(int i = 0; i < Num_sexp_help; i++)
33865  {
33866  if(Sexp_help[i].id == Operators[sexp_idx].value)
33867  {
33868  char* new_buf = new char[2*strlen(Sexp_help[i].help)];
33869  char* dest_ptr = new_buf;
33870  char* curr_ptr = Sexp_help[i].help;
33871  char* end_ptr = curr_ptr + strlen(Sexp_help[i].help);
33872  while(curr_ptr < end_ptr)
33873  {
33874  if(*curr_ptr == '\n')
33875  {
33876  strcpy(dest_ptr, "\n<br>");
33877  dest_ptr+=5;
33878  }
33879  else
33880  {
33881  *dest_ptr++ = *curr_ptr;
33882  }
33883  curr_ptr++;
33884  }
33885  *dest_ptr = '\0';
33886 
33887  fprintf(fp, "<dt><b>%s</b></dt>\n<dd>%s</dd>\n", Operators[sexp_idx].text, new_buf);
33888  delete[] new_buf;
33889 
33890  printed = true;
33891  }
33892  }
33893 
33894  if(!printed)
33895  fprintf(fp, "<dt><b>%s</b></dt>\n<dd>Min arguments: %d, Max arguments: %d</dd>\n", Operators[sexp_idx].text, Operators[sexp_idx].min, Operators[sexp_idx].max);
33896 }
33897 
33901 bool output_sexps(char *filepath)
33902 {
33903  FILE *fp = fopen(filepath,"w");
33904 
33905  if(fp == NULL)
33906  {
33907  MessageBox(NULL,"Error creating SEXP operator list", "Error", MB_OK);
33908  return false;
33909  }
33910 
33911  //Header
33912  if (FS_VERSION_BUILD == 0 && FS_VERSION_REVIS == 0) //-V547
33913  {
33914  fprintf(fp, "<html>\n<head>\n\t<title>SEXP Output - FSO v%i.%i</title>\n</head>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR);
33915  fputs("<body>", fp);
33916  fprintf(fp,"\t<h1>SEXP Output - FSO v%i.%i</h1>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR);
33917  }
33918  else if (FS_VERSION_REVIS == 0)
33919  {
33920  fprintf(fp, "<html>\n<head>\n\t<title>SEXP Output - FSO v%i.%i.%i</title>\n</head>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD);
33921  fputs("<body>", fp);
33922  fprintf(fp,"\t<h1>SEXP Output - FSO v%i.%i.%i</h1>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD);
33923  }
33924  else
33925  {
33926  fprintf(fp, "<html>\n<head>\n\t<title>SEXP Output - FSO v%i.%i.%i.%i</title>\n</head>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, FS_VERSION_REVIS);
33927  fputs("<body>", fp);
33928  fprintf(fp,"\t<h1>SEXP Output - FSO v%i.%i.%i.%i</h1>\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, FS_VERSION_REVIS);
33929  }
33930 
33931  SCP_vector<int> done_sexp_ids;
33932  int x,y,z;
33933 
33934  //Output an overview
33935  fputs("<dl>", fp);
33936  for(x = 0; x < Num_op_menus; x++)
33937  {
33938  fprintf(fp, "<dt><a href=\"#%d\">%s</a></dt>", (op_menu[x].id & OP_CATEGORY_MASK), op_menu[x].name);
33939  for(y = 0; y < Num_submenus; y++)
33940  {
33941  if(((op_submenu[y].id & OP_CATEGORY_MASK) == op_menu[x].id))
33942  {
33943  fprintf(fp, "<dd><a href=\"#%d\">%s</a></dd>", op_submenu[y].id & (OP_CATEGORY_MASK | SUBCATEGORY_MASK), op_submenu[y].name);
33944  }
33945  }
33946  }
33947  fputs("</dl>", fp);
33948 
33949  //Output the full descriptions
33950  fputs("<dl>", fp);
33951  for(x = 0; x < Num_op_menus; x++)
33952  {
33953  fprintf(fp, "<dt id=\"%d\"><h2>%s</h2></dt>\n", (op_menu[x].id & OP_CATEGORY_MASK), op_menu[x].name);
33954  fputs("<dd>", fp);
33955  fputs("<dl>", fp);
33956  for(y = 0; y < Num_submenus; y++)
33957  {
33958  if(((op_submenu[y].id & OP_CATEGORY_MASK) == op_menu[x].id))
33959  {
33960  fprintf(fp, "<dt id=\"%d\"><h3>%s</h3></dt>\n", op_submenu[y].id & (OP_CATEGORY_MASK | SUBCATEGORY_MASK), op_submenu[y].name);
33961  fputs("<dd>", fp);
33962  fputs("<dl>", fp);
33963  for(z = 0; z < Num_operators; z++)
33964  {
33965  if((get_category(Operators[z].value) == op_menu[x].id)
33966  && (get_subcategory(Operators[z].value) != -1)
33967  && (get_subcategory(Operators[z].value) == op_submenu[y].id))
33968  {
33969  output_sexp_html(z, fp);
33970  }
33971  }
33972  fputs("</dl>", fp);
33973  fputs("</dd>", fp);
33974  }
33975  }
33976  for(z = 0; z < Num_operators; z++)
33977  {
33978  if((get_category(Operators[z].value) == op_menu[x].id)
33979  && (get_subcategory(Operators[z].value) == -1))
33980  {
33981  output_sexp_html(z, fp);
33982  }
33983  }
33984  fputs("</dl>", fp);
33985  fputs("</dd>", fp);
33986  }
33987  for(z = 0; z < Num_operators; z++)
33988  {
33989  if(!get_category(Operators[z].value))
33990  {
33991  output_sexp_html(z, fp);
33992  }
33993  }
33994  fputs("</dl>", fp);
33995  fputs("</body>\n</html>\n", fp);
33996 
33997  fclose(fp);
33998 
33999  return true;
34000 }
#define SEXP_CHECK_OP_EXPECTED
Definition: sexp.h:931
int avg_sexp(int n)
Definition: sexp.cpp:4181
void add_data(char *str)
Definition: sexp.cpp:938
#define SSF_ROTATES
Definition: ship.h:292
#define OP_WAS_PROMOTION_GRANTED
Definition: sexp.h:313
#define OP_LOCK_PRIMARY_WEAPON
Definition: sexp.h:597
void updateCustomGaugeFrame(int frame_offset)
Definition: hud.cpp:409
int sexp_key_pressed(int node)
Definition: sexp.cpp:15080
GLenum GLsizei GLenum format
Definition: Gl.h:1509
void send_change_ai_class_packet(ushort net_signature, char *subsystem, int new_ai_class)
Definition: multimsgs.cpp:7568
SCP_string sexp
Definition: sexp.cpp:25556
#define OP_REMOVE_GOAL
Definition: sexp.h:422
#define OP_PRIMARY_FIRED_SINCE
Definition: sexp.h:362
int sexp_num_within_box(int n)
Definition: sexp.cpp:6603
void send_variable_update_packet(int variable_index, char *value)
Definition: multimsgs.cpp:8179
#define OP_HUD_CLEAR_MESSAGES
Definition: sexp.h:699
SCP_vector< SCP_string > backup_log_buffer
Definition: missiongoals.h:124
int sexp_script_eval(int node, int return_type, bool concat_args=false)
Definition: sexp.cpp:22111
void multi_sexp_send_training_message()
Definition: sexp.cpp:15579
#define OP_CLEAR_SHIP_GOALS
Definition: sexp.h:769
#define SSF_MISSILES_IGNORE_IF_DEAD
Definition: ship.h:291
#define P2_SF2_SCRAMBLE_MESSAGES
Definition: missionparse.h:510
#define OP_CUTSCENES_SET_CAMERA
Definition: sexp.h:610
int Neb2_poof_flags
Definition: neb.cpp:64
int sexp_primary_ammo_pct(int node)
Definition: sexp.cpp:15767
#define OPF_ROTATING_SUBSYSTEM
Definition: sexp.h:78
GLuint64EXT * result
Definition: Glext.h:10775
uint respawn
Definition: multi.h:507
void add_nav_waypoint(char *nav, char *WP_path, int vert, char *oswpt_name)
Definition: sexp.cpp:19262
bool Log_event
#define FALSE
Definition: sexp.cpp:115
#define SHIP_VANISHED
Definition: ship.h:1622
#define OPF_AUDIO_VOLUME_OPTION
Definition: sexp.h:103
#define OF_INVULNERABLE
Definition: object.h:107
#define OP_CHANGE_IFF_COLOR
Definition: sexp.h:622
#define SEXP_CHECK_INVALID_MISSION_MOOD
Definition: sexp.h:991
void sexp_turret_lock_all(int node)
Definition: sexp.cpp:17315
#define OPF_MISSION_MOOD
Definition: sexp.h:110
void multi_sexp_change_team_color()
Definition: sexp.cpp:22576
#define OP_HUD_SET_MESSAGE
Definition: sexp.h:646
void sexp_allow_treason(int n)
Definition: sexp.cpp:10085
#define TRIGGER_TYPE_NONE
Definition: modelanim.h:26
#define OP_NUM_ASSISTS
Definition: sexp.h:353
int sexp_and(int n)
Definition: sexp.cpp:4407
#define OP_NOT
Definition: sexp.h:248
int sexp_special_warp_dist(int n)
Definition: sexp.cpp:5593
int alt_type_index
Definition: missionparse.h:422
char Parse_names[MAX_SHIPS+MAX_WINGS][NAME_LENGTH]
#define MESSAGE_PRIORITY_NORMAL
#define stars_mark_sun_unused(x)
Definition: starfield.h:74
#define FIREBALL_EXPLOSION_LARGE2
Definition: fireballs.h:33
#define P_SF_WARP_BROKEN
Definition: missionparse.h:479
void game_start_subspace_ambient_sound()
Definition: fred.cpp:704
bool model_anim_start_type(ship_subsys *pss, int animation_type, int subtype, int direction, bool instant)
Definition: modelanim.cpp:566
int dup_sexp_chain(int node)
Definition: sexp.cpp:1379
int sexp_order(int n)
Definition: sexp.cpp:15458
#define SHIP_GET_UNSILENCED
Definition: ship.h:1789
#define SEXP_CHECK_INVALID_DOCKER_POINT
Definition: sexp.h:952
int shader_effect_duration
Definition: ship.h:767
int flags
Definition: ship.h:150
#define OP_CUTSCENES_RESET_CAMERA
Definition: sexp.h:556
#define OP_ADD_WING_GOAL
Definition: sexp.h:770
int timestamp(int delta_ms)
Definition: timer.cpp:226
#define CDDDDDR(n)
Definition: sexp.h:830
char Neb2_texture_name[MAX_FILENAME_LEN]
Definition: neb.cpp:75
#define OP_AI_CHASE_ANY
Definition: sexp.h:747
int sexp_are_waypoints_done_delay(int node)
Definition: sexp.cpp:5488
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
#define MULTIPLAYER_CLIENT
Definition: multi.h:132
float sim_hull_strength
Definition: object.h:161
int ship_info_lookup(const char *token)
Definition: ship.cpp:12772
vec3d target_pos2
Definition: beam.h:65
#define OP_SHIP_CHANGE_CALLSIGN
Definition: sexp.h:615
void sexp_key_reset(int node)
Definition: sexp.cpp:15102
fix time_subsys_cargo_revealed
Definition: ship.h:374
void sexp_modify_variable(int node)
Definition: sexp.cpp:29032
#define OPF_DAMAGE_TYPE
Definition: sexp.h:107
int Framecount
Definition: systemvars.cpp:22
void obj_set_flags(object *obj, uint new_flags)
Definition: object.cpp:1000
int i
Definition: multi_pxo.cpp:466
float get_max_shield_quad(object *objp)
Definition: object.cpp:260
fix Missiontime
Definition: systemvars.cpp:19
SCP_vector< medal_stuff > Medals
Definition: medals.cpp:33
void sexp_get_object_ship_wing_point_team(object_ship_wing_point_team *oswpt, char *object_name, bool set_parse_flag_too=false)
Definition: sexp.cpp:4717
#define vm_free(ptr)
Definition: pstypes.h:548
int stars_add_bitmap_entry(starfield_list_entry *sle)
Definition: starfield.cpp:2347
void sexp_set_turret_primary_ammo(int node)
Definition: sexp.cpp:18075
#define OP_AND_IN_SEQUENCE
Definition: sexp.h:242
#define OP_RESET_ORDERS
Definition: sexp.h:803
#define AI_GOAL_UNDOCK
Definition: aigoals.h:36
bool sexp_get_subsystem_world_pos(vec3d *subsys_world_pos, int shipnum, char *subsys_name)
Definition: sexp.cpp:6470
void sexp_add_wing_goal(int n)
Definition: sexp.cpp:9654
SCP_string sexp_always
Definition: sexp.cpp:25557
camid cam_create(char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_object, int n_object_host_submodel)
Definition: camera.cpp:888
int mission_parse_add_callsign(const char *name)
float p
Definition: pstypes.h:111
fix team_change_timestamp
Definition: ship.h:814
int get_handler_for_x_of_operator(int node)
Definition: sexp.cpp:9139
#define OP_HUD_SET_RETAIL_GAUGE_ACTIVE
Definition: sexp.h:728
#define OP_CATEGORY_CONDITIONAL
Definition: sexp.h:151
#define MISSION_FLAG_NO_BUILTIN_MSGS
Definition: missionparse.h:71
#define OP_NAV_UNRESTRICT
Definition: sexp.h:675
int sexp_num_players()
Definition: sexp.cpp:7398
#define OP_NAV_DISTANCE
Definition: sexp.h:379
model_subsystem * system_info
Definition: ship.h:314
void sexp_set_thrusters(int node)
Definition: sexp.cpp:17108
#define SEXP_TRUE
Definition: sexp.h:918
int HUD_color_alpha
Definition: hud.cpp:76
#define Verify(x)
Definition: pstypes.h:272
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
#define SEO_VOLUME
Definition: sexp.cpp:864
#define CHANGE_SUBCATEGORY_MISSION_AND_CAMPAIGN
Definition: sexp.h:192
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:103
char name[NAME_LENGTH]
Definition: missionparse.h:346
SCP_vector< ArmorType > Armor_types
Definition: ship.cpp:170
int sexp_has_departed(int n, fix *latest_time)
Definition: sexp.cpp:5075
float Training_context_distance
Definition: sexp.cpp:840
int rotation_snd
Definition: model.h:204
int is_empty()
Definition: sexp.cpp:1030
#define OP_SHIP_COPY_DAMAGE
Definition: sexp.h:604
#define EO_DAMAGE
Definition: sexp.cpp:879
#define SRC_SHIP_ARRIVAL
Definition: sexp.h:842
#define OPF_SUPPORT_SHIP_CLASS
Definition: sexp.h:70
#define SEXP_CHECK_INVALID_SHIP_EFFECT
Definition: sexp.h:983
#define OPF_EVENT_NAME
Definition: sexp.h:55
#define EVENT_INCOMPLETE
Definition: missiongoals.h:80
#define OP_SET_WEAPON_ENERGY
Definition: sexp.h:619
dc_stuff_string(sexp)
#define MIN(a, b)
Definition: pstypes.h:296
#define OP_GET_ETS_VALUE
Definition: sexp.h:723
void sexp_set_weapon(int node, bool primary)
Definition: sexp.cpp:16185
#define SEXP_CHECK_INVALID_SHIP_WING
Definition: sexp.h:944
unsigned int DistanceTo(char *nav)
Definition: autopilot.cpp:1593
#define ASF_SOUNDFX
Definition: audiostr.h:18
#define MAX_SHIP_PRIMARY_BANKS
Definition: globals.h:62
int Locked_sexp_false
Definition: sexp.cpp:828
void sexp_set_camera_facing_object(int n)
Definition: sexp.cpp:21110
#define SEXP_CHECK_INVALID_GOAL_NAME
Definition: sexp.h:949
#define OP_XOR
Definition: sexp.h:256
#define OP_TURRET_CHANGE_WEAPON
Definition: sexp.h:583
#define SSSF_ROTATE
Definition: ship.h:304
float max_weapon_reserve
Definition: ship.h:1276
#define SEXP_CHECK_INVALID_DEPARTURE_LOCATION
Definition: sexp.h:970
void updateCustomGaugeCoords(int _x, int _y)
Definition: hud.cpp:399
#define MESSAGE_SOURCE_NONE
ai_info * Player_ai
Definition: ai.cpp:24
void multi_sexp_change_soundtrack()
Definition: sexp.cpp:10152
#define OP_NAV_DEL
Definition: sexp.h:671
SCP_string secondary_team_name
Definition: ship.h:813
#define MR_NO_CULL
Definition: model.h:879
int team
Definition: ship.h:606
int count_free_sexp_nodes()
Definition: sexp.cpp:1176
int Cmdline_old_collision_sys
Definition: cmdline.cpp:489
int free_sexp(int num)
Definition: sexp.cpp:1281
#define SEXP_VARIABLE_NETWORK
Definition: sexp.h:888
#define SRC_DEBRIEFING
Definition: sexp.h:850
GLbitfield stages
Definition: Glext.h:7177
int sexp_shields_left(int n)
Definition: sexp.cpp:5895
void lock_time_compression(bool is_locked)
Definition: fredstubs.cpp:227
control_info ci
Definition: player.h:126
#define SEXP_CHECK_INVALID_EXPLOSION_OPTION
Definition: sexp.h:982
#define ASF_MENUMUSIC
Definition: audiostr.h:20
void multi_sexp_modify_variable()
Definition: sexp.cpp:29009
int Num_mission_events
int Players_target_timestamp
Definition: sexp.cpp:856
#define SEXP_ATOM_OPERATOR
Definition: sexp.h:911
#define P2_SF2_NO_BUILTIN_MESSAGES
Definition: missionparse.h:494
int flags
Definition: player.h:104
#define OPF_SKILL_LEVEL
Definition: sexp.h:57
int Cmdline_freespace_no_music
Definition: cmdline.cpp:271
#define OPF_ARMOR_TYPE
Definition: sexp.h:97
#define OP_TRAINING_MSG
Definition: sexp.h:793
int beam_info_index
Definition: beam.h:57
char name[NAME_LENGTH]
Definition: weapon.h:322
int ai_class
Definition: ship.h:148
#define CHANGE_SUBCATEGORY_BACKGROUND_AND_NEBULA
Definition: sexp.h:197
int get_effect_from_name(char *name)
Definition: sexp.cpp:22454
void sexp_set_armor_type(int node)
Definition: sexp.cpp:17490
char text[TOKEN_LENGTH]
Definition: sexp.h:1044
waypoint * find_matching_waypoint(const char *name)
Definition: waypoint.cpp:179
#define OP_REMOVE_SUN_BITMAP
Definition: sexp.h:579
float Cutscene_bars_progress
Definition: systemvars.cpp:36
void sexp_variable_sort()
Definition: sexp.cpp:29577
int num_target_priorities
Definition: ship.h:390
vec3d View_position
Definition: 3dsetup.cpp:20
int num_primary_banks
Definition: ship.h:99
int check_for_string(const char *pstr)
Definition: parselo.cpp:517
int arrival_anchor
Definition: ship.h:1541
int objnum
Definition: ship.h:537
control_info ai_override_ci
Definition: ai.h:549
#define P_OF_BEAM_PROTECTED
Definition: missionparse.h:464
#define SEF_BEEN_TAGGED
Definition: ship.h:850
void sexp_pause_unpause_music(bool pause)
Definition: sexp.cpp:10162
#define OP_NAV_UNSET_VISITED
Definition: sexp.h:679
#define OP_SHIP_BOMB_UNTARGETABLE
Definition: sexp.h:589
int Game_mode
Definition: systemvars.cpp:24
void mission_goal_mark_valid(char *name)
#define AIG_TYPE_EVENT_WING
Definition: ai.h:98
int arrival_distance
Definition: ship.h:1540
#define LOGFILE_EVENT_LOG
Definition: generic_log.h:19
void multi_sexp_add_remove_escort()
Definition: sexp.cpp:18575
shockwave_create_info shockwave
Definition: ship.h:1237
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
vec3d mins
Definition: model.h:746
void set_object_host(object *objp, int n_object_host_submodel=-1)
Definition: camera.cpp:105
#define OF_LASER_PROTECTED
Definition: object.h:120
#define OP_IS_DISABLED
Definition: sexp.h:761
#define MISSION_FLAG_FULLNEB
Definition: missionparse.h:70
#define OP_SHIP_DEATHS
Definition: sexp.h:356
#define OP_SKILL_LEVEL_AT_LEAST
Definition: sexp.h:312
#define OP_MAX
Definition: sexp.h:224
int ds_eax_set_volume(float volume)
Definition: ds.cpp:2268
#define OP_AI_FORM_ON_WING
Definition: sexp.h:755
int Training_failure
void sexp_deal_with_afterburner_lock(int node, bool lock)
Definition: sexp.cpp:16335
int sexp_query_orders(int n)
Definition: sexp.cpp:15472
int alt_type_index
Definition: ship.h:556
camid Main_camera
Definition: camera.cpp:25
int mission_parse_lookup_callsign(const char *name)
void sexp_hud_set_coords(int n)
Definition: sexp.cpp:9903
void sexp_show_subtitle_text(int node)
Definition: sexp.cpp:21532
int arrival_location
Definition: ship.h:1539
float frand_range(float min, float max)
Return a floating point number in the range min..max.
Definition: floating.cpp:50
#define OP_WAYPOINT_MISSED
Definition: sexp.h:790
SCP_vector< SCP_string > * Current_event_log_buffer
Definition: sexp.cpp:934
#define OP_IF_THEN_ELSE
Definition: sexp.h:408
#define MSS_FLAG2_TURRET_USE_AMMO
Definition: model.h:143
int div_y
Definition: starfield.h:33
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
#define P_OF_INVULNERABLE
Definition: missionparse.h:458
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
#define OP_GET_NUM_COUNTERMEASURES
Definition: sexp.h:383
#define EVENT_SATISFIED
Definition: missiongoals.h:78
#define OP_FLASH_HUD_GAUGE
Definition: sexp.h:794
#define OP_CATEGORY_CHANGE2
Definition: sexp.h:150
#define OPF_SHIP_CLASS_NAME
Definition: sexp.h:60
bool Nav_UnSet_Hidden(char *Nav)
Definition: autopilot.cpp:1553
#define OP_IS_FACING
Definition: sexp.h:381
#define OPF_POINT
Definition: sexp.h:35
ship_weapon weapons
Definition: ship.h:658
void sexp_set_support_ship(int n)
Definition: sexp.cpp:18657
#define OP_SET_ETS_VALUES
Definition: sexp.h:724
int sound_env_set(sound_env *se)
Definition: sound.cpp:1357
char * Explosion_option[]
Definition: sexp.cpp:886
int sexp_shield_quad_low(int node)
Definition: sexp.cpp:15727
#define AIORF_FORWARD
Definition: ai.h:131
#define OPF_WAYPOINT_PATH
Definition: sexp.h:43
T sign(T t)
Definition: sexp.cpp:8941
int value
Definition: sexp.h:1021
#define OP_CUTSCENES_SHOW_SUBTITLE
Definition: sexp.h:557
#define SEO_DAMPING
Definition: sexp.cpp:866
net_player * Net_player
Definition: multi.cpp:94
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
object * target
Definition: beam.h:62
void sexp_reset_camera(int node)
Definition: sexp.cpp:21395
int rest
Definition: sexp.h:1032
#define CARGO_INDEX_MASK
Definition: missionparse.h:220
int gamesnd_get_by_tbl_index(int index)
Definition: gamesnd.cpp:368
int sexp_node_targeted(int node)
Definition: sexp.cpp:15187
#define OPF_WEAPON_NAME
Definition: sexp.h:59
#define OP_SET_PERSONA
Definition: sexp.h:606
void unset_nav_visited(int node)
Definition: sexp.cpp:19492
void sexp_set_fov(int n)
Definition: sexp.cpp:21328
int sexp_is_destroyed_delay(int n)
Definition: sexp.cpp:5209
fix time_cargo_revealed
Definition: ship.h:608
#define OP_WARP_EFFECT
Definition: sexp.h:512
void sexp_update_sound_environment(int node)
Definition: sexp.cpp:10480
#define OP_CATEGORY_ARITHMETIC
Definition: sexp.h:147
#define OP_HAS_SECONDARY_WEAPON
Definition: sexp.h:373
void sexp_ingame_ship_change_iff_color(ship *shipp, int observer_team, int observed_team, int alternate_iff_color)
Definition: sexp.cpp:9347
#define OP_PERCENT_SHIPS_DISABLED
Definition: sexp.h:288
#define CAR(n)
Definition: sexp.h:820
int add_sexps(int n)
Definition: sexp.cpp:4007
int hud_query_order_issued(char *to, char *order_name, char *target_name, int timestamp, char *from, char *special_argument)
#define OP_HITS_LEFT_SUBSYSTEM_GENERIC
Definition: sexp.h:366
#define OP_IS_SHIP_CLASS
Definition: sexp.h:343
submodel_instance_info submodel_info_1
Definition: ship.h:368
#define OP_EVERY_TIME
Definition: sexp.h:394
void sexp_set_object_orientation(int n)
Definition: sexp.cpp:7033
void sexp_end_campaign(int n)
Definition: sexp.cpp:11183
#define FIREBALL_LARGE_EXPLOSION
Definition: fireballs.h:24
int ambient_light_level
Definition: missionparse.h:152
#define AIORF_FULL
Definition: ai.h:124
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, int ai_flag, int ai_flag2, bool set_flag)
Definition: sexp.cpp:12921
#define SEXP_ERROR_CHECK_MODE
Definition: parselo.h:64
float flFrametime
Definition: fredstubs.cpp:22
#define LOG_SHIP_SUBSYS_DESTROYED
Definition: missionlog.h:27
int sexp_add_variable(const char *text, const char *var_name, int type, int index)
Definition: sexp.cpp:28929
int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
Definition: sexp.cpp:8796
int escort_priority
Definition: ship.h:541
#define CHANGE_SUBCATEGORY_MUSIC_AND_SOUND
Definition: sexp.h:193
void sexp_allow_weapon(int n)
Definition: sexp.cpp:12643
void multi_finished_callback()
Definition: multi_sexp.cpp:562
GLsizei const GLfloat * value
Definition: Glext.h:5646
int last_primary_fire_stamp[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:114
void multi_sexp_set_energy_pct()
Definition: sexp.cpp:5825
#define SF2_NO_SUBSPACE_DRIVE
Definition: ship.h:487
void obj_all_collisions_retime(int checkdly)
Definition: objcollide.cpp:80
SCP_vector< SCP_string > * Current_event_log_variable_buffer
Definition: sexp.cpp:935
#define MR_ALL_XPARENT
Definition: model.h:877
void sexp_grant_medal(int n)
Definition: sexp.cpp:12410
char ** Ai_class_names
Definition: aicode.cpp:268
bool Motion_debris_override
Definition: starfield.cpp:176
GLuint index
Definition: Glext.h:5608
#define OP_NEBULA_TOGGLE_POOF
Definition: sexp.h:581
void multi_sexp_pause_sound_from_file()
Definition: sexp.cpp:10404
void sexp_set_respawns(int node)
Definition: sexp.cpp:19682
int sexp_num_ships_in_battle(int n)
Definition: sexp.cpp:4854
void sexp_mission_set_nebula(int n)
Definition: sexp.cpp:12058
#define CHANGE_SUBCATEGORY_SHIELDS_ENGINES_AND_WEAPONS
Definition: sexp.h:185
int sexp_get_real_speed(object *obj)
Definition: sexp.cpp:4933
#define AI_GOAL_CHASE_WING
Definition: aigoals.h:37
#define OP_TURRET_GET_PRIMARY_AMMO
Definition: sexp.h:387
char * model_get_dock_name(int modelnum, int index)
Definition: modelread.cpp:5103
void multi_sexp_flash_hud_gauge()
Definition: sexp.cpp:20631
int free_one_sexp(int num)
Definition: sexp.cpp:1262
#define AI_GOAL_DOCK
Definition: aigoals.h:30
void sexp_change_iff_color(int n)
Definition: sexp.cpp:9366
#define OP_TURRET_GET_SECONDARY_AMMO
Definition: sexp.h:389
#define SSF_NO_REPLACE
Definition: ship.h:288
int weapon_create(vec3d *pos, matrix *orient, int weapon_type, int parent_obj, int group_id=-1, int is_locked=0, int is_spawned=0, float fof_cooldown=0.0f, ship_subsys *src_turret=NULL)
Definition: weapons.cpp:5246
int active_goal
Definition: ai.h:413
#define NO_OPERATOR_INDEX_DEFINED
Definition: sexp.cpp:923
physics_info phys_info
Definition: object.h:157
#define OPF_FONT
Definition: sexp.h:98
player * m_player
Definition: multi.h:459
#define OP_BEAM_FIRE_COORDS
Definition: sexp.h:695
void skip_white(char **str)
Definition: sexp.cpp:28504
#define OP_HITS_LEFT_SUBSYSTEM
Definition: sexp.h:306
#define MR_FORCE_CLAMP
Definition: model.h:888
int Fred_running
Definition: fred.cpp:44
matrix * vm_angles_2_matrix(matrix *m, const angles *a)
Definition: vecmat.cpp:752
#define MAX_WINGS
Definition: globals.h:50
#define WIF_HUGE
Definition: weapon.h:64
#define AI_GOAL_WAYPOINTS
Definition: aigoals.h:31
#define OP_COND
Definition: sexp.h:780
void sexp_set_energy_pct(int node, int op_num)
Definition: sexp.cpp:5754
float turn_rate
Definition: ship.h:400
void stars_set_nebula(bool activate)
Definition: starfield.cpp:2514
void multi_sexp_hud_disable()
Definition: sexp.cpp:9782
#define MAX_SHIPS
Definition: globals.h:37
#define MISSION_FLAG_USE_AP_CINEMATICS
Definition: missionparse.h:89
void sexp_grant_promotion()
Definition: sexp.cpp:12393
#define MAX_OBJECT_FLAG_NAMES
Definition: object.h:135
#define OP_MISSION_SET_NEBULA
Definition: sexp.h:575
void multi_sexp_hud_set_max_targeting_range()
Definition: sexp.cpp:9957
#define SEXP_CHECK_INVALID_SHIP_TYPE
Definition: sexp.h:945
#define OP_SPEED
Definition: sexp.h:787
char * object_name(int obj)
#define OP_CATEGORY_GOAL_EVENT
Definition: sexp.h:155
#define OP_UNPROTECT_SHIP
Definition: sexp.h:428
#define OP_ACTIVATE_GLOW_POINTS
Definition: sexp.h:503
void stars_set_background_orientation(matrix *orient)
Definition: starfield.cpp:2207
bool Snapshot_all_events
#define OSWPT_TYPE_NONE
Definition: sexp.cpp:4651
void swap_parse_object(p_object *p_obj, int new_ship_class)
#define OPF_VARIABLE_NAME
Definition: sexp.h:65
#define TRAINING_CONTEXT_FLY_PATH
Definition: sexp.h:999
#define OP_ENABLE_ETS
Definition: sexp.h:668
void sexp_set_immobile(int n, bool immobile)
Definition: sexp.cpp:14164
void ai_clear_wing_goals(int wingnum)
Definition: aigoals.cpp:270
#define OP_HAS_UNDOCKED_DELAY
Definition: sexp.h:278
void parse_copy_damage(p_object *target_pobjp, ship *source_shipp)
Definition: sexp.cpp:16569
int ship_explode_area_calc_damage(vec3d *pos1, vec3d *pos2, float inner_rad, float outer_rad, float max_damage, float max_blast, float *damage, float *blast)
Definition: ship.cpp:7895
int sexp_query_has_yet_to_arrive(char *name)
Definition: sexp.cpp:3989
#define LOG_SHIP_ARRIVED
Definition: missionlog.h:22
#define SEXP_CHECK_INVALID_INTEL_NAME
Definition: sexp.h:973
#define MISSION_FLAG_TOGGLE_DEBRIEFING
Definition: missionparse.h:79
#define AI_GOAL_GUARD
Definition: aigoals.h:38
#define WF_WING_GONE
Definition: ship.h:1501
vec3d target_pos1
Definition: beam.h:64
void sexp_play_sound_from_file(int n)
Definition: sexp.cpp:10339
#define SEXP_ALL_BANKS_STRING
Definition: sexp.h:817
void sexp_manipulate_colgroup(int node, bool add_to_group)
Definition: sexp.cpp:22411
void object_set_gliding(object *objp, bool enable, bool force)
Definition: object.cpp:2036
#define OP_SHIELD_RECHARGE_PCT
Definition: sexp.h:323
#define OP_SCRIPT_EVAL_MULTI
Definition: sexp.h:729
int departure_anchor
Definition: ship.h:618
int model_num
Definition: ship.h:1189
#define LOG_GOAL_FAILED
Definition: missionlog.h:34
float ship_max_shield_strength
Definition: ship.h:596
#define AITTV_IGNORE_BANK
Definition: ai.h:119
#define DEFAULT_NMODEL_FLAGS
Definition: starfield.h:20
void multi_send_object(object *objp)
Definition: multi_sexp.cpp:308
int sexp_variable_typed_count(int sexp_variables_index, int variable_type)
Definition: sexp.cpp:29522
#define OP_KAMIKAZE
Definition: sexp.h:521
#define OP_TURRET_SUBSYS_TARGET_DISABLE
Definition: sexp.h:623
#define NUM_COMM_ORDER_ITEMS
Definition: hudsquadmsg.h:36
#define OP_IS_CARGO_KNOWN
Definition: sexp.h:779
void multi_sexp_deal_with_subsys_flag(int ss_flag)
Definition: sexp.cpp:14326
#define OP_SHIELDS_OFF
Definition: sexp.h:479
void sexp_set_training_context_speed(int node)
Definition: sexp.cpp:20653
bool IsVisited(char *nav)
Definition: autopilot.cpp:1610
int arrival_location
Definition: ship.h:610
int sexp_is_ship_visible(int n)
Definition: sexp.cpp:5985
void sexp_clear_ship_goals(int n)
Definition: sexp.cpp:9722
int ship_iff_color[MAX_IFFS][MAX_IFFS]
Definition: ship.h:793
float max_hits
Definition: ship.h:320
#define OP_AFTERBURNER_LEFT
Definition: sexp.h:360
#define OP_AI_IGNORE_NEW
Definition: sexp.h:754
int insert_subsys_status(p_object *pobjp)
#define OP_ENGINE_RECHARGE_PCT
Definition: sexp.h:324
arg_item * get_next()
Definition: sexp.cpp:985
int weapon_info_lookup(const char *name=NULL)
Definition: weapons.cpp:467
#define OP_SIGNUM
Definition: sexp.h:236
int min
distance at which sound will stop getting louder
Definition: sound.h:79
int sexp_hits_left_subsystem(int n)
Definition: sexp.cpp:6114
#define MESSAGE_SOURCE_WINGMAN
#define SEXP_INTEGER_OPERATOR
Definition: sexp.h:1014
void updateActive(bool show)
Definition: hud.cpp:538
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
void multi_sexp_fade(bool fade_in)
Definition: sexp.cpp:20822
#define PF_GLIDING
Definition: physics.h:32
Assert(pm!=NULL)
uint flags2
Definition: model.h:170
int sexp_event_status(int n, int want_true)
Definition: sexp.cpp:13928
int target_objnum
Definition: ai.h:339
int special_exp_blast
Definition: ship.h:586
#define OP_EXPLOSION_EFFECT
Definition: sexp.h:511
void sexp_add_goal(int n)
Definition: sexp.cpp:9672
int sexp_was_promotion_granted(int n)
Definition: sexp.cpp:7439
void set_flag(ai_profile_t *profile, char *name, int flag, int type)
Definition: ai_profiles.cpp:30
int extract_sexp_variable_index(int node)
Definition: sexp.cpp:28790
#define OP_SECONDARY_AMMO_PCT
Definition: sexp.h:327
void sexp_object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship *shipp, bool set_parse_flag_too=false)
#define NP_HIDDEN
Definition: autopilot.h:22
#define P2_OF_TARGETABLE_AS_BOMB
Definition: missionparse.h:493
int sexp_is_cargo(int n)
Definition: sexp.cpp:11648
void get_sexp_text_for_variable(char *text, char *token)
Definition: sexp.cpp:3218
void sexp_add_remove_escort(int node)
Definition: sexp.cpp:18544
#define OP_DISTANCE_SUBSYSTEM
Definition: sexp.h:309
#define OP_CAP_WAYPOINT_SPEED
Definition: sexp.h:468
void _cdecl void void _cdecl void _cdecl void _cdecl WarningEx(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define P2_SF2_NO_ETS
Definition: missionparse.h:506
void sexp_change_team_score(int node)
Definition: sexp.cpp:12485
#define OPF_TURRET_TARGET_ORDER
Definition: sexp.h:89
int departure_location
Definition: ship.h:617
int sexp_directive_value(int n)
Definition: sexp.cpp:6248
bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags)
Definition: autopilot.cpp:1427
int bfi_flags
Definition: beam.h:71
#define SEXP_CHECK_NEGATIVE_NUM
Definition: sexp.h:943
void sexp_send_random_message(int n)
Definition: sexp.cpp:11095
void sexp_turret_set_direction_preference(int node)
Definition: sexp.cpp:17791
void sexp_set_ets_values(int node)
Definition: sexp.cpp:15676
Definition: pstypes.h:88
submodel_instance_info submodel_info_2
Definition: ship.h:369
#define OP_LESS_THAN
Definition: sexp.h:246
#define mprintf(args)
Definition: pstypes.h:238
#define FRONT_QUAD
Definition: objectshield.h:16
#define OP_COLLIDE_INVISIBLE
Definition: sexp.h:495
int departure_anchor
Definition: ship.h:1547
int ai_index
Definition: ship.h:538
#define OP_HAS_ARRIVED_DELAY
Definition: sexp.h:279
ship_weapon weapons
Definition: ship.h:362
#define OP_IS_FRIENDLY_STEALTH_VISIBLE
Definition: sexp.h:336
#define AIORF_FULL_LAT
Definition: ai.h:128
#define OP_FRIENDLY_STEALTH_VISIBLE
Definition: sexp.h:490
#define OP_BEAM_FLOATING_FIRE
Definition: sexp.h:732
void gr_init_alphacolor(color *clr, int r, int g, int b, int alpha, int type)
Definition: 2d.cpp:1173
ushort net_signature
Definition: object.h:163
int sexp_cap_subsys_cargo_known_delay(int n)
Definition: sexp.cpp:7888
void set_position(vec3d *in_position=NULL, float in_translation_time=0.0f, float in_translation_acceleration_time=0.0f, float in_translation_deceleration_time=0.0f, float in_end_velocity=0.0f)
Definition: camera.cpp:162
#define OP_PREVIOUS_GOAL_INCOMPLETE
Definition: sexp.h:776
#define SEXP_VARIABLE_SET
Definition: sexp.h:903
int special_exp_inner
Definition: ship.h:587
#define CDDDR(n)
Definition: sexp.h:828
#define P2_SF2_SECONDARIES_LOCKED
Definition: missionparse.h:496
#define OP_GET_OBJECT_HEADING
Definition: sexp.h:370
int Num_fireball_types
Definition: fireballs.cpp:50
#define SSF_NO_LIVE_DEBRIS
Definition: ship.h:289
void sexp_music_close()
Definition: sexp.cpp:10183
int sexp_is_subsystem_destroyed_delay(int n)
Definition: sexp.cpp:5308
#define DIRECTIVE_WING_ZERO
Definition: sexp.h:1073
float level2_tag_left
Definition: ship.h:728
#define SEXP_CHECK_INVALID_GAME_SND
Definition: sexp.h:995
#define OP_HUD_SET_TEXT
Definition: sexp.h:534
void sexp_send_message(int n)
Definition: sexp.cpp:11025
#define NUM_SKILL_LEVELS
Definition: systemvars.h:150
void sexp_ship_guardian_threshold(int node)
Definition: sexp.cpp:14446
int weapon_recharge_index
Definition: ship.h:638
int departure_path_mask
Definition: missionparse.h:378
void sexp_self_destruct(int node)
Definition: sexp.cpp:11133
#define OBJ_ASTEROID
Definition: object.h:44
int subsystem_stricmp(const char *str1, const char *str2)
Definition: parselo.cpp:3648
#define OP_SHIP_VANISH
Definition: sexp.h:477
#define OP_STRING_GET_LENGTH
Definition: sexp.h:375
void multi_sexp_change_ship_class()
Definition: sexp.cpp:16497
#define OP_CHANGE_TEAM_COLOR
Definition: sexp.h:716
#define OPF_IFF
Definition: sexp.h:36
void sexp_send_one_message(char *name, char *who_from, char *priority, int group, int delay)
Definition: sexp.cpp:10948
#define AI_GOAL_STAY_NEAR_SHIP
Definition: aigoals.h:47
void ship_destroy_instantly(object *ship_objp, int shipnum)
Definition: ship.cpp:7761
#define OP_ALLOW_TREASON
Definition: sexp.h:603
#define SEXP_NAN
Definition: sexp.h:924
void maybe_write_previous_event_to_log(int result)
Definition: sexp.cpp:22738
#define VM_EXTERNAL
Definition: systemvars.h:31
Definition: 2d.h:95
#define OPF_EXPLOSION_OPTION
Definition: sexp.h:102
void sexp_reset_orders(int n)
Definition: sexp.cpp:15508
void stars_preload_sun_bitmap(char *fname)
Definition: starfield.cpp:1873
char * CTEXT(int n)
Definition: sexp.cpp:28821
#define SEXP_CHECK_INVALID_ARRIVAL_LOCATION
Definition: sexp.h:969
int shockwave_create(int parent_objnum, vec3d *pos, shockwave_create_info *sci, int flag, int delay)
Definition: shockwave.cpp:64
#define OPF_ANIMATION_TYPE
Definition: sexp.h:109
#define P_SF2_STEALTH
Definition: missionparse.h:471
void updateColor(int r, int g, int b, int a=255)
Definition: hud.cpp:530
#define SSF_UNTARGETABLE
Definition: ship.h:280
#define OPF_BACKGROUND_BITMAP
Definition: sexp.h:85
int run_sexp(const char *sexpression)
Definition: sexp.cpp:25528
void obj_snd_delete_type(int objnum, int sndnum, ship_subsys *ss)
Definition: objectsnd.cpp:812
#define OP_CATEGORY_STATUS
Definition: sexp.h:148
bool sexp_helper_is_within_box(float *box_vals, vec3d *pos)
Definition: sexp.cpp:6588
#define OP_CHANGE_SOUNDTRACK
Definition: sexp.h:508
#define OPF_CARGO
Definition: sexp.h:68
#define AI_GOAL_CHASE_ANY
Definition: aigoals.h:41
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: Glext.h:5230
#define OP_SUPERNOVA_STOP
Definition: sexp.h:701
#define OP_DIRECTIVE_VALUE
Definition: sexp.h:382
#define OP_RAND
Definition: sexp.h:221
int Num_parse_names
int sexp_get_object_angle(int n, int axis)
Definition: sexp.cpp:6897
#define SEXP_BOOLEAN_OPERATOR
Definition: sexp.h:1013
#define LOG_WING_DEPARTED
Definition: missionlog.h:25
void flush_sexp_tree(int node)
Definition: sexp.cpp:1342
ship_subsys * turret
Definition: beam.h:60
int subsys_guardian_threshold
Definition: ship.h:324
void sexp_toggle_builtin_messages(int node, bool enable_messages)
Definition: sexp.cpp:13490
#define OP_GET_OBJECT_SPEED_X
Definition: sexp.h:376
void set_object_for_clients(object *objp)
Definition: sexp.cpp:6918
#define MAX_AI_FLAG_NAMES
Definition: ai.h:35
void sexp_ship_copy_damage(int node)
Definition: sexp.cpp:16621
void tech_reset_to_default()
Definition: techmenu.cpp:1438
#define OP_SET_NUM_COUNTERMEASURES
Definition: sexp.h:689
int sexp_missile_locked(int node)
Definition: sexp.cpp:19575
#define OPF_SHIP_POINT
Definition: sexp.h:46
#define LOG_SHIP_UNDOCKED
Definition: missionlog.h:28
#define MR_NO_LIGHTING
Definition: model.h:867
#define OP_DEACTIVATE_GLOW_POINT_BANK
Definition: sexp.h:506
int secondary_bank_start_ammo[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:135
#define OP_CUTSCENES_SET_CAMERA_POSITION
Definition: sexp.h:550
struct vec3d::@225::@227 xyz
#define OP_PREVIOUS_EVENT_FALSE
Definition: sexp.h:267
int query_sexp_args_count(int node, bool only_valid_args=false)
Definition: sexp.cpp:1619
void sexp_ship_effect(int n)
Definition: sexp.cpp:22464
int center_h
Definition: 2d.h:363
bool output_sexps(char *filepath)
Definition: sexp.cpp:33901
float afterburner_fuel
Definition: ship.h:648
int sexp_is_in_mission(int node)
Definition: sexp.cpp:22402
int sexp_bitwise_xor(int node)
Definition: sexp.cpp:4309
#define OP_SET_VARIABLE_BY_INDEX
Definition: sexp.h:630
#define OPF_SKYBOX_FLAGS
Definition: sexp.h:114
ship_subsys * Players_targeted_subsys
Definition: sexp.cpp:855
CButton * team
int mission_parse_add_alt(const char *name)
#define OP_SHIP_STEALTHY
Definition: sexp.h:485
#define SEXP_LIST
Definition: sexp.h:863
void sexp_force_glide(int node)
Definition: sexp.cpp:22291
bool cam_set_camera(camid cid)
Definition: camera.cpp:980
ship_subsys * target_subsys
Definition: beam.h:63
#define STATUS_SUBCATEGORY_DISTANCE_AND_COORDINATES
Definition: sexp.h:211
#define OP_PRIMITIVE_SENSORS_SET_RANGE
Definition: sexp.h:498
GLboolean GLuint group
Definition: Glext.h:10591
int physics_paused
Definition: object.cpp:677
void supernova_stop()
Definition: supernova.cpp:89
#define FS_VERSION_MAJOR
Definition: version.h:37
SCP_vector< SCP_string > * Current_event_log_argument_buffer
Definition: sexp.cpp:936
#define SF2_DONT_COLLIDE_INVIS
Definition: ship.h:486
int get_sexp_id(char *sexp_name)
Definition: sexp.cpp:29600
void current_log_to_backup_log_buffer()
Definition: sexp.cpp:22726
GLclampf f
Definition: Glext.h:7097
void sexp_ignore_key(int node)
Definition: sexp.cpp:15114
#define LOG_SHIP_DEPARTED
Definition: missionlog.h:24
#define OP_CHANGE_TEAM_SCORE
Definition: sexp.h:608
object * dock_find_object_at_dockpoint(object *objp, int dockpoint)
Definition: objectdock.cpp:106
int sexp_is_disabled(int n, fix *latest_time)
Definition: sexp.cpp:5111
#define STATUS_SUBCATEGORY_SHIELDS_ENGINES_AND_WEAPONS
Definition: sexp.h:208
int num_block_variables()
Definition: sexp.cpp:3777
#define OP_COPY_VARIABLE_FROM_INDEX
Definition: sexp.h:721
void update_sexp_references(const char *old_name, const char *new_name, int format, int node)
Definition: sexp.cpp:28332
#define OP_BEAM_FIRE
Definition: sexp.h:453
#define OP_SHIP_SUBSYS_TARGETABLE
Definition: sexp.h:590
void sexp_set_subsys_rotation_lock_free(int node, int locked)
Definition: sexp.cpp:18317
#define MAX_OBJECTS
Definition: globals.h:83
bool Nav_Set_NoAccess(char *Nav)
Definition: autopilot.cpp:1538
#define SEXP_NODE_INCREMENT
Definition: sexp.cpp:842
void set_nav_needslink(int node)
Definition: sexp.cpp:19212
void sexp_hud_activate_gauge_type(int n)
Definition: sexp.cpp:10012
void multi_sexp_change_subsystem_name()
Definition: sexp.cpp:16409
#define OPF_AI_CLASS
Definition: sexp.h:69
#define BFIF_TARGETING_COORDS
Definition: beam.h:52
void sexp_set_mission_mood(int node)
Definition: sexp.cpp:13624
bool is_sexp_node_numeric(int node)
Definition: sexp.cpp:29075
bool multi_sexp_discard_operator()
Definition: multi_sexp.cpp:583
int gamesnd_get_by_name(const char *name)
Definition: gamesnd.cpp:301
#define AI_GOAL_WARP
Definition: aigoals.h:33
#define OP_ADD_GOAL
Definition: sexp.h:421
#define OP_ENABLE_BUILTIN_MESSAGES
Definition: sexp.h:596
void sexp_play_sound_from_table(int n)
Definition: sexp.cpp:10256
#define OP_SEND_MESSAGE
Definition: sexp.h:418
int sexp_campaign_persistent_variable_count()
Definition: sexp.cpp:29506
void sexp_force_jump()
Definition: sexp.cpp:12042
void ship_do_cargo_revealed(ship *shipp, int from_network)
Definition: ship.cpp:16138
void hud_cease_targeting()
Definition: hudtarget.cpp:4367
#define OP_TIME_WING_ARRIVED
Definition: sexp.h:297
#define NUM_TURRET_ORDER_TYPES
Definition: ship.h:253
void multi_sexp_play_sound_from_file()
Definition: sexp.cpp:10378
#define OF_NO_SHIELDS
Definition: object.h:110
#define SF2_FRIENDLY_STEALTH_INVIS
Definition: ship.h:484
void sexp_fred_modify_variable(const char *text, const char *var_name, int index, int type)
Definition: sexp.cpp:29289
int special_exp_outer
Definition: ship.h:588
int get_subcategory(int sexp_id)
Definition: sexp.cpp:29635
int is_sexp_top_level(int node)
Definition: sexp.cpp:1515
int Num_cargo
#define AI_GOAL_IGNORE
Definition: aigoals.h:42
#define MAX_PARSE_OBJECT_FLAGS
Definition: missionparse.h:445
bool dock_check_find_direct_docked_object(object *objp, object *other_objp)
Definition: objectdock.cpp:91
#define OP_IS_SHIP_TYPE
Definition: sexp.h:342
ai_info Ai_info[MAX_AI_INFO]
Definition: ai.cpp:23
#define SEXP_ATOM_NUMBER
Definition: sexp.h:912
subsys_status * parse_get_subsys_status(p_object *pobjp, char *subsys_name)
void unset_nav_carry_status(int node)
Definition: sexp.cpp:19169
float afterburner_fuel_capacity
Definition: ship.h:1283
int ai_remove_goal_sexp_sub(int sexp, ai_goal *aigp)
Definition: aigoals.cpp:1037
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
void weapon_mark_as_used(int weapon_id)
Definition: weapons.cpp:6497
#define Assertion(expr, msg,...)
Definition: clang.h:41
void sexp_change_soundtrack(int n)
Definition: sexp.cpp:10141
void sexp_show_subtitle_image(int node)
Definition: sexp.cpp:21726
int is_nav_visited(int node)
Definition: sexp.cpp:19502
vec3d starting_pos
Definition: beam.h:66
void sexp_damage_escort_list(int node)
Definition: sexp.cpp:18596
int query_referenced_in_sexp(int mode, char *name, int *node)
Definition: sexp.cpp:28382
#define PERSONA_FLAG_WINGMAN
#define OP_SECONDARY_FIRED_SINCE
Definition: sexp.h:363
#define SF2_NAVPOINT_CARRY
Definition: ship.h:488
#define OP_SET_PLAYER_THROTTLE_SPEED
Definition: sexp.h:702
#define OP_SHIP_SUBSYS_GUARDIAN_THRESHOLD
Definition: sexp.h:568
object obj_used_list
Definition: object.cpp:53
void multi_sexp_hud_display_gauge()
Definition: sexp.cpp:10066
#define P_OF_NO_SHIELDS
Definition: missionparse.h:451
int sexp_time_docked(int n)
Definition: sexp.cpp:5676
int sexp_get_fov()
Definition: sexp.cpp:21359
void add_block_variable(const char *text, const char *var_name, int type, int index)
Definition: sexp.cpp:28913
#define OP_EVENT_TRUE
Definition: sexp.h:774
void sexp_ships_vaporize(int n, bool vaporize)
Definition: sexp.cpp:14176
void sexp_show_subtitle(int node)
Definition: sexp.cpp:21425
#define AI_GOAL_DISARM_SHIP
Definition: aigoals.h:40
model_subsystem * subsystems
Definition: ship.h:1271
int sexp_are_waypoints_done(int n)
Definition: sexp.cpp:5147
int ship_class
Definition: missionparse.h:351
#define OP_CHANGE_PLAYER_SCORE
Definition: sexp.h:607
Definition: ship.h:1516
#define OPF_SHIP_WING
Definition: sexp.h:48
int subsys_snd_flags
Definition: ship.h:383
int current_primary_bank
Definition: ship.h:106
#define OP_END_MISSION
Definition: sexp.h:482
void set_default_recharge_rates(object *obj)
Definition: hudets.cpp:275
#define SEXP_CHECK_NUM_RANGE_INVALID
Definition: sexp.h:956
#define OP_TURRET_SET_DIRECTION_PREFERENCE
Definition: sexp.h:634
#define OP_NUM_SHIPS_IN_BATTLE
Definition: sexp.h:344
sexp_help_struct Sexp_help[]
Definition: sexp.cpp:30083
int kamikaze_damage
Definition: missionparse.h:399
float dock_orient_and_approach(object *docker_objp, int docker_index, object *dockee_objp, int dockee_index, int dock_mode, rotating_dockpoint_info *rdinfo=NULL)
Definition: aicode.cpp:9070
int ds_eax_get_preset_id(const char *name)
Definition: ds.cpp:2376
#define SEXP_ACTION_OPERATOR
Definition: sexp.h:1011
ship_subsys * targeted_subsys
Definition: ai.h:472
#define SF_ARRIVING
Definition: ship.h:453
int verify_vector(char *text)
Definition: sexp.cpp:28455
void eval_when_do_one_exp(int exp)
Definition: sexp.cpp:8232
#define OP_NAV_HIDE
Definition: sexp.h:672
#define OP_GET_OBJECT_Y
Definition: sexp.h:339
int alloc_sexp(char *text, int type, int subtype, int first, int rest)
Definition: sexp.cpp:1123
void sexp_next_mission(int n)
Definition: sexp.cpp:11148
GLenum mode
Definition: Glext.h:5794
#define OP_DEACTIVATE_GLOW_MAPS
Definition: sexp.h:504
#define OP_EVENT_TRUE_MSECS_DELAY
Definition: sexp.h:270
void sexp_turret_tagged_clear_specific(int node)
Definition: sexp.cpp:18517
int Knossos_warp_ani_used
Definition: fireballs.cpp:33
#define SEXP_CHECK_INVALID_SKYBOX_FLAG
Definition: sexp.h:994
#define SSF_VANISHED
Definition: ship.h:290
int Num_hud_gauge_types
Definition: hudparse.cpp:152
int ship_is_tagged(object *objp)
Definition: ship.cpp:17263
int ship_find_exited_ship_by_name(char *name)
Definition: ship.cpp:5338
int n_quadrants
Definition: object.h:158
sexp_variable Sexp_variables[MAX_SEXP_VARIABLES]
Definition: sexp.cpp:846
int center_w
Definition: 2d.h:363
int Sexp_hud_display_warpout
Definition: sexp.cpp:9964
#define OPF_SHIP_EFFECT
Definition: sexp.h:108
void sexp_turret_set_rate_of_fire(int node)
Definition: sexp.cpp:17835
#define OSWPT_TYPE_SHIP
Definition: sexp.cpp:4652
int sexp_bitwise_not(int node)
Definition: sexp.cpp:4300
#define OP_SEND_RANDOM_MESSAGE
Definition: sexp.h:425
#define MLF_SEXP_TRUE
Definition: missiongoals.h:89
#define OP_WAS_MEDAL_GRANTED
Definition: sexp.h:314
void add_to_event_log_buffer(int op_num, int result)
Definition: sexp.cpp:22838
#define DAMAGE
Definition: sexp.h:893
void multi_sexp_set_time_compression()
Definition: sexp.cpp:21868
#define OP_LESS_OR_EQUAL
Definition: sexp.h:254
int sexp_get_secondary_ammo(int node)
Definition: sexp.cpp:16045
#define SEXP_VARIABLE_NOT_USED
Definition: sexp.h:876
int sexp_is_facing(int node)
Definition: sexp.cpp:15362
int ds_eax_set_decay_time(float seconds)
Definition: ds.cpp:2289
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: Glext.h:5156
#define OP_IS_TAGGED
Definition: sexp.h:318
void sexp_set_camera_shudder(int n)
Definition: sexp.cpp:21927
void set_turret_primary_ammo(ship_subsys *turret, int requested_bank, int requested_ammo, bool update)
Definition: sexp.cpp:18141
#define OP_REVERSE_ROTATING_SUBSYSTEM
Definition: sexp.h:527
#define OP_RED_ALERT
Definition: sexp.h:445
Definition: ai.h:329
void ship_do_cap_subsys_cargo_revealed(ship *shipp, ship_subsys *subsys, int from_network)
Definition: ship.cpp:16161
float dock_calc_docked_speed(object *objp)
Definition: objectdock.cpp:269
#define OP_NAV_IS_VISITED
Definition: sexp.h:290
void sexp_set_camera_rotation(int n)
Definition: sexp.cpp:20948
#define OPR_POSITIVE
Definition: sexp.h:122
void sexp_script_eval_multi(int node)
Definition: sexp.cpp:22200
void unset_nav_needslink(int node)
Definition: sexp.cpp:19237
#define FIREBALL_EXPLOSION_LARGE1
Definition: fireballs.h:32
void sexp_hud_gauge_set_active(int n)
Definition: sexp.cpp:9975
void sexp_set_secondary_ammo(int node)
Definition: sexp.cpp:16089
float weapon_energy
Definition: ship.h:640
#define OPF_DOCKEE_POINT
Definition: sexp.h:39
#define OP_POW
Definition: sexp.h:227
uint flags
Definition: ship.h:644
#define OP_IS_DESTROYED
Definition: sexp.h:759
int eval_any_of(int arg_handler_node, int condition_node)
Definition: sexp.cpp:8724
#define SEXP_HUD_GAUGE_WARPOUT
Definition: sexp.cpp:931
char name[NAME_LENGTH]
int turret_next_fire_stamp
Definition: ship.h:336
#define SRC_UNKNOWN
Definition: sexp.h:852
bool validate_ship_ets_indxes(const int &ship_idx, int(&ets_indexes)[num_retail_ets_gauges])
Definition: hudets.cpp:722
int Training_context_at_waypoint
Definition: sexp.cpp:839
void ai_clear_ship_goals(ai_info *aip)
Definition: aigoals.cpp:251
int model_get_num_dock_points(int modelnum)
Definition: modelread.cpp:5112
void sexp_set_time_compression(int n)
Definition: sexp.cpp:21835
#define SEXP_FLAG_VARIABLE
Definition: sexp.h:868
#define OP_SHIP_BOMB_TARGETABLE
Definition: sexp.h:588
matrix * B
Definition: lua.cpp:445
void ai_good_secondary_time(int team, int weapon_index, int num_weapons, char *shipname)
Definition: aicode.cpp:326
hull_check orient
Definition: lua.cpp:5049
#define OPF_MEDAL_NAME
Definition: sexp.h:58
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
#define OF_PLAYER_SHIP
Definition: object.h:109
void sexp_allow_ship(int n)
Definition: sexp.cpp:12624
#define OP_NUM_SHIPS_IN_WING
Definition: sexp.h:350
void set_fov(float in_fov, float in_fov_time=0.0f, float in_fov_acceleration_time=0.0f, float in_deceleration_time=0.0f)
Definition: camera.cpp:87
#define OP_WAYPOINT_TWICE
Definition: sexp.h:792
int sexp_is_bit_set(int node)
Definition: sexp.cpp:4260
#define OP_PLAY_SOUND_FROM_FILE
Definition: sexp.h:518
#define OP_AI_DISABLE_SHIP
Definition: sexp.h:744
void sexp_beam_lock(int node)
Definition: sexp.cpp:17165
void sexp_change_subsystem_name(int node)
Definition: sexp.cpp:16357
#define P_SF2_FRIENDLY_STEALTH_INVIS
Definition: missionparse.h:472
object * objp
Definition: lua.cpp:3105
int primary_bank_capacity[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:123
int replace_one(char *str, char *oldstr, char *newstr, uint max_len, int range)
Definition: parselo.cpp:3889
float optimum_range
Definition: ship.h:342
#define AIG_TYPE_EVENT_SHIP
Definition: ai.h:97
#define OP_DEBUG
Definition: sexp.h:711
void sexp_remove_sun_bitmap(int n)
Definition: sexp.cpp:12262
void sexp_supernova_start(int node)
Definition: sexp.cpp:20047
#define SEXP_CHECK_INVALID_MISSION_NAME
Definition: sexp.h:948
void sexp_set_object_orient_sub(object *objp, vec3d *location, int turn_time, int bank)
Definition: sexp.cpp:7088
int current_secondary_bank
Definition: ship.h:107
GLfloat GLfloat GLfloat v2
Definition: Glext.h:5640
#define OPF_ARRIVAL_LOCATION
Definition: sexp.h:71
GLsizeiptr size
Definition: Glext.h:5496
#define Int3()
Definition: pstypes.h:292
int get_index_sexp_variable_name(const char *text)
Definition: sexp.cpp:29324
int arrival_anchor
Definition: missionparse.h:371
void multi_handle_sudden_mission_end()
Definition: multiutil.cpp:2135
#define OP_SHIELDS_LEFT
Definition: sexp.h:304
void sexp_show_hide_jumpnode(int node, bool show)
Definition: sexp.cpp:22080
int test_argument_nodes_for_condition(int n, int condition_node, int *num_true, int *num_false, int *num_known_true, int *num_known_false)
Definition: sexp.cpp:8554
SOUNDTRACK_INFO Soundtracks[MAX_SOUNDTRACKS]
Definition: eventmusic.cpp:57
#define CADR(n)
Definition: sexp.h:822
briefing Briefings[MAX_TVT_TEAMS]
#define MLF_FIRST_TRIGGER_ONLY
Definition: missiongoals.h:95
int stuff_sexp_variable_list()
Definition: sexp.cpp:3590
SCP_vector< ship_counts > Ship_type_counts
Definition: ship.cpp:401
int rand32()
Definition: systemvars.cpp:112
camid game_render_frame_setup()
Definition: fredstubs.cpp:235
#define SEXP_NONE_STRING
Definition: sexp.h:815
#define OP_SET_SHIELD_ENERGY
Definition: sexp.h:620
int sexp_is_player(int node)
Definition: sexp.cpp:19618
#define AIF_KAMIKAZE
Definition: ai.h:55
int special_argument_appears_in_sexp_tree(int node)
Definition: sexp.cpp:8192
fix time_first_tagged
Definition: ship.h:726
int GetSCPObjectNumber()
Definition: jumpnode.cpp:133
char Neb2_poof_filenames[MAX_NEB2_POOFS][MAX_FILENAME_LEN]
Definition: neb.cpp:60
#define AI_GOAL_NONE
Definition: ai.h:194
void build_extended_sexp_string(SCP_string &accumulator, int cur_node, int level, int mode)
Definition: sexp.cpp:3870
#define OP_BEAM_FREE_ALL
Definition: sexp.h:455
int get_sexp_main()
Definition: sexp.cpp:25494
#define SEXP_CHECK_INVALID_MEDAL_NAME
Definition: sexp.h:959
void multi_start_callback()
Definition: multi_sexp.cpp:79
ship * shipp
Definition: lua.cpp:9162
int arrival_delay
Definition: ship.h:1544
vec3d pos
Definition: object.h:152
#define VM_TOPDOWN
Definition: systemvars.h:43
#define SEXP_CHECK_INVALID_SUBSYS_TYPE
Definition: sexp.h:977
#define SEXP_CHECK_INVALID_DOCKEE_POINT
Definition: sexp.h:953
#define PLAYER_FLAGS_PROMOTED
Definition: player.h:41
#define OP_TURRET_SUBSYS_TARGET_ENABLE
Definition: sexp.h:624
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
#define OP_SET_SCANNED
Definition: sexp.h:483
void ship_apply_whack(vec3d *force, vec3d *hit_pos, object *objp)
Definition: shiphit.cpp:1740
int damage_type_idx_sav
Definition: weapon.h:520
void sexp_hud_set_text_num(int n)
Definition: sexp.cpp:9811
int query_operator_argument_type(int op, int argnum)
Definition: sexp.cpp:26169
void multi_sexp_show_hide_jumpnode(bool show)
Definition: sexp.cpp:22097
void sexp_end_mission(int n)
Definition: sexp.cpp:12320
#define OP_IS_SECONDARY_SELECTED
Definition: sexp.h:328
mission_goal Mission_goals[MAX_GOALS]
#define OP_HUD_SET_DIRECTIVE
Definition: sexp.h:654
#define OP_NAV_SET_CARRY
Definition: sexp.h:677
#define OP_IS_DISARMED_DELAY
Definition: sexp.h:276
int Training_context_speed_min
Definition: sexp.cpp:834
float awacs_radius
Definition: ship.h:360
int ai_flags
Definition: ai.h:330
#define OP_HITS_LEFT
Definition: sexp.h:305
#define STATUS_SUBCATEGORY_MULTIPLAYER
Definition: sexp.h:206
void sexp_supernova_stop(int node)
Definition: sexp.cpp:20052
#define SEXP_CHECK_INVALID_EVENT_NAME
Definition: sexp.h:957
float volume
Definition: sound.h:93
#define OP_OR
Definition: sexp.h:243
script_state Script_system("FS2_Open Scripting")
#define SEXP_CHECK_UNKNOWN_OP
Definition: sexp.h:932
#define OP_CUTSCENES_SET_FOV
Definition: sexp.h:554
#define LOG_WING_ARRIVED
Definition: missionlog.h:23
void sexp_tech_add_intel_xstr(int node)
Definition: sexp.cpp:12581
int multi_find_player_by_ship_name(const char *ship_name, bool inc_respawning)
Definition: multiutil.cpp:570
void sexp_set_arrival_info(int node)
Definition: sexp.cpp:18772
bool Nav_UnSet_NoAccess(char *Nav)
Definition: autopilot.cpp:1560
void cam_reset_camera()
Definition: camera.cpp:1002
#define OP_CUTSCENES_RESET_TIME_COMPRESSION
Definition: sexp.h:559
int mod_sexps(int n)
Definition: sexp.cpp:4103
char * name
#define OP_SET_MOBILE
Definition: sexp.h:649
void actually_remove_weapons(int weapon_info_index)
Definition: sexp.cpp:19732
int signature
Definition: object.h:145
#define OP_EQUALS
Definition: sexp.h:244
#define STATUS_SUBCATEGORY_CARGO
Definition: sexp.h:209
int subobj_num
Definition: model.h:175
int Training_context_speed_timestamp
Definition: sexp.cpp:836
int sexp_get_ets_value(int node)
Definition: sexp.cpp:15646
#define OP_ORDER
Definition: sexp.h:789
void sexp_mission_set_subspace(int n)
Definition: sexp.cpp:12073
std::deque< bool > glow_point_bank_active
Definition: ship.h:763
void sexp_set_motion_debris(int node)
Definition: sexp.cpp:22629
#define OPF_AWACS_SUBSYSTEM
Definition: sexp.h:67
int div_x
Definition: starfield.h:33
#define OP_ARE_SHIP_FLAGS_SET
Definition: sexp.h:386
void sexp_change_ship_class(int n)
Definition: sexp.cpp:16427
int special_argument_appears_in_sexp_list(int node)
Definition: sexp.cpp:8214
int sexp_distance(int n)
Definition: sexp.cpp:6391
#define OPF_ORDER_RECIPIENT
Definition: sexp.h:93
#define OP_SET_MISSION_MOOD
Definition: sexp.h:712
GLenum type
Definition: Gl.h:1492
bool multi_get_bool(bool &value)
Definition: multi_sexp.cpp:759
#define OP_QUERY_ORDERS
Definition: sexp.h:804
void multi_sexp_alter_ship_flag()
Definition: sexp.cpp:13337
#define SEXP_CHECK_INVALID_SHIP
Definition: sexp.h:938
#define CHANGE_SUBCATEGORY_OTHER
Definition: sexp.h:201
int translate_key_to_index(const char *key, bool find_override=true)
#define OP_DAMAGED_ESCORT_LIST_ALL
Definition: sexp.h:492
void sexp_set_docked(int n)
Definition: sexp.cpp:11964
#define OP_SET_SOUND_ENVIRONMENT
Definition: sexp.h:640
#define gr_set_ambient_light
Definition: 2d.h:908
#define OPF_WHO_FROM
Definition: sexp.h:41
#define SHIP_GUARDIAN_THRESHOLD_DEFAULT
Definition: ship.h:47
int arrival_delay
Definition: missionparse.h:374
SCP_string death_message
Definition: player.h:208
#define MSS_FLAG_AWACS
Definition: model.h:111
void log_string(int logfile_type, const char *string, int add_time)
#define OP_IS_DESTROYED_DELAY
Definition: sexp.h:273
int sexp_weapon_fired_delay(int node, int op_num)
Definition: sexp.cpp:13639
config_item Control_config[]
Stores the keyboard configuration.
void multi_sexp_set_object_position()
Definition: sexp.cpp:7015
#define OP_NAV_SET_NEEDSLINK
Definition: sexp.h:680
void sexp_fade(bool fade_in, int duration, ubyte R, ubyte G, ubyte B)
Definition: sexp.cpp:20719
int obj_snd_assign(int objnum, int sndnum, vec3d *pos, int main, int flags, ship_subsys *associated_sub)
Definition: objectsnd.cpp:705
#define IS_VEC_NULL_SQ_SAFE(v)
Definition: vecmat.h:24
char * text
Definition: sexp.h:1055
#define CLAMP(x, min, max)
Definition: pstypes.h:488
#define OP_SHIP_SET_DAMAGE_TYPE
Definition: sexp.h:661
waypoint * find_waypoint_with_objnum(int objnum)
Definition: waypoint.cpp:234
void multi_handle_end_mission_request()
Definition: multiutil.cpp:2218
#define OPF_FLEXIBLE_ARGUMENT
Definition: sexp.h:81
#define SEXP_CHECK_DOCKING_NOT_ALLOWED
Definition: sexp.h:955
#define OPF_BOOL
Definition: sexp.h:30
GLint GLsizei width
Definition: Gl.h:1505
#define AIORF_HEADING
Definition: ai.h:127
void ai_do_objects_docked_stuff(object *docker, int docker_point, object *dockee, int dockee_point, bool update_clients=true)
Definition: aicode.cpp:3008
#define OP_SET_AMBIENT_LIGHT
Definition: sexp.h:621
void sexp_set_jumpnode_color(int n)
Definition: sexp.cpp:21988
#define SEXP_CHECK_INVALID_ARRIVAL_ANCHOR_ALL
Definition: sexp.h:971
Definition: hud.h:201
void ship_actually_depart(int shipnum, int method)
Definition: ship.cpp:7748
#define OP_CUTSCENES_FADE_IN
Definition: sexp.h:547
int sexp_has_arrived(int n, fix *latest_time)
Definition: sexp.cpp:5046
int sexp_sound_environment_option_lookup(char *text)
Definition: sexp.cpp:10412
#define OP_LAST_ORDER_TIME
Definition: sexp.h:310
#define OP_MINUS
Definition: sexp.h:217
int sexp_not(int n)
Definition: sexp.cpp:4507
int weapon_info_index
Definition: weapon.h:164
void sexp_set_object_speed(object *objp, int speed, int axis, int subjective)
Definition: sexp.cpp:6652
#define SF2_SCRAMBLE_MESSAGES
Definition: ship.h:509
void sexp_variable_delete(int index)
Definition: sexp.cpp:29545
#define OP_SET_RESPAWNS
Definition: sexp.h:617
#define FBF_WARP_3D
Definition: fireballs.h:61
bool isValid()
Definition: camera.cpp:851
#define OSWPT_TYPE_WING
Definition: sexp.cpp:4653
#define P_SF_HIDDEN_FROM_SENSORS
Definition: missionparse.h:459
GLfloat angle
Definition: Glext.h:10324
SCP_vector< waypoint > & get_waypoints()
Definition: waypoint.cpp:89
void sexp_flash_hud_gauge(int node)
Definition: sexp.cpp:20612
int audiostream_is_playing(int i)
Definition: audiostr.cpp:1827
int sexp_mission_time_msecs()
Definition: sexp.cpp:5584
#define SNF_ARGUMENT_SELECT
Definition: sexp.h:1039
void sexp_close_sound_from_file(int n)
Definition: sexp.cpp:10318
#define OP_GOAL_INCOMPLETE
Definition: sexp.h:260
int ship_type_name_lookup(const char *name)
Definition: ship.cpp:12923
#define OP_IS_IN_BOX
Definition: sexp.h:384
#define CDR(n)
Definition: sexp.h:821
void sexp_beam_floating_fire(int n)
Definition: sexp.cpp:16982
int Directive_count
Definition: sexp.cpp:826
int sexp_waypoint_twice()
Definition: sexp.cpp:15524
int arrival_path_mask
Definition: missionparse.h:372
int objnum
Definition: ship.h:1483
void sexp_set_primary_ammo(int node)
Definition: sexp.cpp:15941
#define OF_TARGETABLE_AS_BOMB
Definition: object.h:118
ship_subsys subsys_list
Definition: ship.h:630
int query_operator_return_type(int op)
Definition: sexp.cpp:25589
#define OP_TURRET_SET_PRIMARY_AMMO
Definition: sexp.h:733
#define OP_TECH_ADD_SHIP
Definition: sexp.h:447
int sexp_bitwise_and(int node)
Definition: sexp.cpp:4278
#define OP_CATEGORY_TRAINING
Definition: sexp.h:153
#define OP_TIME_SHIP_DESTROYED
Definition: sexp.h:293
int arrival_path_mask
Definition: ship.h:1542
int sexp_targeted(int node)
Definition: sexp.cpp:15153
#define OP_TRUE
Definition: sexp.h:239
#define OP_MUL
Definition: sexp.h:219
int rand_sexp(int n, bool multiple)
Definition: sexp.cpp:4315
#define OPR_AI_GOAL
Definition: sexp.h:121
#define OP_MISSION_TIME
Definition: sexp.h:299
#define OP_IS_AI_CLASS
Definition: sexp.h:341
int Training_context_goal_waypoint
Definition: sexp.cpp:838
void sexp_copy_variable_between_indexes(int node)
Definition: sexp.cpp:29234
void multi_sexp_set_persona()
Definition: sexp.cpp:13607
float Sexp_fov
Definition: camera.cpp:16
int object_is_docked(object *objp)
Definition: object.cpp:2019
char name[NAME_LENGTH]
Definition: missionparse.h:313
int sexp_hits_left(int n)
Definition: sexp.cpp:5928
SCP_vector< MMessage > Messages
bool Nav_Set_Visited(char *Nav)
Definition: autopilot.cpp:1545
char * HUD_gauge_text[NUM_HUD_GAUGES]
Definition: sexp.cpp:771
#define OP_CARGO_NO_DEPLETE
Definition: sexp.h:475
int m_kill_count_ok
Definition: scoring.h:115
#define OP_TIME_UNDOCKED
Definition: sexp.h:302
int Sexp_clipboard
Definition: sexp.cpp:831
void do_preload_for_arguments(void(*preloader)(char *), int arg_node, int arg_handler_node)
Definition: sexp.cpp:3233
int Num_op_menus
Definition: sexp.cpp:33851
#define VM_FREECAMERA
Definition: systemvars.h:44
float scale_x
Definition: starfield.h:32
#define OP_NAV_ADD_SHIP
Definition: sexp.h:670
int sexp_string_to_int(int n)
Definition: sexp.cpp:20316
int orders_accepted
Definition: ship.h:624
void sexp_mark_persistent(int n)
Definition: sexp.cpp:1220
void stars_preload_background_bitmap(char *fname)
Definition: starfield.cpp:1889
int Locked_sexp_true
Definition: sexp.cpp:828
bool use_special_explosion
Definition: ship.h:584
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define OP_CATEGORY_OBJECTIVE
Definition: sexp.h:144
#define OBJ_WAYPOINT
Definition: object.h:36
void sexp_set_departure_info(int node)
Definition: sexp.cpp:18887
#define MAX_SHIP_SECONDARY_BANKS
Definition: globals.h:63
int mission_parse_lookup_alt(const char *name)
int sexp_previous_event_status(int n, int status)
Definition: sexp.cpp:13847
void sexp_set_turret_secondary_ammo(int node)
Definition: sexp.cpp:18222
#define OP_ADD_SHIP_GOAL
Definition: sexp.h:768
void set_object_target(object *objp, int n_object_target_submodel=-1)
Definition: camera.cpp:135
int instance
Definition: object.h:150
void multi_sexp_set_camera_facing_object()
Definition: sexp.cpp:21145
#define SHOCK_SPEED
Definition: sexp.h:896
#define OP_WARP_BROKEN
Definition: sexp.h:437
#define OP_UPDATE_SOUND_ENVIRONMENT
Definition: sexp.h:641
char * Parse_object_flags[MAX_PARSE_OBJECT_FLAGS]
int sexp_was_destroyed_by(int n, fix *latest_time)
Definition: sexp.cpp:5239
void sexp_clear_goals(int n)
Definition: sexp.cpp:9754
#define OPF_SHIP
Definition: sexp.h:32
int sexp_facing(int node)
Definition: sexp.cpp:15327
#define OP_CATEGORY_CHANGE
Definition: sexp.h:149
void sexp_set_camera_facing(int n)
Definition: sexp.cpp:21014
void expunge()
Definition: sexp.cpp:996
void sexp_nodes_init()
Definition: sexp.cpp:1036
int waypoint_speed_cap
Definition: ai.h:375
SCP_vector< HudGauge * > default_hud_gauges
Definition: hud.cpp:57
#define OPF_SUBSYSTEM_TYPE
Definition: sexp.h:94
void afterburners_stop(object *objp, int key_released)
#define OP_TURRET_SET_TARGET_PRIORITIES
Definition: sexp.h:635
angles ang
Definition: starfield.h:34
#define FIREBALL_MEDIUM_EXPLOSION
Definition: fireballs.h:23
struct object_ship_wing_point_team object_ship_wing_point_team
#define OP_SET_OBJECT_SPEED_X
Definition: sexp.h:572
matrix * vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
Definition: vecmat.cpp:850
int get_index_sexp_variable_name_special(const char *startpos)
Definition: sexp.cpp:29359
void red_alert_start_mission()
Definition: redalert.cpp:1037
GLenum GLint * range
Definition: Glext.h:7096
Definition: player.h:85
float ship_get_subsystem_strength(ship *shipp, int type)
Definition: ship.cpp:13446
int sexp_secondary_ammo_pct(int node)
Definition: sexp.cpp:15838
void sexp_sabotage_subsystem(int n)
Definition: sexp.cpp:11218
#define OP_SPECIAL_CHECK
Definition: sexp.h:795
p_object * mission_parse_get_arrival_ship(const char *name)
Returns the parse object on the ship arrival list associated with the given name. ...
#define OP_COPY_VARIABLE_BETWEEN_INDEXES
Definition: sexp.h:722
#define SEXP_CHECK_UNKNOWN_ERROR
Definition: sexp.h:966
void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_objnum, int target_is_locked=0, ship_subsys *target_subsys=NULL)
Definition: weapons.cpp:5093
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
float a1d[3]
Definition: pstypes.h:93
const float PI2
Definition: pstypes.h:305
#define MISSION_FLAG_DEACTIVATE_AP
Definition: missionparse.h:90
char pof_file[MAX_FILENAME_LEN]
Definition: ship.h:1183
#define OP_GRANT_PROMOTION
Definition: sexp.h:432
void sexp_set_sound_environment(int node)
Definition: sexp.cpp:10431
void sexp_set_skybox_model(int n)
Definition: sexp.cpp:16801
#define OP_NEBULA_CHANGE_STORM
Definition: sexp.h:580
int shader_effect_start_time
Definition: ship.h:768
int Game_subspace_effect
Definition: fredstubs.cpp:163
int m_okKills[MAX_SHIP_CLASSES]
Definition: scoring.h:113
#define OP_NEXT_MISSION
Definition: sexp.h:758
#define OF_IMMOBILE
Definition: object.h:122
int type_flags
Definition: multi.h:493
ship_subsys * ship_get_indexed_subsys(ship *sp, int index, vec3d *attacker_pos)
Definition: ship.cpp:13340
#define SEXP_CHECK_UNKNOWN_MESSAGE
Definition: sexp.h:946
GLdouble GLdouble GLdouble r
Definition: Glext.h:5337
int Num_sound_environment_options
Definition: sexp.cpp:869
shader Viewer_shader
Definition: systemvars.cpp:39
char * Departure_location_names[MAX_DEPARTURE_NAMES]
#define MAX_DEPARTURE_NAMES
Definition: missionparse.h:244
int sexp_val
Definition: sexp.cpp:25568
float pitch
Definition: physics.h:100
int Num_sexp_nodes
Definition: sexp.cpp:843
void SetModel(char *model_name, bool show_polys=false)
Definition: jumpnode.cpp:190
#define OP_WHEN_ARGUMENT
Definition: sexp.h:393
int eval_num(int node)
Definition: sexp.cpp:29585
int flags
Definition: ship.h:322
#define OP_CAP_SUBSYS_CARGO_KNOWN_DELAY
Definition: sexp.h:316
void unhide_nav(int node)
Definition: sexp.cpp:19467
#define OPF_PERSONA
Definition: sexp.h:91
#define EO_BLAST
Definition: sexp.cpp:880
float max_shield_recharge
Definition: missionparse.h:428
#define SIF_BIG_SHIP
Definition: ship.h:944
int ship_class_query_general_type(int ship_class)
Definition: ship.cpp:14485
bool is_blank_argument_op(int op_const)
Definition: sexp.cpp:9167
#define OP_PERCENT_SHIPS_DISARMED
Definition: sexp.h:287
int target_priority[32]
Definition: ship.h:389
int intel_info_lookup(char *name)
Definition: techmenu.cpp:1422
struct matrix::@228::@230 vec
#define WF_NO_DEPARTURE_WARP
Definition: ship.h:1510
int sub_sexps(int n)
Definition: sexp.cpp:4040
int armor_type_idx
Definition: ship.h:1403
#define SIF_NAVBUOY
Definition: ship.h:891
int sexp_is_secondary_selected(int node)
Definition: sexp.cpp:20057
#define OP_HUD_SET_FRAME
Definition: sexp.h:537
#define SEXP_NOT_USED
Definition: sexp.h:862
int sexp_time_undocked(int n)
Definition: sexp.cpp:5691
int mission_log_get_time(int type, char *pname, char *sname, fix *time)
Definition: missionlog.cpp:498
unsigned int uint
Definition: pstypes.h:64
void send_debrief_event()
Definition: multiutil.cpp:4159
#define OP_TURRET_TAGGED_ONLY_ALL
Definition: sexp.h:471
#define OP_WARP_NEVER
Definition: sexp.h:439
#define LOG_WING_DESTROYED
Definition: missionlog.h:21
void ai_remove_wing_goal_sexp(int sexp, int wingnum)
Definition: aigoals.cpp:1175
#define SEXP_HULL_STRING
Definition: sexp.h:809
#define OP_GREATER_THAN
Definition: sexp.h:245
#define SEXP_ARGUMENT_OPERATOR
Definition: sexp.h:1010
arg_item Sexp_applicable_argument_list
Definition: sexp.cpp:910
#define OP_FOR_COUNTER
Definition: sexp.h:407
void sexp_end_of_campaign(int n)
Definition: sexp.cpp:11171
char dockee[NAME_LENGTH]
#define LOG_SHIP_DISABLED
Definition: missionlog.h:29
int subtype
Definition: lua.cpp:9763
void set_use_ap(int node)
Definition: sexp.cpp:19437
float ship_max_hull_strength
Definition: ship.h:597
#define OP_IS_SUBSYSTEM_DESTROYED
Definition: sexp.h:760
GLboolean GLboolean g
Definition: Glext.h:5781
void stars_set_background_model(char *model_name, char *texture_name, int flags)
Definition: starfield.cpp:2172
int mission_log_get_time_indexed(int type, char *pname, char *sname, int count, fix *time)
Definition: missionlog.cpp:430
#define AIORF_ROLL
Definition: ai.h:125
#define OPF_GAME_SND
Definition: sexp.h:115
int sexp_get_energy_pct(int node, int op_num)
Definition: sexp.cpp:5854
#define OP_EVENT_FALSE_MSECS_DELAY
Definition: sexp.h:271
#define OP_TURRET_SET_OPTIMUM_RANGE
Definition: sexp.h:632
#define OP_GET_THROTTLE_SPEED
Definition: sexp.h:365
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
#define CHANGE_SUBCATEGORY_ARMOR_AND_DAMAGE_TYPES
Definition: sexp.h:188
#define OP_TURRET_TAGGED_SPECIFIC
Definition: sexp.h:523
#define MR_NO_ZBUFFER
Definition: model.h:878
#define OP_SET_DEPARTURE_INFO
Definition: sexp.h:707
int sexp_depart_node_delay(int n)
Definition: sexp.cpp:7640
uint flags
Definition: model.h:169
#define OP_MISSION_SET_SUBSPACE
Definition: sexp.h:522
void eval_when_for_each_special_argument(int cur_node)
Definition: sexp.cpp:8138
#define OP_HAS_DOCKED
Definition: sexp.h:763
const int num_retail_ets_gauges
Definition: hudets.h:40
int div_sexps(int n)
Definition: sexp.cpp:4078
#define P_OF_FLAK_PROTECTED
Definition: missionparse.h:465
#define SEXP_CHECK_INVALID_HUD_ELEMENT
Definition: sexp.h:979
int hud_gauge_type_lookup(char *name)
Definition: sexp.cpp:10004
#define LOG_GOAL_SATISFIED
Definition: missionlog.h:33
int max_sexp(int n)
Definition: sexp.cpp:4163
#define nprintf(args)
Definition: pstypes.h:239
void ignore_gray_space()
Definition: parselo.cpp:83
int Multi_sexp_bytes_left
Definition: multi_sexp.cpp:46
#define GM_MULTIPLAYER
Definition: systemvars.h:18
int Ignored_keys[CCFG_MAX]
Definition: keycontrol.cpp:471
int sexp_string_compare(int n, int op)
Definition: sexp.cpp:4618
#define P_SF_WARP_NEVER
Definition: missionparse.h:480
float cargo_size
Definition: weapon.h:388
void sexp_remove_goal(int n)
Definition: sexp.cpp:9690
int sexp_last_order_time(int n)
Definition: sexp.cpp:7352
int sexp_mission_time()
Definition: sexp.cpp:5576
void multi_sexp_ship_change_callsign()
Definition: sexp.cpp:15027
SCP_vector< squadmsg_history > Squadmsg_history
#define SEXP_FALSE
Definition: sexp.h:919
#define f2i(a)
Definition: fix.h:22
int sexp_num_valid_arguments(int n)
Definition: sexp.cpp:9041
void sexp_turret_tagged_only_all(int node)
Definition: sexp.cpp:17347
#define OP_SABOTAGE_SUBSYSTEM
Definition: sexp.h:415
#define OP_WEAPON_SET_DAMAGE_TYPE
Definition: sexp.h:660
#define OP_CUTSCENES_SET_CUTSCENE_BARS
Definition: sexp.h:545
int primary_bank_ammo[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:121
#define OP_NUM_PLAYERS
Definition: sexp.h:311
#define OP_NOP
Definition: sexp.h:452
#define SEXP_CHECK_INVALID_TEAM_COLOR
Definition: sexp.h:993
#define OP_PLAYER_IS_CHEATING_BASTARD
Definition: sexp.h:718
#define OPF_SHIP_WING_SHIPONTEAM_POINT
Definition: sexp.h:50
#define WIF_IN_TECH_DATABASE
Definition: weapon.h:67
void sexp_stop_music(int fade=1)
Definition: sexp.cpp:10174
void sexp_set_debriefing_toggled(int node)
Definition: sexp.cpp:12367
#define OP_SHIP_SUBSYS_NO_LIVE_DEBRIS
Definition: sexp.h:651
void sexp_weapon_create(int n)
Definition: sexp.cpp:14632
#define OP_UNLOCK_AFTERBURNER
Definition: sexp.h:614
#define CHANGE_SUBCATEGORY_MODELS_AND_TEXTURES
Definition: sexp.h:190
#define OP_CUTSCENES_FADE_OUT
Definition: sexp.h:549
#define SW_FLAG_TURRET_LOCK
Definition: ship.h:95
#define OP_TURRET_SET_SECONDARY_AMMO
Definition: sexp.h:734
int build_sexp_string(SCP_string &accumulator, int cur_node, int level, int mode)
Definition: sexp.cpp:3839
#define OP_TURRET_FREE_ALL
Definition: sexp.h:461
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
#define OP_STRING_LESS_THAN
Definition: sexp.h:251
#define OP_RANDOM_OF
Definition: sexp.h:398
GLclampf GLclampf blue
Definition: Glext.h:5177
#define OP_PLAY_SOUND_FROM_TABLE
Definition: sexp.h:517
char Mission_alt_types[MAX_ALT_TYPE_NAMES][NAME_LENGTH]
void neb2_eye_changed()
Definition: neb.cpp:1111
int secondary_bank_capacity[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:136
#define OP_CHANGE_IFF
Definition: sexp.h:413
#define OP_BITWISE_AND
Definition: sexp.h:228
bool multi_get_int(int &value)
Definition: multi_sexp.cpp:616
int objnum
Definition: weapon.h:165
#define OPF_NEBULA_POOF
Definition: sexp.h:88
op_menu_struct op_submenu[]
Definition: sexp.cpp:33815
void sexp_set_jumpnode_model(int n)
Definition: sexp.cpp:22037
void multi_sexp_eval()
Definition: sexp.cpp:25196
void sexp_int_to_string(int n)
Definition: sexp.cpp:20347
int armor_type_get_idx(char *name)
Definition: ship.cpp:18332
#define OP_CATEGORY_TIME
Definition: sexp.h:145
#define OP_DO_FOR_VALID_ARGUMENTS
Definition: sexp.h:404
int flags
Definition: ship.h:1227
#define OP_TURRET_SET_TARGET_ORDER
Definition: sexp.h:584
float get_hull_pct(object *objp)
Definition: object.cpp:271
void sexp_destroy_instantly(int n)
Definition: sexp.cpp:14752
#define SEXP_VARIABLE_BLOCK
Definition: sexp.h:878
#define MSS_FLAG_ROTATES
Definition: model.h:106
int sexp_shield_recharge_pct(int node)
Definition: sexp.cpp:15592
void sexp_copy_variable_from_index(int node)
Definition: sexp.cpp:29183
int departure_anchor
Definition: missionparse.h:377
#define SIF_SMALL_SHIP
Definition: ship.h:943
void sexp_turret_lock(int node)
Definition: sexp.cpp:17288
void sexp_subsys_set_random(int node)
Definition: sexp.cpp:19982
int test_argument_vector_for_condition(SCP_vector< char * > argument_vector, bool already_dupped, int condition_node, int *num_true, int *num_false, int *num_known_true, int *num_known_false)
Definition: sexp.cpp:8636
char * filename
int sexp_is_disarmed_delay(int n)
Definition: sexp.cpp:5360
void sexp_hud_disable_except_messages(int n)
Definition: sexp.cpp:9792
#define fl_degrees(fl)
Definition: floating.h:45
#define strnicmp(s1, s2, n)
Definition: config.h:272
#define OP_DESTROY_INSTANTLY
Definition: sexp.h:709
int distance_to_nav(int node)
Definition: sexp.cpp:19528
void sexp_change_argument_validity(int n, bool invalidate)
Definition: sexp.cpp:9064
netgame_info Netgame
Definition: multi.cpp:97
#define OPF_TARGET_PRIORITIES
Definition: sexp.h:96
object * sexp_camera_get_objsub(int node, int *o_submodel)
Definition: sexp.cpp:21223
#define OP_CATEGORY_AI
Definition: sexp.h:152
#define OP_ADJUST_AUDIO_VOLUME
Definition: sexp.h:643
#define OP_TURRET_LOCK
Definition: sexp.h:462
#define OP_TIME_WING_DEPARTED
Definition: sexp.h:298
int damage_type_idx
Definition: weapon.h:519
#define OPR_NUMBER
Definition: sexp.h:118
int num_secondary_banks
Definition: ship.h:100
ai_goal goals[MAX_AI_GOALS]
Definition: ai.h:412
#define OBJ_WEAPON
Definition: object.h:33
void sexp_set_oswpt_facing(object_ship_wing_point_team *oswpt, vec3d *location, int turn_time=0, int bank=0)
Definition: sexp.cpp:7134
#define OP_SHIP_UNTAG
Definition: sexp.h:541
int snd_play_3d(game_snd *gs, vec3d *source_pos, vec3d *listen_pos, float radius, vec3d *source_vel, int looping, float vol_scale, int priority, vec3d *sound_fvec, float range_factor, int force, bool is_ambient)
Definition: sound.cpp:594
int subtype
Definition: sexp.h:1030
int sexp_get_sound_index(int node)
Definition: sexp.cpp:10227
int sexp_set_bit(int node, bool set_it)
Definition: sexp.cpp:4242
#define OPF_AI_GOAL
Definition: sexp.h:37
#define BLAST
Definition: sexp.h:894
mission_event Mission_events[MAX_MISSION_EVENTS]
Persona * Personas
#define OP_VALIDATE_ARGUMENT
Definition: sexp.h:403
#define OPF_HUD_ELEMENT
Definition: sexp.h:99
int find_argnum(int parent, int arg)
Definition: sexp.cpp:1539
fix time
Definition: ai.h:140
bool AddNav_Ship(char *Nav, char *TargetName, int flags)
Definition: autopilot.cpp:1384
void multi_send_string(char *string)
Definition: multi_sexp.cpp:344
#define OPF_SHIP_WING_POINT
Definition: sexp.h:51
void sexp_dont_collide_invisible(int n, bool dont_collide)
Definition: sexp.cpp:14158
#define P_OF_LASER_PROTECTED
Definition: missionparse.h:466
#define SRC_MISSION_GOAL
Definition: sexp.h:847
#define CHANGE_SUBCATEGORY_AI_CONTROL
Definition: sexp.h:183
#define OP_IS_IFF
Definition: sexp.h:346
int flags
Definition: sexp.h:1057
arg_item()
Definition: sexp.h:1060
#define OP_SHIP_CREATE
Definition: sexp.h:570
#define MAX_WEAPON_TYPES
Definition: globals.h:73
int ship_get_SIF(ship *shipp)
Definition: ship.cpp:16096
void send_change_iff_packet(ushort net_signature, int new_team)
Definition: multimsgs.cpp:7483
void sexp_nebula_change_storm(int n)
Definition: sexp.cpp:12277
int sexp_get_damage_caused(int node)
Definition: sexp.cpp:7512
#define OP_PERCENT_SHIPS_DESTROYED
Definition: sexp.h:284
void zero_one_ets(int *reduce, int *add1, int *add2)
Definition: hudets.cpp:651
void sexp_scramble_messages(int node, bool scramble)
Definition: sexp.cpp:20661
int stars_find_bitmap(char *name)
Definition: starfield.cpp:2217
int sexp_calculate_coordinate(vec3d *origin, matrix *orient, vec3d *relative_location, int axis)
Definition: sexp.cpp:6783
float hull_strength
Definition: object.h:160
#define NOT_A_SEXP_OPERATOR
Definition: sexp.cpp:924
#define OP_CLOSE_SOUND_FROM_FILE
Definition: sexp.h:519
#define SEXP_CHECK_INVALID_ANIMATION_TYPE
Definition: sexp.h:990
int persona_index
Definition: ship.h:696
#define OP_AND
Definition: sexp.h:241
#define OP_FACING2
Definition: sexp.h:797
void sexp_pause_sound_from_file(int node)
Definition: sexp.cpp:10392
int Num_skybox_flags
Definition: sexp.cpp:816
#define OP_AI_DOCK
Definition: sexp.h:738
void game_shudder_apply(int, float)
Definition: fredstubs.cpp:207
void vm_vec_sub2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:187
void message_translate_tokens(char *buf, char *text)
#define MISSION_FLAG_END_TO_MAINHALL
Definition: missionparse.h:92
#define OP_ADD_TO_COLGROUP
Definition: sexp.h:690
void ship_subsys_set_name(ship_subsys *ss, char *n_name)
Definition: ship.cpp:15017
#define MESSAGE_SOURCE_SHIP
#define w(p)
Definition: modelsinc.h:68
#define MAX_MODEL_SUBSYSTEMS
Definition: model.h:103
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
GLint location
Definition: Glext.h:5627
int eval_in_sequence(int arg_handler_node, int condition_node)
Definition: sexp.cpp:8888
#define NG_TYPE_TEAM
Definition: multi.h:650
#define STATUS_SUBCATEGORY_MISSION
Definition: sexp.h:204
int ai_mode
Definition: ai.h:136
ai_flag_name Ai_flag_names[]
Definition: aicode.cpp:203
float ship_max_hull_strength
Definition: missionparse.h:425
#define AIORF_SIDEWAYS
Definition: ai.h:130
#define OP_SHIP_EFFECT
Definition: sexp.h:693
#define MAX_CARGO
Definition: missionparse.h:222
void multi_discard_remaining_callback_data()
Definition: multi_sexp.cpp:819
void hud_gauge_start_flash(int gauge_index)
Call HUD function to flash gauge.
Definition: hud.cpp:3066
float damage_ship[MAX_DAMAGE_SLOTS]
Definition: ship.h:694
#define OP_IS_PLAYER
Definition: sexp.h:358
void sexp_trigger_submodel_animation(int node)
Definition: sexp.cpp:18429
float forward
Definition: physics.h:105
#define BFIF_FLOATING_BEAM
Definition: beam.h:53
int Intel_info_size
Definition: techmenu.cpp:247
bool multi_get_string(char *buffer)
Definition: multi_sexp.cpp:726
#define OP_SET_POST_EFFECT
Definition: sexp.h:631
void multi_sexp_reset_camera()
Definition: sexp.cpp:21413
#define WF_NO_ARRIVAL_WARP
Definition: ship.h:1509
#define OPF_TEAM_COLOR
Definition: sexp.h:112
#define OP_DONT_COLLIDE_INVISIBLE
Definition: sexp.h:496
#define OP_NAV_USEAP
Definition: sexp.h:683
int sexp_is_destroyed(int n, fix *latest_time)
Definition: sexp.cpp:4965
int get_sexp()
Definition: sexp.cpp:3295
void set_time_compression(float multiplier, float change_time)
Definition: fredstubs.cpp:229
#define SEXP_ANY_STRING
Definition: sexp.h:816
#define MAX_AI_GOALS
Definition: ai.h:91
#define CAMPAIGN_PERSISTENT_SHIP
void hud_shield_quadrant_hit(object *objp, int quadrant)
Definition: hudshield.cpp:541
GLdouble GLdouble z
Definition: Glext.h:5451
void set_primary_ammo(int ship_index, int requested_bank, int requested_ammo, int rearm_limit, bool update)
Definition: sexp.cpp:15983
#define OP_TIME_SHIP_ARRIVED
Definition: sexp.h:294
int Num_operators
Definition: sexp.cpp:829
ship * sexp_get_ship_from_node(int node)
Definition: sexp.cpp:3967
#define OP_END_CAMPAIGN
Definition: sexp.h:449
#define P_OF_MISSILE_PROTECTED
Definition: missionparse.h:467
#define OP_WARP_ALLOWED
Definition: sexp.h:440
#define SF_HIDDEN_FROM_SENSORS
Definition: ship.h:464
int Current_mission_mood
int n_subsystems
Definition: ship.h:1270
int flag
Definition: ai.h:30
#define SEXP_MODE_CAMPAIGN
Definition: sexp.h:857
int op_index
Definition: sexp.h:1028
int sexp_num_ships_in_wing(int n)
Definition: sexp.cpp:4900
void multi_sexp_reset_time_compression()
Definition: sexp.cpp:21893
#define OP_SHIP_ROT_MANEUVER
Definition: sexp.h:627
#define SEXP_CHECK_INVALID_POINT
Definition: sexp.h:942
#define SEXP_NAN_FOREVER
Definition: sexp.h:925
void multi_sexp_set_camera_shudder()
Definition: sexp.cpp:21940
#define OF_PROTECTED
Definition: object.h:108
#define OP_MIN
Definition: sexp.h:223
void sexp_unmark_persistent(int n)
Definition: sexp.cpp:1242
#define OPR_NULL
Definition: sexp.h:120
#define OP_SCRIPT_EVAL_BLOCK
Definition: sexp.h:731
bool generate_special_explosion_block_variables()
Definition: sexp.cpp:3726
void sexp_set_ship_man(object *objp, int duration, int heading, int pitch, int bank, bool apply_all_rotate, int up, int sideways, int forward, bool apply_all_lat)
Definition: sexp.cpp:7211
void sexp_turret_set_optimum_range(int node)
Definition: sexp.cpp:17874
#define OP_AI_EVADE_SHIP
Definition: sexp.h:748
#define SUBSYSTEM_TURRET
Definition: model.h:54
void multi_send_ship(int shipnum)
Definition: multi_sexp.cpp:276
void sexp_hud_set_message(int n)
Definition: sexp.cpp:9834
int sexp_is_tagged(int node)
Definition: sexp.cpp:19549
void hud_add_ship_to_escort(int objnum, int supress_feedback)
Definition: hudescort.cpp:849
int Sexp_useful_number
Definition: sexp.cpp:827
#define OP_BEAM_LOCK
Definition: sexp.h:456
int free_sexp2(int num)
Definition: sexp.cpp:1321
#define OP_CUTSCENES_FORCE_PERSPECTIVE
Definition: sexp.h:560
#define OP_SHIELDS_ON
Definition: sexp.h:478
#define OPF_SUN_BITMAP
Definition: sexp.h:86
int total_departed
Definition: ship.h:1534
int iff_lookup(char *iff_name)
Definition: iff_defs.cpp:540
int special_exp_deathroll_time
Definition: ship.h:591
#define SSF_CARGO_REVEALED
Definition: ship.h:279
#define vm_strdup(ptr)
Definition: pstypes.h:549
fix Skybox_timestamp
Definition: systemvars.cpp:20
void set_secondary_ammo(int ship_index, int requested_bank, int requested_ammo, int rearm_limit, bool update)
Definition: sexp.cpp:16131
void sexp_toggle_cutscene_bars(int node, int set)
Definition: sexp.cpp:20696
#define OP_SHIP_VULNERABLE
Definition: sexp.h:444
int stars_find_sun(char *name)
Definition: starfield.cpp:2236
int alt_iff_color[MAX_IFFS][MAX_IFFS]
Definition: missionparse.h:435
#define OPF_NEBULA_PATTERN
Definition: sexp.h:113
int sexp_xor(int node)
Definition: sexp.cpp:4530
void DeselectNav()
Definition: autopilot.cpp:1585
#define OP_UNLOCK_SECONDARY_WEAPON
Definition: sexp.h:601
void sexp_set_countermeasures(int node)
Definition: sexp.cpp:16293
void sexp_field_set_damage_type(int node)
Definition: sexp.cpp:17713
#define OP_HUD_DISABLE
Definition: sexp.h:520
#define NUM_HUD_GAUGES
Definition: hudgauges.h:16
void sexp_parse_ship_change_iff(p_object *parse_obj, int new_team)
Definition: sexp.cpp:9288
char cargo1
Definition: ship.h:549
void multi_sexp_add_nav_waypoint()
Definition: sexp.cpp:19336
int sexp_explosion_option_lookup(char *text)
Definition: sexp.cpp:10557
void SetVisibility(bool enabled)
Definition: jumpnode.cpp:241
#define OP_TRIGGER_SUBMODEL_ANIMATION
Definition: sexp.h:698
int required_string(const char *pstr)
Definition: parselo.cpp:468
int sexp_ship_type_destroyed(int n)
Definition: sexp.cpp:5533
void multi_sexp_set_camera_facing()
Definition: sexp.cpp:21059
sexp_com_order Sexp_comm_orders[]
void sexp_ships_visible(int n, bool visible)
Definition: sexp.cpp:14187
#define OP_BEAM_FREE
Definition: sexp.h:454
void unrestrict_nav(int node)
Definition: sexp.cpp:19475
#define OP_SET_SUBSYSTEM_STRNGTH
Definition: sexp.h:416
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
#define MAX_DAMAGE_SLOTS
Definition: ship.h:516
int arrival_location
Definition: missionparse.h:369
int eval_perform_actions(int n)
Definition: sexp.cpp:8365
#define AI_GOAL_STAY_STILL
Definition: aigoals.h:52
#define OP_SHIP_VISIBLE
Definition: sexp.h:442
void sexp_ingame_ship_change_iff(ship *shipp, int new_team)
Definition: sexp.cpp:9276
#define OP_MODIFY_VARIABLE
Definition: sexp.h:451
int engine_recharge_index
Definition: ship.h:639
GLuint buffer
Definition: Glext.h:5492
#define SF_PRIMARY_LINKED
Definition: ship.h:458
#define fl_abs(fl)
Definition: floating.h:31
#define OPF_NAV_POINT
Definition: sexp.h:79
int Num_wings
Definition: ship.cpp:120
#define MB_OK
Definition: config.h:179
#define SEXP_CHECK_INVALID_AI_CLASS
Definition: sexp.h:965
#define FS_VERSION_MINOR
Definition: version.h:38
void multi_sexp_script_eval_multi()
Definition: sexp.cpp:22262
#define PF_FORCE_GLIDE
Definition: physics.h:33
void multi_sexp_set_camera_position()
Definition: sexp.cpp:20924
void sexp_change_goal_validity(int n, int flag)
Definition: sexp.cpp:11631
int sexp_special_warpout_name(int node)
Definition: sexp.cpp:7739
fix game_get_overall_frametime()
Definition: fredstubs.cpp:230
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:104
#define OP_NAV_USECINEMATICS
Definition: sexp.h:682
int Num_teams
#define OP_GREATER_OR_EQUAL
Definition: sexp.h:253
HudGauge * hud_get_gauge(const char *name)
Definition: hud.cpp:3721
int Num_ai_classes
Definition: aicode.cpp:195
int query_sexp_ai_goal_valid(int sexp_ai_goal, int ship_num)
Definition: sexp.cpp:28771
#define OP_BITWISE_XOR
Definition: sexp.h:231
#define OP_TIME_WING_DESTROYED
Definition: sexp.h:296
GLdouble s
Definition: Glext.h:5321
int sexp_or(int n)
Definition: sexp.cpp:4367
void multi_send_parse_object(p_object *pobjp)
Definition: multi_sexp.cpp:326
#define HUD_OBJECT_MESSAGES
Definition: hudparse.h:70
#define OPF_MESSAGE_OR_STRING
Definition: sexp.h:105
#define SEXP_CANT_EVAL
Definition: sexp.h:926
#define OP_ALLOW_WEAPON
Definition: sexp.h:435
#define OPF_GOAL_NAME
Definition: sexp.h:47
#define OP_ALLOW_SHIP
Definition: sexp.h:434
bool can_construe_as_integer(const char *text)
Definition: parselo.cpp:3778
int Training_context_speed_max
Definition: sexp.cpp:835
#define OPF_SHIP_FLAG
Definition: sexp.h:111
void lcl_replace_stuff(char *text, size_t max_len)
Definition: localize.cpp:573
void sexp_primitive_sensors_set_range(int n)
Definition: sexp.cpp:19102
int sexp_skill_level_at_least(int n)
Definition: sexp.cpp:7415
void sexp_awacs_set_radius(int node)
Definition: sexp.cpp:19074
#define SEXP_CHECK_ORDER_NOT_ALLOWED
Definition: sexp.h:954
object * dock_get_first_docked_object(object *objp)
Definition: objectdock.cpp:47
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:355
void sexp_deal_with_secondary_lock(int node, bool lock)
Definition: sexp.cpp:16349
void sexp_parse_ship_alt_name(p_object *parse_obj, int alt_index)
Definition: sexp.cpp:14901
#define MAX_PLAYERS
Definition: pstypes.h:32
#define OP_FACING
Definition: sexp.h:788
int sexp_percent_ships_arrive_depart_destroy_disarm_disable(int n, int what)
Definition: sexp.cpp:7575
void multi_sexp_set_ets_values()
Definition: sexp.cpp:15711
char skybox_model[MAX_FILENAME_LEN]
Definition: missionparse.h:147
#define OP_CUTSCENES_SET_TIME_COMPRESSION
Definition: sexp.h:558
#define OPF_DOCKER_POINT
Definition: sexp.h:38
#define P_OF_PROTECTED
Definition: missionparse.h:449
void multi_sexp_set_fov()
Definition: sexp.cpp:21345
#define LOG_CAP_SUBSYS_CARGO_REVEALED
Definition: missionlog.h:38
int current_count
Definition: ship.h:1530
char * Turret_target_order_names[NUM_TURRET_ORDER_TYPES]
Definition: aiturret.cpp:50
int ai_query_goal_valid(int ship, int ai_goal_type)
Definition: aigoals.cpp:208
void sexp_tech_add_weapon(int node)
Definition: sexp.cpp:12534
void select_nav(int node)
Definition: sexp.cpp:19534
void sexp_ship_subsys_guardian_threshold(int num)
Definition: sexp.cpp:14475
#define OP_GET_DAMAGE_CAUSED
Definition: sexp.h:359
void del_nav(int node)
Definition: sexp.cpp:19399
void sexp_change_iff(int n)
Definition: sexp.cpp:9296
#define OP_PERFORM_ACTIONS
Definition: sexp.h:257
void sexp_clear_wing_goals(int n)
Definition: sexp.cpp:9738
void SelectNav(char *Nav)
Definition: autopilot.cpp:1574
void sexp_reset_fov()
Definition: sexp.cpp:21374
#define OP_EVERY_OF
Definition: sexp.h:397
#define CDDDDR(n)
Definition: sexp.h:829
void sexp_beam_free(int node)
Definition: sexp.cpp:17077
#define OPF_ANYTHING
Definition: sexp.h:82
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)
Definition: sexp.cpp:12667
int collision_damage_type_idx
Definition: ship.h:798
int ship_has_energy_weapons(ship *shipp)
Definition: ship.cpp:17611
int subsys_cargo_name
Definition: ship.h:373
void ai_set_rearm_status(int team, int new_status)
Definition: aicode.cpp:300
bool dc_optional_string_either(const char *str1, const char *str2)
Searches for an optional string and it's alias.
int sexp_current_speed(int n)
Definition: sexp.cpp:4943
int validate_float(char **str)
Definition: sexp.cpp:28511
int callsign_index
Definition: ship.h:557
int op_num
Definition: multi_sexp.cpp:48
#define DEFAULT_SHIELD_SECTIONS
Definition: object.h:24
void actually_set_camera_facing_object(char *object_name, float rot_time, float rot_acc_time, float rot_dec_time)
Definition: sexp.cpp:21084
#define OP_FORCE_JUMP
Definition: sexp.h:533
#define OP_PLAYER_NOT_USE_AI
Definition: sexp.h:530
int sexp_is_subsystem_destroyed(int n)
Definition: sexp.cpp:5020
float current_hits
Definition: ship.h:319
void insertion_sort(void *array_base, size_t array_size, size_t element_size, int(*fncompare)(const void *, const void *))
Definition: systemvars.cpp:599
void sexp_set_subsystem_strength(int n)
Definition: sexp.cpp:11438
int turret_targeting_order[NUM_TURRET_ORDER_TYPES]
Definition: ship.h:341
void do_subobj_destroyed_stuff(ship *ship_p, ship_subsys *subsys, vec3d *hitpos, bool no_explosion)
Definition: shiphit.cpp:108
#define OPF_PRIORITY
Definition: sexp.h:42
#define RIGHT_QUAD
Definition: objectshield.h:19
void sexp_ship_change_callsign(int node)
Definition: sexp.cpp:14986
void sexp_hud_set_retail_gauge_active(int node)
Definition: sexp.cpp:10035
void multi_sexp_hud_disable_except_messages()
Definition: sexp.cpp:9802
int armor_type_idx
Definition: ship.h:325
int sexp_is_disarmed(int n, fix *latest_time)
Definition: sexp.cpp:5174
Definition: ship.h:534
#define OP_VALIDATE_ALL_ARGUMENTS
Definition: sexp.h:406
#define OP_PLUS
Definition: sexp.h:216
#define OP_NOT_EQUAL
Definition: sexp.h:252
#define SRC_WING_DEPARTURE
Definition: sexp.h:845
#define OPF_SHIP_WING_WHOLETEAM
Definition: sexp.h:49
int category_of_subcategory(int subcategory_id)
Definition: sexp.cpp:29623
GLenum GLuint id
Definition: Glext.h:5156
#define SIF_BALLISTIC_PRIMARIES
Definition: ship.h:880
int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, int ferror=1, int duplicate=0)
Definition: modelread.cpp:2573
int ship_get_random_ship_in_wing(int wingnum, int flags, float max_dist, int get_first)
Definition: ship.cpp:14623
#define OP_SHIP_MANEUVER
Definition: sexp.h:626
#define OP_HUD_SET_MAX_TARGETING_RANGE
Definition: sexp.h:539
char Mission_filename[80]
void sexp_cargo_no_deplete(int n)
Definition: sexp.cpp:12006
#define OP_TECH_ADD_INTEL_XSTR
Definition: sexp.h:719
void emp_apply(vec3d *pos, float inner_radius, float outer_radius, float emp_intensity, float emp_time, bool use_emp_time_for_capship_turrets)
Definition: emp.cpp:103
int generate_event_log_flags_mask(int result)
Definition: sexp.cpp:22676
#define AIORF_UP
Definition: ai.h:129
#define OP_GRANT_MEDAL
Definition: sexp.h:433
#define AI_GOAL_EVADE_SHIP
Definition: aigoals.h:44
#define OP_CATEGORY_LOGICAL
Definition: sexp.h:146
int get_operator_index(const char *token)
Definition: sexp.cpp:1561
#define OP_HAS_TIME_ELAPSED
Definition: sexp.h:247
int initial_shields
Definition: missionparse.h:367
int total_destroyed
Definition: ship.h:1533
void message_training_queue(char *text, int timestamp, int length)
#define SRC_EVENT
Definition: sexp.h:846
void multi_send_ushort(ushort value)
Definition: multi_sexp.cpp:436
int beam_fire(beam_fire_info *fire_info)
Definition: beam.cpp:281
#define OP_IGNORE_KEY
Definition: sexp.h:806
#define OPF_MISSION_NAME
Definition: sexp.h:45
void model_page_in_textures(int modelnum, int ship_info_index=-1)
#define OP_SCRIPT_EVAL_NUM
Definition: sexp.h:348
#define OP_HAS_ARRIVED
Definition: sexp.h:765
float apply_damage_to_shield(object *objp, int quadrant, float damage)
Definition: shield.cpp:644
#define SEXP_CHECK_INVALID_TARGET_PRIORITIES
Definition: sexp.h:987
void sexp_set_jumpnode_name(int n)
Definition: sexp.cpp:21951
int sexp_get_variable_by_index(int node)
Definition: sexp.cpp:29147
int find_free_sexp()
Definition: sexp.cpp:1200
#define OP_AI_KEEP_SAFE_DISTANCE
Definition: sexp.h:750
#define MESSAGE_PRIORITY_LOW
int idx
Definition: multiui.cpp:761
#define FIRST_OP
Definition: sexp.h:137
#define OPF_HUGE_WEAPON
Definition: sexp.h:62
#define OPF_HUD_GAUGE_NAME
Definition: sexp.h:61
#define OP_SET_PLAYER_ORDERS
Definition: sexp.h:700
uint respawn_count
Definition: missionparse.h:419
#define FIREBALL_WARP
Definition: fireballs.h:29
void sexp_force_perspective(int n)
Definition: sexp.cpp:21901
#define OP_GET_OBJECT_SPEED_Y
Definition: sexp.h:377
char * sexp_get_result_as_text(int result)
Definition: sexp.cpp:22803
int secondary_bank_ammo[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:134
void sexp_add_array_block_variable(int index, bool is_numeric)
Definition: sexp.cpp:28954
unsigned __int64 uint64_t
Definition: stdint.h:90
cfbp fp
Definition: cfile.cpp:1065
SCP_vector< char * > Applicable_arguments_temp
Definition: sexp.cpp:907
sexp_node * Sexp_nodes
Definition: sexp.cpp:844
#define OP_TIME_SHIP_DEPARTED
Definition: sexp.h:295
GLdouble GLdouble t
Definition: Glext.h:5329
int sexp_distance_subsystem(int n)
Definition: sexp.cpp:6502
int sexp_distance2(object *objp1, object_ship_wing_point_team *oswpt2)
Definition: sexp.cpp:6320
GLclampf green
Definition: Glext.h:5177
void audiostream_unpause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1960
void ship_set_new_ai_class(int ship_num, int new_ai_class)
Definition: ship.cpp:17362
int arrival_distance
Definition: missionparse.h:370
#define SF_NO_DEPARTURE_WARP
Definition: ship.h:441
#define SIF_IN_TECH_DATABASE
Definition: ship.h:897
#define OP_TURRET_FREE
Definition: sexp.h:460
#define SEXP_CHECK_INVALID_WING
Definition: sexp.h:939
#define OP_DEPART_NODE_DELAY
Definition: sexp.h:285
int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, int mode)
Definition: sexp.cpp:1658
bool sexp_check_flag_arrays(char *flag_name, int &object_flag, int &object_flag2, int &ship_flags, int &ship_flags2, int &parse_obj_flag, int &parse_obj_flag2, int &ai_flag, int &ai_flag2)
Definition: sexp.cpp:13113
void sexp_exchange_cargo(int n)
Definition: sexp.cpp:11860
#define OP_INVALIDATE_GOAL
Definition: sexp.h:423
ubyte c
Definition: 2d.h:84
void ship_recalc_subsys_strength(ship *shipp)
Definition: ship.cpp:6020
#define OP_SET_OBJECT_FACING_OBJECT
Definition: sexp.h:515
int sexp_weapon_recharge_pct(int node)
Definition: sexp.cpp:15626
#define stars_mark_bitmap_unused(x)
Definition: starfield.h:75
#define OP_STRING_TO_INT
Definition: sexp.h:374
#define OP_AI_STAY_STILL
Definition: sexp.h:752
char name[NAME_LENGTH]
vec3d * vm_vec_unrotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:959
void sexp_set_skybox_orientation(int n)
Definition: sexp.cpp:16782
#define OP_NAV_SELECT
Definition: sexp.h:713
int get_string(char *str, int max)
Definition: parselo.cpp:1157
#define OP_SHIP_VAPORIZE
Definition: sexp.h:493
#define OP_HITS_LEFT_SUBSYSTEM_SPECIFIC
Definition: sexp.h:367
void multi_oo_send_changed_object(object *changedobj)
Definition: multi_obj.cpp:1485
#define AIORF_PITCH
Definition: ai.h:126
#define OSWPT_TYPE_WHOLE_TEAM
Definition: sexp.cpp:4656
void ship_apply_global_damage(object *ship_objp, object *other_obj, vec3d *force_center, float damage)
Definition: shiphit.cpp:2476
sexp_ai_goal_link Sexp_ai_goal_links[]
Definition: sexp.cpp:746
int ship_query_state(char *name)
Definition: ship.cpp:12945
#define OP_SHIP_SCORE
Definition: sexp.h:355
sexp_oper Operators[]
Definition: sexp.cpp:118
int Sexp_current_argument_nesting_level
Definition: sexp.cpp:906
#define OP_JUMP_NODE_SET_JUMPNODE_MODEL
Definition: sexp.h:563
void sexp_remove_background_bitmap(int n)
Definition: sexp.cpp:12169
void maybe_write_to_event_log(int result)
Definition: sexp.cpp:22769
#define OP_ANY_OF
Definition: sexp.h:396
int wave_count
Definition: ship.h:1527
#define OP_TECH_RESET_TO_DEFAULT
Definition: sexp.h:510
#define SEXP_CHECK_INVALID_ARMOR_TYPE
Definition: sexp.h:985
#define AI_GOAL_IGNORE_NEW
Definition: aigoals.h:57
char * Subsystem_types[SUBSYSTEM_MAX]
Definition: modelread.cpp:95
#define OP_NUM_CLASS_KILLS
Definition: sexp.h:322
void event_sexp_change_soundtrack(char *name)
#define SEXP_ALL_TURRETS_STRING
Definition: sexp.h:813
void multi_sexp_show_subtitle_image()
Definition: sexp.cpp:21810
font Fonts[MAX_FONTS]
Definition: font.cpp:35
int num_target_priorities
Definition: model.h:231
void sexp_change_all_argument_validity(int n, bool invalidate)
Definition: sexp.cpp:9008
int Training_context
Definition: sexp.cpp:832
camid cam_get_current()
Definition: camera.cpp:952
int type
Definition: sexp.h:1043
#define OP_MISSION_TIME_MSECS
Definition: sexp.h:300
#define SEXP_FLAG_PERSISTENT
Definition: sexp.h:867
void sexp_explosion_effect(int n)
Definition: sexp.cpp:10660
#define MAX_PARSE_OBJECT_FLAGS_2
Definition: missionparse.h:486
void hide_nav(int node)
Definition: sexp.cpp:19451
#define OP_PATH_FLOWN
Definition: sexp.h:791
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
for(int idx=0;idx< i;idx++)
Definition: multi_pxo.cpp:472
#define OPF_SOUND_ENVIRONMENT_OPTION
Definition: sexp.h:101
int rand_internal(int low, int high, int seed=0)
Definition: sexp.cpp:4122
void object_jettison_cargo(object *objp, object *cargo_objp)
Definition: ship.cpp:16911
#define OP_NAV_RESTRICT
Definition: sexp.h:673
#define MESSAGE_LENGTH
Definition: globals.h:23
long fix
Definition: pstypes.h:54
GLclampd n
Definition: Glext.h:7286
#define SNF_ARGUMENT_VALID
Definition: sexp.h:1038
int ssm_info_lookup(const char *name)
#define AITTV_VIA_SEXP
Definition: ai.h:118
#define WF_NAV_CARRY
Definition: ship.h:1513
#define OP_SET_MOTION_DEBRIS
Definition: sexp.h:726
#define SEXP_CHECK_INVALID_SUPPORT_SHIP_CLASS
Definition: sexp.h:967
#define MULTI_NOT_DOGFIGHT
Definition: multi.h:661
unsigned char ubyte
Definition: pstypes.h:62
void sexp_set_training_context_fly_path(int node)
Definition: sexp.cpp:20640
#define AI_GOAL_PLAY_DEAD
Definition: aigoals.h:53
#define OP_SHIELD_QUAD_LOW
Definition: sexp.h:326
#define OP_SHIP_TYPE_DESTROYED
Definition: sexp.h:282
#define OP_GOAL_TRUE_DELAY
Definition: sexp.h:261
#define stars_get_num_bitmaps()
Definition: starfield.h:68
int wi_flags
Definition: weapon.h:384
void sexp_tech_reset_to_default()
Definition: sexp.cpp:12611
int sexp_variable_count()
Definition: sexp.cpp:29490
void sexp_turret_free_all(int node)
Definition: sexp.cpp:17255
#define ARG_ITEM_F_DUP
Definition: sexp.h:1049
uint flags
Definition: physics.h:37
void sexp_alter_ship_flag(int node)
Definition: sexp.cpp:13234
void hud_set_draw(int draw)
Definition: hud.cpp:1276
void sexp_string_set_substring(int node)
Definition: sexp.cpp:20484
#define OP_IS_BIT_SET
Definition: sexp.h:235
int sexp_number_compare(int n, int op)
Definition: sexp.cpp:4544
int ship_create(matrix *orient, vec3d *pos, int ship_type, char *ship_name)
Definition: ship.cpp:9690
#define OP_SET_ARMOR_TYPE
Definition: sexp.h:636
float primary_bank_fof_cooldown[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:128
#define P_SF_GUARDIAN
Definition: missionparse.h:468
void sexp_jettison_cargo(int n)
Definition: sexp.cpp:11918
#define OP_PREVIOUS_EVENT_TRUE
Definition: sexp.h:266
#define OP_ADD_BACKGROUND_BITMAP
Definition: sexp.h:576
#define OP_TURRET_SET_RATE_OF_FIRE
Definition: sexp.h:645
int sexp_player_is_cheating_bastard()
Definition: sexp.cpp:22621
void send_force_end_mission_packet()
Definition: multimsgs.cpp:3821
int get_generic_subsys(char *subsy_name)
Definition: sexp.cpp:22636
#define AI_GOAL_WAYPOINTS_ONCE
Definition: aigoals.h:32
void sexp_protect_ships(int n, bool flag)
Definition: sexp.cpp:14118
#define OP_SHIP_CHANGE_ALT_NAME
Definition: sexp.h:542
int objnum
Definition: player.h:124
int sexp_path_flown()
Definition: sexp.cpp:15535
void sexp_set_skybox_model_preload(char *name)
Definition: sexp.cpp:16852
#define SF_NO_ARRIVAL_WARP
Definition: ship.h:440
#define OP_AI_CHASE_WING
Definition: sexp.h:772
int mission_campaign_find_mission(char *name)
#define OPF_SKYBOX_MODEL_NAME
Definition: sexp.h:83
#define OP_SET_CAMERA_SHUDDER
Definition: sexp.h:602
float Energy_levels[NUM_ENERGY_LEVELS]
Definition: hudets.cpp:26
#define OP_DEACTIVATE_GLOW_POINTS
Definition: sexp.h:502
#define OBJ_INDEX(objp)
Definition: object.h:235
#define SEXP_CHECK_INVALID_SHIP_CLASS_NAME
Definition: sexp.h:961
#define OP_SHIP_INVULNERABLE
Definition: sexp.h:443
void set_current_hud()
Definition: hudparse.cpp:669
int abs_sexp(int n)
Definition: sexp.cpp:4139
int sexp_goal_incomplete(int n)
Definition: sexp.cpp:14100
#define MULTI_TEAM
Definition: multi.h:655
#define OP_CLEAR_GOALS
Definition: sexp.h:420
int shield_armor_type_idx
Definition: ship.h:797
void mission_goal_mark_invalid(char *name)
int query_node_in_sexp(int node, int sexp)
Definition: sexp.cpp:1437
#define OP_TURRET_LOCK_ALL
Definition: sexp.h:464
ship * Player_ship
Definition: ship.cpp:124
void sexp_friendly_stealth_invisible(int n, bool invisible)
Definition: sexp.cpp:14228
#define OP_ACTIVATE_GLOW_MAPS
Definition: sexp.h:505
int sexp_has_been_tagged_delay(int n)
Definition: sexp.cpp:8063
#define SEXP_ARITHMETIC_OPERATOR
Definition: sexp.h:1012
char * Sound_environment_option[]
Definition: sexp.cpp:868
DCF(sexp,"Runs the given sexp")
Definition: sexp.cpp:25573
#define MLF_STATE_CHANGE
Definition: missiongoals.h:97
int num_waves
Definition: ship.h:1522
#define OP_IS_DISABLED_DELAY
Definition: sexp.h:275
SCP_string team_name
Definition: ship.h:812
#define LOG_SHIP_DESTROYED
Definition: missionlog.h:20
int ai_override_flags
Definition: ai.h:548
int ds_eax_set_damping(float damp)
Definition: ds.cpp:2310
#define OP_HAS_DEPARTED_DELAY
Definition: sexp.h:280
void sexp_ingame_ship_alt_name(ship *shipp, int alt_index)
Definition: sexp.cpp:14879
matrix orient
Definition: object.h:153
#define gr_post_process_set_effect
Definition: 2d.h:914
int inited
Definition: fredrender.cpp:76
bool ship_class_unchanged(int ship_index)
Definition: sexp.cpp:22650
waypoint_list * Training_context_path
Definition: sexp.cpp:837
#define OP_HUD_SET_TEXT_NUM
Definition: sexp.h:535
int ship_guardian_threshold
Definition: ship.h:601
void sexp_set_camera_fov(int n)
Definition: sexp.cpp:21161
int wi_flags2
Definition: weapon.h:385
bool use_shockwave
Definition: ship.h:589
float Cutscene_delta_time
Definition: systemvars.cpp:34
#define LOG_SHIP_DOCKED
Definition: missionlog.h:26
#define OPF_SUBSYSTEM_OR_NONE
Definition: sexp.h:90
#define OP_CHANGE_SUBSYSTEM_NAME
Definition: sexp.h:605
#define SEXP_CHECK_INVALID_SOUND_ENVIRONMENT_OPTION
Definition: sexp.h:981
void sexp_ship_create(int n)
Definition: sexp.cpp:14567
#define NOX(s)
Definition: pstypes.h:473
int last_secondary_fire_stamp[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:116
void ship_copy_damage(ship *target_shipp, ship *source_shipp)
Definition: sexp.cpp:16525
camera * sexp_get_set_camera(bool reset=false)
Definition: sexp.cpp:20837
#define SUBSYSTEM_NONE
Definition: model.h:52
int Num_explosion_options
Definition: sexp.cpp:887
#define MEF_USING_TRIGGER_COUNT
Definition: missiongoals.h:85
#define SND_PRIORITY_MUST_PLAY
Definition: sound.h:26
#define TRUE
Definition: sexp.cpp:114
flag_def_list Hud_gauge_types[]
Definition: hudparse.cpp:99
float get_sim_hull_pct(object *objp)
Definition: object.cpp:289
#define OPF_SSM_CLASS
Definition: sexp.h:80
int Hud_max_targeting_range
Definition: hud.cpp:99
int max
distance at which sound is inaudible
Definition: sound.h:80
#define OP_SET_SUBSPACE_DRIVE
Definition: sexp.h:705
#define OP_SET_DEATH_MESSAGE
Definition: sexp.h:592
GLuint start
Definition: Gl.h:1502
void ssm_create(object *target, vec3d *start, size_t ssm_index, ssm_firing_info *override, int team)
#define OPR_STRING
Definition: sexp.h:123
sexp_variable Block_variables[MAX_SEXP_VARIABLES]
Definition: sexp.cpp:847
#define OP_HUD_DISABLE_EXCEPT_MESSAGES
Definition: sexp.h:532
int sexp_get_countermeasures(int node)
Definition: sexp.cpp:16279
#define OBJ_SHIP
Definition: object.h:32
void sexp_ship_set_damage_type(int node)
Definition: sexp.cpp:17613
GLfloat GLfloat v1
Definition: Glext.h:5639
int used
has control been used yet in mission? If so, this is the timestamp
#define OP_AI_WAYPOINTS_ONCE
Definition: sexp.h:742
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
float turret_rof_scaler
Definition: model.h:236
int flag
Definition: ship.h:424
int ai_override_timestamp
Definition: ai.h:550
void sexp_set_object_position(int n)
Definition: sexp.cpp:6930
void ai_add_ship_goal_sexp(int sexp, int type, ai_info *aip)
Definition: aigoals.cpp:1201
#define OP_TECH_ADD_WEAPON
Definition: sexp.h:448
#define OP_SHIP_SUBSYS_NO_REPLACE
Definition: sexp.h:647
float bank
Definition: physics.h:104
int sexp_get_colgroup(int node)
Definition: sexp.cpp:22446
#define IIF_IN_TECH_DATABASE
Definition: techmenu.h:29
float decay
Definition: sound.h:95
#define AI_GOAL_GUARD_WING
Definition: aigoals.h:43
int special_warpout_objnum
Definition: ship.h:741
#define P_OF_PLAYER_START
Definition: missionparse.h:453
int sexp_var_compare(const void *var1, const void *var2)
Definition: sexp.cpp:29552
GLbitfield flags
Definition: Glext.h:6722
#define OP_SET_DEBRIEFING_TOGGLED
Definition: sexp.h:704
#define OP_CUTSCENES_SET_CAMERA_FOV
Definition: sexp.h:609
float forward_cruise_percent
Definition: physics.h:106
#define SEXP_SIM_HULL_STRING
Definition: sexp.h:810
#define OP_FORCE_GLIDE
Definition: sexp.h:644
SCP_vector< subtitle > Subtitles
Definition: camera.cpp:21
#define OSWPT_TYPE_WAYPOINT
Definition: sexp.cpp:4654
int Num_weapon_types
Definition: weapons.cpp:105
#define OPF_POST_EFFECT
Definition: sexp.h:95
int flags
Definition: sexp.h:1034
void set_rotation(matrix *in_orientation=NULL, float in_rotation_time=0.0f, float in_rotation_acceleration_time=0.0f, float in_rotation_deceleration_time=0.0f)
Definition: camera.cpp:195
int sound_env_get(sound_env *se, int preset)
Definition: sound.cpp:1372
void multi_sexp_toggle_cutscene_bars(int set)
Definition: sexp.cpp:20710
#define OP_SET_ARRIVAL_INFO
Definition: sexp.h:706
#define GOAL_INCOMPLETE
Definition: missiongoals.h:40
#define OP_DESTROYED_DEPARTED_DELAY
Definition: sexp.h:286
#define SIF_HUGE_SHIP
Definition: ship.h:945
#define SF2_NO_BUILTIN_MESSAGES
Definition: ship.h:491
int wing_name_lookup(const char *name, int ignore_count)
Definition: ship.cpp:12706
void sanity_check_ets_inputs(int(&ets_indexes)[num_retail_ets_gauges])
Definition: hudets.cpp:681
#define OP_NODE_TARGETED
Definition: sexp.h:805
#define SEXP_CHECK_BAD_ARG_COUNT
Definition: sexp.h:934
neb2_detail * Nd
Definition: neb.cpp:213
#define SF2_NO_THRUSTERS
Definition: ship.h:505
#define OF_MISSILE_PROTECTED
Definition: object.h:121
void multi_del_nav()
Definition: sexp.cpp:19410
#define OPF_AI_ORDER
Definition: sexp.h:56
#define OP_TRANSFER_CARGO
Definition: sexp.h:426
int Sexp_music_handle
Definition: sexp.cpp:860
void sexp_ships_stealthy(int n, bool stealthy)
Definition: sexp.cpp:14208
#define CHANGE_SUBCATEGORY_MESSAGING
Definition: sexp.h:182
#define OP_FALSE
Definition: sexp.h:240
int is_sexp_true(int cur_node, int referenced_node)
Definition: sexp.cpp:22665
int flags
Definition: techmenu.h:24
GLuint const GLchar * name
Definition: Glext.h:5608
#define OPF_SHIP_WITH_BAY
Definition: sexp.h:74
#define OPR_AMBIGUOUS
Definition: sexp.h:124
void multi_send_float(float value)
Definition: multi_sexp.cpp:398
#define SEXP_CHECK_INVALID_SHIP_WITH_BAY
Definition: sexp.h:968
void object_ship_wing_point_team_set_ship(object_ship_wing_point_team *oswpt, ship *shipp, bool set_parse_flag_too)
Definition: sexp.cpp:4695
#define SEXP_CHECK_UNKNOWN_TYPE
Definition: sexp.h:935
int departure_path_mask
Definition: ship.h:1548
#define INNER_RAD
Definition: sexp.h:891
#define OP_NUM_KILLS
Definition: sexp.h:319
int eval_when(int n, int when_op_num)
Definition: sexp.cpp:8401
float get_damage_caused(int damaged_ship, int attacker)
Definition: sexp.cpp:7478
int get_special_anchor(char *name)
#define SW_FLAG_TAGGED_ONLY
Definition: ship.h:96
int secondary_bank_rearm_time[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:138
void sexp_hud_set_color(int n)
Definition: sexp.cpp:9926
#define P_SF_VAPORIZE
Definition: missionparse.h:470
float awacs_get_level(object *target, ship *viewer, int use_awacs)
Definition: awacs.cpp:168
int Player_use_ai
void sexp_adjust_audio_volume(int node)
Definition: sexp.cpp:10532
#define OSWPT_TYPE_EXITED
Definition: sexp.cpp:4658
GLuint GLfloat * val
Definition: Glext.h:6741
bool Nav_UnSet_Visited(char *Nav)
Definition: autopilot.cpp:1567
#define OP_SUBSYS_SET_RANDOM
Definition: sexp.h:473
int final_death_time
Definition: ship.h:569
int sexp_is_ship_type(int n)
Definition: sexp.cpp:9483
int Training_context_speed_set
Definition: sexp.cpp:833
void init_sexp_vars()
Definition: sexp.cpp:28902
void sexp_send_message_list(int n)
Definition: sexp.cpp:11049
#define SRC_BRIEFING
Definition: sexp.h:851
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
#define OP_SET_SECONDARY_WEAPON
Definition: sexp.h:594
void multi_sexp_remove_weapons()
Definition: sexp.cpp:19769
void sexp_activate_deactivate_glow_points(int n, bool activate)
Definition: sexp.cpp:16656
int Players_mlocked_timestamp
Definition: sexp.cpp:857
int Num_personas
#define SEXP_CHECK_INVALID_SUBSYS
Definition: sexp.h:940
#define OP_AI_UNDOCK
Definition: sexp.h:739
#define OP_SET_SPECIAL_WARPOUT_NAME
Definition: sexp.h:476
#define SUBSYSTEM_ENGINE
Definition: model.h:53
vec3d vel
Definition: physics.h:77
#define vm_realloc(ptr, size)
Definition: pstypes.h:551
#define OP_HAS_BEEN_TAGGED_DELAY
Definition: sexp.h:317
#define OP_TURRET_UNPROTECT_SHIP
Definition: sexp.h:665
int Cutscene_bar_flags
Definition: systemvars.cpp:32
char command_sender[NAME_LENGTH]
Definition: missionparse.h:159
#define TOKEN_LENGTH
Definition: globals.h:41
void game_stop_subspace_ambient_sound()
Definition: fred.cpp:705
#define OP_CHANGE_SHIP_CLASS
Definition: sexp.h:499
void supernova_start(int seconds)
Definition: supernova.cpp:67
ushort net_signature
Definition: ship.h:1560
int check_operator_argument_count(int count, int op)
Definition: sexp.cpp:1640
Definition: hudets.h:45
#define SIF_SUPPORT
Definition: ship.h:878
#define CDDR(n)
Definition: sexp.h:827
#define OP_SET_PRIMARY_WEAPON
Definition: sexp.h:593
bool sexp_replace_variable_names_with_values(char *text, int max_len)
Definition: sexp.cpp:29395
#define SF2_PRIMARIES_LOCKED
Definition: ship.h:492
void sexp_send_training_message(int node)
Definition: sexp.cpp:15546
#define OP_SHIP_SHOCKWAVE_SET_DAMAGE_TYPE
Definition: sexp.h:662
#define TRAINING_CONTEXT_SPEED
Definition: sexp.h:998
#define OP_END_OF_CAMPAIGN
Definition: sexp.h:781
int multi_sexp_get_operator()
Definition: multi_sexp.cpp:541
int find_sexp_list(int num)
Definition: sexp.cpp:1459
float ship_class_get_length(ship_info *sip)
Definition: ship.cpp:17354
#define SF_VAPORIZE
Definition: ship.h:470
void sexp_good_secondary_time(int n)
Definition: sexp.cpp:13462
ship_flag_name Ship_flag_names[]
Definition: ship.cpp:372
void sexp_weapon_set_damage_type(int node)
Definition: sexp.cpp:17560
#define OSWPT_TYPE_WING_NOT_PRESENT
Definition: sexp.cpp:4659
#define SEXP_CHECK_INVALID_PERSONA_NAME
Definition: sexp.h:975
#define OP_PERCENT_SHIPS_DEPARTED
Definition: sexp.h:283
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
void sexp_string_get_substring(int node)
Definition: sexp.cpp:20431
void send_weapon_or_ammo_changed_packet(int ship_index, int bank_type, int bank_number, int ammo_left, int rearm_limit, int new_weapon_index)
Definition: multimsgs.cpp:8097
int model_find_dock_name_index(int modelnum, char *name)
Definition: modelread.cpp:5055
void multi_sexp_set_turret_primary_ammo()
Definition: sexp.cpp:18126
int iff_init_color(int r, int g, int b)
Definition: iff_defs.cpp:62
void stuff_int(int *i)
Definition: parselo.cpp:2372
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
int sexp_team_score(int node)
Definition: sexp.cpp:6085
void sexp_set_explosion_option(int node)
Definition: sexp.cpp:10576
#define OP_SIM_HITS_LEFT
Definition: sexp.h:307
int sexp_has_departed_delay(int n)
Definition: sexp.cpp:5458
#define DOA_DOCK_STAY
Definition: ai.h:78
#define STATUS_SUBCATEGORY_DAMAGE
Definition: sexp.h:210
float get_shield_pct(object *objp)
Definition: object.cpp:308
void audiostream_close_file(int i, int fade)
Definition: audiostr.cpp:1772
#define OP_PROTECT_SHIP
Definition: sexp.h:417
#define SF_DEPARTING
Definition: ship.h:475
#define SEXP_CHECK_NONOP_ARGS
Definition: sexp.h:930
#define OP_JETTISON_CARGO
Definition: sexp.h:450
#define OP_SET_OBJECT_POSITION
Definition: sexp.h:516
#define MESSAGE_PRIORITY_HIGH
intel_data Intel_info[MAX_INTEL_ENTRIES]
Definition: techmenu.cpp:246
#define OP_LOCK_ROTATING_SUBSYSTEM
Definition: sexp.h:525
char status
#define OP_PREVIOUS_GOAL_FALSE
Definition: sexp.h:269
int get_category(int sexp_id)
Definition: sexp.cpp:29611
int sexp_get_turret_primary_ammo(int node)
Definition: sexp.cpp:18019
#define CMISSION_FLAG_SKIPPED
SCP_vector< ship_effect > Ship_effects
Definition: ship.cpp:412
GLuint GLenum option
Definition: Glext.h:10682
CJumpNode * jumpnode_get_by_name(const CString &name)
#define OP_SHIP_SUBSYS_UNTARGETABLE
Definition: sexp.h:591
#define OP_CURRENT_SPEED
Definition: sexp.h:345
#define OP_SET_AFTERBURNER_ENERGY
Definition: sexp.h:618
bool Nebula_sexp_used
Definition: neb.cpp:34
#define OP_SET_IMMOBILE
Definition: sexp.h:648
int sexp_is_ship_class(int n)
Definition: sexp.cpp:9450
int initial_hull
Definition: missionparse.h:366
int total_arrived_count
Definition: ship.h:1528
#define OP_SET_SKYBOX_MODEL
Definition: sexp.h:569
int ship_get_by_signature(int signature)
Definition: ship.cpp:16106
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
#define OPF_WEAPON_BANK_NUMBER
Definition: sexp.h:104
void stuff_sexp_text_string(SCP_string &dest, int node, int mode)
Definition: sexp.cpp:3785
bool test_point_within_box(vec3d *test_point, vec3d *box_corner_1, vec3d *box_corner_2, object *reference_ship_obj)
Definition: sexp.cpp:22319
GLuint GLuint num
Definition: Glext.h:9089
void sexp_ship_shockwave_set_damage_type(int node)
Definition: sexp.cpp:17671
#define OP_SEND_MESSAGE_LIST
Definition: sexp.h:467
#define WING_INDEX(wingp)
Definition: ship.h:1601
void shockwave_create_info_init(shockwave_create_info *sci)
Definition: shockwave.cpp:811
#define SUBCATEGORY_MASK
Definition: sexp.h:180
void set_use_ap_cinematics(int node)
Definition: sexp.cpp:19423
int mission_log_get_count(int type, char *pname, char *sname)
Definition: missionlog.cpp:505
#define OP_HUD_SET_COLOR
Definition: sexp.h:538
void sexp_ingame_ship_kamikaze(ship *shipp, int kdamage)
Definition: sexp.cpp:14789
int sexp_and_in_sequence(int n)
Definition: sexp.cpp:4450
#define SEXP_CHECK_INVALID_VARIABLE_TYPE
Definition: sexp.h:976
#define OP_AI_DESTROY_SUBSYS
Definition: sexp.h:743
#define OP_IS_IN_MISSION
Definition: sexp.h:385
#define SEXP_GOAL_OPERATOR
Definition: sexp.h:1015
void sexp_debug(int node)
Definition: sexp.cpp:20561
#define EVENT_FAILED
Definition: missiongoals.h:79
#define OP_NUM_TYPE_KILLS
Definition: sexp.h:321
void sexp_set_variable_by_index(int node)
Definition: sexp.cpp:29093
#define OP_DISTANCE
Definition: sexp.h:308
ship_subsys * ship_get_subsys(ship *shipp, char *subsys_name)
Definition: ship.cpp:17024
#define OP_STRING_EQUALS
Definition: sexp.h:249
void sexp_rotating_subsys_set_turn_time(int node)
Definition: sexp.cpp:18394
int sexp_bitwise_or(int node)
Definition: sexp.cpp:4289
#define EO_SHOCKWAVE_SPEED
Definition: sexp.cpp:883
int primitive_sensor_range
Definition: ship.h:748
vec3d pnt
Definition: model.h:178
int Num_submenus
Definition: sexp.cpp:33852
#define P2_SF2_PRIMARIES_LOCKED
Definition: missionparse.h:495
void sexp_parse_ship_change_iff_color(p_object *parse_obj, int observer_team, int observed_team, int alternate_iff_color)
Definition: sexp.cpp:9358
void CAP(T &v, T mn, T mx)
Definition: pstypes.h:478
#define OP_SET_SUPPORT_SHIP
Definition: sexp.h:501
void sexp_tech_add_intel(int node)
Definition: sexp.cpp:12557
int sexp_num_class_kills(int node)
Definition: sexp.cpp:19935
waypoint_list * find_matching_waypoint_list(const char *name)
Definition: waypoint.cpp:164
bool ship_has_dock_bay(int shipnum)
Definition: ship.cpp:17435
#define OP_GET_COLGROUP_ID
Definition: sexp.h:692
void SetName(const char *new_name)
Definition: jumpnode.cpp:224
#define OP_NAV_UNSELECT
Definition: sexp.h:714
void sexp_ships_bomb_targetable(int n, bool targetable)
Definition: sexp.cpp:14440
#define SEXP_CHECK_INVALID_GAUGE_NAME
Definition: sexp.h:962
#define OP_EVERY_TIME_ARGUMENT
Definition: sexp.h:395
campaign Campaign
#define OPF_HUD_GAUGE
Definition: sexp.h:106
int Fade_end_timestamp
Definition: systemvars.cpp:42
float tag_left
Definition: ship.h:725
#define OP_SHIP_GUARDIAN_THRESHOLD
Definition: sexp.h:567
#define OP_AI_CHASE
Definition: sexp.h:737
#define OPF_JUMP_NODE_NAME
Definition: sexp.h:64
int m_medal_earned
Definition: scoring.h:107
void sexp_add_sun_bitmap(int n)
Definition: sexp.cpp:12184
float favor_current_facing
Definition: ship.h:343
void sexp_hud_set_max_targeting_range(int n)
Definition: sexp.cpp:9943
GLint GLsizei GLsizei height
Definition: Gl.h:1505
Definition: pstypes.h:606
float vm_vec_dist_quick(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:417
#define strcat_s(...)
Definition: safe_strings.h:68
#define P_AIF_KAMIKAZE
Definition: missionparse.h:461
int sexp_is_cargo_known(int n, int check_delay)
Definition: sexp.cpp:7776
#define FS_VERSION_REVIS
Definition: version.h:40
#define OP_GOALS_ID
Definition: sexp.h:757
#define EOF_CHAR
Definition: parselo.h:31
#define SF_WARP_BROKEN
Definition: ship.h:460
#define SF2_NO_ETS
Definition: ship.h:503
float desired_turn_rate
Definition: model.h:81
#define SEXP_CONDITIONAL_OPERATOR
Definition: sexp.h:1009
#define AI_GOAL_KEEP_SAFE_DISTANCE
Definition: aigoals.h:48
#define NAME_LENGTH
Definition: globals.h:15
void sexp_turret_change_weapon(int node)
Definition: sexp.cpp:17401
void sexp_set_subspace_drive(int node)
Definition: sexp.cpp:13452
#define OP_KEY_PRESSED
Definition: sexp.h:784
void multi_sexp_set_jumpnode_name()
Definition: sexp.cpp:21972
#define BFIF_FORCE_FIRING
Definition: beam.h:51
void sexp_ship_turret_target_order(int node)
Definition: sexp.cpp:17968
void multi_add_nav_ship()
Definition: sexp.cpp:19380
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
#define SEXP_SAVE_MODE
Definition: parselo.h:63
#define LEFT_QUAD
Definition: objectshield.h:18
#define P2_OF_IMMOBILE
Definition: missionparse.h:505
int Players_mlocked
Definition: sexp.cpp:854
#define OP_REPAIR_SUBSYSTEM
Definition: sexp.h:414
void neb2_post_level_init()
Definition: neb.cpp:332
void sexp_ships_guardian(int n, int guardian)
Definition: sexp.cpp:14536
#define AI_GOAL_DISABLE_SHIP
Definition: aigoals.h:39
int ship_docking_valid(int docker, int dockee)
Definition: ship.cpp:14494
#define OSWPT_TYPE_PARSE_OBJECT
Definition: sexp.cpp:4657
int sexp_is_iff(int n)
Definition: sexp.cpp:9200
void sexp_set_ambient_light(int node)
Definition: sexp.cpp:16712
void sexp_ships_invulnerable(int n, bool invulnerable)
Definition: sexp.cpp:14435
#define CHANGE_SUBCATEGORY_HUD
Definition: sexp.h:194
bool multi_get_parse_object(p_object *&pobjp)
Definition: multi_sexp.cpp:702
void clear_nesting_level()
Definition: sexp.cpp:1013
bool has_special_explosion_block_index(ship *shipp, int *index)
Definition: sexp.cpp:3703
#define OP_NUMBER_OF
Definition: sexp.h:399
void sexp_transfer_cargo(int n)
Definition: sexp.cpp:11808
camid cam_lookup(char *name)
Definition: camera.cpp:965
#define OPF_SUBSYSTEM
Definition: sexp.h:34
void sexp_activate_deactivate_glow_point_bank(int n, bool activate)
Definition: sexp.cpp:16673
#define OP_TURRET_PROTECT_SHIP
Definition: sexp.h:664
#define fl2i(fl)
Definition: floating.h:33
#define SEXP_CHECK_INVALID_PRIORITY
Definition: sexp.h:947
#define MULTI_CONNECTED(np)
Definition: multi.h:136
#define OP_DESTROY_SUBSYS_INSTANTLY
Definition: sexp.h:710
#define SEXP_CHECK_INVALID_SKYBOX_NAME
Definition: sexp.h:974
#define SUBSYSTEM_UNKNOWN
Definition: model.h:63
void hud_remove_ship_from_escort(int objnum)
Definition: hudescort.cpp:954
#define OPF_SOUNDTRACK_NAME
Definition: sexp.h:75
#define OP_INVALIDATE_ARGUMENT
Definition: sexp.h:400
int submodel
Definition: lua.cpp:5007
#define CUB_CUTSCENE
Definition: systemvars.h:52
void hud_disable_except_messages(int disable)
Definition: hud.cpp:1288
int audiostream_is_paused(int i)
Definition: audiostr.cpp:1885
#define OP_SHIP_UNSTEALTHY
Definition: sexp.h:486
#define MAX_COMPLETE_ESCORT_LIST
Definition: globals.h:68
void multi_sexp_reset_fov()
Definition: sexp.cpp:21386
#define SEXP_ATOM
Definition: sexp.h:864
#define CHANGE_SUBCATEGORY_SPECIAL_EFFECTS
Definition: sexp.h:199
int sexp_speed(int node)
Definition: sexp.cpp:15207
int multi_find_player_by_parse_object(p_object *p_objp)
Definition: multiutil.cpp:554
void sexp_hud_set_custom_gauge_active(int node)
Definition: sexp.cpp:9987
#define OP_RANDOM_MULTIPLE_OF
Definition: sexp.h:401
#define CHANGE_SUBCATEGORY_JUMP_NODES
Definition: sexp.h:198
int eval_sexp(int cur_node, int referenced_node)
Definition: sexp.cpp:22894
player * Player
int Num_fonts
Definition: font.cpp:34
int sexp_time_ship_arrived(int n)
Definition: sexp.cpp:5706
void add_data_set_dup(char *str)
Definition: sexp.cpp:969
void read_mission_goal_list(int num)
#define OP_ALTER_SHIP_FLAG
Definition: sexp.h:715
p_object * mission_parse_get_parse_object(ushort net_signature)
void multi_sexp_ignore_key()
Definition: sexp.cpp:15142
void do_action_for_each_special_argument(int cur_node)
Definition: sexp.cpp:8169
int sexp_facing2(int node)
Definition: sexp.cpp:15423
#define OP_HAS_UNDOCKED
Definition: sexp.h:764
bool multi_get_float(float &value)
Definition: multi_sexp.cpp:774
int special_ship
Definition: ship.h:1537
void sexp_call_ssm_strike(int node)
Definition: sexp.cpp:22598
GLenum target
Definition: Glext.h:6872
#define OP_EXCHANGE_CARGO
Definition: sexp.h:427
#define OP_CUTSCENES_SET_CAMERA_FACING_OBJECT
Definition: sexp.h:552
void multi_end_callback()
Definition: multi_sexp.cpp:107
int Campaign_ending_via_supernova
#define OP_SHIP_SUBSYS_IGNORE_IF_DEAD
Definition: sexp.h:653
int departure_location
Definition: ship.h:1546
#define OP_SECONDARIES_DEPLETED
Definition: sexp.h:796
class camera * getCamera()
Definition: camera.cpp:833
screen gr_screen
Definition: 2d.cpp:46
#define OP_GET_SECONDARY_AMMO
Definition: sexp.h:352
#define WIF_BEAM
Definition: weapon.h:76
void multi_sexp_play_sound_from_table()
Definition: sexp.cpp:10294
void help()
float heading
Definition: physics.h:102
char * Parse_object_flags_2[MAX_PARSE_OBJECT_FLAGS_2]
#define CHANGE_SUBCATEGORY_CARGO
Definition: sexp.h:187
#define OP_CUTSCENES_UNSET_CUTSCENE_BARS
Definition: sexp.h:546
bool Dynamic_environment
Definition: starfield.cpp:175
int Num_sexp_help
Definition: sexp.cpp:33850
#define OP_GOOD_SECONDARY_TIME
Definition: sexp.h:436
#define OPF_NULL
Definition: sexp.h:29
struct debris debris
#define OP_MISSILE_LOCKED
Definition: sexp.h:799
int sexp_time_destroyed(int n)
Definition: sexp.cpp:5653
#define OP_JUMP_NODE_SET_JUMPNODE_COLOR
Definition: sexp.h:562
#define OP_NAV_UNSET_NEEDSLINK
Definition: sexp.h:681
#define SEXP_KNOWN_TRUE
Definition: sexp.h:922
#define OP_LOCK_SECONDARY_WEAPON
Definition: sexp.h:600
GLint first
Definition: Gl.h:1491
__int64 longlong
Definition: pstypes.h:60
int Num_messages
void sexp_player_use_ai(int flag)
Definition: sexp.cpp:10079
int sexp_was_destroyed_by_delay(int n)
Definition: sexp.cpp:5279
#define SF2_GLOWMAPS_DISABLED
Definition: ship.h:494
void sexp_ship_deal_with_subsystem_flag(int node, int ss_flag, bool sendit=false, bool setit=false)
Definition: sexp.cpp:14253
#define OP_FREE_ROTATING_SUBSYSTEM
Definition: sexp.h:526
#define SEXP_VARIABLE_CAMPAIGN_PERSISTENT
Definition: sexp.h:886
unsigned short ushort
Definition: pstypes.h:63
mgoal * goals
#define OP_UNSCRAMBLE_MESSAGES
Definition: sexp.h:544
#define NETINFO_FLAG_RESPAWNING
Definition: multi.h:609
float damping
Definition: sound.h:94
void sexp_hud_clear_messages()
Definition: sexp.cpp:9880
#define SEXP_CHECK_INVALID_JUMP_NODE
Definition: sexp.h:963
#define OP_BEAM_UNPROTECT_SHIP
Definition: sexp.h:459
char subobj_name[MAX_NAME_LEN]
Definition: model.h:172
#define OP_SET_UNSCANNED
Definition: sexp.h:484
#define OP_TIME_DOCKED
Definition: sexp.h:301
#define OP_FIELD_SET_DAMAGE_TYPE
Definition: sexp.h:663
int sexp_destroyed_departed_delay(int n)
Definition: sexp.cpp:7685
void multi_do_callback()
Definition: multi_sexp.cpp:142
#define OP_HAS_PRIMARY_WEAPON
Definition: sexp.h:372
int sexp_is_ship_stealthy(int n)
Definition: sexp.cpp:6033
#define SEXP_CHECK_INVALID_SKILL_LEVEL
Definition: sexp.h:958
#define OP_AI_WARP
Definition: sexp.h:778
#define CARGO_NO_DEPLETE
Definition: missionparse.h:221
void sexp_set_object_facing(int n, bool facing_object)
Definition: sexp.cpp:7159
#define OP_WHEN
Definition: sexp.h:392
void hud_setup_escort_list(int level)
Definition: hudescort.cpp:651
int pow_sexp(int node)
Definition: sexp.cpp:4197
float vm_vec_copy_normalize(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:427
void ship_do_cargo_hidden(ship *shipp, int from_network)
Definition: ship.cpp:16190
int Num_special_expl_blocks
Definition: sexp.cpp:849
#define OP_AI_WAYPOINTS
Definition: sexp.h:741
void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec=NULL, int sexp_flags=0)
Definition: aicode.cpp:1131
float scale_y
Definition: starfield.h:32
int eval_number_of(int arg_handler_node, int condition_node)
Definition: sexp.cpp:8766
#define OP_NAV_ADD_WAYPOINT
Definition: sexp.h:669
bool shader_effect_active
Definition: ship.h:769
#define OP_EVENT_FALSE
Definition: sexp.h:775
#define CHANGE_SUBCATEGORY_NAV
Definition: sexp.h:195
void sexpLockConfigColor(bool lock)
Definition: hud.cpp:525
ship_obj Ship_obj_list
Definition: ship.cpp:162
object * shooter
Definition: beam.h:58
bool True_loop_argument_sexps
Definition: mod_table.cpp:19
bool Perspective_locked
Definition: keycontrol.cpp:213
#define OP_IS_PRIMARY_SELECTED
Definition: sexp.h:329
int timestamp_has_time_elapsed(int stamp, int time)
Definition: timer.cpp:272
#define MAX_SHIP_FLAG_NAMES
Definition: ship.h:429
int sexp_time_ship_departed(int n)
Definition: sexp.cpp:5730
int departure_delay
Definition: missionparse.h:380
#define OP_IS_SHIP_STEALTHY
Definition: sexp.h:334
#define OP_SET_SKYBOX_ORIENT
Definition: sexp.h:708
int departure_delay
Definition: ship.h:1550
void multi_sexp_close_sound_from_file()
Definition: sexp.cpp:10330
int ship_info_index
Definition: ship.h:539
#define SEXP_CHECK_INVALID_HUD_GAUGE
Definition: sexp.h:989
#define MLF_FIRST_REPEAT_ONLY
Definition: missiongoals.h:93
#define OP_SHIP_LAT_MANEUVER
Definition: sexp.h:628
#define SEXP_NODE_TYPE(n)
Definition: sexp.h:907
GLfloat GLfloat p
Definition: Glext.h:8373
#define MAX_NEB2_POOFS
Definition: neb.h:45
#define OP_RESPAWNS_LEFT
Definition: sexp.h:357
#define OPF_STRING
Definition: sexp.h:77
bool multi_get_ship(int &value)
Definition: multi_sexp.cpp:632
#define SEXP_CHECK_INVALID_SOUNDTRACK_NAME
Definition: sexp.h:972
int sexp_get_primary_ammo(int node)
Definition: sexp.cpp:15887
#define MULTIPLAYER_MASTER
Definition: multi.h:130
#define SEXP_VARIABLE_CHAR
Definition: sexp.h:871
int verify_sexp_tree(int node)
Definition: sexp.cpp:1353
int Event_index
float vertical
Definition: physics.h:101
#define OPF_POSITIVE
Definition: sexp.h:44
int sexp_query_type_match(int opf, int opr)
Definition: sexp.cpp:28538
void message_send_unique_to_player(char *id, void *data, int m_source, int priority, int group, int delay)
An overhauled/updated debug console to allow monitoring, testing, and general debugging of new featur...
void ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
Definition: aigoals.cpp:1210
void reset()
Definition: camera.cpp:53
void multi_sexp_set_jumpnode_model()
Definition: sexp.cpp:22059
Definition: ai.h:198
int min_sexp(int n)
Definition: sexp.cpp:4145
char * Ship_class_names[MAX_SHIP_CLASSES]
#define SEXP_CHECK_INVALID_LEVEL
Definition: sexp.h:950
int sexp_determine_team(char *subj)
Definition: sexp.cpp:6277
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
dc_printf("SEXP '%s' run, sexp_val = %d\n", sexp_always.c_str(), sexp_val)
#define LOCATION
Definition: pstypes.h:245
#define OP_NUM_VALID_ARGUMENTS
Definition: sexp.h:409
#define OF_FLAK_PROTECTED
Definition: object.h:119
void sexp_hud_display_gauge(int n)
Definition: sexp.cpp:9966
float Master_event_music_volume
Definition: eventmusic.cpp:40
#define MLF_SEXP_FALSE
Definition: missiongoals.h:90
float ship_max_shield_strength
Definition: missionparse.h:426
#define SIF_KNOSSOS_DEVICE
Definition: ship.h:912
#define OP_STRING_SET_SUBSTRING
Definition: sexp.h:688
int type
Definition: sexp.h:1029
#define OP_REMOVE_FROM_COLGROUP
Definition: sexp.h:691
#define SEXP_CHECK_INVALID_IFF
Definition: sexp.h:941
int cmp_sexp_chains(int node1, int node2)
Definition: sexp.cpp:1408
#define OP_TECH_ADD_INTEL
Definition: sexp.h:509
#define EO_DEATH_ROLL_TIME
Definition: sexp.cpp:884
int MessageBox(HWND h, const char *s1, const char *s2, int i)
#define SF2_AFTERBURNER_LOCKED
Definition: ship.h:499
int departure_delay
Definition: ship.h:621
const char * Skill_level_names(int skill_level, int translate=1)
Definition: aicode.cpp:208
void sexp_tech_add_ship(int node)
Definition: sexp.cpp:12512
#define OP_IS_SUBSYSTEM_DESTROYED_DELAY
Definition: sexp.h:274
#define OP_AI_STAY_NEAR_SHIP
Definition: sexp.h:749
int Viewer_mode
Definition: systemvars.cpp:28
int get_operator_const(const char *token)
Definition: sexp.cpp:1595
char * sexp_error_message(int num)
Definition: sexp.cpp:28570
int model_anim_match_type(char *p)
Definition: modelanim.cpp:38
#define OP_BITWISE_NOT
Definition: sexp.h:230
#define OP_JUMP_NODE_HIDE_JUMPNODE
Definition: sexp.h:566
#define OP_SET_OBJECT_SPEED_Y
Definition: sexp.h:573
#define OP_STRING_CONCATENATE
Definition: sexp.h:658
void sexp_set_persona(int node)
Definition: sexp.cpp:13556
#define SNF_DEFAULT_VALUE
Definition: sexp.h:1040
float VIEWER_ZOOM_DEFAULT
Definition: camera.cpp:15
#define OP_CUTSCENES_RESET_FOV
Definition: sexp.h:555
SCP_vector< DamageTypeStruct > Damage_types
Definition: ship.cpp:171
SCP_vector< float > shield_quadrant
Definition: object.h:159
void set_nav_visited(int node)
Definition: sexp.cpp:19484
#define OPF_SHIP_OR_NONE
Definition: sexp.h:84
int sexp_distance3(object *objp1, object *objp2)
Definition: sexp.cpp:6298
#define SEXP_ATOM_LIST
Definition: sexp.h:910
#define OF_SHOULD_BE_DEAD
Definition: object.h:106
#define OP_DIV
Definition: sexp.h:220
SCP_vector< exited_ship > Ships_exited
Definition: ship.cpp:152
vec3d * get_subsystem_world_pos(object *parent_obj, ship_subsys *subsys, vec3d *world_pos)
Definition: hudtarget.cpp:4395
int sexp_event_delay_status(int n, int want_true, bool use_msecs=false)
Definition: sexp.cpp:13967
mevent * events
#define OPF_ARRIVAL_ANCHOR_ALL
Definition: sexp.h:72
#define CHANGE_SUBCATEGORY_COORDINATE_MANIPULATION
Definition: sexp.h:191
int ship_get_default_orders_accepted(ship_info *sip)
Definition: ship.cpp:5480
void set_turret_secondary_ammo(ship_subsys *turret, int requested_bank, int requested_ammo, bool update)
Definition: sexp.cpp:18290
#define PI
Definition: pstypes.h:303
char docker[NAME_LENGTH]
#define OP_WAS_DESTROYED_BY_DELAY
Definition: sexp.h:291
#define MAX_WEAPONS
Definition: globals.h:71
void multi_send_int(int value)
Definition: multi_sexp.cpp:257
hull_check pos
Definition: lua.cpp:5050
int get_index_sexp_variable_from_node(int node)
Definition: sexp.cpp:29303
void set_nav_carry_status(int node)
Definition: sexp.cpp:19129
void audiostream_play(int i, float volume, int looping)
Definition: audiostr.cpp:1803
#define MISSION_FLAG_NO_BUILTIN_COMMAND
Definition: missionparse.h:86
void error_display(int error_level, char *format,...)
Definition: parselo.cpp:308
#define EO_INNER_RADIUS
Definition: sexp.cpp:881
int Num_soundtracks
Definition: eventmusic.cpp:58
int Game_skill_level
Definition: fredstubs.cpp:170
int ship_is_visible_by_team(object *target, ship *viewer)
Definition: awacs.cpp:442
#define OP_NUM_WITHIN_BOX
Definition: sexp.h:347
int process_special_sexps(int index)
Definition: sexp.cpp:20142
void ignore_white_space()
Definition: parselo.cpp:77
const GLfloat * m
Definition: Glext.h:10319
#define SIF2_MODEL_POINT_SHIELDS
Definition: ship.h:936
void sexp_shields_off(int n, bool shields_off)
Definition: sexp.cpp:14783
#define CHANGE_SUBCATEGORY_SHIP_STATUS
Definition: sexp.h:184
GLsizei GLsizei GLuint * obj
Definition: Glext.h:5619
bool EvalString(const char *string, const char *format=NULL, void *rtn=NULL, const char *debug_str=NULL)
Definition: scripting.cpp:1083
#define OP_NAV_ISLINKED
Definition: sexp.h:380
#define OP_TURRET_TAGGED_CLEAR_ALL
Definition: sexp.h:472
int sexp_is_ai_class(int n)
Definition: sexp.cpp:9517
void sexp_deal_with_primary_lock(int node, bool lock)
Definition: sexp.cpp:16342
float get_fov()
Definition: camera.cpp:284
arg_item * next
Definition: sexp.h:1056
FadeType Fade_type
Definition: systemvars.cpp:40
#define OP_SHIP_TURRET_TARGET_ORDER
Definition: sexp.h:585
#define OP_PRIMARY_AMMO_PCT
Definition: sexp.h:333
#define SEXP_CHECK_INVALID_SHIP_FLAG
Definition: sexp.h:992
float cube_inner
Definition: neb.h:80
int armor_type_idx
Definition: ship.h:796
#define SEXP_CHECK_INVALID_TURRET_TARGET_ORDER
Definition: sexp.h:984
#define OPF_DEPARTURE_LOCATION
Definition: sexp.h:73
object * multi_get_network_object(ushort net_signature)
Definition: multiutil.cpp:220
void mission_campaign_save_persistent(int type, int sindex)
#define OP_INT_TO_STRING
Definition: sexp.h:659
void change_ship_type(int n, int ship_type, int by_sexp)
Definition: ship.cpp:9983
#define MAX_TVT_TEAMS
Definition: globals.h:57
#define AI_GOAL_CHASE
Definition: aigoals.h:29
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
void multi_sexp_set_jumpnode_color()
Definition: sexp.cpp:22016
#define OPF_SOUND_ENVIRONMENT
Definition: sexp.h:100
debriefing Debriefings[MAX_TVT_TEAMS]
GLenum GLuint GLenum GLsizei length
Definition: Glext.h:5156
void SetAlphaColor(int r, int g, int b, int alpha)
Definition: jumpnode.cpp:173
void shield_set_strength(object *objp, float strength)
GLenum GLenum variable
Definition: Glext.h:8502
void get_unformatted_sexp_variable_name(char *unformatted, char *formatted_pre)
Definition: sexp.cpp:3194
float accuracy
Definition: beam.h:61
int departure_path_mask
Definition: ship.h:619
#define OP_SET_CARGO
Definition: sexp.h:487
void set_pos(vec3d *pos)
Definition: waypoint.cpp:61
char cargo1
Definition: missionparse.h:355
#define i2fl(i)
Definition: floating.h:32
#define SEXP_CHECK_INVALID_DAMAGE_TYPE
Definition: sexp.h:986
void asteroid_hit(object *pasteroid_obj, object *other_obj, vec3d *hitpos, float damage)
Definition: asteroid.cpp:1368
#define OP_AI_PLAY_DEAD
Definition: sexp.h:753
#define OP_AI_IGNORE
Definition: sexp.h:751
#define OP_SET_EXPLOSION_OPTION
Definition: sexp.h:642
float sideways
Definition: physics.h:103
int Num_sexp_ai_goal_links
Definition: sexp.cpp:830
player * get_player_from_ship_node(int node, bool test_respawns=false)
Definition: sexp.cpp:3922
void add_nav_ship(int node)
Definition: sexp.cpp:19368
#define OP_SHIP_SUBSYS_VANISHED
Definition: sexp.h:652
int sexp_calculate_angle(matrix *orient, int axis)
Definition: sexp.cpp:6805
void sexp_set_post_effect(int node)
Definition: sexp.cpp:16765
GLint GLsizei count
Definition: Gl.h:1491
GLsizei GLsizei GLchar * source
Definition: Glext.h:5625
#define OP_WEAPON_ENERGY_LEFT
Definition: sexp.h:361
int sexp_special_training_check(int node)
Definition: sexp.cpp:20597
int sexp_return_player_data(int node, int type)
Definition: sexp.cpp:19779
int Players_target
Definition: sexp.cpp:853
int arrival_anchor
Definition: ship.h:612
int sexp_time_wing_destroyed(int n)
Definition: sexp.cpp:5665
char status
#define OP_SUPERNOVA_START
Definition: sexp.h:474
#define OP_CATEGORY_MASK
Definition: sexp.h:158
p_object Ship_arrival_list
#define OP_SET_OBJECT_ORIENTATION
Definition: sexp.h:657
void sexp_destroy_subsys_instantly(int n)
Definition: sexp.cpp:11560
#define i2f(a)
Definition: fix.h:23
#define OSWPT_TYPE_SHIP_ON_TEAM
Definition: sexp.cpp:4655
#define OP_CUTSCENES_SHOW_SUBTITLE_IMAGE
Definition: sexp.h:638
int sexp_are_ship_flags_set(int node)
Definition: sexp.cpp:13177
#define OP_NAV_SET_VISITED
Definition: sexp.h:676
#define FIREBALL_KNOSSOS
Definition: fireballs.h:30
void sexp_nebula_change_pattern(int n)
Definition: sexp.cpp:12306
int find_parent_operator(int node)
Definition: sexp.cpp:1476
#define SEXP_VARIABLE_NUMBER
Definition: sexp.h:873
GLenum GLsizei len
Definition: Glext.h:6283
void sexp_turret_free(int node)
Definition: sexp.cpp:17224
int first
Definition: sexp.h:1031
void ship_self_destruct(object *objp)
Definition: shiphit.cpp:1697
object * Player_obj
Definition: object.cpp:56
int sexp_is_primary_selected(int node)
Definition: sexp.cpp:20088
#define OP_CUTSCENES_SET_CAMERA_HOST
Definition: sexp.h:611
void sexp_ship_vanish(int n)
Definition: sexp.cpp:14728
void sexp_nebula_toggle_poof(int n)
Definition: sexp.cpp:12284
#define FS_VERSION_BUILD
Definition: version.h:39
#define OP_SHIP_GUARDIAN
Definition: sexp.h:469
int sexp_was_medal_granted(int n)
Definition: sexp.cpp:7447
#define SF_ESCORT
Definition: ship.h:438
#define OP_UNSET_BIT
Definition: sexp.h:234
void _cdecl void void _cdecl void _cdecl void _cdecl void _cdecl ReleaseWarning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
void sexp_good_time_to_rearm(int n)
Definition: sexp.cpp:12380
#define STATUS_SUBCATEGORY_OTHER
Definition: sexp.h:213
void sexp_hud_set_frame(int n)
Definition: sexp.cpp:9915
int value
Definition: sexp.h:1033
GLuint GLdouble GLdouble GLint GLint order
Definition: Glext.h:10665
void sexp_reset_time_compression()
Definition: sexp.cpp:21884
#define SF_CARGO_REVEALED
Definition: ship.h:456
void sexp_set_camera_host(int node)
Definition: sexp.cpp:21274
void sexp_add_ship_goal(int n)
Definition: sexp.cpp:9638
Definition: ai.h:134
#define MAX_ARRIVAL_NAMES
Definition: missionparse.h:236
#define OP_REMOVE_BACKGROUND_BITMAP
Definition: sexp.h:577
uint flags2
Definition: ship.h:645
#define OP_GET_OBJECT_BANK
Definition: sexp.h:369
void multi_sexp_set_respawns()
Definition: sexp.cpp:19715
#define P_SF_NO_ARRIVAL_WARP
Definition: missionparse.h:455
char variable_name[TOKEN_LENGTH]
Definition: sexp.h:1045
void multi_sexp_set_camera_fov()
Definition: sexp.cpp:21202
#define SEXP_SHIELD_STRING
Definition: sexp.h:811
#define SF_DYING
Definition: ship.h:447
#define SEXP_CHECK_INVALID_MSG_SOURCE
Definition: sexp.h:951
int temp
Definition: lua.cpp:4996
int kamikaze_damage
Definition: ai.h:523
int special_hitpoints
Definition: ship.h:593
int audiostream_open(const char *filename, int type)
Definition: audiostr.cpp:1713
#define OUTER_RAD
Definition: sexp.h:892
#define OP_SET_OBJECT_SPEED_Z
Definition: sexp.h:574
#define OP_SET_TRAINING_CONTEXT_SPEED
Definition: sexp.h:801
#define SEXP_CHECK_INVALID_NUM
Definition: sexp.h:937
void send_change_iff_color_packet(ushort net_signature, int observer_team, int observed_team, int alternate_iff_color)
Definition: multimsgs.cpp:7523
int ship_index[MAX_SHIPS_PER_WING]
Definition: ship.h:1531
#define OP_SCRAMBLE_MESSAGES
Definition: sexp.h:543
#define OP_HUD_SET_CUSTOM_GAUGE_ACTIVE
Definition: sexp.h:727
#define P_SF_NO_DEPARTURE_WARP
Definition: missionparse.h:456
int team_change_time
Definition: ship.h:815
void multi_sexp_show_subtitle_text()
Definition: sexp.cpp:21682
#define WIF2_BALLISTIC
Definition: weapon.h:84
polymodel * pm
Definition: lua.cpp:1598
#define OP_AI_DISARM_SHIP
Definition: sexp.h:745
int get_objnum()
Definition: waypoint.cpp:51
int m_player_deaths
Definition: scoring.h:124
#define OPF_MESSAGE
Definition: sexp.h:40
#define OP_CARGO_KNOWN_DELAY
Definition: sexp.h:315
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, int ai_flag, int ai_flag2, bool set_flag)
Definition: sexp.cpp:13088
void multi_sexp_set_countermeasures()
Definition: sexp.cpp:16320
#define SPECIAL_CHECK_TRAINING_FAILURE
Definition: sexp.h:1002
void unselect_nav()
Definition: sexp.cpp:19540
void sexp_kamikaze(int n, int kamikaze)
Definition: sexp.cpp:14825
#define OP_GET_OBJECT_X
Definition: sexp.h:338
void gr_create_shader(shader *shade, ubyte r, ubyte g, ubyte b, ubyte c)
Definition: 2d.cpp:1211
#define OP_JUMP_NODE_SHOW_JUMPNODE
Definition: sexp.h:564
void multi_sexp_set_ambient_light()
Definition: sexp.cpp:16756
int special_exp_damage
Definition: ship.h:585
void sexp_hud_set_directive(int n)
Definition: sexp.cpp:9859
void multi_sexp_set_turret_secondary_ammo()
Definition: sexp.cpp:18275
int primary_bank_rearm_time[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:125
int ship_get_subsys_index(ship *sp, char *ss_name, int error_bypass)
Definition: ship.cpp:13421
void sexp_load_music(char *fname, int type=-1)
Definition: sexp.cpp:10193
cmdline_parm env("-noenv", NULL, AT_NONE)
#define MAX(a, b)
Definition: pstypes.h:299
Definition: camera.h:18
int shader_effect_num
Definition: ship.h:766
void toggle_cutscene_bars(float delta_speed, int set)
Definition: sexp.cpp:20676
void sexp_add_background_bitmap(int n)
Definition: sexp.cpp:12086
void multi_send_bool(bool value)
Definition: multi_sexp.cpp:379
SCP_map< SCP_string, team_color > Team_Colors
Definition: alphacolors.cpp:15
SCP_vector< SCP_string > Builtin_moods
void sexp_turret_tagged_clear_all(int node)
Definition: sexp.cpp:17374
float fvi_ray_plane(vec3d *new_pnt, const vec3d *plane_pnt, const vec3d *plane_norm, const vec3d *ray_origin, const vec3d *ray_direction, float rad)
Definition: fvi.cpp:118
int is_white_space(char ch)
Definition: parselo.cpp:59
#define OP_KEY_RESET
Definition: sexp.h:785
int arrival_path_mask
Definition: ship.h:613
Definition: starfield.h:30
#define OPF_NONE
Definition: sexp.h:28
#define MLF_LAST_REPEAT_ONLY
Definition: missiongoals.h:94
float hud_find_target_distance(object *targetee, object *targeter)
Definition: hudtarget.cpp:2009
#define LOG_WAYPOINTS_DONE
Definition: missionlog.h:36
int sexp_is_in_box(int n)
Definition: sexp.cpp:22338
char * Adjust_audio_options[]
Definition: sexp.cpp:872
int primary_bank_start_ammo[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:122
#define OP_PREVIOUS_EVENT_INCOMPLETE
Definition: sexp.h:777
int nesting_level
Definition: sexp.h:1058
subsys_status * Subsys_status
#define OPF_WING
Definition: sexp.h:33
void eval_when_do_all_exp(int all_actions, int when_op_num)
Definition: sexp.cpp:8294
#define OP_NAV_UNHIDE
Definition: sexp.h:674
int shield_armor_type_idx
Definition: ship.h:1404
void restrict_nav(int node)
Definition: sexp.cpp:19459
char * Skybox_flags[]
Definition: sexp.cpp:817
int Num_adjust_audio_options
Definition: sexp.cpp:873
#define OP_GET_OBJECT_PITCH
Definition: sexp.h:368
int ship_name_lookup(const char *name, int inc_players)
Definition: ship.cpp:12900
void lcl_ext_localize(const char *in, char *out, size_t max_len, int *id)
Definition: localize.cpp:831
#define OPF_INTEL_NAME
Definition: sexp.h:76
void multi_sexp_set_camera_target()
Definition: sexp.cpp:21311
#define OP_SPECIAL_WARP_DISTANCE
Definition: sexp.h:330
int audio_volume_option_lookup(char *text)
Definition: sexp.cpp:10514
void ship_do_cap_subsys_cargo_hidden(ship *shipp, ship_subsys *subsys, int from_network)
Definition: ship.cpp:16210
bool multi_get_ushort(ushort &value)
Definition: multi_sexp.cpp:804
#define FIREBALL_EXPLOSION_MEDIUM
Definition: fireballs.h:28
int collision_group_id
Definition: object.h:169
void audiostream_pause(int i, bool via_sexp_or_script)
Definition: audiostr.cpp:1943
#define OP_DISABLE_BUILTIN_MESSAGES
Definition: sexp.h:595
GLboolean reset
Definition: Glext.h:5243
void sexp_turret_protect_ships(int n, bool flag)
Definition: sexp.cpp:14140
char filename[MAX_FILENAME_LEN]
Definition: starfield.h:31
#define OS_SUBSYS_ROTATION
Definition: objectsnd.h:23
#define GM_NORMAL
Definition: systemvars.h:19
#define MLF_LAST_TRIGGER_ONLY
Definition: missiongoals.h:96
#define CHANGE_SUBCATEGORY_BEAMS_AND_TURRETS
Definition: sexp.h:189
obj_flag_name Object_flag_names[]
Definition: object.cpp:97
int Multi_team_score[MAX_TVT_TEAMS]
Definition: multi_team.cpp:41
int get_nth_variable_index(int nth, int variable_type)
Definition: sexp.cpp:29471
#define SF2_STEALTH
Definition: ship.h:485
uint flags
Definition: object.h:151
#define SEO_DECAY_TIME
Definition: sexp.cpp:865
float optimum_range
Definition: model.h:233
#define SEXP_KNOWN_FALSE
Definition: sexp.h:921
#define CHANGE_SUBCATEGORY_SUBSYSTEMS
Definition: sexp.h:186
#define SUBSYSTEM_MAX
Definition: model.h:64
void sexp_beam_free_all(int node)
Definition: sexp.cpp:17131
int ship_find_exited_ship_by_signature(int signature)
Definition: ship.cpp:5353
#define SEXP_CHECK_INVALID_VARIABLE
Definition: sexp.h:964
void sexp_set_player_orders(int n)
Definition: sexp.cpp:10098
int eval_every_of(int arg_handler_node, int condition_node)
Definition: sexp.cpp:8745
void preload_turret_change_weapon(char *text)
Definition: sexp.cpp:3279
mission The_mission
#define OP_GOOD_REARM_TIME
Definition: sexp.h:430
void ship_apply_tag(int ship_num, int tag_level, float tag_time, object *target, vec3d *start, int ssm_index, int ssm_team)
Definition: shiphit.cpp:2324
#define FIREBALL_WARP_EFFECT
Definition: fireballs.h:25
#define GOAL_COMPLETE
Definition: missiongoals.h:39
bool Nav_Set_Hidden(char *Nav)
Definition: autopilot.cpp:1530
#define AI_GOAL_DESTROY_SUBSYSTEM
Definition: aigoals.h:34
#define OP_SET_THRUSTERS
Definition: sexp.h:697
int supernova_active()
Definition: supernova.cpp:240
#define CUB_GRADUAL
Definition: systemvars.h:54
int shield_quad_near_max(int quadnum)
Definition: sexp.cpp:20120
GLint level
Definition: Glext.h:5180
#define OP_HUD_GAUGE_SET_ACTIVE
Definition: sexp.h:655
#define SF2_NAVPOINT_NEEDSLINK
Definition: ship.h:497
int sexp_get_turret_secondary_ammo(int node)
Definition: sexp.cpp:18174
#define MESSAGE_SOURCE_SPECIAL
fix time_gone
Definition: ship.h:1525
#define VM_CHASE
Definition: systemvars.h:34
int sexp_hits_left_subsystem_generic(int node)
Definition: sexp.cpp:6171
int Num_goals
void sexp_turret_set_target_order(int node)
Definition: sexp.cpp:17745
void sexp_set_camera_position(int n)
Definition: sexp.cpp:20876
bool DelNavPoint(char *Nav)
Definition: autopilot.cpp:1355
float h
Definition: pstypes.h:111
int sexp_has_time_elapsed(int n)
Definition: sexp.cpp:5563
#define SEXP_CHECK_INVALID_SSM_CLASS
Definition: sexp.h:996
#define OPF_NEBULA_STORM_TYPE
Definition: sexp.h:87
#define OP_AI_GUARD
Definition: sexp.h:746
char team
Definition: beam.h:72
int model_num
Definition: lua.cpp:4996
GLclampf GLclampf GLclampf alpha
Definition: Glext.h:5177
#define OP_WAYPOINTS_DONE_DELAY
Definition: sexp.h:281
void snd_adjust_audio_volume(int type, float percent, int time)
Definition: sound.cpp:1465
#define OP_HUD_SET_COORDS
Definition: sexp.h:536
#define OP_EVENT_FALSE_DELAY
Definition: sexp.h:265
#define OP_SET_SECONDARY_AMMO
Definition: sexp.h:587
#define OPR_FLEXIBLE_ARGUMENT
Definition: sexp.h:125
#define OP_BITWISE_OR
Definition: sexp.h:229
int sexp_goal_delay_status(int n, int want_true)
Definition: sexp.cpp:14068
void sexp_string_concatenate(int n)
Definition: sexp.cpp:20381
#define OP_VALIDATE_GOAL
Definition: sexp.h:424
char type
Definition: object.h:146
#define SEXP_UNKNOWN
Definition: sexp.h:923
int sexp_secondaries_depleted(int node)
Definition: sexp.cpp:15296
#define OP_CHANGE_AI_CLASS
Definition: sexp.h:488
void sexp_activate_deactivate_glow_maps(int n, int activate)
Definition: sexp.cpp:16692
#define OP_SET_OBJECT_FACING
Definition: sexp.h:513
#define OP_EVENT_TRUE_DELAY
Definition: sexp.h:264
#define OP_ROTATING_SUBSYS_SET_TURN_TIME
Definition: sexp.h:528
#define OPF_AMBIGUOUS
Definition: sexp.h:66
void sexp_set_ship_maneuver(int n, int op_num)
Definition: sexp.cpp:7286
#define OP_HUD_ACTIVATE_GAUGE_TYPE
Definition: sexp.h:656
#define OP_BEAM_PROTECT_SHIP
Definition: sexp.h:458
int target_priority[32]
Definition: model.h:230
#define MESSAGE_SOURCE_COMMAND
vec3d vmd_zero_vector
Definition: vecmat.cpp:24
support_ship_info support_ships
Definition: missionparse.h:143
void sexp_set_scanned_unscanned(int n, int flag)
Definition: sexp.cpp:7999
#define SRC_SHIP_DEPARTURE
Definition: sexp.h:843
#define OP_AI_GUARD_WING
Definition: sexp.h:773
#define OP_SCRIPT_EVAL
Definition: sexp.h:500
shockwave_create_info shockwave
Definition: weapon.h:367
#define OP_REMOVE_WEAPONS
Definition: sexp.h:625
#define OP_WARP_NOT_BROKEN
Definition: sexp.h:438
#define MR_NO_GLOWMAPS
Definition: model.h:886
void sexp_disable_ets(int n, bool disable)
Definition: sexp.cpp:14170
#define OP_RAND_MULTIPLE
Definition: sexp.h:226
#define OP_FRIENDLY_STEALTH_INVISIBLE
Definition: sexp.h:489
#define OPF_NUMBER
Definition: sexp.h:31
#define OP_CLEAR_WING_GOALS
Definition: sexp.h:771
void sexp_turret_set_target_priorities(int node)
Definition: sexp.cpp:17913
void get_cap_subsys_cargo_flags(int shipnum, char *subsys_name, int *known, fix *time_revealed)
Definition: sexp.cpp:7869
void init_sexp()
Definition: sexp.cpp:1090
#define OP_AI_WARP_OUT
Definition: sexp.h:740
#define OP_BEAM_LOCK_ALL
Definition: sexp.h:457
void preload_change_ship_class(char *text)
Definition: sexp.cpp:3260
int sound_env_disable()
Definition: sound.cpp:1389
int sexp_is_friendly_stealth_visible(int n)
Definition: sexp.cpp:6059
#define CHANGE_SUBCATEGORY_VARIABLES
Definition: sexp.h:200
int multi_find_player_by_object(object *objp)
Definition: multiutil.cpp:500
#define wp(p)
Definition: modelsinc.h:69
void multi_sexp_set_object_speed()
Definition: sexp.cpp:6716
#define OP_SELF_DESTRUCT
Definition: sexp.h:419
#define MISSION_FLAG_NO_TRAITOR
Definition: missionparse.h:72
#define CAMPAIGN_PERSISTENT_WEAPON
int sexp_previous_goal_status(int n, int status)
Definition: sexp.cpp:13768
void obj_collide_retime_cached_pairs(int checkdly)
int sexp_primaries_depleted(int node)
Definition: sexp.cpp:15254
#define OP_WEAPON_RECHARGE_PCT
Definition: sexp.h:325
#define SF2_SECONDARIES_LOCKED
Definition: ship.h:493
#define OP_WEAPON_CREATE
Definition: sexp.h:571
#define MAX_NAME_LEN
Definition: model.h:29
void sexp_set_death_message(int n)
Definition: sexp.cpp:15057
void sexp_change_team_color(int n)
Definition: sexp.cpp:22538
void sexp_start_music(int loop)
Definition: sexp.cpp:10216
void sexp_set_camera_target(int node)
Definition: sexp.cpp:21290
char * Cargo_names[]
void updateCustomGaugeText(const char *txt)
Definition: hud.cpp:422
#define STATUS_SUBCATEGORY_VARIABLES
Definition: sexp.h:212
#define OP_PREVIOUS_GOAL_TRUE
Definition: sexp.h:268
#define OP_TARGETED
Definition: sexp.h:786
void sexp_repair_subsystem(int n)
Definition: sexp.cpp:11327
void add_data_dup(char *str)
Definition: sexp.cpp:953
SCP_vector< asteroid_info > Asteroid_info
Definition: asteroid.cpp:62
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
int Num_medals
Definition: medals.cpp:30
void sexp_hud_set_text(int n)
Definition: sexp.cpp:9823
float max_shield_recharge
Definition: ship.h:599
#define OP_ADD_REMOVE_ESCORT
Definition: sexp.h:465
#define OP_CUTSCENES_SHOW_SUBTITLE_TEXT
Definition: sexp.h:637
#define stars_get_num_suns()
Definition: starfield.h:69
void sexp_beam_lock_all(int node)
Definition: sexp.cpp:17192
#define OP_STRING_GET_SUBSTRING
Definition: sexp.h:687
void sexp_set_oswpt_maneuver(object_ship_wing_point_team *oswpt, int duration, int heading, int pitch, int bank, bool apply_all_rotate, int up, int sideways, int forward, bool apply_all_lat)
Definition: sexp.cpp:7262
int timer_get_milliseconds()
Definition: timer.cpp:150
SCP_vector< ai_target_priority > Ai_tp_list
Definition: ship.cpp:396
#define OP_CLEAR_SUBTITLES
Definition: sexp.h:694
void gameseq_post_event(int event)
GLenum GLint GLuint mask
Definition: Glext.h:5605
void sexp_warp_effect(int n)
Definition: sexp.cpp:10847
int sexp_has_weapon(int node, int op_num)
Definition: sexp.cpp:13694
#define OP_WAYPOINTS_DONE
Definition: sexp.h:767
float aav_music_volume
Definition: sound.cpp:79
int multi_sexp_get_next_operator()
Definition: multi_sexp.cpp:523
char text[TOKEN_LENGTH]
Definition: sexp.h:1027
int sexp_num_type_kills(int node)
Definition: sexp.cpp:19879
int shield_recharge_index
Definition: ship.h:637
#define OP_HAS_DEPARTED
Definition: sexp.h:766
#define OP_DAMAGED_ESCORT_LIST
Definition: sexp.h:491
int sexp_get_object_speed(object *objp, int axis, int subjective)
Definition: sexp.cpp:6729
#define OP_KEY_RESET_MULTIPLE
Definition: sexp.h:802
#define GM_CAMPAIGN_MODE
Definition: systemvars.h:29
#define stricmp(s1, s2)
Definition: config.h:271
#define OP_NAV_UNSET_CARRY
Definition: sexp.h:678
void sexp_turret_tagged_specific(int node)
Definition: sexp.cpp:18490
#define OP_GET_OBJECT_SPEED_Z
Definition: sexp.h:378
#define OP_UNLOCK_PRIMARY_WEAPON
Definition: sexp.h:598
#define OP_SCRIPT_EVAL_STRING
Definition: sexp.h:349
angles * vm_extract_angles_matrix_alternate(angles *a, const matrix *m)
Definition: vecmat.cpp:1064
#define OPF_KEYPRESS
Definition: sexp.h:54
int sexp_has_docked_or_undocked(int n, int op_num)
Definition: sexp.cpp:5386
char * Mp
Definition: parselo.cpp:48
int departure_location
Definition: missionparse.h:376
#define SEXP_ATOM_STRING
Definition: sexp.h:913
#define OP_ABS
Definition: sexp.h:222
void sexp_damage_escort_list_all(int n)
Definition: sexp.cpp:18998
matrix vmd_identity_matrix
Definition: vecmat.cpp:28
#define SEXP_CHECK_INVALID_SOUND_ENVIRONMENT
Definition: sexp.h:980
void sexp_clear_subtitles()
Definition: sexp.cpp:21520
int Mission_alt_type_count
#define P_SF2_DONT_COLLIDE_INVIS
Definition: missionparse.h:473
void sexp_ship_tag(int n, int tag)
Definition: sexp.cpp:14365
int is_nav_linked(int node)
Definition: sexp.cpp:19512
void sexp_beam_protect_ships(int n, bool flag)
Definition: sexp.cpp:14129
#define AI_GOAL_FORM_ON_WING
Definition: aigoals.h:35
#define OP_PAUSE_SOUND_FROM_FILE
Definition: sexp.h:730
#define OPF_SHIP_NOT_PLAYER
Definition: sexp.h:63
#define OP_CUTSCENES_SET_CAMERA_TARGET
Definition: sexp.h:612
#define OP_IS_DISARMED
Definition: sexp.h:762
#define OPF_SHIP_TYPE
Definition: sexp.h:53
bool is_blank_of_op(int op_const)
Definition: sexp.cpp:9181
#define OP_MOD
Definition: sexp.h:218
#define OP_CALL_SSM_STRIKE
Definition: sexp.h:725
int cmeasure_count
Definition: ship.h:651
#define PROPAGATE
Definition: sexp.h:895
#define OP_ADD_SUN_BITMAP
Definition: sexp.h:578
char * help
Definition: sexp.h:1205
int armor_type_idx
Definition: model.h:181
#define OP_CUTSCENES_SET_CAMERA_FACING
Definition: sexp.h:551
int Cheats_enabled
Definition: key.cpp:100
void sexp_ship_change_alt_name(int node)
Definition: sexp.cpp:14923
#define SEXP_ALL_ENGINES_STRING
Definition: sexp.h:812
void sexp_change_player_score(int node)
Definition: sexp.cpp:12445
#define LOG_SHIP_DISARMED
Definition: missionlog.h:30
void sexp_hud_disable(int n)
Definition: sexp.cpp:9772
int eval_for_counter(int arg_handler_node, int condition_node)
Definition: sexp.cpp:8950
int sexp_event_incomplete(int n)
Definition: sexp.cpp:14037
char ship_name[NAME_LENGTH]
Definition: ship.h:604
#define SEXP_CHECK_INVALID_FONT
Definition: sexp.h:978
int sexp_time_wing_departed(int n)
Definition: sexp.cpp:5742
int special_exp_shockwave_speed
Definition: ship.h:590
#define CHANGE_SUBCATEGORY_CUTSCENES
Definition: sexp.h:196
#define OP_SHIP_TAG
Definition: sexp.h:540
SCP_vector< char * > Sexp_replacement_arguments
Definition: sexp.cpp:905
SCP_vector< int > Current_sexp_operator
Definition: sexp.cpp:851
int arrival_distance
Definition: ship.h:611
Definition: hudets.h:45
void sexp_set_camera(int node)
Definition: sexp.cpp:20859
#define SF_WARP_NEVER
Definition: ship.h:461
#define OP_INVALIDATE_ALL_ARGUMENTS
Definition: sexp.h:405
#define STATUS_SUBCATEGORY_SHIP_STATUS
Definition: sexp.h:207
#define OPF_SUBSYS_OR_GENERIC
Definition: sexp.h:92
#define OP_ACTIVATE_GLOW_POINT_BANK
Definition: sexp.h:507
void set_rotation_facing(vec3d *in_target, float in_rotation_time=0.0f, float in_rotation_acceleration_time=0.0f, float in_rotation_deceleration_time=0.0f)
Definition: camera.cpp:225
#define FBF_WARP_VIA_SEXP
Definition: fireballs.h:62
#define OP_SHIP_NO_VAPORIZE
Definition: sexp.h:494
#define OPR_BOOL
Definition: sexp.h:119
#define OP_EVENT_INCOMPLETE
Definition: sexp.h:263
#define OP_STRING_GREATER_THAN
Definition: sexp.h:250
void sexp_parse_ship_kamikaze(p_object *parse_obj, int kdamage)
Definition: sexp.cpp:14808
#define OP_IS_SHIP_VISIBLE
Definition: sexp.h:331
#define OP_LOCK_AFTERBURNER
Definition: sexp.h:613
int myrand()
Definition: systemvars.cpp:102
int sexp_engine_recharge_pct(int node)
Definition: sexp.cpp:15609
int eval_cond(int n)
Definition: sexp.cpp:8514
#define OP_SET_PRIMARY_AMMO
Definition: sexp.h:586
#define OP_HUD_DISPLAY_GAUGE
Definition: sexp.h:639
#define OP_HAS_DOCKED_DELAY
Definition: sexp.h:277
void multi_sexp_set_camera_rotation()
Definition: sexp.cpp:20993
#define SEXP_VARIABLE_STRING
Definition: sexp.h:874
float rof_scaler
Definition: ship.h:399
#define SEXP_CHECK_INVALID_WEAPON_NAME
Definition: sexp.h:960
int mul_sexps(int n)
Definition: sexp.cpp:4059
void nebl_set_storm(char *name)
int sexp_waypoint_missed()
Definition: sexp.cpp:15513
#define OP_SHIP_NO_GUARDIAN
Definition: sexp.h:470
cmission missions[MAX_CAMPAIGN_MISSIONS]
int ets_idx
Definition: lua.cpp:9580
int sexp_string_get_length(int node)
Definition: sexp.cpp:20425
void multi_sexp_deal_with_ship_flag()
Definition: sexp.cpp:12814
#define LOG_SELF_DESTRUCTED
Definition: missionlog.h:39
void sexp_set_cargo(int n)
Definition: sexp.cpp:11722
#define OP_IN_SEQUENCE
Definition: sexp.h:402
int sexp_has_arrived_delay(int n)
Definition: sexp.cpp:5432
#define MAX_SEXP_VARIABLES
Definition: sexp.h:23
int debris_damage_type_idx
Definition: ship.h:799
#define EO_OUTER_RADIUS
Definition: sexp.cpp:882
int stars_add_sun_entry(starfield_list_entry *sun_ptr)
Definition: starfield.cpp:2256
Definition: hudets.h:45
#define OP_PLAYER_USE_AI
Definition: sexp.h:529
#define MISSION_FLAG_SUBSPACE
Definition: missionparse.h:68
void sexp_set_player_throttle_speed(int node)
Definition: sexp.cpp:15235
#define SW_FLAG_BEAM_FREE
Definition: ship.h:94
char name[MAX_NAME_LEN]
Definition: model.h:171
void sexp_reverse_rotating_subsystem(int node)
Definition: sexp.cpp:18363
#define SSF_NO_SS_TARGETING
Definition: ship.h:281
void sexp_remove_weapons(int node)
Definition: sexp.cpp:19748
float b
Definition: pstypes.h:111
#define OP_IS_CARGO
Definition: sexp.h:335
GLint y
Definition: Gl.h:1505
#define BLOCK_EXP_SIZE
Definition: sexp.h:890
int current_target_is_locked
Definition: ai.h:490
int arrival_delay
Definition: ship.h:615
#define OPF_SHIP_WING_POINT_OR_NONE
Definition: sexp.h:52
int sexp_get_throttle_speed(int node)
Definition: sexp.cpp:15220
#define OP_CUTSCENES_SET_CAMERA_ROTATION
Definition: sexp.h:553
int sexp_time_wing_arrived(int n)
Definition: sexp.cpp:5718
#define SEXP_VARIABLE_MODIFIED
Definition: sexp.h:904
#define STATUS_SUBCATEGORY_PLAYER
Definition: sexp.h:205
int flags
Definition: ship.h:1556
void convert_sexp_to_string(SCP_string &dest, int cur_node, int mode)
Definition: sexp.cpp:3904
void initalise_sexp_packet()
Definition: multi_sexp.cpp:62
#define OP_GET_VARIABLE_BY_INDEX
Definition: sexp.h:629
#define OP_SET_BIT
Definition: sexp.h:233
ai_goal ai_goals[MAX_AI_GOALS]
Definition: ship.h:1558
scoring_struct stats
Definition: player.h:127
#define OP_AWACS_SET_RADIUS
Definition: sexp.h:466
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, int reverse, vec3d *velocity, float warp_lifetime, int ship_class, matrix *orient_override, int low_res, int extra_flags, int warp_open_sound, int warp_close_sound)
Definition: fireballs.cpp:788
#define fl_radians(fl)
Definition: floating.h:42
#define OF_BEAM_PROTECTED
Definition: object.h:115
int sexp_get_object_coordinate(int n, int axis)
Definition: sexp.cpp:6833
#define OP_PRIMARIES_DEPLETED
Definition: sexp.h:798
#define OP_TEAM_SCORE
Definition: sexp.h:332
#define SEXP_VARIABLE_UNKNOWN
Definition: sexp.h:875
void multi_sexp_clear_subtitles()
Definition: sexp.cpp:21527
#define strcpy_s(...)
Definition: safe_strings.h:67
Definition: sound.h:72
#define OP_TURRET_TAGGED_CLEAR_SPECIFIC
Definition: sexp.h:524
void ship_subsystem_set_new_ai_class(int ship_num, char *subsystem, int new_ai_class)
Definition: ship.cpp:17380
void sexp_deal_with_warp(int n, bool repairable, bool damage_it)
Definition: sexp.cpp:13433
#define SEXP_VARIABLE_PLAYER_PERSISTENT
Definition: sexp.h:883
#define OP_SET_TRAINING_CONTEXT_FLY_PATH
Definition: sexp.h:800
#define SRC_WING_ARRIVAL
Definition: sexp.h:844
#define OP_PERCENT_SHIPS_ARRIVED
Definition: sexp.h:289
#define OP_GET_OBJECT_Z
Definition: sexp.h:340
int special_hitpoints
Definition: missionparse.h:410
bool multi_get_object(object *&objp)
Definition: multi_sexp.cpp:676
#define OP_JUMP_NODE_SET_JUMPNODE_NAME
Definition: sexp.h:561
#define OP_GET_PRIMARY_AMMO
Definition: sexp.h:351
int Fade_start_timestamp
Definition: systemvars.cpp:41
int sexp_hits_left_subsystem_specific(int node)
Definition: sexp.cpp:6215
#define SEXP_CHECK_INVALID_AUDIO_VOLUME_OPTION
Definition: sexp.h:988
void sexp_cap_waypoint_speed(int n)
Definition: sexp.cpp:11886
#define GOAL_FAILED
Definition: missiongoals.h:38
#define SEF_CARGO_KNOWN
Definition: ship.h:848
int signum_sexp(int node)
Definition: sexp.cpp:4226
int sexp_is_disabled_delay(int n)
Definition: sexp.cpp:5334
#define SW_SHIP_DEATH
Definition: shockwave.h:23
int sexp_sim_hits_left(int n)
Definition: sexp.cpp:5953
#define UNINITIALIZED
Definition: pstypes.h:30
#define OP_DISABLE_ETS
Definition: sexp.h:666
#define REAR_QUAD
Definition: objectshield.h:17
#define WEAPON_RESERVE_THRESHOLD
Definition: ship.h:52
#define SEXP_CHECK_TYPE_MISMATCH
Definition: sexp.h:933
#define OP_AVG
Definition: sexp.h:225
void sexp_beam_fire(int node, bool at_coords)
Definition: sexp.cpp:16868
#define OP_NEBULA_CHANGE_PATTERN
Definition: sexp.h:717
void sexp_change_ai_class(int n)
Definition: sexp.cpp:9581
#define OP_GOAL_FALSE_DELAY
Definition: sexp.h:262
#define OP_SHIP_INVISIBLE
Definition: sexp.h:441
char * Arrival_location_names[MAX_ARRIVAL_NAMES]
#define SEXP_NUM_EVAL
Definition: sexp.h:927
#define OP_CUTSCENES_GET_FOV
Definition: sexp.h:364
op_menu_struct op_menu[]
Definition: sexp.cpp:33799
#define SEXP_ARGUMENT_STRING
Definition: sexp.h:814
#define OP_SET_DOCKED
Definition: sexp.h:696