Descent3/scripts/DallasFuncs.cpp
Jan Engelhardt e867977543 scripts: resolve strict aliasing violations in level DLLs
$GIT/scripts/LEVEL15.cpp: In function ‘void aMatCenPuzzleInit()’:
$GIT/scripts/LEVEL15.cpp:833:38: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  833 | #define MagicMatCenSwitchSequence (*((int *)(&User_vars[17])))
$GIT/scripts/LEVEL15.cpp:834:25: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  834 | #define MatCenStateA (*((int *)(&User_vars[0])))
...
$GIT/scripts/Level6.cpp: In function ‘void aPriestKeyEnter(int)’:
$GIT/scripts/Level6.cpp:910:47: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
  910 | #define Var_ThereIsPlayerInPriestKeyPuzzle (*((int *)(&User_vars[7])))

Turn ``User_var`` into an array of std::variant, the latter of which can hold
either float or int. Savegames do not carry the necessary type information
which variant (float/int) is in use; instead, this is statically decided by
the level DLL logic on a per-index basis. This approach is retained for now.

A lot of ``Var_something = 0`` is used despite Var_something being
logically used as float, so we need to override op= to keep the
variant type as-is.
2024-09-09 15:42:00 +02:00

6686 lines
158 KiB
C++

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $Logfile: /DescentIII/Data/scripts/DallasFuncs.cpp $
* $Revision: 1.1 $
* $Date: 2000-04-18 01:45:34 $
* $Author: icculus $
*
* Definitions for the D3 actions & queries for Dallas
*
* $Log: not supported by cvs2svn $
*
* 214 10/27/99 4:19p Josh
* upped timer handle count once again to 50
*
* 213 10/23/99 2:56p Chris
* Fixed the place object on object goal
*
* 212 10/23/99 2:42a Chris
* Added the PutObjectOnObject AI Goal
*
* 211 10/17/99 9:04p Samir
* added a complex cinematic function for moving camera to position from
* position on the clipboard.
*
* 210 10/16/99 9:56p Jeff
* added a way to strip all players of all weapons and energy
*
* 209 10/16/99 8:44p Jeff
* created an action to remove all powerups from a room. Created an
* action to strip a player of all weapons
*
* 208 10/15/99 6:05p Samir
* added a query for max speed of an object.
*
* 207 10/12/99 12:43p Jeff
* added actions and queries for virus infection and negative light
*
* 206 10/08/99 4:15p Samir
* added frametime query
*
* 205 5/20/99 4:11p Jeff
* null terminate string for message when adding to inventory correctly
* (\0 not 0)
*
* 204 5/20/99 3:12p Chris
* Fixed bug in blockage code
*
* 203 5/19/99 4:57p Matt
* Added an action & a query.
*
* 202 5/19/99 2:55p Chris
* Fixed bug with aAISetTarget
*
* 201 5/19/99 12:25p Chris
* Added new functions
*
* 200 5/19/99 11:25a Matt
* Added multisafe functions & Dallas actions for showing a timer on the
* screen and adding custom HUD messages.
*
* 199 5/11/99 5:17p Jeff
* added query to get difficulty level
*
* 198 5/11/99 11:49a Matt
* Added the ability to specify a name when adding an item to the
* inventory.
*
* 197 5/08/99 10:10p Nate
* Fixed Level Goal Item index problem
*
* 196 5/08/99 2:39p Chris
* Added a new function for dallas
*
* 195 5/07/99 11:56p Matt
* Added an action to give a player an "invisible" key -- one that doesn't
* get added to the inventory or shown on the HUD.
*
* 194 5/07/99 8:22p 3dsmax
* Fixed goal query bugs
*
* 193 5/07/99 7:22p Chris
* Added some level goal querys
*
* 192 5/07/99 2:58p Matt
* Increased the maximum number of timer handles from 20 to 40.
*
* 191 5/06/99 4:11a Jeff
* created multisafe function to destroy robots in the level (helps boss
* fights)
*
* 190 5/04/99 6:52p Jeff
* added new canned cinematic to fade screen to white and endlevel. Fixed
* crash bug with invalid player path for canned cine with player paths
*
* 189 5/04/99 12:13p Matt
* Renamed fire-flare symbol to fire-weapon.
*
* 188 5/04/99 1:05a Matt
* Added new fire weapon function, and added a #define to make the old
* fire flare function use it.
*
* 187 5/02/99 1:36a Jason
* added moving object lighting viseffects
*
* 186 4/30/99 6:52p Matt
* Changed comment
*
* 185 4/30/99 6:51p Matt
* Added a query to check if an object is on the terrain.
*
* 184 4/30/99 4:32p Matt
* Added a Dallas action to fire a flare from an object.
*
* 183 4/29/99 4:50p Jeff
* fixed evil evil merge problems
*
* 182 4/29/99 12:30p Chris
* Dumb bug (Follow path simple now takes and USES the priority field)
*
* 181 4/29/99 1:59a Chris
* Added the portal blockage support
*
* 179 4/28/99 7:34p Matt
* Increased the number of spew handles from 20 to 50.
*
* 178 4/28/99 5:15p Jeff
* fixed bug with adding items to inventory...should not timeout on spew
* for spewable
*
* 177 4/27/99 5:37p Matt
* Added action to set/clear physics flags for an object.
*
* 176 4/26/99 10:35p Chris
*
* 175 4/26/99 1:43p Chris
*
* 174 4/26/99 1:40p Nate
* Fixed bug with undeclared 'ctype' identifier
*
* 173 4/26/99 11:11a Chris
* Added a new function
*
* 172 4/25/99 10:37p Matt
* Changes in death flags
*
* 171 4/25/99 3:06p Matt
* Increased the max number of spew handles from 10 to 20.
*
* 170 4/24/99 2:18a Chris
* Added some new functions.
*
* 169 4/19/99 6:14p Chris
* Added two new AI Queries for Nate
*
* 168 4/07/99 11:25a Matt
* Added fail level action
*
* 167 4/07/99 3:05a Chris
* Improved the team stuff and fixed a compile bug in
* LightningCreateGunpoints
*
* 166 4/06/99 11:44p Matt
* Added action to create a lighting bolt between two gunpoints on the
* same object, and queries to return an object's original shields and to
* multiply a percent times a float.
*
* 165 4/06/99 8:44p Matt
* Added a couple actions for Mark's energy/shield collector
*
* 164 4/06/99 11:00a Jeff
*
* 163 4/05/99 5:44p Chris
* Added a drop all objects functions
*
* 162 4/05/99 1:07p Chris
* Added a goal failed state
*
* 161 4/04/99 6:20p Matt
* Added distance-based shake Dallas action.
*
* 160 4/03/99 3:51p Chris
*
* 159 4/03/99 3:16p Chris
*
* 158 4/03/99 2:49p Chris
* Fixed a bug with the ScriptedDeath DALLAS func.
*
* 157 4/03/99 1:12a Jeff
* added multisafe/dallas actions to set an object on fire
*
* 156 4/02/99 6:41p Matt
* Added query to find the closest player to an object.
*
* 155 4/02/99 1:20p Nate
* Fixed dallas syntax bug with qGetAttachedChild
*
* 154 4/02/99 12:57p Chris
* Added 2 new DALLAS actions for Nate
*
* 153 4/02/99 11:27a Nate
* Upped the SavedObjectHandle limit to 20
*
* 152 4/02/99 11:24a Matt
* Added kill object action that allows the caller to specify the death.
*
* 151 3/31/99 11:40a Jason
* added support for attached thick lightning
*
* 150 3/30/99 7:40p Chris
*
* 149 3/30/99 7:39p Chris
*
* 148 3/30/99 7:25p Chris
* Make the weath_lightning stuff more flexable
*
* 147 3/29/99 8:41p Nate
* Jason fix
*
* 146 3/29/99 8:02p Nate
* Added qObjCanSeePlayerAdvancedWithStore
*
* 145 3/29/99 7:30p Jason
* added cool new energy effect
*
* 144 3/29/99 6:04p Nate
* Changed aLightningCreate header for new abilities.
*
* 143 3/29/99 5:26p Chris
* Added the unattach form object and the set max speed functions to
* DALLAS
*
* 142 3/29/99 11:11a Jeff
* fixed fvi calls for view cone functions (hit_none is a valid hit)
*
* 141 3/28/99 6:47p Matt
* Added default value for spark rate
*
* 140 3/28/99 5:56p Matt
* Added Dallas action to turn on object sparking
*
* 139 3/28/99 3:29p Sean
* Jeff: Fixed misnamed dallas func
*
* 138 3/27/99 9:14p Jeff
* added advanced object view cones dallas funcs
*
* 137 3/27/99 7:22p Jeff
* fixed cinematics when going from one cut to another immediatly. Added
* start transition
*
* 136 3/26/99 12:38p Jeff
* added cloak predefs
*
* 135 3/25/99 9:09p Nate
* Fixed Land On Object action
*
* 134 3/25/99 4:56p Chris
* Added code for the land on object DALLAS goal
*
* 133 3/24/99 10:02a Matt
* Added Dallas action to set music region for all players
*
* 132 3/23/99 6:42p Chris
* Added the Get to Object Goal for DALLAS
*
* 131 3/23/99 4:30p Chris
* Fixed a bug in the AIGoalGoToRoom() (parameters where out of order)
*
* 130 3/22/99 6:35p Matt
* Added Dallas action to create a lightning bolt between two objects.
* Jason will implement this.
*
* 129 3/22/99 1:59p Matt
* Added break glass Dallas action
*
* 128 3/04/99 6:13p Matt
* Pass second game message string in message2. Also changed color of the
* HUD message.
*
* 127 3/03/99 3:02p Matt
* Added Game Message action in Dallas
*
* 126 3/02/99 11:19a Jeff
* added comment
*
* 125 2/28/99 11:24p Matt
* Changed a literal to a symbolic constant
*
* 124 2/28/99 8:31p Jeff
* added fade and move player dallas action. Fixed the end-level sequence
* changing view back to player for split second.
*
* 123 2/27/99 1:41p Matt
* Added saved object handles to savegame read/write functions.
*
* 122 2/26/99 1:57a Jeff
* added text to end level sequence
*
* 121 2/25/99 8:53p Jeff
* Inventory supports level change persistant items. Inventory supports
* time-out objects. Inventory Reset changed (takes a level of reset
* now). Quad lasers stay across level change (single player). Guidebot
* bug fixed (now back in ship on level start). Quads time out when
* spewed. Invulnerability and cloak powerups no longer use game
* event/callbacks, so they can be saved in game saves (moved to
* MakePlayerInvulnerable and MakeObjectInvisible)
*
* 120 2/23/99 7:34p Jeff
* save out position clipboard, fixed up add inventory item
*
* 119 2/23/99 7:23p Matt
* Fixed function parms for new types.
*
* 118 2/23/99 11:09a Matt
* Fixed level goal actions/queries
*
* 117 2/22/99 10:21p Matt
* Added (but did not test) several actions and queries for level goals.
*
* 116 2/22/99 10:53a Matt
* Added a version of the streaming audio action that takes a text string,
* for sounds that aren't in the table file.
*
* 115 2/22/99 10:40a Luke
* fixed aAIGoalFollowPath with new data types
*
* 114 2/22/99 1:19a Jeff
* added support for inventory (simple) in dallas. Moved end-level
* sequence to use IGC. Add position clipboard stuff for dallas. Fixed
* some inventory bug with storing object handles
*
* 113 2/21/99 8:35p Jeff
* misc changes to handle new matcen and path types of dallas
*
* 112 2/21/99 6:35p Matt
* Finished action for setting object movement type, and fixed the attach
* new object action.
*
* 111 2/21/99 6:05p Matt
* Use new types for matcens, paths, & streaming audio.
*
* 110 2/21/99 5:49p Matt
* Added Dallas action to set an object's volume
*
* 109 2/21/99 4:55p Matt
* Added actions to set an object's movement type and to enable/disable
* gravity for a object.
*
* 108 2/19/99 6:44p Chris
*
* 107 2/16/99 9:36p Jeff
* added low text layout for cinematics
*
* 106 2/16/99 12:37a Matt
* Added set object velocity action
*
* 105 2/15/99 9:57p Matt
* Several small changes
*
* 104 2/15/99 3:30p Dan
* Fixed typo
*
* 103 2/15/99 3:19p Dan
* Added integer add & subtract queries (MattT on Dan's machine)
*
* 102 2/15/99 11:09a Matt
* Added function to count the number of a certain type of object in the
* level. (Also added HUD actions to print an int and float.)
*
* 101 2/14/99 4:27a Jeff
* forgot to unset a flag when ending a custom cinematic. and set a flag
* when starting a custom cinematic.
*
* 100 2/13/99 8:44p Jeff
* made intro cinematic into a 'canned' cinematic. Added ability to
* create custom in-game cinematics (SUPER powerful)
*
* 99 2/13/99 5:33p Matt
* Changed pathname in endlevel sequence from string to specific string
*
* 98 2/12/99 6:14p Matt
* Added object is type query
*
* 97 2/12/99 4:17p Matt
* Added key name & HUD message to give key action
*
* 96 2/12/99 12:07p Matt
* Make region action use enumerated type
*
* 95 2/11/99 1:07p Matt
* Added action to enable/disable triggers
*
* 94 2/11/99 2:53a Jeff
* improvements to introcam
*
* 93 2/10/99 4:06p Matt
* Changed the object type name parameter to the attach action to a
* specific string.
*
* 92 2/10/99 2:56p Matt
* Fixed typo
*
* 91 2/10/99 2:31p Matt
* Added Enable/Disable Matcen action.
*
* 90 2/10/99 1:47p Matt
* Changed object handle symbolic constants
*
* 89 2/10/99 1:21p Matt
* Added UserFlags and a query to return a user var as an integer.
*
* 88 2/09/99 1:29p Matt
* Added Matcen IDs, object handle saves, random value query, player in
* room query.
*
* 87 2/08/99 5:08p Matt
* Added MatcenID user type, and added No Reorientation flag to flag masks
* for all the AI actions.
*
* 86 2/08/99 3:10a Jeff
* added a multisafe type for player control type setting. Improved intro
* cinematic action function, player now follows path.
*
* 85 2/06/99 10:03p Matt
* Added keys system
*
* 84 2/06/99 1:52a Matt
* Added a bunch of Dallas funcs, mostly for Sean
*
* 83 2/05/99 5:51p Chris
* Added rereorienation to ai goal flags
*
* 82 2/05/99 1:29p Matt
* Changed wind to use direction vector & speed instead of velocity
* vector, and added some defaults to some actions.
*
* 81 2/04/99 3:24p Matt
* Increased the number of user vars to 25, and added save/load code for
* user vars and sound & spew handles.
*
* 80 2/03/99 5:48p Matt
* Added room damage system
*
* 79 2/03/99 2:56a Jeff
* ship permission actions and queries
*
* 78 2/03/99 12:24a Matt
* Got HUD message, 2D sound, streaming sound, and player-is-visible all
* working correctly in multiplayer.
*
* 77 2/02/99 3:58p Jeff
* started to implement level intro cinematic (need ai functions first).
* No longer need camera object to do cinematic (auto-created)...path
* cameras use speed based on distance needed to travel.
*
* 76 2/02/99 3:38p Luke
* Changed Matcen names to take direct string input instead of using
* messages
*
* 75 2/02/99 12:35p Jeff
* changed cinematic path parameter to use a instead of s
*
* 74 2/01/99 2:08p Kevin
* Fixed parameter order for qObjCanSeeObj
*
* 73 2/01/99 1:11p Matt
* Changed a bunch of stuff to work with object handles instead of player
* numbers. Also fixed the view cone action, which ignored distance.
*
* 72 2/01/99 12:41p Kevin
* Moved some functions into the training system script
*
* 71 1/31/99 11:06p Matt
* Changed timers from handles to IDs, and implemented music region set.
*
* 70 1/31/99 9:00p Jeff
* added new in game cinematics system
*
* 69 1/31/99 8:11p Matt
* Added player visible query, and made zoom work with popup cameras.
*
* 68 1/31/99 7:15p Matt
* Added physics flags for spew
*
* 67 1/30/99 7:54p Chris
*
* 66 1/30/99 3:46p Luke
* Changed two boolean parameters to be FALSE by default (0 didn't work)
*
* 65 1/30/99 3:19p Matt
* Made Dallas spews work from object centers in addition to gunpoints
*
* 64 1/29/99 3:14p Matt
* Deleted some obsolete Dallas actions, and made the player controls
* actions take player numbers instead of the player object.
*
* 63 1/29/99 2:50p Luke
* Added a bunch of default values to help designers and fixed a few
* parameter listings, but modified no actual code
*
* 62 1/29/99 12:57p Kevin
* Added cone to ObjCanSeeObj
*
* 61 1/29/99 12:49p Matt
* Added door actions & queries, chagned the working of the math queries,
* adding math queries for percentages, and reworded a few other queries.
*
* 60 1/26/99 6:39p Kevin
* Added energy get/set
*
* 59 1/26/99 5:17p Matt
* Added user types and stop object sound action.
*
* 58 1/26/99 12:53p Kevin
* Added SetTeam function
*
* 57 1/26/99 10:51a Matt
* Fixed stupid oversight.
*
* 56 1/25/99 6:32p Matt
* A bunch of stuff: sounds, goal flag masks, pick up with radius.
*
* 55 1/25/99 12:19p Matt
* Fixed stupid bugs
*
* 54 1/25/99 11:13a Matt
* Changed a bunch of actions to use enums for On/Off, Enable/Disable,
* etc. instead of bools. Also changed the Player controls action to use
* flags.
*
* 53 1/25/99 10:15a Matt
* AI Goal stuff
*
* 52 1/25/99 7:23a Chris
* Added the GUID (Goal Unique Id) and added the ability for weapon
* batteries to always fire exactly forward.
*
* 51 1/24/99 6:28p Matt
* Added path follow action
*
* 50 1/23/99 5:37p Matt
* Deleted AI goal flags that the user won't be using
*
* 49 1/23/99 5:19p Matt
* Added AI goal flags
*
* 48 1/23/99 4:48p Matt
* Added some default parameter values
*
* 47 1/23/99 2:56a Jeff
* added target field to boss intro struct
*
* 46 1/22/99 7:50p Kevin
* Training mission additions..
*
* 45 1/22/99 5:42p Matt
* Added a couple AI actions, though I haven't tested them fully yet.
*
* 44 1/22/99 3:09p Matt
* Added forcefield state query
*
* 43 1/21/99 7:03p Matt
* Added action to set/clear secret flag
*
* 42 1/20/99 9:30p Matt
* Got AISetMode action working
*
* 41 1/20/99 6:26p Matt
* Added several actions
*
* 40 1/20/99 3:49p Kevin
* Added some glue functions
*
* 39 1/20/99 3:44a Jeff
* created functions and struct for boss introduction cinematic sequence
*
* 38 1/19/99 6:54p Matt
* Added queries to add & subtract floats
*
* 37 1/19/99 6:13p Matt
* Added an action & query for lighting distance
*
* 36 1/19/99 3:43p Kevin
* Added msafe functionality to set an object to render type RT_NONE
*
* 35 1/19/99 12:16p Matt
* Added start endlevel sequence action
*
* 34 1/19/99 10:33a Kevin
*
* 33 1/19/99 10:02a Matt
* Added unfinished sound action
*
* 32 1/18/99 7:31p Matt
* Added a bunch of Dallas actions
*
* 31 1/18/99 6:18p Kevin
* Added controller masking to DALLAS
*
* 30 1/18/99 3:30p Matt
* Added some default values and ranges
*
* 29 1/15/99 5:02p Matt
* Got activate/deactive matcen actions working
*
* 28 1/15/99 11:04a Matt
* Added actions for matcens (not working) and fog (working)
*
* 27 1/13/99 5:48p Nate
* Fixed "Sheild" in function prototypes
*
* 26 1/13/99 12:42p Matt
* Added an action to close a popup view
*
* 25 1/11/99 8:43p Nate
* Added custom DALLAS queries
*
* 24 1/11/99 6:23p Nate
* Fixed two broken queries, some spelling errors, and made "Obj type"
* return an ObjectType (specific enumerated type)
*
* 23 1/11/99 4:53p Matt
* Change spew action to use enum, and added real values for SpewType
*
* 22 1/11/99 2:14p Chris
* Massive work on OSIRIS and AI
*
* 21 1/11/99 10:43a Matt
* Made forcefield on/off/toggle optionally do both sides of a portal
*
* 20 1/11/99 10:25a Matt
* Added spew handles and got spew off working. Also added functions to
* init, load, & save variables.
*
* 19 1/08/99 6:07p Matt
* Added some comments
*
* 18 1/08/99 4:33p Matt
* Got popup views working in Dallas
*
* 17 1/08/99 3:00p Luke
* (Jeff) fixed ObjPlayAnim bug (never filled in objhandle)
*
* 16 1/06/99 12:02p Matt
* Fixed some function name mismatches
*
* 15 1/05/99 6:53p Jeff
* fixed hud message color
*
* 14 1/05/99 6:38p Jeff
* fixed spew errors, added some defines
*
* 13 1/05/99 4:31p Matt
* Added a bunch more actions
*
* 12 1/05/99 3:41p Jeff
* added spew create and stop functions
*
* 11 1/04/99 11:03p Matt
* Added a bunch of actions & queries, and renamed a bunch of others
*
* 10 1/02/99 3:50p Matt
* Added ENUM defines to comment block, and made aShowHUDMessage() take
* var args.
*
* 9 1/01/99 3:25p Matt
* Fixed lightning actions
*
* 8 12/30/98 6:56p Matt
* Added a bunch more actions and queries
*
* 7 12/23/98 6:43p Nate
* Fixed the category for the qIsPlayerWeapon Query
*
* 6 12/23/98 6:10p Matt
* Added toggle forcefield action
*
* 5 12/23/98 4:29p Matt
* Un-did hack from previous version. Now works w/ scripts.
*
* 4 12/23/98 3:02p Luke
* Nate: temp fix so that editor will compile
*
* 3 12/23/98 1:46p Matt
* Renamed the portal render/forcefield actions
*
* 2 12/23/98 1:39p Matt
* Added DallasFuncs.cpp to project
*
* 1 12/23/98 1:36p Matt
*
*/
#include <algorithm>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <cstdarg>
#include <cfloat>
#include "osiris_vector.h"
#include "psrand.h"
#include "osiris_import.h"
#include "osiris_common.h"
#include "DallasFuncs.h"
/*
Dallas types:
ID Name How passed
o object object handle
d door handle of door object
r room integer room number
t trigger integer trigger number
i int integer
b bool usigned byte
f float single-precision float (4 bytes)
p percentage single-precision float in range 0.0 - 1.0
v vector pointer to triplet of floats
s string pointer to null-terminated string
e enum integer
a name a specific (non-localizable) name, as of a matcen. Does not appear in the
message file. n sound sound name h path integer path number m matcen
integer matcen numer l level goal integer level goal number z streaming audio pointer to null-terminated name
of audio file
Dallas Action Categories. Used by Dallas to build the action list.
$$CATEGORIES
Objects
Players
Doors
Rooms
Triggers
Spew
Weather
AI
Sound && Music
Timer
Level Goals
Mission
Math
User Vars
Misc
Scripts
Cinematics
Custom
$$END
Enumerated types:
$$ENUM Axis
0:X
1:Y
2:Z
$$END
$$ENUM SpewType
0:Explosion0
1:Explosion1
2:Explosion2
3:Explosion3
4:Explosion4
5:Explosion5
6:Explosion6
7:Grey Smoke
8:Black Smoke
15:Red Spark
16:Blue Spark
23:Napalm
28:Raindrop
35:Corona0
36:Corona1
37:Corona2
38:Corona3
39:Snowflake
41:Blue Fire
$$END
//I've just defined the flags that spew needs, but feel free to define others if you need them
$$FLAG PhysicsFlags
128:Gravity
2048:Fixed Velocity
32768:Reverse Gravity
65536:No Collide
2097152:Ignore Concussive Force
8388608:Lock X
16777216:Lock Y
33554432:Lock Z
$$END
$$FLAG FVIHitFlags
1:Check against objects
2:Hit backfaces of poly objects
4:Go through transparent walls if hit
8:Ignore powerups
16:Check for collisions with backfaces (default ignored)
32:Solid Portals
256:Ignore Moving Objects
512:Ignore Non-Lightmap Objects
1024:Ignore all objects besides players
2048:Ignore all walls
4096:Check terrain ceiling
8192:Ignore all objects but doors
524288:Ignore external rooms
1048576:Ignore weapons
2097152:Ignore terrain
4194304:Treat players as spheres
8388608:Treat Robots as spheres
$$END
Total: 16269119
$$ENUM ObjectType
2:Robot
4:Player
5:Weapon
6:Viewer
7:Powerup
8:Debris
10:Shockwave
11:Clutter
16:Building
17:Door
$$END
$$FLAG PlayerControl
1:Forward Thrust
2:Reverse Thrust
4:Slide Left
8:Slide Right
16:Slide Up
32:Slide Down
64:Pitch Up
128:Pitch Down
256:Heading Left
512:Heading Right
1024:Roll Left
2048:Roll Right
4096:Primary
8192:Secondary
16384:Afterburner
$$END
$$ENUM Enabled/Disabled
0:DISABLED
1:ENABLED
$$END
$$ENUM Enable/Disable
0:DISABLE
1:ENABLE
$$END
$$ENUM Completed
0:NOT COMPLETED
1:COMPLETED
$$END
$$ENUM Failed
0:NOT FAILED
1:FAILED
$$END
$$ENUM Can/Cannot
0:CANNOT
1:CAN
$$END
$$ENUM On/Off
0:OFF
1:ON
$$END
$$ENUM Yes/No
0:NO
1:YES
$$END
$$ENUM Activate/Deactivate
0:DEACTIVATE
1:ACTIVATE
$$END
$$ENUM Teams
0:PTMC
65536:Rebel
131072:Hostile
196608:Neutral
$$END
*/
//
// Variables
//
std::vector<user_var> User_vars(MAX_USER_VARS);
int Spew_handles[MAX_SPEW_HANDLES];
#define MAX_SOUND_HANDLES 10 // make sure this value matches the USERTYPE definition
int Sound_handles[MAX_SOUND_HANDLES];
int Saved_object_handles[MAX_SAVED_OBJECT_HANDLES];
int User_flags;
class cPositionClipboard {
public:
cPositionClipboard() { has_pos = false; }
bool has_pos;
int room;
vector pos;
matrix orient;
};
cPositionClipboard PositionClipboard;
#define SOUND_INVALID_HANDLE -1
#define SPEW_INVALID_HANDLE -1
/*
Tell Dallas about our handles
$$USERTYPE UserVar:24
$$USERTYPE UserFlag:31
$$USERTYPE SpewHandle:49
$$USERTYPE TimerID:49
$$USERTYPE SavedObjectSlot:19
*/
// TEMP!!!
#ifndef OBJECT_HANDLE_NONE
#define OBJECT_HANDLE_NONE -1
#endif
//
// System functions
//
// Initialize vars
void dfInit(const std::initializer_list<int> &uv_int) {
int i;
for (i = 0; i < MAX_SPEW_HANDLES; i++)
Spew_handles[i] = SPEW_INVALID_HANDLE;
for (i = 0; i < MAX_SOUND_HANDLES; i++)
Sound_handles[i] = SOUND_INVALID_HANDLE;
for (i = 0; i < MAX_USER_VARS; i++)
User_vars[i] = 0.0;
for (auto idx : uv_int)
User_vars[idx].set_type<int32_t>();
for (i = 0; i < MAX_SAVED_OBJECT_HANDLES; i++)
Saved_object_handles[i] = OBJECT_HANDLE_NONE;
User_flags = 0;
}
// Save vars
void dfSave(void *fileptr) {
int i;
for (i = 0; i < MAX_SPEW_HANDLES; i++)
File_WriteInt(Spew_handles[i], fileptr);
for (i = 0; i < MAX_SOUND_HANDLES; i++)
File_WriteInt(Sound_handles[i], fileptr);
for (i = 0; i < MAX_USER_VARS; i++) {
if (const auto *value = std::get_if<float>(&User_vars[i]))
File_WriteFloat(*value, fileptr);
else
File_WriteInt(std::get<int32_t>(User_vars[i]), fileptr);
}
for (i = 0; i < MAX_SAVED_OBJECT_HANDLES; i++)
File_WriteInt(Saved_object_handles[i], fileptr);
File_WriteInt(User_flags, fileptr);
File_WriteByte(PositionClipboard.has_pos, fileptr);
File_WriteInt(PositionClipboard.room, fileptr);
File_WriteFloat(PositionClipboard.pos.x, fileptr);
File_WriteFloat(PositionClipboard.pos.y, fileptr);
File_WriteFloat(PositionClipboard.pos.z, fileptr);
File_WriteFloat(PositionClipboard.orient.fvec.x, fileptr);
File_WriteFloat(PositionClipboard.orient.fvec.y, fileptr);
File_WriteFloat(PositionClipboard.orient.fvec.z, fileptr);
File_WriteFloat(PositionClipboard.orient.uvec.x, fileptr);
File_WriteFloat(PositionClipboard.orient.uvec.y, fileptr);
File_WriteFloat(PositionClipboard.orient.uvec.z, fileptr);
File_WriteFloat(PositionClipboard.orient.rvec.x, fileptr);
File_WriteFloat(PositionClipboard.orient.rvec.y, fileptr);
File_WriteFloat(PositionClipboard.orient.rvec.z, fileptr);
}
// Restore vars
void dfRestore(void *fileptr) {
int i;
for (i = 0; i < MAX_SPEW_HANDLES; i++)
Spew_handles[i] = File_ReadInt(fileptr);
for (i = 0; i < MAX_SOUND_HANDLES; i++)
Sound_handles[i] = File_ReadInt(fileptr);
for (i = 0; i < MAX_USER_VARS; i++)
if (std::get_if<int32_t>(&User_vars[i]))
User_vars[i] = File_ReadInt(fileptr);
else
User_vars[i] = File_ReadFloat(fileptr);
for (i = 0; i < MAX_SAVED_OBJECT_HANDLES; i++)
Saved_object_handles[i] = File_ReadInt(fileptr);
User_flags = File_ReadInt(fileptr);
PositionClipboard.has_pos = (File_ReadByte(fileptr)) ? true : false;
PositionClipboard.room = File_ReadInt(fileptr);
PositionClipboard.pos.x = File_ReadFloat(fileptr);
PositionClipboard.pos.y = File_ReadFloat(fileptr);
PositionClipboard.pos.z = File_ReadFloat(fileptr);
PositionClipboard.orient.fvec.x = File_ReadFloat(fileptr);
PositionClipboard.orient.fvec.y = File_ReadFloat(fileptr);
PositionClipboard.orient.fvec.z = File_ReadFloat(fileptr);
PositionClipboard.orient.uvec.x = File_ReadFloat(fileptr);
PositionClipboard.orient.uvec.y = File_ReadFloat(fileptr);
PositionClipboard.orient.uvec.z = File_ReadFloat(fileptr);
PositionClipboard.orient.rvec.x = File_ReadFloat(fileptr);
PositionClipboard.orient.rvec.y = File_ReadFloat(fileptr);
PositionClipboard.orient.rvec.z = File_ReadFloat(fileptr);
}
int dfGetPlayer(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_WEAPON) {
MSafe_GetValue(MSAFE_OBJECT_PARENT, &mstruct);
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_PLAYER || mstruct.type == OBJ_OBSERVER || mstruct.type == OBJ_GHOST) {
return mstruct.objhandle;
} else {
mprintf(0, "---------------------NOT A PLAYER OR PLAYER WEAPON!!!!!!!!!-------------\n");
return objhandle;
}
} else if (mstruct.type == OBJ_PLAYER || mstruct.type == OBJ_OBSERVER || mstruct.type == OBJ_GHOST) {
return objhandle;
} else {
mprintf(0, "---------------------NOT A PLAYER OR PLAYER WEAPON!!!!!!!!!-------------\n");
}
return objhandle;
}
//
// D3 actions
//
/*
$$ACTION
Rooms
[e:Enable/Disable] forcefield at portal [i:PortalNum] in room [r:Room]; Double-sided = [b:DoublesidedFlag=1]
aPortalRenderSet
Enable/Disable forcefield
Turns on or off the specified forcefield
Parameters:
Room: The room the forcefield is in
PortalNum: The portal number of the forcefield
$$END
*/
void aPortalRenderSet(int state, int portalnum, int roomnum, bool doublesided) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.portalnum = portalnum;
mstruct.flags = doublesided ? 1 : 0;
mstruct.state = state;
MSafe_CallFunction(MSAFE_ROOM_PORTAL_RENDER, &mstruct);
}
/*
$$ACTION
Rooms
[e:Enable/Disable] Blockage at portal [i:PortalNum] in room [r:Room]
aPortalBlockageSet
Enable/Disable Blockage
Turns on or off the blockage at a specified portal
Parameters:
Room: The room the blockage is in
PortalNum: The portal number of the blockage
$$END
*/
void aPortalBlockageSet(int state, int portalnum, int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.portalnum = portalnum;
mstruct.state = state;
MSafe_CallFunction(MSAFE_ROOM_PORTAL_BLOCK, &mstruct);
}
/*
$$ACTION
Rooms
Toggle forcefield at portal [i:PortalNum] in room [r:Room]; Double-sided = [b:DoublesidedFlag=1]
aPortalRenderToggle
Toggle forcefield
Turns off the specified forcefield if it's on, and on if it's off
Parameters:
Room: The room the forcefield is in
PortalNum: The portal number of the forcefield
$$END
*/
void aPortalRenderToggle(int portalnum, int roomnum, bool doublesided) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.portalnum = portalnum;
MSafe_GetValue(MSAFE_ROOM_PORTAL_RENDER, &mstruct);
mstruct.flags = doublesided ? 1 : 0;
mstruct.state = !mstruct.state;
MSafe_CallFunction(MSAFE_ROOM_PORTAL_RENDER, &mstruct);
}
/*
$$ACTION
Rooms
Break glass at portal [i:PortalNum] in room [r:Room]
aPortalBreakGlass
Break glass
Breaks the glass in the specified portal
Parameters:
PortalNum: The portal number of the forcefield
Room: The room the forcefield is in
$$END
*/
void aPortalBreakGlass(int portalnum, int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.portalnum = portalnum;
MSafe_CallFunction(MSAFE_ROOM_BREAK_GLASS, &mstruct);
}
/*
Damage sound types
$$ENUM DamageSoundType
0:None
1:Energy Weapon
2:Matter Weapon
3:Melee Attach
4:Concussive Force
5:Wall Hit
$$END
*/
/*
$$ACTION
Rooms
Set room [r:Room] damage to [f:Damage] with sound type [e:DamageSoundType]
aRoomSetDamage
Set room damage
Sets the sepecifed room to damage the player
Parameters:
Room: The room that will cause the damage
Damage: the damage rate, in shield units per second
$$END
*/
void aRoomSetDamage(int roomnum, float damage, int soundtype) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.amount = damage;
mstruct.index = soundtype;
MSafe_CallFunction(MSAFE_ROOM_DAMAGE, &mstruct);
}
/*
$$ACTION
Misc
Show HUD message [s:Message]
aShowHUDMessage
Show HUD message
Shows a HUD message for all players
Parameters:
Message: The message to show
$$END
*/
void aShowHUDMessage(const char *format, ...) {
msafe_struct mstruct;
va_list args;
va_start(args, format);
std::vsnprintf(mstruct.message, sizeof(mstruct.message) - 1, format, args);
va_end(args);
mstruct.message[sizeof(mstruct.message) - 1] = 0; // if message too long, vsnprintf() won't terminate
mstruct.state = 0; // means all players
mstruct.color = GR_RGB(0, 255, 0);
MSafe_CallFunction(MSAFE_MISC_HUD_MESSAGE, &mstruct);
}
/*
$$ACTION
Misc
Show HUD message [s:Message] for player [o:PlayerObject=IT]
aShowHUDMessageObj
Show HUD message
Shows a HUD message for a specific player
Parameters:
Message: The message to show
PlayerObject: The player who sees the object
$$END
*/
void aShowHUDMessageObj(const char *format, int objhandle, ...) {
msafe_struct mstruct;
va_list args;
va_start(args, objhandle);
std::vsnprintf(mstruct.message, sizeof(mstruct.message) - 1, format, args);
va_end(args);
mstruct.message[sizeof(mstruct.message) - 1] = 0; // if message too long, vsnprintf() won't terminate
mstruct.state = 1; // means specific player
mstruct.objhandle = dfGetPlayer(objhandle);
mstruct.color = GR_RGB(0, 255, 0);
MSafe_CallFunction(MSAFE_MISC_HUD_MESSAGE, &mstruct);
}
/*
$$ACTION
Misc
Show Colored HUD message of color [i:Red] [i:Green] [i:Blue] saying [s:Message]
aShowColoredHUDMessage
Show Colored HUD message
Shows a colored HUD message for all players
Parameters:
Red: Red component of color (0-255)
Green: Green component of color (0-255)
Blue: Blue component of color (0-255)
Message: The message to show
$$END
*/
void aShowColoredHUDMessage(int red, int green, int blue, const char *format, ...) {
msafe_struct mstruct;
va_list args;
va_start(args, format);
std::vsnprintf(mstruct.message, sizeof(mstruct.message) - 1, format, args);
va_end(args);
mstruct.message[sizeof(mstruct.message) - 1] = 0; // if message too long, vsnprintf() won't terminate
mstruct.state = 0; // means all players
mstruct.color = GR_RGB((uint8_t)red, (uint8_t)green, (uint8_t)blue);
MSafe_CallFunction(MSAFE_MISC_HUD_MESSAGE, &mstruct);
}
/*
$$ACTION
Misc
Show Colored HUD message of color [i:Red] [i:Green] [i:Blue] saying [s:Message] for player [o:PlayerObject=IT]
aShowColoredHUDMessageObj
Show Colored HUD message
Shows a colored HUD message for a specific player
Parameters:
Red: Red component of color (0-255)
Green: Green component of color (0-255)
Blue: Blue component of color (0-255)
Message: The message to show
PlayerObject: The player who sees the object
$$END
*/
void aShowColoredHUDMessageObj(int red, int green, int blue, const char *format, int objhandle, ...) {
msafe_struct mstruct;
va_list args;
va_start(args, objhandle);
std::vsnprintf(mstruct.message, sizeof(mstruct.message) - 1, format, args);
va_end(args);
mstruct.message[sizeof(mstruct.message) - 1] = 0; // if message too long, vsnprintf() won't terminate
mstruct.state = 1;
mstruct.objhandle = dfGetPlayer(objhandle);
mstruct.color = GR_RGB((uint8_t)red, (uint8_t)green, (uint8_t)blue);
MSafe_CallFunction(MSAFE_MISC_HUD_MESSAGE, &mstruct);
}
/*
$$ACTION
Misc
Add Game Message [s:GameMessage] with HUD mesage [s:HUDMessage]
aAddGameMessage
Add Game Message
Adds a message to the game message log, and shows another message on the HUD
Parameters:
GameMessage: The message that's added to the game message log
HUDMessage: The message that's displayed on the HUD
$$END
*/
void aAddGameMessage(const char *game_message, const char *hud_message) {
msafe_struct mstruct;
strncpy(mstruct.message, game_message, sizeof(mstruct.message));
mstruct.message[sizeof(mstruct.message) - 1] = 0;
strncpy(mstruct.message2, hud_message, sizeof(mstruct.message2));
mstruct.message[sizeof(mstruct.message) - 1] = 0;
mstruct.color = GR_RGB(0, 242, 148);
mstruct.state = 0; // means all players
MSafe_CallFunction(MSAFE_MISC_GAME_MESSAGE, &mstruct);
}
/*
$$ACTION
Weather
Turn rain ON with density = [p:Density=0.5:0.0|1.0]
aRainTurnOn
Turn rain ON
Turns on the rain
Parameters:
??
$$END
*/
void aRainTurnOn(float density) {
msafe_struct mstruct;
mstruct.scalar = density;
mstruct.state = true;
MSafe_CallFunction(MSAFE_WEATHER_RAIN, &mstruct);
}
/*
$$ACTION
Weather
Turn rain OFF
aRainTurnOff
Turn rain OFF
Turns off the rain
Parameters:
None.
$$END
*/
void aRainTurnOff() {
msafe_struct mstruct;
mstruct.state = false;
MSafe_CallFunction(MSAFE_WEATHER_RAIN, &mstruct);
}
/*
$$ACTION
Weather
Turn snow ON with density = [p:Density=0.5:0.0|1.0]
aSnowTurnOn
Turn snow ON
Turns on the snow
Parameters:
??
$$END
*/
void aSnowTurnOn(float density) {
msafe_struct mstruct;
mstruct.scalar = density;
mstruct.state = true;
MSafe_CallFunction(MSAFE_WEATHER_SNOW, &mstruct);
}
/*
$$ACTION
Weather
Turn snow OFF
aSnowTurnOff
Turn snow OFF
Turns off the snow
Parameters:
None
$$END
*/
void aSnowTurnOff() {
msafe_struct mstruct;
mstruct.state = false;
MSafe_CallFunction(MSAFE_WEATHER_SNOW, &mstruct);
}
/*
$$ACTION
Weather
Turn lightning ON with frequency of [f:Seconds=5.0] and probability of [p:Probability=0.5]
aLightningTurnOn
Turn lightning ON
Turns on the lightning
Parameters:
Seconds: How often to check to create lightning
Probability: The chance of creating lightning at each check
$$END
*/
void aLightningTurnOn(float check_delay, float prob) {
msafe_struct mstruct;
mstruct.state = true;
mstruct.scalar = check_delay;
mstruct.randval = static_cast<int>(prob * static_cast<float>(D3_RAND_MAX));
MSafe_CallFunction(MSAFE_WEATHER_LIGHTNING, &mstruct);
}
/*
$$ACTION
Weather
Turn lightning OFF
aLightningTurnOff
Turn lightning OFF
Turns off the lightning
Parameters:
None
$$END
*/
void aLightningTurnOff() {
msafe_struct mstruct;
mstruct.state = false;
MSafe_CallFunction(MSAFE_WEATHER_LIGHTNING, &mstruct);
}
/*
$$ACTION
Weather
Create lighting between [o:Object1] and [o:Object2]; with [f:Lifetime=1.0], [f:Thickness=1.0], [i:NumTiles=1],
[u:Texture], [f:SlideTime=0], [i:TimesDrawn=1], and color=[i:Red=255],[i:Green=255],[i:Blue=255],
AutoTile=[b:AutoTile=false] aLightningCreate Create lighting between two objects Creates a lighting effect between two
specified obejcts
Parameters:
Object1, Object2: Where the lighting is created
Lifetime: How long the lighting lasts
Thickness: How thick the lightning is
NumTiles: How many times to tile the texture within the bolt
Texture: The texture to be used for the lighting
SlideTime: The time it will take to slide the entire bolt once
TimesDrawn: The number of times to draw the bolt (saturation)
Red, Green, Blue: The color of the lighting (0-255)
AutoTile - For automatic UV tiling based on the length of the bolt
$$END
*/
void aLightningCreate(int objhandle1, int objhandle2, float lifetime, float thickness, int numtiles, int texture_id,
float slidetime, int timesdrawn, int red, int green, int blue, bool autotile) {
msafe_struct mstruct;
int type;
Obj_Value(objhandle1, VF_GET, OBJV_I_TYPE, &type);
if (type == OBJ_NONE)
return;
Obj_Value(objhandle2, VF_GET, OBJV_I_TYPE, &type);
if (type == OBJ_NONE)
return;
Obj_Value(objhandle1, VF_GET, OBJV_I_ROOMNUM, &mstruct.roomnum);
Obj_Value(objhandle1, VF_GET, OBJV_V_POS, &mstruct.pos);
Obj_Value(objhandle2, VF_GET, OBJV_V_POS, &mstruct.pos2);
mstruct.objhandle = objhandle1;
mstruct.ithandle = objhandle2;
mstruct.lifetime = lifetime;
mstruct.size = thickness;
mstruct.interval = slidetime;
mstruct.count = timesdrawn;
mstruct.index = numtiles;
mstruct.texnum = texture_id;
mstruct.color = ((red >> 3) << 10) | ((green >> 3) << 5) | (blue >> 3);
if (autotile)
mstruct.state = 1;
else
mstruct.state = 0;
mstruct.flags = 0;
MSafe_CallFunction(MSAFE_WEATHER_LIGHTNING_BOLT, &mstruct);
}
/*
$$ACTION
Weather
Create lighting between gunpoints [i:Gunpoint1=0] & [i:Gunpoint2=1] of [o:Object=OWNER]; with [f:Lifetime=1.0],
[f:Thickness=1.0], [i:NumTiles=1], [u:Texture], [f:SlideTime=0], [i:TimesDrawn=1], and
color=[i:Red=255],[i:Green=255],[i:Blue=255], AutoTile=[b:AutoTile=false] aLightningCreateGunpoints Create lighting
between gunpoints Creates a lighting effect between two specified gunpoints on an object
Parameters:
Object: Where the lighting is created
Gunpoint1,Gunpoint2: The points between which the lightning is created
Lifetime: How long the lighting lasts
Thickness: How thick the lightning is
NumTiles: How many times to tile the texture within the bolt
Texture: The texture to be used for the lighting
SlideTime: The time it will take to slide the entire bolt once
TimesDrawn: The number of times to draw the bolt (saturation)
Red, Green, Blue: The color of the lighting (0-255)
AutoTile - For automatic UV tiling based on the length of the bolt
$$END
*/
void aLightningCreateGunpoints(int gunpoint1, int gunpoint2, int objhandle, float lifetime, float thickness,
int numtiles, int texture_id, float slidetime, int timesdrawn, int red, int green,
int blue, bool autotile) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct);
if (mstruct.roomnum == -1)
return;
mstruct.g1 = gunpoint1;
mstruct.g2 = gunpoint2;
mstruct.lifetime = lifetime;
mstruct.size = thickness;
mstruct.interval = slidetime;
mstruct.count = timesdrawn;
mstruct.index = numtiles;
mstruct.texnum = texture_id;
mstruct.color = ((red >> 3) << 10) | ((green >> 3) << 5) | (blue >> 3);
if (autotile)
mstruct.state = 1;
else
mstruct.state = 0;
mstruct.flags = 1;
MSafe_CallFunction(MSAFE_WEATHER_LIGHTNING_BOLT, &mstruct);
}
/*
$$ACTION
User Vars
Set user flag [e:UserFlag] to [b:True/False]
aUserFlagSet
Set user flag
Set a flag to true or flase
Parameters:
UserFlag: The variable to set
True/False: What to set the flag to
$$END
*/
void aUserFlagSet(int flagnum, bool state) {
if ((flagnum >= 0) && (flagnum < 32)) {
int bit = 1 << flagnum;
if (state)
User_flags |= bit;
else
User_flags &= ~bit;
}
}
/*
$$ACTION
User Vars
Set user var [e:UserVar] to [f:value]
aUserVarSet
Set user var
Set a user variable to specific value
Parameters:
UserVar: The variable to set
Value: The value assigned to the variable
$$END
*/
void aUserVarSet(int varnum, float value) {
if ((varnum >= 0) && (varnum < MAX_USER_VARS))
User_vars[varnum] = value;
}
/*
$$ACTION
User Vars
Increment user var [e:UserVar]
aUserVarInc
Increment user var
Adds one to a user variable
Parameters:
UserVar: The variable to increment
$$END
*/
void aUserVarInc(int varnum) {
if ((varnum >= 0) && (varnum < MAX_USER_VARS))
User_vars[varnum]++;
}
/*
$$ACTION
User Vars
Decrement user var [e:UserVar]
aUserVarDec
Decrement user var
Subtracts one to a user variable
Parameters:
UserVar: The variable to decrement
$$END
*/
void aUserVarDec(int varnum) {
if ((varnum >= 0) && (varnum < MAX_USER_VARS))
User_vars[varnum]--;
}
/*
$$ACTION
User Vars
Add [f:value] to user var [e:UserVar]
aUserVarAdd
Add to user var
Adds to a user variable
Parameters:
Value: The amount to add to the user variable
UserVar: The variable to be modified
$$END
*/
void aUserVarAdd(float value, int varnum) {
if ((varnum >= 0) && (varnum < MAX_USER_VARS))
User_vars[varnum] += value;
}
/*
$$ACTION
User Vars
Subtract [f:value] from user var [e:UserVar]
aUserVarSub
Subtract from user var
Subtracts from a user variable
Parameters:
Value: The amount to subtract from the user variable
UserVar: The variable to be modified
$$END
*/
void aUserVarSub(float value, int varnum) {
if ((varnum >= 0) && (varnum < MAX_USER_VARS))
User_vars[varnum] -= value;
}
/*
$$ENUM Lock/Unlock
0:UNLOCK
1:LOCK
$$END
*/
/*
$$ACTION
Doors
[e:Lock/Unlock] door [d:DoorName]
aDoorLockUnlock
Lock/Unlock door
Locks or unlocks the specified door
Parameters:
DoorName: the object name of the door to be locked or unlocked
$$END
*/
void aDoorLockUnlock(int state, int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.state = state;
MSafe_CallFunction(MSAFE_DOOR_LOCK_STATE, &mstruct);
}
/*
$$ACTION
Doors
Activate door [d:Door]
aDoorActivate
Activate door
Activates (i.e. opens and possibly closes) the specified door
Parameters:
Door: the object of the door to be activated
$$END
*/
void aDoorActivate(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_CallFunction(MSAFE_DOOR_ACTIVATE, &mstruct);
}
/*
$$ACTION
Doors
Set door [d:Door] position to [p:Position]
aDoorSetPos
Set door position
Moves the door to the specified position
Parameters:
Door: the object of the door to be set
Position: the position of the door, with 0% being fully closed and 100% fully open
$$END
*/
void aDoorSetPos(int objhandle, float pos) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.scalar = pos;
MSafe_CallFunction(MSAFE_DOOR_POSITION, &mstruct);
}
/*
$$ACTION
Doors
Stop door [d:Door]
aDoorStop
Stop door
Stops the specified door if it's animating
Parameters:
Door: the object of the door to stop
$$END
*/
void aDoorStop(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_CallFunction(MSAFE_DOOR_STOP, &mstruct);
}
/*
$$ACTION
Misc
Create Popup View at gunpoint [i:GunPoint] of [o:Object] for [f:Time=10.0] seconds with zoom [f:Zoom=1.0]
aCreatePopupView
Creates a temorary view window
Parameters:
GunPoint: the gun number where the viewer should be placed
Object: the object that is the viewer
Time: how long the view lasts. If time set to 0, popup stays up until explicitly closed.
Zoom: the relative zoom of the viewer camera. 1.0 is the normal zoom.
$$END
*/
void aCreatePopupView(int gunpoint, int objref, float time, float zoom) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.interval = time;
mstruct.gunpoint = gunpoint;
mstruct.scalar = zoom;
MSafe_CallFunction(MSAFE_MISC_POPUP_CAMERA, &mstruct);
}
/*
$$ACTION
Misc
Close the popup view
aClosePopupView
Closes the popup view, if it's up
Parameters:
None.
$$END
*/
void aClosePopupView() { MSafe_CallFunction(MSAFE_MISC_CLOSE_POPUP, NULL); }
/*
$$ACTION
Objects
Set object [o:Object] shields to [f:Shields]
aObjSetShields
Set object shields
Sets an object's shields to a specific value
Parameters:
Object: the object whose shields are being set
Shields: the value to assign to the object's shields
$$END
*/
void aObjSetShields(int objref, float shields) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.shields = shields;
MSafe_CallFunction(MSAFE_OBJECT_SHIELDS, &mstruct);
}
/*
$$ACTION
Objects
Set object [o:Object] energy to [f:Energy]
aObjSetEnergy
Set object energy
Sets an object's energy to a specific value
Parameters:
Object: the object whose energy are being set
Energy: the value to assign to the object's energy
$$END
*/
void aObjSetEnergy(int objref, float energy) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.energy = energy;
MSafe_CallFunction(MSAFE_OBJECT_ENERGY, &mstruct);
}
/*
$$ACTION
Objects
Play object [o:Object] animation from frame [i:StartFrame] to [i:EndFrame=1], cycle time = [f:CycleTime=1.0], looping =
[b:Looping=FALSE] aObjPlayAnim Play object animation Plays an animation for an object
Parameters:
Object: the object to animate
StartFrame: the frame number of the start of the animation
EndFrame: the frame number of the end of the animation
CycleTime: how long the entire animation takes
Looping: if true, animation repeats. If false, animation plays once
$$END
*/
void aObjPlayAnim(int objref, int startframe, int endframe, float cycletime, bool looping) {
int flags = 0;
if (looping)
flags |= AIAF_LOOPING;
Obj_SetCustomAnim(objref, (float)startframe, (float)endframe, cycletime, flags, -1, -1);
}
/*
$$ACTION
Objects
Damage object [o:Object] by [f:DamageAmount]
aObjApplyDamage
Damage object
Applies damage to an object
Parameters:
Object: the object to damage
DamageAmount: how much damage to apply to the object (scaled by difficulty level)
$$END
*/
void aObjApplyDamage(int objref, float damage) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.killer_handle = objref;
mstruct.damage_type = 0;
mstruct.amount = damage;
MSafe_CallFunction(MSAFE_OBJECT_DAMAGE_OBJECT, &mstruct);
}
/*
Death info
$$ENUM DeathDelayType
0:No Delay
1:Delay Min/Max
2:Delay from Anim
$$END
$$ENUM DeathExplosionSize
0:Small
1:Medium
2:Large
$$END
$$FLAG DeathFlags
4:During Delay: Sparks
8:During Delay: Loses anti-grav
16:During Delay: Smokes
1048576:During Delay: Flies in air
2097152:During Delay: Fireballs
4194304:During Delay: Fades away
32:On Death: Fireballs
64:On Death: Breaks apart
128:On Death: Blast ring
256:On Death: Remains
512:On Death: Loses anti-grav
8388608:On Death: Fades away
4096:On Contact: Fireball
8192:On Contact: Breaks apart
16384:On Contact: Blask ring
32768:On Contact: Remains
65536:Debris: Smokes
131072:Debris Death: Fireball
262144:Debris Death: Blast ring
524288:Debris Death: Remains
$$END
$$ACTION
Objects
Kill object [o:Object]; delay type = [e:DeathDelayType], explosion size = [e:DeathExplosionSize], death flags =
[g:DeathFlags], Min/Max delay = [f:MinDelay] / [f:MaxDelay] aObjKill Kill Object Kills the specified object using the
specified death info
Parameters:
Object: the object to kill
$$END
*/
void aObjKill(int objhandle, int delay_type, int expl_size, int death_flags, float min_delay, float max_delay) {
death_flags |= (expl_size << DF_EXPL_SIZE_SHIFT);
if (delay_type == 2)
death_flags |= DF_DELAY_FROM_ANIM;
if (delay_type == 0)
min_delay = max_delay = 0;
Obj_Kill(objhandle, OBJECT_HANDLE_NONE, 1000.0f, death_flags, min_delay, max_delay);
}
/*
$$ACTION
Objects
Kill object [o:Object] with its default death
aObjDestroy
Kill Object with default death
Kills the specified object using the object's default death
Parameters:
Object: the object to kill
$$END
*/
void aObjDestroy(int objhandle) { Obj_Kill(objhandle, OBJECT_HANDLE_NONE, 1000.0f, -1, 0.0, 0.0); }
/*
$$ACTION
Objects
Delete object [o:Object]
aObjDelete
Delete Object
Delete the specified object. The object disappears with no death.
Parameters:
Object: the object to delete
$$END
*/
void aObjDelete(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.playsound = 0;
MSafe_CallFunction(MSAFE_OBJECT_REMOVE, &mstruct);
}
/*
$$ACTION
Objects
Set object [o:Object] lighting distance to [f:Distance]
aObjSetLightingDist
Set object lighting distance
Sets the lighting distance for an object
Parameters:
Object: the object to set
Distance: how far the light from the object will cast
$$END
*/
void aObjSetLightingDist(int objhandle, float dist) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.light_distance = dist;
MSafe_CallFunction(MSAFE_OBJECT_LIGHT_DIST, &mstruct);
}
/*
$$ACTION
Objects
Set object [o:Object] lighting color = [f:Red=0.5],[f:Green=0.5],[f:Blue=0.5]
aObjSetLightingColor
Set object lighting color
Sets the lighting color for an object
Parameters:
Object: the object to set
R,G,B: the fog color (0.0 to 1.0 for each of R,G, & B)
$$END
*/
void aObjSetLightingColor(int objhandle, float r, float g, float b) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.r1 = r;
mstruct.g1 = g;
mstruct.b1 = b;
MSafe_CallFunction(MSAFE_OBJECT_LIGHT_COLOR, &mstruct);
}
/*
$$ACTION
Objects
[e:Enable/Disable] gravity for object [o:Object]
aObjGravityEnable
Enable/Disable object gravity
Enable or Disable gravity for the specified object
Parameters:
Enable/Disable: whether gravity should be on or off
Object: the object to set
$$END
*/
void aObjGravityEnable(int enable, int objhandle) {
int flags = PF_GRAVITY;
Obj_Value(objhandle, enable ? VF_SET_FLAGS : VF_CLEAR_FLAGS, OBJV_I_PHYSICS_FLAGS, &flags);
}
/*
Object movement types
$$ENUM MovementType
0:None
1:Physics
2:Walking
$$END
*/
/*
$$ACTION
Objects
Set movement type for [o:Object] to [e:MovementType]
aObjSetMovementType
Set movement type for object
Sets the movement type for an object
Parameters:
Object: the object to set
MovementType: how this object moves
$$END
*/
void aObjSetMovementType(int objhandle, int mtype) { Obj_Value(objhandle, VF_SET, OBJV_C_MOVEMENT_TYPE, &mtype); }
/*
$$ACTION
Objects
Set object [o:Object] movement direction = <[f:X],[f:Y],[f:Z]>, speed = [f:Speed=1.0]
aObjSetVelocity
Set object movement direction and speed
Sets the movement direction and speed for an object
Parameters:
Object: the object to set
X,Y,Z: the direction vector for the wind
Speed: the speed of the wind (10.0 is faster than the player ship)
$$END
*/
void aObjSetVelocity(int objhandle, float x, float y, float z, float speed) {
vector velocity;
velocity.x = x * speed;
velocity.y = y * speed;
velocity.z = z * speed;
Obj_Value(objhandle, VF_SET, OBJV_V_VELOCITY, &velocity);
}
/*
$$ACTION
Rooms
Turn [e:On/Off] Strobe in room [r:Room]
aRoomSetLightingStrobe
Turn On/Off strobe in room
Turns on or off the light stobe in a room
Parameters:
On/Off: whether the stobe should be on or off
Room: the room to set
$$END
*/
void aRoomSetLightingStrobe(int state, int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.state = state;
MSafe_CallFunction(MSAFE_ROOM_LIGHT_STROBE, &mstruct);
}
/*
$$ACTION
Rooms
Turn [e:On/Off] Flicker in room [r:Room]
aRoomSetLightingFlicker
Turn On/Off flicker in room
Turns on or off the light flicker in a room
Parameters:
On/Off: whether the flicker should be on or off
Room: the room to set
$$END
*/
void aRoomSetLightingFlicker(int state, int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.state = state;
MSafe_CallFunction(MSAFE_ROOM_LIGHT_FLICKER, &mstruct);
}
/*
$$ACTION
Rooms
Turn [e:On/Off] fuelcen in room [r:Room]
aRoomSetFuelcen
Turn On/Off fuelcen in room
Turns on or off the fuelcen in a room
Parameters:
On/Off: whether the fuelcen should be on or off
Room: the room to set
$$END
*/
void aRoomSetFuelcen(int state, int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.state = state;
MSafe_CallFunction(MSAFE_ROOM_REFUEL, &mstruct);
}
/*
$$ACTION
Rooms
Set room [r:Room] lighting pulse time = [f:PulseTime] offset = [f:PulseOffset]
aRoomSetLightingPulse
Set room lighting pulse values
Sets the lighting pulse values for a room
Parameters:
Room: the room to set
PulseTime: how long a pulse cycle takes, or 0 to turn off pulse
PulseOffset: the time offset for this pulse
$$END
*/
void aRoomSetLightingPulse(int roomnum, float time, float offset) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.pulse_time = (uint8_t)(time * 100);
mstruct.pulse_offset = (uint8_t)(offset * 100);
MSafe_CallFunction(MSAFE_ROOM_LIGHT_PULSE, &mstruct);
}
/*
$$ACTION
Misc
Set waypoint [i:Number]
aSetWaypoint
Set waypoint
Sets the specified waypoint as active
Parameters:
Number: which waypoint to set
$$END
*/
void aSetWaypoint(int number) {
msafe_struct mstruct;
mstruct.index = number;
MSafe_CallFunction(MSAFE_MISC_WAYPOINT, &mstruct);
}
/*
$$ACTION
Spew
Turn ON spew from [o:Object] at gunpoint
[i:GunNum];[e:SpewType=7],[f:Mass=0.0],[f:Drag=0.0],[g:PhysicsFlags=65536:100480],[b:IsRealObject=FALSE],[f:BlobLifetime=1.5],[f:BlobInterval=0.15],[f:SpewLife=30.0],[f:BlobSize=4.0],[f:BlobSpeed=20.0],[b:Randomize].
Handle = [e:SpewHandle] aTurnOnSpew Turn on spew Turns on spew and sets the spew type and other variables
Parameters:
Object: the object to spew from
GunNum: the gunpoint on the object to spew from, or -1 to spew from center of object
SpewType: The type of effect the blobs of spew should be
Mass: the mass of each blob of spew
Drag: the drag of the blob as it moves through the atmosphere
PhysicsFlags: how the slews blobs are treated by the physics
IsRealObject: if set than the spew blobs are real objects, else it's just a viseffect (leave it as is unless you know
what you are doing) BlobLifetime: the lifetime of each blob of spew BlobInterval: how often a new blob of spew should be
created SpewLife: the lifetime of the spewer (-1 for infinite) BlobSize: the size of each blob of spew BlobSpeed: the
speed of each blob spew Randomize: if set than BlobSize, BlobSpeed and BlobLifetime are randomized a little (+/- some)
for each blob SpewHandle: Where to store the handle for this spewer
$$END
*/
void aTurnOnSpew(int objref, int gunpoint, int effect_type, float mass, float drag, int gravity_type, uint8_t isreal,
float lifetime, float interval, float longevity, float size, float speed, uint8_t random,
int handle_slot) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.gunpoint = gunpoint;
mstruct.effect_type = effect_type;
mstruct.mass = mass;
mstruct.drag = drag;
mstruct.phys_info = gravity_type;
mstruct.is_real = isreal;
mstruct.lifetime = lifetime;
mstruct.interval = interval;
mstruct.longevity = longevity;
mstruct.size = size;
mstruct.speed = speed;
mstruct.random = (random) ? SPEW_RAND_SIZE | SPEW_RAND_LIFETIME | SPEW_RAND_SPEED : 0;
MSafe_CallFunction(MSAFE_OBJECT_START_SPEW, &mstruct);
if ((handle_slot >= 0) && (handle_slot < MAX_SPEW_HANDLES))
Spew_handles[handle_slot] = mstruct.id;
}
/*
$$ACTION
Spew
Turn OFF spew from [e:SpewHandle]
aTurnOffSpew
Turn off spew
Turns off spew that was created with Turn On Spew. Pass in the handle given by Turn On Spew.
Parameters:
SpewHandle: the handle of the spewer to stop
$$END
*/
void aTurnOffSpew(int handle_slot) {
msafe_struct mstruct;
if ((handle_slot >= 0) && (handle_slot < MAX_SPEW_HANDLES)) {
mstruct.id = Spew_handles[handle_slot];
if (mstruct.id != SPEW_INVALID_HANDLE) {
MSafe_CallFunction(MSAFE_OBJECT_STOP_SPEW, &mstruct);
Spew_handles[handle_slot] = SPEW_INVALID_HANDLE;
}
}
}
/*
$$ACTION
Objects
Attach new object of type [a:ChildTypeName] attachpoint [i:ChildPoint] to object [o:Parent] at attachpoint
[i:ParentPoint] aAttachObject Attach new object Creates a new object attached to another object
Parameters:
$$END
*/
void aAttachObject(const char *objtypename, int childpoint, int objref, int parentpoint) {
int child_handle;
int child_type = Obj_FindType(objtypename);
int child_id = Obj_FindID(objtypename);
if (child_id >= 0) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct);
child_handle = Obj_Create(child_type, child_id, mstruct.roomnum, &mstruct.pos);
if (child_handle != OBJECT_HANDLE_NONE) {
if (!Obj_AttachObjectAP(objref, parentpoint, child_handle, childpoint, 1)) {
//!!Error attaching, so delete new object
}
}
}
}
/*
$$ACTION
Objects
UnAttach [o:AttachedObject] from an object
aUnAttachObject
UnAttach an object from another one
Unattaches an object
Parameters:
$$END
*/
void aUnAttachObject(int objref) { Obj_UnattachFromParent(objref); }
/*
$$ACTION
Objects
Object [o:ParentObject] drop all attached objects
aDropObjects
Drop attached objects
Makes an object drop objects attached to it
Parameters:
$$END
*/
void aDropObjects(int objref) { Obj_UnattachChildren(objref); }
/*
$$ACTION
Objects
Attach existing object [o:Child] attachpoint [i:ChildPoint] to object [o:Parent] at attachpoint [i:ParentPoint]
aAttachExistingObject
Attach existing object to another object
Attaches an existing object to another object
Parameters:
$$END
*/
void aAttachExistingObject(int child_ref, int childpoint, int objref, int parentpoint) {
if (!Obj_AttachObjectAP(objref, parentpoint, child_ref, childpoint, 1)) {
//!!Error attaching, so delete new object
}
}
/*
$$ACTION
Sound && Music
Set music region to [e:Region] for player [o:PlayerObject=IT]
aMusicSetRegion
Set music region
Sets the specified region as the active region for the music system
Parameters:
Region: which region is now active
PlayerObject: which player gets the music change
$$END
*/
void aMusicSetRegion(int region_num, int objhandle) {
msafe_struct mstruct;
mstruct.state = 0; // specific player
mstruct.index = region_num;
mstruct.objhandle = objhandle;
MSafe_CallFunction(MSAFE_MUSIC_REGION, &mstruct);
}
/*
$$ACTION
Sound && Music
Set music region to [e:Region] for all players
aMusicSetRegionAll
Set music region for all players
Sets the specified region as the active region for the music system for all players
Parameters:
Region: which region is now active
$$END
*/
void aMusicSetRegionAll(int region_num) {
msafe_struct mstruct;
mstruct.state = 0; // all players
mstruct.index = region_num;
MSafe_CallFunction(MSAFE_MUSIC_REGION, &mstruct);
}
/*
$$ACTION
Timer
Generate object [o:Object] timer event in [f:Time] seconds with ID [e:TimerID]
aSetObjectTimer
Generate object timer event
Sets an object timer to go off in the specified amount of time
Parameters:
Object: the object to receive the timer notification
Time: how long in seconds until notification
TimerID: the ID for this timer
$$END
*/
void aSetObjectTimer(int objref, float time, int id) {
tOSIRISTIMER timer_info;
timer_info.flags = 0;
timer_info.repeat_count = 0;
timer_info.object_handle = objref;
timer_info.object_handle_detonator = OBJECT_HANDLE_NONE;
timer_info.timer_interval = time;
timer_info.id = id;
Scrpt_CreateTimer(&timer_info);
}
/*
$$ACTION
Timer
Generate level timer event in [f:Time] seconds using with ID [e:TimerID]
aSetLevelTimer
Generate level timer event
Sets a level timer to go off in the specified amount of time
Parameters:
Time: how long in seconds until notification
TimerID: the ID for this timer
$$END
*/
void aSetLevelTimer(float time, int id) {
tOSIRISTIMER timer_info;
timer_info.flags = OTF_LEVEL;
timer_info.repeat_count = OTF_LEVEL;
timer_info.object_handle_detonator = OBJECT_HANDLE_NONE;
timer_info.timer_interval = time;
timer_info.id = id;
Scrpt_CreateTimer(&timer_info);
}
/*
$$ACTION
Timer
Cancel Timer [e:TimerID]
aCancelTimer
Cancels a timer event
Cancels a timer
Parameters:
TimerID: the ID for this timer
$$END
*/
void aCancelTimer(int id) { Scrpt_CancelTimerID(id); }
/*
$$ACTION
Timer
Show Timer [e:TimerID] on HUD
aTimerShow
Show Timer on HUD
Shows the specified timer on the HUD
Parameters:
TimerID: the ID for this timer
$$END
*/
void aTimerShow(int id) {
msafe_struct mstruct;
mstruct.index = id;
mstruct.color = GR_RGB(0, 255, 0);
MSafe_CallFunction(MSAFE_MISC_START_TIMER, &mstruct);
}
/*
$$ACTION
Mission
End level
aEndLevel
End level
Terminates the level
Parameters:
None.
$$END
*/
void aEndLevel() {
msafe_struct mstruct;
mstruct.state = 1; // success
MSafe_CallFunction(MSAFE_MISC_END_LEVEL, &mstruct);
}
/*
$$ACTION
Mission
Fail Level
aFailLevel
Fail Level
Terminates the level in failure. Level will restart.
Parameters:
None.
$$END
*/
void aFailLevel() {
msafe_struct mstruct;
mstruct.state = 0; // failure
MSafe_CallFunction(MSAFE_MISC_END_LEVEL, &mstruct);
}
/*
$$ACTION
Cinematics
Start endlevel sequence; camera = [o:Camera], path = [h:PlayerPath], time = [f:Time=10.0], text = [s:Text]
aStartEndlevelSequence
Start endlevel sequence
Start the endlevel camera sequence
Parameters:
Camera: the viewer object for the sequence
PlayerPath: the path the player ship follows
Time: how long before the level ends
Text: Any text (if any) you want to display (pass empty message if you want none)
$$END
*/
void aStartEndlevelSequence(int objhandle, int pathid, float time, const char *text) {
tCannedCinematicInfo info;
info.object_to_use_for_point = objhandle;
info.target_pathid = pathid;
info.text_to_display = text;
info.time = time;
info.type = CANNED_LEVEL_END_POINT;
Cine_StartCanned(&info);
}
/*
$$ACTION
Cinematics
Start endlevel sequence with camera on path; camera path = [h:CameraPath], player path = [h:PlayerPath], time =
[f:Time=10.0], text = [s:Text] aStartEndlevelSequencePath Start endlevel sequence on Path Start the endlevel camera
sequence, with the camera on a path
Parameters:
CameraPath: the path the camera should follow for the sequence
PlayerPath: the path the player ship follows
Time: how long before the level ends
Text: Any text (if any) you want to display (pass empty message if you want none)
$$END
*/
void aStartEndlevelSequencePath(int camerapath, int pathid, float time, const char *text) {
tCannedCinematicInfo info;
info.camera_pathid = camerapath;
info.target_pathid = pathid;
info.text_to_display = text;
info.time = time;
info.type = CANNED_LEVEL_END_PATH;
Cine_StartCanned(&info);
}
/*
$$ACTION
Cinematics
Fade Screen to white, and end level time = [f:Time=10.0], text = [s:Text]
aFadeWhiteAndEndlevel
Fades the screen to white and ends the level
Parameters:
Time: how long before the level ends (the screen fades to white across this time)
Text: Any text (if any) you want to display (pass empty message if you want none)
$$END
*/
void aFadeWhiteAndEndlevel(float time, const char *text) {
tCannedCinematicInfo info;
info.text_to_display = text;
info.time = time;
info.type = CANNED_LEVEL_END_FADE_WHITE;
Cine_StartCanned(&info);
}
/*
$$ACTION
Players
Fade Screen out and move [o:Player] to Position Clipboard
aFadeAndMovePlayer
Fades the screen out and 'warps' the player to the position in the
position clipboard.
Parameters:
Player: the player to move
$$END
*/
void aFadeAndMovePlayer(int Player) {
if (PositionClipboard.has_pos) {
tCannedCinematicInfo info;
info.room = PositionClipboard.room;
info.pos = PositionClipboard.pos;
info.orient = PositionClipboard.orient;
info.target_objhandle = Player;
info.type = CANNED_MOVE_PLAYER_FADE;
Cine_StartCanned(&info);
} else {
mprintf(0, "No ClipBoard Data Filled In\n");
}
}
/*
$$ACTION
Mission
Set mission flag [i:FlagNum] to [b:State]
aMissionSetFlag
Set mission flag
Sets the specified mission flag
Parameters:
FlagNum: the flag to set
State: the value to set the flag to
$$END
*/
void aMissionSetFlag(int flagnum, bool state) { Msn_FlagSet(flagnum, state); }
/*
$$ACTION
Mission
Set secret level flag to [b:State]
aMissionSetSecretFlag
Set secret level flags
Sets/Clears the secret level flag, so the next secret level will be enabled/disabled
Parameters:
State: whether to set or clear the flag
$$END
*/
void aMissionSetSecretFlag(bool state) { Msn_FlagSet(32, state); }
/*
$$ACTION
Mission
Set level objective flag [i:FlagNum] to [b:State=1]
aMissionSetLevelFlag
Set level objective flag
Sets the specified level objective flag
Parameters:
FlagNum: the flag to set
State: the value to set the flag to
$$END
*/
void aMissionSetLevelFlag(int flagnum, bool state) {
//!!Add code here
}
/*
$$ACTION
Sound && Music
Play 2D Sound [n:Sound] for player [o:PlayerObject=IT], volume = [p:Volume=1.0:0.0|1.0]
aSoundPlay2DObj
Play 2D Sound
Plays a sound in 2D
Parameters:
Sound: the sound to play
PlayerObject: the player who hears the sound
Volume: how loud to play the sound
$$END
*/
void aSoundPlay2DObj(int soundnum, int objhandle, float volume) {
msafe_struct mstruct;
mstruct.state = 1; // specific player
mstruct.index = soundnum;
mstruct.objhandle = dfGetPlayer(objhandle);
mstruct.volume = volume;
MSafe_CallFunction(MSAFE_SOUND_2D, &mstruct);
}
/*
$$ACTION
Sound && Music
Play 2D Sound [n:Sound] for all players, volume = [p:Volume=1.0:0.0|1.0]
aSoundPlay2D
Play 2D Sound
Plays a sound in 2D
Parameters:
Sound: the sound to play
Volume: how loud to play the sound
$$END
*/
void aSoundPlay2D(int soundnum, float volume) {
msafe_struct mstruct;
mstruct.state = 0; // all players
mstruct.index = soundnum;
mstruct.volume = volume;
MSafe_CallFunction(MSAFE_SOUND_2D, &mstruct);
}
/*
$$ACTION
Sound && Music
Play Sound [n:Sound] from object [o:Object], volume = [p:Volume=1.0:0.0|1.0]
aSoundPlayObject
Play Object Sound
Plays a sound from an object
Parameters:
Sound: the sound to play
Object: the object to attach the sound to
Volume: how loud to play the sound
$$END
*/
void aSoundPlayObject(int soundnum, int objref, float volume) {
msafe_struct mstruct;
mstruct.index = soundnum;
mstruct.volume = volume;
mstruct.objhandle = objref;
MSafe_CallFunction(MSAFE_SOUND_OBJECT, &mstruct);
}
/*
$$ACTION
Sound && Music
Play streaming sound [z:Sound] for all players, volume = [p:Volume=1.0:0.0|1.0]
aSoundPlaySteaming
Play Steaming Sound
Plays a streaming sound sample
Parameters:
Sound: the sound to play
Volume: how loud to play the sound
$$END
*/
void aSoundPlaySteaming(const char *soundname, float volume) {
msafe_struct mstruct;
mstruct.state = 0; // all players
strncpy(mstruct.name, soundname, sizeof(mstruct.name) - 1);
mstruct.name[sizeof(mstruct.name) - 1] = 0;
mstruct.volume = volume;
MSafe_CallFunction(MSAFE_SOUND_STREAMING, &mstruct);
}
/*
$$ACTION
Sound && Music
Play streaming sound [z:Sound] for player [o:PlayerObject=IT], volume = [p:Volume=1.0:0.0|1.0]
aSoundPlaySteamingObj
Play Steaming Sound
Plays a streaming sound sample
Parameters:
Sound: the sound to play
Volume: how loud to play the sound
$$END
*/
void aSoundPlaySteamingObj(const char *soundname, int objhandle, float volume) {
msafe_struct mstruct;
mstruct.state = 1; // specific player
mstruct.objhandle = objhandle;
strncpy(mstruct.name, soundname, sizeof(mstruct.name) - 1);
mstruct.name[sizeof(mstruct.name) - 1] = 0;
mstruct.volume = volume;
MSafe_CallFunction(MSAFE_SOUND_STREAMING, &mstruct);
}
/*
$$ACTION
Sound && Music
Set volume for object [o:Object] to [p:Volume=1.0:0.0|1.0]
aSoundVolumeObj
Set volume for object sound
Sets the volume for all sounds attached to an object
Parameters:
Object - the object whose sound to stop
Volume - the volume to set
$$END
*/
void aSoundVolumeObj(int objhandle, float volume) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.volume = volume;
MSafe_CallFunction(MSAFE_SOUND_VOLUME_OBJ, &mstruct);
}
/*
$$ACTION
Sound && Music
Stop sound for object [o:Object]
aSoundStopObj
Stop sound for object
Stops all sounds attached to an object
Parameters:
Object - the object whose sound to stop
$$END
*/
void aSoundStopObj(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_CallFunction(MSAFE_SOUND_STOP_OBJ, &mstruct);
}
/*
$$ENUM Ghost/Unghost
0:UNGHOST
1:GHOST
$$END
*/
/*
$$ACTION
Objects
[e:Ghost/Unghost] object [o:Object]
aObjGhostSet
Ghost/Unghost an object
Ghosts or Unghosts an object
Parameters:
Ghost/Unghost: whether to ghost or unghost the object
Object: the object to ghost or unghost
$$END
*/
void aObjGhostSet(int state, int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_CallFunction(state ? MSAFE_OBJECT_GHOST : MSAFE_OBJECT_UNGHOST, &mstruct);
}
/*
$$ACTION
Objects
Hide object [o:Object]
aObjHide
Hide an object
Makes an object not render. It will still be there but be invisible.
Parameters:
Object: the object to hide
$$END
*/
void aObjHide(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_CallFunction(MSAFE_OBJECT_NO_RENDER, &mstruct);
}
/*
$$ACTION
Objects
Make object [o:Object] invulnerable for [i:Time=20.0]
aObjMakeInvuln
Makes object invulnerable
Makes object invulnerable
Parameters:
Object: the object to make invulnerable
Time: how long the object stays invulnerable
$$END
*/
void aObjMakeInvuln(int objref, int time) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.state = 1;
mstruct.lifetime = time;
MSafe_CallFunction(MSAFE_OBJECT_INVULNERABLE, &mstruct);
}
/*
$$ACTION
Objects
Make object [o:Object] vulnerable
aObjMakeVulnerable
Makes object invulnerable
Makes object invulnerable
Parameters:
Object: the object to make vulnerable again
$$END
*/
void aObjMakeVulnerable(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
mstruct.state = 0;
MSafe_CallFunction(MSAFE_OBJECT_INVULNERABLE, &mstruct);
}
/*
$$ACTION
Objects
Deform object [o:Object] by [f:Amount=.1:0|1.0] for [f:Time] seconds
aObjDeform
Deform object
Deforms an object (applies the microwave cannon effect)
Parameters:
Object: the object to deform
Amount: how much to deform the object. 0.1 is a "normal" amount; 0.4 is a big amount.
Time: how long to deform the object
$$END
*/
void aObjDeform(int objhandle, float amount, float time) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.amount = amount;
mstruct.lifetime = time;
MSafe_CallFunction(MSAFE_OBJECT_DEFORM, &mstruct);
}
/*
$$ACTION
Objects
Make object [o:Object] spark at a rate of [f:SparkRate=50] for [f:Time] seconds
aObjSpark
Make object spark
Makes an object have sparks for the given amount of time
Parameters:
Object: the object to apply sparks to
SparkRate: how many sparks per second the object will have
Time: how long the sparking will last
$$END
*/
void aObjSpark(int objhandle, float rate, float time) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.amount = rate;
mstruct.lifetime = time;
MSafe_CallFunction(MSAFE_OBJECT_SPARKS, &mstruct);
}
/*
$$ACTION
Misc
Shake viewer by [f:Amount=40.0:0|100.0]
aMiscViewerShake
Shake view
Shakes the viewer
Parameters:
Amount: how much to shake the viewer (0-100)
$$END
*/
void aMiscViewerShake(float amount) {
msafe_struct mstruct;
mstruct.amount = amount;
MSafe_CallFunction(MSAFE_OBJECT_VIEWER_SHAKE, &mstruct);
}
/*
$$ACTION
Misc
Shake area around object [o:Object] by [f:Amount=40.0:0|100.0] over a distance of [f:Dist=100]
aMiscShakeArea
Shake the area around an object
Shakes the viewer proportional to the distance to an object
Parameters:
Object: the epicenter of the shake
Amount: how much to shake the viewer (0-100)
Dist: how far away the shake can be felt.
$$END
*/
void aMiscShakeArea(int objhandle, float amount, float dist) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.amount = amount;
mstruct.scalar = dist;
MSafe_CallFunction(MSAFE_OBJECT_SHAKE_AREA, &mstruct);
}
/*
$$ACTION
Rooms
Set texture on room [r:Room] face [i:FaceNum] to [u:Texture]
aRoomSetFaceTexture
Change face texture
Sets the texture for a room face
Parameters:
Room: the room the face is in
FaceNum: the face whose texture is changed
TextureName: the texture to assign to the specified face
$$END
*/
void aRoomSetFaceTexture(int roomnum, int facenum, int texturenum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.facenum = facenum;
mstruct.index = texturenum;
MSafe_CallFunction(MSAFE_ROOM_TEXTURE, &mstruct);
}
/*
$$ACTION
Misc
[e:Activate/Deactivate] matcen [m:Matcen]
aMatcenSetState
Activate/Deactivate matcen
Activates or Deactivates a matcen, so it starts or stops producing
Parameters:
Activate/Deactivate: whether to start or stop the matcen
Matcen: the matcen to activate
$$END
*/
void aMatcenSetState(int state, int matcen_id) {
int flags = MSTAT_ACTIVE;
if (matcen_id >= 0)
Matcen_Value(matcen_id, state ? VF_SET_FLAGS : VF_CLEAR_FLAGS, MTNV_I_STATUS, &flags);
}
/*
$$ACTION
Misc
[e:Enable/Disable] matcen [m:Matcen]
aMatcenSetEnableState
Enable/disable matcen
Enable or disable a matcen, so it's capable of producing
Parameters:
Enable/Disable: whether the matcen is cabable of producing
Matcen: the matcen to enable or disable
$$END
*/
void aMatcenSetEnableState(int state, int matcen_id) {
int flags = MSTAT_DISABLED;
if (matcen_id >= 0)
Matcen_Value(matcen_id, state ? VF_CLEAR_FLAGS : VF_SET_FLAGS, MTNV_I_STATUS, &flags);
}
/*
$$ACTION
Misc
Set matcen [m:Matcen] max produced = [i:MaxProduced=-1], production rate multiplier = [f:Multiplier=1.0], max alive
children = [i:MaxAlive=-1:1|32] aMatcenSetValues Set matcen values Set matcen values for max produced, production rate
multiplier, and max alive children
Parameters:
Matcen: the matcen to set
MaxProduced: the total number this matcen will produce in its lifetime, or -1 for no limit
Multiplier: controls the speed of the matcen. 1.0 is the normal speed
MaxAlive: the maximum number of created object that will be alive at one time, or -1 for no limit
$$END
*/
void aMatcenSetValues(int matcen_id, int max_produced, float multiplier, int max_alive) {
if (matcen_id >= 0) {
Matcen_Value(matcen_id, VF_SET, MTNV_I_MAX_PROD, &max_produced, 0);
Matcen_Value(matcen_id, VF_SET, MTNV_F_PROD_MULTIPLIER, &multiplier, 0);
Matcen_Value(matcen_id, VF_SET, MTNV_I_MAX_ALIVE_CHILDREN, &max_alive, 0);
}
}
/*
$$ACTION
Rooms
Set fog in room [r:Room] to color = [f:Red=0.5],[f:Green=0.5],[f:Blue=0.5], depth = [f:Depth=300.0]
aRoomSetFog
Set room fog
Sets the fog color and depth for a room
Parameters:
Room: the room to set
R,G,B: the fog color (0-1)
Depth: how deep the fog should be
$$END
*/
void aRoomSetFog(int roomnum, float r, float g, float b, float depth) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.fog_depth = depth;
mstruct.fog_r = r;
mstruct.fog_g = g;
mstruct.fog_b = b;
MSafe_CallFunction(MSAFE_ROOM_FOG, &mstruct);
}
/*
$$ACTION
Rooms
Change fog in room [r:Room] to color = [f:Red=0.5],[f:Green=0.5],[f:Blue=0.5], delpth = [f:Depth=200.0] over
[f:Time=20.0] seconds aRoomChangeFog Change room fog Changes the fog in a room over time
Parameters:
Room: the room to set
R,G,B: the new fog color (0-1)
Depth: how deep the fog should be after the change (starts from the current fog depth)
Time: how long in seconds the change takes
$$END
*/
void aRoomChangeFog(int roomnum, float r, float g, float b, float depth, float time) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.fog_depth = depth;
mstruct.fog_r = r;
mstruct.fog_g = g;
mstruct.fog_b = b;
mstruct.interval = time;
MSafe_CallFunction(MSAFE_ROOM_CHANGING_FOG, &mstruct);
}
/*
$$ACTION
Rooms
Turn fog [e:On/Off] in room [r:Room]
aRoomFogSetState
Turn fog On/Off
Turns On or Off the fog in a room
Parameters:
On/Off: whether to turn the fog on or off
Room: the room in which to turn on or off the fog
$$END
*/
void aRoomFogSetState(int state, int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.state = state;
MSafe_CallFunction(MSAFE_ROOM_FOG_STATE, &mstruct);
}
/*
$$ACTION
Rooms
Toggle fog in room [r:Room]
aRoomToggleFog
Toggle room fog
Toggles the fog state in a room
Parameters:
Room: the room in which to turn off the fog
$$END
*/
void aRoomToggleFog(int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
MSafe_GetValue(MSAFE_ROOM_FOG_STATE, &mstruct);
mstruct.state = !mstruct.state;
MSafe_CallFunction(MSAFE_ROOM_FOG_STATE, &mstruct);
}
/*
$$ACTION
Rooms
Set wind in room [r:Room], direction = <[f:X],[f:Y],[f:Z]>, speed = [f:Speed=1.0]
aRoomSetWind
Set wind in room
Sets the wind in a room
Parameters:
Room: the room in which to set the wind
X,Y,Z: the direction vector for the wind
Speed: the speed of the wind (10.0 is faster than the player ship)
$$END
*/
void aRoomSetWind(int roomnum, float x, float y, float z, float speed) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
//!!mstruct.wind = *v;
mstruct.wind.x = x * speed;
mstruct.wind.y = y * speed;
mstruct.wind.z = z * speed;
MSafe_CallFunction(MSAFE_ROOM_WIND, &mstruct);
}
/*
$$ACTION
Rooms
Change wind in room [r:Room] to direction = <[f:X],[f:Y],[f:Z]>, speed = [f:Speed=1.0] over [f:Time=10.0] seconds
aRoomChangeWind
Change wind in room
Changes the wind in a room over time
Parameters:
Room: the room in which to set the wind
X,Y,Z: the direction vector for the wind
Speed: the speed of the wind (10.0 is faster than the player ship)
Time: how long the change takes
$$END
*/
void aRoomChangeWind(int roomnum, float x, float y, float z, float speed, float time) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
//!!mstruct.wind = *v;
mstruct.wind.x = x * speed;
mstruct.wind.y = y * speed;
mstruct.wind.z = z * speed;
mstruct.interval = time;
MSafe_CallFunction(MSAFE_ROOM_CHANGING_WIND, &mstruct);
}
/*
$$ACTION
AI
Object For [o:Object] turn the AI scripted death flag [e:On/Off]
aSetScriptedDeath
Turn On/Off the AI scripted death flag
Turns on/off the scripted death flag for the specified object
Parameters:
Object - the object in question
On/Off - whether to turn on/off the AI Scripted Death Flag
$$END
*/
void aSetScriptedDeath(int objhandle, int state) {
int flags = OF_AI_DEATH;
Obj_Value(objhandle, state ? VF_SET_FLAGS : VF_CLEAR_FLAGS, OBJV_I_FLAGS, &flags);
}
/*
$$ACTION
AI
Turn [e:On/Off] the AI for object [o:Object]
aAISetState
Turn On/Off the AI for object
Turns on or off the AI for the specified object
Parameters:
On/Off - whether to turn the AI on or off
Object - the object whose AI is turned on or off
$$END
*/
void aAISetState(int state, int objhandle) { AI_PowerSwitch(objhandle, state != 0); }
/*
$$ACTION
AI
Set the FOV of [o:Object] to [f:FOV] degrees
aAISetFOV
Sets the FOV for an AI object (0 - 360)
Sets the FOV for an AI object (0 - 360)
Parameters:
Object - the object whose AI is turned on or off
FOV - the number of angles of the FOV
$$END
*/
void aAISetFOV(int objhandle, float fov) {
fov = cos(fov * PI / (360.0));
AI_Value(objhandle, VF_SET, AIV_F_FOV, &fov);
}
/*
$$ACTION
AI
Set the Target of [o:Object] to [o:Target]
aAISetTarget
Sets the target for an AI object
Sets the target for an AI object
Parameters:
Object - the object whose AI target is being set
Target - the object to be targeted for attack
$$END
*/
void aAISetTarget(int objhandle, int targethandle) { AI_Value(objhandle, VF_SET, AIV_I_TARGET_HANDLE, &targethandle); }
/*
$$ACTION
AI
Set Team to [e:Teams] for the AI for object [o:Object]
aAISetTeam
Sets the team for a specific object
Sets the team for a specific object
Parameters:
Team: Which team you want the object to belong to
Object - the object whose team you want to change
$$END
*/
void aAISetTeam(int team, int objhandle) {
int flags = AIF_TEAM_MASK;
AI_Value(objhandle, VF_CLEAR_FLAGS, AIV_I_FLAGS, &flags);
flags = team; // AIF_TEAM_REBEL;
AI_Value(objhandle, VF_SET_FLAGS, AIV_I_FLAGS, &flags);
int target_handle = OBJECT_HANDLE_NONE;
AI_Value(objhandle, VF_SET, AIV_I_TARGET_HANDLE, &target_handle);
}
/*
$$ACTION
AI
Clear the [e:GoalPriority=3] prioriity goal for object [o:Object]
aAIClearGoal
Clears a goal for a specific object
Clears a goal for a specific object
Parameters:
GoalPriority: The priority of the goal you can to clear
Object: the object whose goal you want to clear
$$END
*/
void aAIClearGoal(int slot, int handle) { AI_ClearGoal(handle, slot); }
/*
$$ENUM AIModeType
1:Stalker
2:Standard Attack
3:Guardian
4:Stationary Turret
6:Melee
7:Bird Flock
9:Herd
$$END
Luke would additionally like these types:
Wander
Berzerker
Pursue
Sniper
Survival
Sneak Attack
Supervisor
*/
/*
$$ACTION
AI
Set AI mode for object [o:Object] to [e:AIModeType]
aAISetMode
Set AI mode
Sets the AI mode for an objectTurn ON AI for object
Parameters:
Object - the object whose AI mode is set
AIModeType - which mode to set for the object
$$END
*/
void aAISetMode(int objhandle, int modetype) { AI_SetType(objhandle, modetype); }
/*
$$ACTION
AI
Set [o:Object] to have a max speed of [f:MaxSpeed]
aAISetMaxSpeed
Set the max speed of an object
Set the max speed of an object
Parameters:
Object - the object whose AI mode is set
MaxSpeed - Maximum speed
$$END
*/
void aAISetMaxSpeed(int objhandle, float max_speed) { AI_Value(objhandle, VF_SET, AIV_F_MAX_SPEED, &max_speed); }
// Used for all AI Goal calls
#define DEFAULT_INFLUENCE 1.0
/*
Flags for AI Goals
$$FLAG AIGoalFlags
1:Permanent
4:Keep at Completion
16:Object is Target
128:Go Directly to Goal if Visible
256:Force Awareness
512:Objects are Friends
1024:Objects are Species
2048:Objects are Enemies
4096:Orient Velocity
65536:Orient Target
131072:No Reorientation
262144:Orient Goal Object
1048576:Orient Path Node
2097152:Follow Path Exactly
4194304:Reverse at End of Path
8388608:Circle at End of Path
16777216:Follow Path in Reverse Direction
$$END
Flags for AI
$$FLAG AIFlags
1:Weapon Attack 1
2:Weapon Attack 2
4:Melee Attack 1
8:Melee Attack 2
32: Act as team neutral until shot
64:Persistant (always using CPU cycles)
128:Dodging
256:Firing Ranged Weapons
512:Flinching
1024:Determining Targets
2048:Aiming
8192:Auto-avoid walls
16384:Disabled
32768:Team PTMC (WARNING - NEVER SET TWO TEAMS)
65536:Team Rebel (WARNING - NEVER SET TWO TEAMS)
131072:Team Hostile to everyone (WARNING - NEVER SET TWO TEAMS)
196608:Team Neutral to everyone (WARNING - NEVER SET TWO TEAMS)
524288:Orientate to velocity
4194304:Target by distance
8388608:Disable ranged weapon firing (even in script)
16777216:Disable melee attacks (even in script)
33554432:Auto-avoid friends
268435456:Biased Flight Height
536870912:Force awareness (always using CPU cycles)
$$END
User type for Goal IDs
$$USERTYPE GoalID:99
AI Goal slot values
$$ENUM GoalPriority
3:High
0:Low
$$END
$$ENUM Set/Clear
0:Clear
1:Set
$$END
*/
/*
$$ACTION
AI
[e:Set/Clear=1] AI Flags [g:AIFlags=0] for Object [o:Object]
aAIFlags
Sets and clears AI flags
Sets and clears AI flags
Parameters:
Set/Clear - Set or Clear the specified flags
AIFlags - the flags to either set or clear (other flags are not effected)
Object - The object of which you want to alter the AI flags
$$END
*/
void aAIFlags(int set, int flags, int handle) {
bool f_team = false;
// Because it is a bitfield, I had to hack a team value... Team PTMC was 0; so, it was
// impossible to set... 32768 wasn't used, so I hacked it here. O' The shame... :(
if (!set)
flags &= ~(AIF_TEAM_MASK);
else
f_team = (flags & (AIF_TEAM_MASK | 32768)) != 0;
// hacked PTMC team value
flags &= ~(32768);
// Since it is a bit field... clear out the old value
if (f_team) {
int team_mask = AIF_TEAM_MASK;
AI_Value(handle, VF_CLEAR_FLAGS, AIV_I_FLAGS, &team_mask);
}
AI_Value(handle, (set) ? VF_SET_FLAGS : VF_CLEAR_FLAGS, AIV_I_FLAGS, &flags);
}
/*
$$ACTION
AI
Set AI object [o:Object] goal Priority = [e:GoalPriority=3] circle distance to [f:distance]
aAIGoalSetCircleDistance
Sets the circle distance for a goal
Sets the circle distance for a goal
Parameters:
Object - the object who is send to the room
Priority - priority of the goal in question
$$END
*/
void aAIGoalSetCircleDistance(int objhandle, int slot, float distance) {
AI_GoalValue(objhandle, slot, VF_SET, AIGV_F_CIRCLE_DIST, &distance);
}
/*
$$ACTION
AI
Send AI object [o:Object] to room [r:Room]; Priority = [e:GoalPriority=3], Flags = [g:AIGoalFlags=4352:201109], GoalID =
[e:GoalID=-1] aAIGoalGotoRoom Send AI object to room Instructs an AI object to go to a specific room
Parameters:
Object - the object who is send to the room
Room - the room to go do
Priority - if High, overrides the default goals; if Low, does only when the object has no other enabled goals
Flags - the flags for this goal
GoalID - an ID for this goal
$$END
*/
void aAIGoalGotoRoom(int objhandle, int roomnum, int slot, int flags, int goalid) {
vector pos;
Room_Value(roomnum, VF_GET, RMSV_V_PATH_PNT, &pos, 0);
AI_AddGoal(objhandle, AIG_GET_TO_POS, slot, DEFAULT_INFLUENCE, goalid, flags, &pos, roomnum);
}
/*
$$ACTION
AI
Send AI object [o:Object] to object [o:Target]; Priority = [e:GoalPriority=3], Flags = [g:AIGoalFlags=4352:201109],
GoalID = [e:GoalID=-1] aAIGoalGotoObject Send AI object to a specified object Instructs an AI object to go to a specific
object
Parameters:
Object - the object who is send to the room
Target - the object to get to
Priority - if High, overrides the default goals; if Low, does only when the object has no other enabled goals
Flags - the flags for this goal
GoalID - an ID for this goal
$$END
*/
void aAIGoalGotoObject(int objhandle, int target, int slot, int flags, int goalid) {
AI_AddGoal(objhandle, AIG_GET_TO_OBJ, slot, DEFAULT_INFLUENCE, goalid, flags, target);
}
/*
$$ACTION
AI
Send AI object [o:Object] on path [h:Path]; Flags = [g:AIGoalFlags=4352:32706959], GoalID = [e:GoalID=-1], Priority =
[e:GoalPriority=3] aAIGoalFollowPathSimple Send AI object on path Instructs an AI object to follow a path
Parameters:
Object - the object who is send to the room
Path - the path to follow
Flags - the flags for this goal
GoalID - an ID for this goal
Priority - The priority of the goal
$$END
*/
void aAIGoalFollowPathSimple(int objhandle, int pathid, int flags, int goalid, int priority) {
//!!GoalID not used yet
if (pathid != -1)
AI_GoalFollowPathSimple(objhandle, pathid, goalid, flags, priority);
}
/*
$$ACTION
AI
Send AI object [o:Object] on path [h:Path] between nodes [i:FirstNode] and [i:LastNode], starting at [i:StartNode];
Priority = [e:GoalPriority=3], Flags = [g:AIGoalFlags=4352:32706959], GoalID = [e:GoalID=-1] aAIGoalFollowPath Send AI
object on path Instructs an AI object to follow a path
Parameters:
Object - the object who is send to the room
Path - the path to follow
FirstNode, LastNode - the endpoints of the part of the path to follow
StartNode - where to start following the path
Priority - if High, overrides the default goals; if Low, does only when the object has no other enabled goals
Flags - the flags for this goal
GoalID - an ID for this goal
$$END
*/
void aAIGoalFollowPath(int objhandle, int pathid, int firstnode, int lastnode, int startnode, int slot, int flags,
int goalid) {
if (pathid != -1)
AI_AddGoal(objhandle, AIG_FOLLOW_PATH, slot, DEFAULT_INFLUENCE, goalid, flags, pathid, firstnode, lastnode,
startnode);
}
/*
$$ACTION
AI
Make object [o:Picker] (attachpoint [i:PickerPoint]) pick up object [o:Pickee] (attachpoint = [i:PickeePoint]); Aligned
= [b:Aligned]; Priority = [e:GoalPriority=3], Flags = [g:AIGoalFlags:463253], GoalID = [e:GoalID=-1] aAIGoalPickUpObject
Make object pick up object
Make one object pick up another
Parameters:
Picker - the object doing the picking up
PickerPoint - the attach point on the picker
Pickee - the object being picked up
PickeePoint - the attach point on the pickee
Aligned - if true, aligns the two object
Priority - if High, overrides the default goals; if Low, does only when the object has no other enabled goals
Flags - the flags for this goal
GoalID - an ID for this goal
$$END
*/
void aAIGoalPickUpObject(int pickerhandle, int pickerpoint, int pickeehandle, int pickeepoint, bool aligned, int slot,
int flags, int goalid) {
AI_AddGoal(pickerhandle, AIG_ATTACH_TO_OBJ, slot, DEFAULT_INFLUENCE, goalid, flags, pickeehandle, pickerpoint,
pickeepoint, 0.0, aligned, 0);
}
/*
$$ACTION
AI
Make object [o:Picker] (attachpoint [i:CarriedObjectPoint]) be set down onto object [o:LandOnObject] (attachpoint =
[i:LandOnPoint]); Priority = [e:GoalPriority=3], Flags = [g:AIGoalFlags:463253], GoalID = [e:GoalID=-1]
aAIGoalSetObjectOnObject
Make object pick up object
Make one object pick up another
Parameters:
Picker - the object doing the picking up
CarriedObjectPoint - the attach point on the picker
LandOnObject - the object being picked up
LandOnPoint - the attach point on the pickee
Priority - if High, overrides the default goals; if Low, does only when the object has no other enabled goals
Flags - the flags for this goal
GoalID - an ID for this goal
$$END
*/
void aAIGoalSetObjectOnObject(int pickerhandle, int pickerpoint, int pickeehandle, int pickeepoint, int slot, int flags,
int goalid) {
AI_AddGoal(pickerhandle, AIG_PLACE_OBJ_ON_OBJ, slot, DEFAULT_INFLUENCE, goalid, flags, pickeehandle, pickerpoint,
pickeepoint, 0.0, true, 0);
}
/*
$$ACTION
AI
Make object [o:LandingObject] (attachpoint [i:LanderAttachPoint]) land on object [o:ObjectToLandOn] (attachpoint =
[i:LandOnObjectAttachPoint]); Priority = [e:GoalPriority=3], Flags = [g:AIGoalFlags:463253], GoalID = [e:GoalID=-1]
aAIGoalLandOnObject
Make an object land on another object
Make one object and on another object
Parameters:
LandingObject - the object that is going to land
LanderAttachPoint - the attach point that the landing object uses
ObjectToLandOn - the object being landed on
LandOnObjectAttachPoint - the attach point of the object being landed on
Priority - if High, overrides the default goals; if Low, does only when the object has no other enabled goals
Flags - the flags for this goal
GoalID - an ID for this goal
$$END
*/
void aAIGoalLandOnObject(int pickerhandle, int pickerpoint, int pickeehandle, int pickeepoint, int slot, int flags,
int goalid) {
AI_AddGoal(pickerhandle, AIG_ATTACH_TO_OBJ, slot, DEFAULT_INFLUENCE, goalid, flags | GF_IS_ATTACH_CHILD, pickeehandle,
pickerpoint, pickeepoint, 0.0, true, 0);
}
/*
$$ACTION
AI
Make object [o:Picker] (attachpoint [i:PickerPoint]) pick up object [o:Pickee] with radius = [p:RadiusRatio=1.0];
Priority = [e:GoalPriority=3], Flags = [g:AIGoalFlags:463253], GoalID = [e:GoalID=-1] aAIGoalPickUpObjectRad Make object
pick up object Make one object pick up another
Parameters:
Picker - the object doing the picking up
PickerPoint - the attach point on the picker
Pickee - the object being picked up
RadiusRatio - how close to hold the object relative to the object's size
Priority - if High, overrides the default goals; if Low, does only when the object has no other enabled goals
Flags - the flags for this goal
GoalID - an ID for this goal
$$END
*/
void aAIGoalPickUpObjectRad(int pickerhandle, int pickerpoint, int pickeehandle, float radius, int slot, int flags,
int goalid) {
AI_AddGoal(pickerhandle, AIG_ATTACH_TO_OBJ, slot, DEFAULT_INFLUENCE, goalid, flags, pickeehandle, pickerpoint, -1,
radius, 0, 1);
}
/*
$$ACTION
Objects
[e:Set/Clear=1] Physics Flags [g:PhysicsFlags=0] for Object [o:Object]
aPhysFlags
Set/Clear Physics flags
Sets or and clears physics flags
Parameters:
Set/Clear - Set or Clear the specified flags
PhysicsFlags - the flags to either set or clear (other flags are not effected)
Object - The object of which you want to alter the physics flags
$$END
*/
void aPhysFlags(int set, int flags, int handle) {
Obj_Value(handle, (set) ? VF_SET_FLAGS : VF_CLEAR_FLAGS, OBJV_I_PHYSICS_FLAGS, &flags);
}
/*
$$ACTION
Cinematics
Simple letterbox format cinematic, using path [h:CameraPath], with text [s:Text] targeting [o:Target] for
[f:Seconds=10.0f] has fade in [b:FadeIn] aCinematicSimple CinematicSimple This creates a simple cinematic, in Letterbox
mode. The camera will follow the given path. And the given text will be shown at the bottom of the screen. There is no
'quick exit' by keypress. To do more than one line of text, separate each line of text using a pipe ('|').
Parameters:
CameraPath: The path the camera should follow
Text: The text to be displayed on the screen
Target: Object to target during the cinematic
Seconds: how long the cinematic should last
FadeIn: If TRUE then the cinematic will fade in
$$END
*/
void aCinematicSimple(int pathid, const char *Text, int Target, float Seconds, bool FadeIn) {
tGameCinematic info;
info.flags = 0;
info.flags = (GCF_LETTERBOX | GCF_USEPATH | GCF_TEXT_WIPEIN | GCF_LAYOUT_BOTTOM);
info.target_objhandle = Target;
info.max_time_play = Seconds;
info.callback = NULL;
info.text_display.min = 0.40f;
info.text_display.max = 1.0f;
info.track_target.min = 0.0f;
info.track_target.max = 1.0f;
info.player_disabled.min = 0.0f;
info.player_disabled.max = 1.0f;
info.in_camera_view.min = 0.0f;
info.in_camera_view.max = 1.0f;
info.quick_exit.min = 1.0f;
info.quick_exit.max = 1.0f;
info.end_transition = GCTT_FADEINOUT;
info.start_transition = (FadeIn) ? GCTT_FADE : GCTT_NONE;
info.pathid = pathid;
Cine_Start(&info, Text);
}
/*
$$ACTION
Cinematics
Introduction fly-in using path [h:CameraPath], with text [s:Text] following player position [o:TotallyNotUsedTarget] on
[h:PlayerPath] for [f:Seconds=10.0f]. aCinematicIntro CinematicIntro THE TARGET IS NOT USED, IT'S HERE FOR BACKWARD
COMPATIBILITY This starts a level introduction cinematic. The camera will follow the given path. And the given text will
be shown at the bottom of the screen. There is a 'quick exit' by keypress, after the first quarter of the cinematic is
done. To do more than one line of text, separate each line of text using a pipe ('|').
Parameters:
ONCE AGAIN, THE TARGET IS NOT USED, IT'S HERE FOR BACKWARD COMPATIBILITY
ONCE AGAIN, THE TARGET IS NOT USED, IT'S HERE FOR BACKWARD COMPATIBILITY
CameraPath: The path the camera should follow
Text: The text to be displayed on the screen
Target: NO LONGER USED (it's the player object)
PlayerPath: The path the target object should follow
Seconds: how long the cinematic should last
ONCE AGAIN, THE TARGET IS NOT USED, IT'S HERE FOR BACKWARD COMPATIBILITY
ONCE AGAIN, THE TARGET IS NOT USED, IT'S HERE FOR BACKWARD COMPATIBILITY
$$END
*/
void aCinematicIntro(int camera_path, const char *Text, int NoLongerUserTarget, int PlayerPath, float Seconds) {
tCannedCinematicInfo info;
info.type = CANNED_LEVEL_INTRO;
info.camera_pathid = camera_path;
info.target_pathid = PlayerPath;
info.text_to_display = Text;
info.time = Seconds;
Cine_StartCanned(&info);
}
/*
$$ACTION
Cinematics
Stops the currently playing in-game cinematic
aCinematicStop
CinematicStop
Stops a currently playing in-game cinematic, restoring everything
$$END
*/
void aCinematicStop(void) { Cine_Stop(); }
class complex_cinematic {
public:
complex_cinematic() {
being_made = false;
memset(&info, 0, sizeof(tGameCinematic));
}
tGameCinematic info;
bool being_made;
};
complex_cinematic ccinematic;
/*
$$ACTION
Cinematics
Complex Cinematic: Start
aComplexCinematicStart
ComplexCinematicStart
Starts the creation process of a 'complex' in-game cinematic.
$$END
*/
void aComplexCinematicStart(void) {
ccinematic.being_made = true;
memset(&ccinematic.info, 0, sizeof(tGameCinematic));
ccinematic.info.flags = (GCF_LETTERBOX | GCF_USEPATH | GCF_TEXT_WIPEIN | GCF_LAYOUT_BOTTOM | GCF_STOPIFTAGETDEAD);
ccinematic.info.target_objhandle = OBJECT_HANDLE_NONE;
ccinematic.info.max_time_play = 10.0f;
ccinematic.info.callback = NULL;
ccinematic.info.text_display.min = 0.40f;
ccinematic.info.text_display.max = 1.0f;
ccinematic.info.track_target.min = 0.0f;
ccinematic.info.track_target.max = 1.0f;
ccinematic.info.player_disabled.min = 0.0f;
ccinematic.info.player_disabled.max = 1.0f;
ccinematic.info.in_camera_view.min = 0.0f;
ccinematic.info.in_camera_view.max = 1.0f;
ccinematic.info.quick_exit.min = 1.0f;
ccinematic.info.quick_exit.max = 1.0f;
ccinematic.info.end_transition = GCTT_FADEINOUT;
ccinematic.info.start_transition = GCTT_NONE;
ccinematic.info.pathid = -1;
}
/*
$$ACTION
Cinematics
Complex Cinematic: End, cinematic text: [s:Text] play time: [f:Seconds=10.0]
aComplexCinematicEnd
ComplexCinematicEnd
Ends the creation process of a 'complex' in-game cinematic and starts it running.
Params:
Text: The text you want displayed during the cinematic
Seconds: How long cinematic should play
$$END
*/
void aComplexCinematicEnd(const char *Text, float Seconds) {
if (!ccinematic.being_made)
return;
ccinematic.info.max_time_play = Seconds;
Cine_Start(&ccinematic.info, Text);
ccinematic.being_made = false;
}
/*
$$ACTION
Cinematics
Complex Cinematic: Text Display Start [p:Start=0.4] until End [p:End=0.8]
aComplexCinematicText
ComplexCinematicText
Determines the range (based on a percentage into the cinematic) that the text should display
Params:
Start: At what percentage of time into the cinematic should text start displaying
End: At what percentage of time into the cinematic should text stop displaying
$$END
*/
void aComplexCinematicText(float Start, float End) {
ccinematic.info.text_display.min = Start;
ccinematic.info.text_display.max = End;
}
/*
$$ACTION
Cinematics
Complex Cinematic: Track Target [o:Target] Start [p:Start=0.0] until End [p:End=1.0]
aComplexCinematicTrack
ComplexCinematicTrack
Determines the range (based on a percentage into the cinematic) that the target should be tracked
(NOTE: it should be the entire time...0->100% but you may feel different)
Params:
Target: Object to target
Start: At what percentage of time into the cinematic should target be tracked
End: At what percentage of time into the cinematic should target stop being tracked
$$END
*/
void aComplexCinematicTrack(int Target, float Start, float End) {
ccinematic.info.target_objhandle = Target;
ccinematic.info.track_target.min = Start;
ccinematic.info.track_target.max = End;
}
/*
$$ACTION
Cinematics
Complex Cinematic: Player Disabled Start [p:Start=0.0] until End [p:End=1.0]
aComplexCinematicPlayerDisabled
ComplexCinematicPlayerDisabled
Determines the range (based on a percentage into the cinematic) that the player's
controls are disabled.
Params:
Start: At what percentage of time into the cinematic should controls disable
End: At what percentage of time into the cinematic should controls be renabled
$$END
*/
void aComplexCinematicPlayerDisabled(float Start, float End) {
ccinematic.info.player_disabled.min = Start;
ccinematic.info.player_disabled.max = End;
}
/*
$$ACTION
Cinematics
Complex Cinematic: View From Camera Start [p:Start=0.0] until End [p:End=1.0]
aComplexCinematicCameraView
ComplexCinematicCameraView
Determines the range (based on a percentage into the cinematic) that the view is from
the camera
Params:
Start: At what percentage of time into the cinematic should the view be in the camera
End: At what percentage of time into the cinematic should the view be back to the player
$$END
*/
void aComplexCinematicCameraView(float Start, float End) {
ccinematic.info.in_camera_view.min = Start;
ccinematic.info.in_camera_view.max = End;
}
/*
$$ACTION
Cinematics
Complex Cinematic: Quick Exit Start [p:Start=1.0] until End [p:End=1.0]
aComplexCinematicQuickExit
ComplexCinematicQuickExit
Determines the range (based on a percentage into the cinematic) that the player can quick
exit from the cinematic by pressing a key (usually 0%-100% or 100%-100%)
Params:
Start: At what percentage of time into the cinematic can the player quick exit
End: At what percentage of time into the cinematic can't the player quick exit
$$END
*/
void aComplexCinematicQuickExit(float Start, float End) {
ccinematic.info.quick_exit.min = Start;
ccinematic.info.quick_exit.max = End;
}
/*
$$ENUM CineEndTransition
0:None
1:Wacky
2:Fade In
3:Fade Out/In
$$END
*/
/*
$$ACTION
Cinematics
Complex Cinematic: Set End Transition to [e:CineEndTransition=3]
aComplexCinematicEndTrans
ComplexCinematicEndTrans
Sets the end transition setting.
$$END
*/
void aComplexCinematicEndTrans(int End) { ccinematic.info.end_transition = End; }
/*
$$ACTION
Cinematics
Complex Cinematic: Set Start Fade in to [b:Enable]
aComplexCinematicStartTrans
ComplexCinematicStartTrans
Sets whether the cinematic should fade in to start
$$END
*/
void aComplexCinematicStartTrans(bool Enable) { ccinematic.info.start_transition = (Enable) ? GCTT_FADE : GCTT_NONE; }
/*
$$ACTION
Cinematics
Complex Cinematic: Put Camera On Path [h:Path]
aComplexCinematicCameraOnPath
ComplexCinematicCameraOnPath
Tells the cinematic that the camera should be on the given path
$$END
*/
void aComplexCinematicCameraOnPath(int Path) {
ccinematic.info.flags |= GCF_USEPATH;
ccinematic.info.flags &= ~GCF_USEPOINT;
ccinematic.info.pathid = Path;
}
/*
$$ACTION
Cinematics
Complex Cinematic: Put Camera At Position [v:Position] in room [r:Room]
aComplexCinematicCameraAtPoint
ComplexCinematicCameraAtPoint
Tells the cinematic that the camera should be on a point
Params:
Position: The position of the camera in the world
Room: The room that that position is in
$$END
*/
void aComplexCinematicCameraAtPoint(vector *Position, int Room) {
ccinematic.info.flags &= ~GCF_USEPATH;
ccinematic.info.flags |= GCF_USEPOINT;
ccinematic.info.position = *Position;
ccinematic.info.room = Room;
}
/*
$$ACTION
Cinematics
Complex Cinematic: Put Camera At Position in clipboard in room [r:Room]
aComplexCinematicCameraAtStoredPt
ComplexCinematicCameraAtStored Point
Tells the cinematic that the camera should be on a point stored in clipboard
Params:
Room: The room that that position is in
$$END
*/
void aComplexCinematicCameraAtStoredPt(int Room) {
if (!PositionClipboard.has_pos)
return;
ccinematic.info.flags &= ~GCF_USEPATH;
ccinematic.info.flags |= GCF_USEPOINT;
ccinematic.info.position = PositionClipboard.pos;
ccinematic.info.room = Room;
}
/*
$$ENUM CineScreenMode
0:LetterBox
1:FullScreen
$$END
*/
/*
$$ACTION
Cinematics
Complex Cinematic: Set Screen Mode to [e:CineScreenMode=0]
aComplexCinematicScreenMode
ComplexCinematicScreenMode
Sets what type of screen mode the cinematic should be in
$$END
*/
void aComplexCinematicScreenMode(int Mode) {
ccinematic.info.flags &= ~GCF_SCREENFORMAT;
ccinematic.info.flags |= Mode;
}
/*
$$ENUM CineTextMode
0:None
4:WipeIn
8:FadeInOut
$$END
*/
/*
$$ACTION
Cinematics
Complex Cinematic: Set Text Display Mode to [e:CineTextMode=8]
aComplexCinematicTextMode
ComplexCinematicTextMode
Sets what type of text effect the cinematic should use
$$END
*/
void aComplexCinematicTextMode(int Mode) {
ccinematic.info.flags &= ~GCF_TEXT_MASK;
ccinematic.info.flags |= Mode;
}
/*
$$ENUM CineTextLayoutMode
0:Bottom
16:Top
32:Middle
64:Low
$$END
*/
/*
$$ACTION
Cinematics
Complex Cinematic: Set Text Screen Layout to [e:CineTextLayoutMode=0]
aComplexCinematicTextLayoutMode
ComplexCinematicTextLayoutMode
Sets what type of text layout the cinematic should use
$$END
*/
void aComplexCinematicTextLayoutMode(int Mode) {
ccinematic.info.flags &= ~GCF_LAYOUT_MASK;
ccinematic.info.flags |= Mode;
}
/*
$$FLAG CinematicFlags
256:Stop If Target Is Dead
512:Force Target To End of Path on Quick Exit
$$END
*/
/*
$$ACTION
Cinematics
Complex Cinematic: Flags: [g:CinematicFlags=256:768]
aComplexCinematicFlags
ComplexCinematicFlags
Sets special flags for the cinematic
$$END
*/
void aComplexCinematicFlags(int flags) {
ccinematic.info.flags &= ~(GCF_STOPIFTAGETDEAD | GCF_FORCETARGETTOEND);
ccinematic.info.flags |= flags;
}
/*
$$ACTION
Mission
Enable the given ship [a:Ship], so it can be chosen in single player
aEnableShip
EnableShip
Enables a ship (given its name) so it can be chosen in
single player ship selection dialog.
Parameters:
Ship: The name of the ship you want to enable
$$END
*/
void aEnableShip(const char *Ship) {
// this doesn't have to be multiplayer friendly, since it's a single
// player only thing
Game_EnableShip(Ship, true);
}
/*
$$ACTION
Mission
Disable the given ship [a:Ship], so it can't be chosen in single player
aDisableShip
DisableShip
Disables a ship (given its name) so it can't be chosen in
single player ship selection dialog.
Parameters:
Ship: The name of the ship you want to disable
$$END
*/
void aDisableShip(const char *Ship) {
// this doesn't have to be multiplayer friendly, since it's a single
// player only thing
Game_EnableShip(Ship, false);
}
/*
$$ACTION
Triggers
[e:Enable/Disable] trigger [t:Trigger]
aTriggerSetState
Enable/Disable a trigger
Enables or disables the specified trigger
Parameters:
Enable/Disable: whether to enable or disable the trigger
Trigger: which trigger to set
$$END
*/
void aTriggerSetState(int state, int trigger_num) {
msafe_struct mstruct;
mstruct.trigger_num = trigger_num;
mstruct.state = state;
MSafe_CallFunction(MSAFE_TRIGGER_SET, &mstruct);
}
/*
$$ACTION
Players
Add [o:Object] to [o:PlayerObject]'s inventory, Spewable when player dies [b:Spewable=FALSE]
aAddObjectToInventory
Adds a specific object to a player's inventory
Parameters:
Object: Object to add
PlayerObject: Player to get object
Spewable: Whether the object should be spewed from the inventory when the player dies
$$END
*/
void aAddObjectToInventory(int Object, int PlayerObject, bool Spewable) {
msafe_struct mstruct;
mstruct.objhandle = PlayerObject;
mstruct.ithandle = Object;
mstruct.message[0] = '\0'; // no name
if (Spewable)
mstruct.flags = 0;
else
mstruct.flags = INVAF_NOTSPEWABLE;
MSafe_CallFunction(MSAFE_INVEN_ADD_OBJECT, &mstruct);
}
/*
$$ACTION
Players
Add [o:Object] to [o:PlayerObject]'s inventory with name [s:ItemName], Spewable when player dies [b:Spewable=FALSE]
aAddObjectToInventoryNamed
Adds a specific object to a player's inventory with a custom name
Parameters:
Object: Object to add
PlayerObject: Player to get object
ItemName: The name for this object
Spewable: Whether the object should be spewed from the inventory when the player dies
$$END
*/
void aAddObjectToInventoryNamed(int Object, int PlayerObject, const char *name, bool Spewable) {
msafe_struct mstruct;
mstruct.objhandle = PlayerObject;
mstruct.ithandle = Object;
strncpy(mstruct.message, name, sizeof(mstruct.message) - 1);
mstruct.message[sizeof(mstruct.message) - 1] = '\0';
if (Spewable)
mstruct.flags = 0;
else
mstruct.flags = INVAF_NOTSPEWABLE;
MSafe_CallFunction(MSAFE_INVEN_ADD_OBJECT, &mstruct);
}
/*
$$ACTION
Players
Remove [o:Object] from [o:PlayerObject]'s inventory
aRemoveObjectFromInventory
Removes a specific object from a player's inventory
Parameters:
Object: Object to remove
PlayerObject: Which Player
$$END
*/
void aRemoveObjectFromInventory(int Object, int PlayerObject) {
msafe_struct mstruct;
mstruct.objhandle = PlayerObject;
mstruct.ithandle = Object;
MSafe_CallFunction(MSAFE_INVEN_REMOVE_OBJECT, &mstruct);
}
/*
$$ACTION
Objects
Store [o:Object] position in position clipboard
aStoreObjectInPositionClipboard
Stores the position of an object in the internal 'clipboard'
Parameters:
Object: object whose position you want to store
$$END
*/
void aStoreObjectInPositionClipboard(int Object) {
msafe_struct mstruct;
mstruct.objhandle = Object;
MSafe_GetValue(MSAFE_OBJECT_WORLD_POSITION, &mstruct);
PositionClipboard.pos = mstruct.pos;
PositionClipboard.orient = mstruct.orient;
PositionClipboard.room = mstruct.roomnum;
PositionClipboard.has_pos = true;
}
/*
$$ACTION
Objects
Move [o:Object] to position in position clipboard
aMoveObjectToPositionClipboard
Moves an object to the position stored in the internal 'clipboard'
Parameters:
Object: object whose position you want to change
$$END
*/
void aMoveObjectToPositionClipboard(int Object) {
if (!PositionClipboard.has_pos)
return;
msafe_struct mstruct;
mstruct.objhandle = Object;
mstruct.pos = PositionClipboard.pos;
mstruct.orient = PositionClipboard.orient;
mstruct.roomnum = PositionClipboard.room;
MSafe_CallFunction(MSAFE_OBJECT_WORLD_POSITION, &mstruct);
}
/*
$$ACTION
Objects
Cloak [o:Object] for [f:Seconds] seconds
aCloakObject
Cloaks an object for the time specified.
Parameters:
Object: object to cloak
Seconds: how long should it be cloaked
$$END
*/
void aCloakObject(int Object, float Seconds) {
msafe_struct mstruct;
mstruct.objhandle = Object;
mstruct.state = 1;
mstruct.lifetime = Seconds;
MSafe_CallFunction(MSAFE_OBJECT_CLOAK, &mstruct);
}
/*
$$ACTION
Objects
UnCloak [o:Object]
aUnCloakObject
UnCloaks an object
Parameters:
Object: object to uncloak
$$END
*/
void aUnCloakObject(int Object) {
msafe_struct mstruct;
mstruct.objhandle = Object;
mstruct.state = 0;
MSafe_CallFunction(MSAFE_OBJECT_CLOAK, &mstruct);
}
/*
$$ACTION
Players
Cloak all players for [f:Seconds] seconds
aCloakAllPlayers
Cloaks all the Players in the game
Parameters:
Seconds: how long should the players be cloaked
$$END
*/
void aCloakAllPlayers(float Seconds) {
msafe_struct mstruct;
mstruct.state = 1;
mstruct.lifetime = Seconds;
MSafe_CallFunction(MSAFE_OBJECT_CLOAKALLPLAYERS, &mstruct);
}
/*
$$ACTION
Players
UnCloak all players
aUnCloakAllPlayers
UnCloaks all the Players in the game
$$END
*/
void aUnCloakAllPlayers(void) {
msafe_struct mstruct;
mstruct.state = 0;
MSafe_CallFunction(MSAFE_OBJECT_CLOAKALLPLAYERS, &mstruct);
}
/*
$$ACTION
Objects
Set [o:Object] on Fire for [f:Seconds] doing [f:Damage] damage per second
aSetObjectOnFire
Sets an object on fire
Parameters:
Object = object to be set on fire
Seconds = how long it should be on fire
Damage = how much damage per second the fire should do
$$END
*/
void aSetObjectOnFire(int obj, float seconds, float dps) {
msafe_struct mstruct;
mstruct.objhandle = obj;
mstruct.longevity = seconds;
mstruct.interval = dps;
mstruct.ithandle = OBJECT_HANDLE_NONE;
MSafe_CallFunction(MSAFE_OBJECT_SETONFIRE, &mstruct);
}
/*
$$ACTION
Objects
Fire weapon [a:WeaponName] from gun number [i:GunNum] of object [o:Object]
aObjFireWeapon
Fire weapon
Fires the specified weapon from the given gun number of an object
Parameters:
WeaponName - the weapon to fire
GunNum - the gun number to fire from, or -1 to fire from the object's center
Object - the object to fire the flare
$$END
*/
void aObjFireWeapon(const char *weapon_name, int gun_num, int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.index = Wpn_FindID(weapon_name);
if (mstruct.index == -1)
return;
mstruct.gunpoint = gun_num;
MSafe_CallFunction(MSAFE_OBJECT_FIRE_WEAPON, &mstruct);
}
////////////////////////////////////////////////////////////////////////////////////////////
// The following code is to handle a 'kill all object except these' Dallas command sequence.
// these are beneficial for areas like Boss rooms with no escape or something, were it is
// just nice to kill all objects in the level, except what is needed, for framerate
// It will only kill robots in the level, except those designated to spare.
struct tKillRobotListNode {
tKillObjectItem item;
tKillRobotListNode *next;
};
class CKillRobotList {
public:
CKillRobotList() { list = NULL; };
~CKillRobotList() { clear(); }
void clear(void);
void add(tKillObjectItem *data);
tKillRobotListNode *list;
};
CKillRobotList KillRobotList;
void CKillRobotList::clear(void) {
tKillRobotListNode *next, *curr = list;
while (curr) {
next = curr->next;
free(curr);
curr = next;
}
list = NULL;
}
void CKillRobotList::add(tKillObjectItem *data) {
tKillRobotListNode *curr = list;
if (!curr) {
list = curr = (tKillRobotListNode *)malloc(sizeof(tKillRobotListNode));
} else {
while (curr->next) {
curr = curr->next;
}
curr->next = (tKillRobotListNode *)malloc(sizeof(tKillRobotListNode));
curr = curr->next;
}
if (!curr)
return;
curr->next = NULL;
memcpy(&curr->item, data, sizeof(tKillObjectItem));
}
/*
$$ACTION
Objects
Destroy All Robots: Start
aDestroyAllRobotsInit
Initializes the "Destroy All Robots" DALLAS command sequence. Call this BEFORE doing
any other of the "Destroy All Robots" commands.
NOTE: It is VERY important that the entire command sequence happens all in the same
action, and in proper order.
$$END
*/
void aDestroyAllRobotsInit(void) { KillRobotList.clear(); }
/*
$$ACTION
Objects
Destroy All Robots: Spare robots of this type [a:RobotID]
aDestroyAllRobotsSpareType
Spares any robot that has if of the species given (i.e. Tubbs)
Parameters:
RobotID - the name of the group of robots to Spare
$$END
*/
void aDestroyAllRobotsSpareType(const char *name) {
int id = Obj_FindID(name);
if (id != -1) {
tKillObjectItem item;
item.info_type = KOI_ID;
item.id = id;
KillRobotList.add(&item);
}
}
/*
$$ACTION
Objects
Destroy All Robots: Spare robot ([o:RobotHandle])
aDestroyAllRobotsSpareHandle
Spares the robot with the given handle
Parameters:
RobotHandle - the handle of the robot to Spare
$$END
*/
void aDestroyAllRobotsSpareHandle(int handle) {
if (handle != OBJECT_HANDLE_NONE) {
tKillObjectItem item;
item.info_type = KOI_HANDLE;
item.objhandle = handle;
KillRobotList.add(&item);
}
}
/*
$$ACTION
Objects
Destroy All Robots: End
aDestroyAllRobotsEnd
Destroys the robots (except those spared) in the level
$$END
*/
void aDestroyAllRobotsEnd(void) {
tKillRobotListNode *curr = KillRobotList.list;
int count = 0;
if (!curr)
return;
while (curr) {
count++;
curr = curr->next;
}
curr = KillRobotList.list;
tKillObjectItem *kolist = NULL;
kolist = (tKillObjectItem *)malloc(sizeof(tKillObjectItem) * count);
if (!kolist)
return;
count = 0;
while (curr) {
memcpy(&kolist[count], &curr->item, sizeof(tKillObjectItem));
count++;
curr = curr->next;
}
msafe_struct ms;
ms.count = count;
ms.list = kolist;
MSafe_CallFunction(MSAFE_OBJECT_DESTROY_ROBOTS_EXCEPT, &ms);
free(kolist);
KillRobotList.clear();
}
/*
$$ACTION
Objects
[e:Enable/Disable] virus infections signs for [o:Object]
aEnableVirusInfection
Enables or disables the graphical effects related to an object being infected
with a virus
$$END
*/
void aEnableVirusInfection(int enable, int handle) {
char cenable;
cenable = (enable) ? 1 : 0;
Obj_Value(handle, VF_SET, OBJV_C_VIRUS_INFECTED, &cenable);
}
/*
$$ACTION
Objects
[e:Enable/Disable] negative lighting for [o:Object]
aEnableNegativeLighting
Enables or disables negative dynamic lighting (ala black hole) for the object
$$END
*/
void aEnableNegativeLighting(int enable, int handle) {
char cenable;
cenable = (enable) ? 1 : 0;
Obj_Value(handle, VF_SET, OBJV_C_NEGATIVE_LIGHT, &cenable);
}
/*
$$ACTION
Players
Strip all weapons and energy from player [o:Object]
aStripWeaponsEnergy
Removes all weapons (but lasers) and ammo, and reduces energy to 0.
$$END
*/
void aStripWeaponsEnergy(int Object) {
int val = 0;
Player_Value(Object, VF_SET, PLYV_I_STRIP_WEAPONS, &val);
}
/*
$$ACTION
Players
Strip all weapons and energy from all players
aStripWeaponsEnergyFromAll
Removes all weapons (but lasers) and ammo, and reduces energy to 0.
$$END
*/
void aStripWeaponsEnergyFromAll(void) {
int val = -1;
Player_Value(OBJECT_HANDLE_NONE, VF_SET, PLYV_I_STRIP_WEAPONS, &val);
}
/*
$$ACTION
Rooms
Remove all powerups from room [r:Room]
aRemovePowerupsInRoom
Removes all the powerups in the room given
$$END
*/
void aRemovePowerupsInRoom(int Room) {
msafe_struct mstruct;
mstruct.roomnum = Room;
MSafe_CallFunction(MSAFE_ROOM_REMOVE_ALL_POWERUPS, &mstruct);
}
/*
$$QUERY
Objects
b:Is [o:Object] virus infected
qVirusInfected
Returns true if the object is showing signs of being infected by a virus
$$END
*/
bool qVirusInfected(int handle) {
char cenable;
Obj_Value(handle, VF_GET, OBJV_C_VIRUS_INFECTED, &cenable);
return (cenable) ? true : false;
}
/*
$$QUERY
Objects
b:Is [o:Object] giving off negative dynamic light (ala black hole)
qNegativeLight
Returns true if the object is giving off negative light, like a black hole (it is
removing light from the world)
$$END
*/
bool qNegativeLight(int handle) {
char cenable;
Obj_Value(handle, VF_GET, OBJV_C_NEGATIVE_LIGHT, &cenable);
return (cenable) ? true : false;
}
/*
$$QUERY
Mission
i:Get difficulty level
qGetDifficulty
Returns the difficulty level (0 = trainee,4 = insane)
$$END
*/
int qGetDifficulty(void) { return Game_GetDiffLevel(); }
/*
Requested by Luke 1/15/99
PickupPowerup [OBJECT]
-deletes powerup and plays powerup sound
AddToInventory [OBJECT]
-add powerup to the player's inventory
Turn Fog in Room [ROOM] to [TRUE/FALSE]
-turns on/off the fog flag
Fade Fog in Room [ROOM] to Distance [DIST] and Color [RGB] over Time
[TIME]
-needs new code, but should be easy (like SetRoomFog over time)
-ask Jason for new code if need be
Fade Wind in Room [ROOM] to Direction [XYZ] over Time [TIME]
-another new code one, but also easy (like SetRoomWind over time)
-Jason also can help on this one
AI: Fire when close [ROBOT], Distance [DIST]
-Robot fires constantly when a player is within DIST meters
*/
/*
MatcenSetStatus
ChangeFaceTexture
PlaySoundLoc3d
TouchSound
*/
/*
$$QUERY
Objects
f:[o:Object] cloak time left
qObjectCloakTime
Parameters:
Object: object to get cloak time left (0 if it's not cloaked)
$$END
*/
float qObjectCloakTime(int Object) {
msafe_struct mstruct;
mstruct.objhandle = Object;
mstruct.state = 0;
mstruct.lifetime = 0;
MSafe_GetValue(MSAFE_OBJECT_CLOAK, &mstruct);
return (mstruct.state) ? mstruct.lifetime : 0;
}
/*
$$QUERY
Objects
f:Get [o:Object] position on [e:Axis=0] axis
qObjectPosition
Parameters:
Object: object to get cloak time left (0 if it's not cloaked)
$$END
*/
float qObjectPosition(int handle, int axis) {
float value = 0.0f;
int type;
Obj_Value(handle, VF_GET, OBJV_I_TYPE, &type);
if (type != OBJ_NONE) {
vector pos;
Obj_Value(handle, VF_GET, OBJV_V_POS, &pos);
switch (axis) {
case 0:
value = pos.x;
break;
case 1:
value = pos.y;
break;
case 2:
value = pos.z;
break;
}
}
return value;
}
/*
$$QUERY
AI
b:[o:Object] close to target
qAICloseToTarget
Parameters:
Object: Is this object near its target
$$END
*/
bool qAICloseToTarget(int me) {
int target = OBJECT_HANDLE_NONE;
bool f_close = false;
char ctype;
int status;
float awareness;
Obj_Value(me, VF_GET, OBJV_C_CONTROL_TYPE, &ctype);
if (ctype == CT_AI) {
AI_Value(me, VF_GET, AIV_I_TARGET_HANDLE, &target);
if (target != OBJECT_HANDLE_NONE) {
AI_Value(me, VF_GET, AIV_F_AWARENESS, &awareness);
if (awareness >= AWARE_BARELY) {
AI_Value(me, VF_GET, AIV_I_STATUS_REG, &status);
f_close = ((status & AISR_CIRCLE_DIST) != 0);
}
}
}
return f_close;
}
/*
$$QUERY
AI
b:Is [o:Object] aware
qAIIsObjectAware
Parameters:
Object: Is this object near its target
$$END
*/
bool qAIIsObjectAware(int me) {
bool f_aware = false;
char ctype;
Obj_Value(me, VF_GET, OBJV_C_CONTROL_TYPE, &ctype);
if (ctype == CT_AI) {
float awareness;
AI_Value(me, VF_GET, AIV_F_AWARENESS, &awareness);
if (awareness >= AWARE_BARELY) {
f_aware = true;
}
}
return f_aware;
}
/*
$$QUERY
AI
o:[o:Object] get target
qAIGetTarget
Parameters:
Object: object we want the the target of
$$END
*/
int qAIGetTarget(int me) {
int target = OBJECT_HANDLE_NONE;
char ctype;
Obj_Value(me, VF_GET, OBJV_C_CONTROL_TYPE, &ctype);
if (ctype == CT_AI) {
AI_Value(me, VF_GET, AIV_I_TARGET_HANDLE, &target);
}
return target;
}
/*
$$QUERY
Players
b:[o:Player] has [o:Object] in their inventory
qHasObjectInInventory
Parameters:
Player: Player to check
Object: Which object to check for
$$END
*/
bool qHasObjectInInventory(int PlayerObject, int Object) {
msafe_struct mstruct;
mstruct.objhandle = PlayerObject;
mstruct.ithandle = Object;
MSafe_GetValue(MSAFE_INVEN_CHECK_OBJECT, &mstruct);
return mstruct.state;
}
/*
$$ACTION
Objects
Save object handle for [o:Object] in slot [e:SavedObjectSlot]
aObjSaveHandle
Save object handle
Saves an object handle for later user
Parameters:
o:Object: the object whose handle is saved
SavedObjectSlot: the slot in which to save the handle
$$END
*/
void aObjSaveHandle(int objhandle, int slot) {
if ((slot >= 0) && (slot < MAX_SAVED_OBJECT_HANDLES))
Saved_object_handles[slot] = objhandle;
}
/*
$$ACTION
Level Goals
Set goal [l:LevelGoal] as [e:Completed]
aGoalCompleted
Set goal completion state
Tells the goal system that the specified goal has been completed or not
Parameters:
LevelGoal: the goal to set
Completed: whether or not the goal has been completed
$$END
*/
void aGoalCompleted(int goal_index, int completed) {
int flags = LGF_COMPLETED;
LGoal_Value(completed ? VF_SET_FLAGS : VF_CLEAR_FLAGS, LGSV_I_STATUS, &flags, goal_index);
}
/*
$$ACTION
Level Goals
Set goal [l:LevelGoal] item number [i:ItemIndex] as [e:Completed]
aGoalItemCompleted
Set goal item completion state
Tells the goal system that the specified goal item has been completed or not
Parameters:
LevelGoal: the goal
ItemIndex: the index of the item in question
Completed: whether or not the goal item has been completed
$$END
*/
void aGoalItemCompleted(int goal_index, int item_index, int completed) {
bool f_set = (completed != 0);
LGoal_Value(VF_SET, LGSSV_B_ITEM_DONE, &f_set, goal_index, item_index - 1);
}
/*
$$ACTION
Level Goals
Set goal [l:LevelGoal] as [e:Failed]
aGoalFailed
Set goal fail state
Tells the goal system that the specified goal has been failed or not
Parameters:
LevelGoal: the goal to set
Failed: whether or not the goal has been failed
$$END
*/
void aGoalFailed(int goal_index, int failed) {
int flags = LGF_FAILED;
LGoal_Value(failed ? VF_SET_FLAGS : VF_CLEAR_FLAGS, LGSV_I_STATUS, &flags, goal_index);
}
/*
$$ACTION
Level Goals
[e:Enable/Disable] goal [l:LevelGoal]
aGoalEnableDisable
Enable/disable goal
Enable or disable the specified goal
Parameters:
Enable/Disable: whether the goal should be enabled or disabled
LevelGoal: the goal to set
$$END
*/
void aGoalEnableDisable(int enabled, int goal_index) {
int flags = LGF_ENABLED;
LGoal_Value(enabled ? VF_SET_FLAGS : VF_CLEAR_FLAGS, LGSV_I_STATUS, &flags, goal_index);
}
/*
$$ACTION
Level Goals
Set goal [l:LevelGoal] priority = [i:Priority]
aGoalSetPriority
Set goal priority
Sets the priority of the specified goal
Parameters:
LevelGoal: the goal to set
Priority: the priority to set
$$END
*/
void aGoalSetPriority(int goal_index, int priority) { LGoal_Value(VF_SET, LGSV_I_PRIORITY, &priority, goal_index); }
/*
$$ACTION
Level Goals
Set goal [l:LevelGoal] completion message = [s:Message]
aGoalSetCompletionMessage
Set goal completion message
Sets the completion message for the specified goal
Parameters:
LevelGoal: the goal to set
Message: the message for the goal
$$END
*/
void aGoalSetCompletionMessage(int goal_index, const char *message) {
LGoal_Value(VF_SET, LGSV_PC_COMPLETION_MESSAGE, (void *) message, goal_index);
}
/*
$$ACTION
Level Goals
GuideBot [e:Can/Cannot] lead the player to goal [l:LevelGoal]
aGoalSetGBKnowledge
GuideBot can/cannot lead the player to goal
Tells the goal system whether the GuideBot is allowed to lead the player to the specified goal
Parameters:
Can/Cannot: whether or not the GuideBot can lead the player to the goal
LevelGoal: the goal to set
$$END
*/
void aGoalSetGBKnowledge(int enabled, int goal_index) {
int flags = LGF_GB_DOESNT_KNOW_LOC;
LGoal_Value(enabled ? VF_CLEAR_FLAGS : VF_SET_FLAGS, LGSV_I_STATUS, &flags, goal_index);
}
//
// D3 queries
//
/* NOTE: The following query is handled internally by DALLAS
$$QUERY
Scripts
b:Script [x:ScriptID] has executed
qScriptExecuted_DALLAS
Has this script been executed?
Determines if the specified script has executed at least once
Parameters:
ScriptID: The script to check
$$END
*/
/* NOTE: The following query is handled internally by DALLAS
$$QUERY
Scripts
i:Times Script [x:ScriptID] has been executed
qTimesScriptExecuted_DALLAS
How many times has this script been executed?
Returns the number of times the specified script has executed
Parameters:
ScriptID: The script to check
$$END
*/
/*
$$QUERY
Objects
b:[o:Object] exists
qObjExists
Does this object exist?
Determines if the specified object exists in the world
Parameters:
Object: The object to check
$$END
*/
bool qObjExists(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
return (mstruct.type != -1);
}
/*
$$QUERY
Objects
b:[o:Object=IT] is a player
qObjIsPlayer
Is this object a player?
Determines if the specified object is a player
Parameters:
Object: The object to check
$$END
*/
bool qObjIsPlayer(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
return (mstruct.type == OBJ_PLAYER);
}
/*
$$QUERY
Objects
b:[o:Object=IT] is a player weapon
qObjIsPlayerWeapon
Is this object a player weapon?
Determines if the specified object is a player weapon
Parameters:
Object: The object to check
$$END
*/
bool qObjIsPlayerWeapon(int handle) {
msafe_struct mstruct;
mstruct.objhandle = handle;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_WEAPON) {
MSafe_GetValue(MSAFE_OBJECT_PARENT, &mstruct);
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_PLAYER)
return 1;
}
return 0;
}
/*
$$QUERY
Objects
b:[o:Object=IT] is a player or player weapon
qObjIsPlayerOrPlayerWeapon
Is this object either a player or a player weapon?
Determines if the specified object is either a player or a player weapon
Parameters:
Object: The object to check
$$END
*/
bool qObjIsPlayerOrPlayerWeapon(int handle) {
msafe_struct mstruct;
mstruct.objhandle = handle;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_PLAYER)
return 1;
if (mstruct.type == OBJ_WEAPON) {
MSafe_GetValue(MSAFE_OBJECT_PARENT, &mstruct);
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_PLAYER)
return 1;
}
return 0;
}
/*
$$QUERY
Objects
b:[o:Object=IT] is an energy weapon
qObjIsEnergyWeapon
Is this object an energy weapon?
Determines if the specified object is an energy weapon
Parameters:
Object: The object to check
$$END
*/
bool qObjIsEnergyWeapon(int handle) {
msafe_struct mstruct;
mstruct.objhandle = handle;
MSafe_GetValue(MSAFE_OBJECT_ENERGY_WEAPON, &mstruct);
return mstruct.state;
}
/*
$$QUERY
Objects
b:[o:Object=IT] is a [e:ObjectType]
qObjIsType
Is this object the specified type?
Determines if the specified object is the specified type
Parameters:
Object: The object to check
ObjectType: The type to check
$$END
*/
bool qObjIsType(int objhandle, int type) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
return (mstruct.type == type);
}
/*
$$QUERY
Objects
b:[o:TargetObject] is within the [i:Cone=90] degree view cone of [o:Object]
qObjCanSeeObj
Can object see the target object
Determines if the specified object can see the other object
Parameters:
Object: The object doing the looking
TargetObject: The target object
Cone: Angle between 0-360 which makes the viewcone that determines if the object can see the other object
$$END
*/
bool qObjCanSeeObj(int handletarget, int cone, int handlesrc) {
vector vsource, vtarget;
msafe_struct mstruct;
// Get half of the angle that the user specified because they specified a cone, and we want an angle
double cangle = (double)((double)cone / (double)2);
double testangle = cos(cangle * PI / 180);
mstruct.objhandle = handletarget;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vtarget = mstruct.pos;
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vsource = mstruct.pos;
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_ORIENT, &mstruct);
vector subvec = vtarget - vsource;
vm_VectorNormalizeFast(&subvec);
float dotp = vm_DotProduct(&subvec, &mstruct.orient.fvec);
if (dotp > testangle) {
return true;
}
return false;
}
/*
$$QUERY
Objects
b:[o:TargetObject] is within the [i:Cone=90] degree view cone of [o:Object] using flags [g:FVIHitFlags=1048585:16269119]
qObjCanSeeObjAdvanced
Can object see the target object
Determines if the specified object can see the other object using the given flags
Parameters:
Object: The object doing the looking
TargetObject: The target object
Cone: Angle between 0-360 which makes the viewcone that determines if the object can see the other object
FVIHitFlags: Flags used to determine visibility
$$END
*/
bool qObjCanSeeObjAdvanced(int handletarget, int cone, int handlesrc, int fvi_flags) {
vector vsource, vtarget;
int sourceroom;
msafe_struct mstruct;
// Get half of the angle that the user specified because they specified a cone, and we want an angle
double cangle = (double)((double)cone / (double)2);
double testangle = cos(cangle * PI / 180);
mstruct.objhandle = handletarget;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vtarget = mstruct.pos;
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vsource = mstruct.pos;
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct);
sourceroom = mstruct.roomnum;
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_ORIENT, &mstruct);
vector subvec = vtarget - vsource;
vm_VectorNormalizeFast(&subvec);
float dotp = vm_DotProduct(&subvec, &mstruct.orient.fvec);
if (dotp > testangle) {
// see if we can cast a ray to the object
ray_info ray;
fvi_flags |= FQ_CHECK_OBJS;
int fate = FVI_RayCast(handlesrc, &vsource, &vtarget, sourceroom, 0.0f, fvi_flags, &ray);
if (fate == HIT_NONE)
return true;
if (fate == HIT_OBJECT) {
if (ray.hit_object == handletarget) {
return true;
}
}
}
return false;
}
/*
$$QUERY
Objects
o:[o:Object=IT] parent
qObjParent
Object parent
Gets the parent of the specified object
Parameters:
Object: The object whose parent is returned
$$END
*/
int qObjParent(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_OBJECT_PARENT, &mstruct);
return mstruct.objhandle;
}
/*
$$QUERY
Objects
o:Get attached child of [o:Object] at attach point [i:AttachPoint]
qGetAtachedChild
Attached child
Gets the attached child of the specified object
Parameters:
Object: The object who we want to determine its attached child
AttachPoint: The attach point the child is attached to
$$END
*/
int qGetAtachedChild(int objhandle, int attachpoint) { return Obj_GetAttachChildHandle(objhandle, attachpoint); }
/*
$$QUERY
Objects
r:[o:Object=IT] room
qObjRoom
Object Room
Returns the room the specified object is in
Parameters:
Object: The object whose room you want to know
$$END
*/
int qObjRoom(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct);
return mstruct.roomnum;
}
// These should be in object_external.h
#define ROOMNUM_CELLNUM_FLAG 0x80000000
#define ROOMNUM_OUTSIDE(roomnum) (((roomnum) & ROOMNUM_CELLNUM_FLAG) != 0)
/*
$$QUERY
Objects
b:[o:Object=IT] is on the terrain
qObjOnTerrain
Object on terrain?
Determines if the specified object is on the terrain
Parameters:
Object: The object to check
$$END
*/
bool qObjOnTerrain(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct);
return ROOMNUM_OUTSIDE(mstruct.roomnum);
}
/*
$$QUERY
Objects
e(ObjectType):[o:Object=IT] type
qObjType
Object type
Returns the specified object's type
Parameters:
Object: The object whose type you want to know
$$END
*/
int qObjType(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
return mstruct.type;
}
/*
$$QUERY
User Vars
f:User Variable [e:UserVar]
qUserVarValue
User Variable
Returns the value of the specified user variable
Parameters:
UserVar: The variable whose value to return
$$END
*/
float qUserVarValue(int varnum) {
if (varnum < 0 || varnum >= MAX_USER_VARS)
return 0;
if (const auto *value = std::get_if<int32_t>(&User_vars[varnum]))
return *value;
return std::get<float>(User_vars[varnum]);
}
/*
$$QUERY
User Vars
i:User Variable [e:UserVar] (Integer)
qUserVarValueInt
User Variable (Integer)
Returns the value of the specified user variable rounded to the nearest integer
Parameters:
UserVar: The variable whose value to return
$$END
*/
int qUserVarValueInt(int varnum) {
if (varnum < 0 || varnum >= MAX_USER_VARS)
return 0;
if (const auto *value = std::get_if<int32_t>(&User_vars[varnum]))
return *value;
auto value = std::get<float>(User_vars[varnum]);
// Check boundaries first, else float=>int conversion is UB
if (value < std::nexttoward(INT_MIN, 0))
return INT_MIN;
if (value >= std::nexttoward(INT_MAX, 0))
return INT_MAX;
return value + 0.5;
}
/*
$$QUERY
User Vars
b:User Flag [e:UserFlag]
qUserFlag
User flag
Returns the state of the specified user flag
Parameters:
UserFlag: The flag whose state to return
$$END
*/
bool qUserFlag(int flagnum) {
if ((flagnum >= 0) && (flagnum < 32))
return ((User_flags & (1 << flagnum)) != 0);
else
return 0;
}
/*
$$QUERY
Objects
f:Object [o:Object] shields
qObjShields
Get an object's shields
Gets an object's shields
Parameters:
Object: the object whose shields are being queried
$$END
*/
float qObjShields(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_SHIELDS, &mstruct);
return mstruct.shields;
}
/*
$$QUERY
Objects
f:Object [o:Object] energy
qObjEnergy
Get an object's energy
Gets an object's energy
Parameters:
Object: the object whose energy are being queried
$$END
*/
float qObjEnergy(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_ENERGY, &mstruct);
return mstruct.energy;
}
/*
$$QUERY
Objects
f:Object [o:Object] original shields
qObjShieldsOriginal
Object's original shields
Gets an object's original (full-strength) shields
Parameters:
Object: the object whose shields are being queried
$$END
*/
float qObjShieldsOriginal(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_OBJECT_SHIELDS_ORIGINAL, &mstruct);
return mstruct.shields;
}
/*
$$QUERY
Doors
b:Door [d:Door] is locked
qDoorLocked
Door locked
Determines if a door is locked
Parameters:
Door: the door to check
$$END
*/
bool qDoorLocked(int objref) {
msafe_struct mstruct;
mstruct.objhandle = objref;
MSafe_GetValue(MSAFE_DOOR_LOCK_STATE, &mstruct);
return mstruct.state;
}
/*
$$QUERY
Doors
b:Door [d:Door] is openable by [o:Object=IT]
qDoorOpenable
Door openable
Determines if a door is openable by the specified object
Parameters:
Door: the door to check
Object: the object to check
$$END
*/
bool qDoorOpenable(int door_handle, int opener_handle) {
msafe_struct mstruct;
mstruct.objhandle = door_handle;
mstruct.ithandle = opener_handle;
MSafe_GetValue(MSAFE_DOOR_OPENABLE, &mstruct);
return mstruct.state;
}
/*
$$QUERY
Doors
p:Door [d:Door] position
qDoorGetPos
Get door position
Gets the position of the specified door
Parameters:
Door: the object of the door
$$END
*/
float qDoorGetPos(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_DOOR_POSITION, &mstruct);
return mstruct.scalar;
}
/*
$$QUERY
Mission
b:Mission flag [i:FlagNum] is set
aMissionGetFlag
Get a mission flag
Gets the specified mission flag
Parameters:
FlagNum: the flag to get
$$END
*/
bool aMissionGetFlag(int flagnum) { return Msn_FlagGet(flagnum); }
/*
$$QUERY
Mission
b:Level objective flag [i:FlagNum] is set
aMissionGetLevelFlag
Get a level objective flag
Gets the specified level objective flag
Parameters:
FlagNum: the flag to get
$$END
*/
bool aMissionGetLevelFlag(int flagnum) {
//!!Add code here
return 0;
}
/*
$$QUERY
Objects
f:Object [o:Object] animation frame
qObjAnimFrame
Object animation frame
Get an object's animation frame
Parameters:
Object: the object whose animation frame is being queried
$$END
*/
float qObjAnimFrame(int objref) {
float anim_frame;
Obj_Value(objref, VF_GET, OBJV_F_ANIM_FRAME, &anim_frame);
return anim_frame;
}
/*
$$QUERY
Rooms
b:Room [r:Room] fog is on
qRoomFogOn
Room fog is on
Checks if the fog is on in a room
Parameters:
Room: the room to check
$$END
*/
bool qRoomFogOn(int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
MSafe_GetValue(MSAFE_ROOM_FOG_STATE, &mstruct);
return mstruct.state;
}
/*
$$ACTION
Players
[e:Enable/Disable] player controls [g:PlayerControl] for [o:PlayerObject]
aTogglePlayerObjControl
TogglePlayerControl
Sets a players control either disabled or enabled
Parameters:
Object: The player object
PlayerObject: The player this affects
Enable/Disable: Whether to Enable or Disable the specified controls
$$END
*/
void aTogglePlayerObjControl(int enable, int controlmask, int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
mstruct.control_mask = controlmask;
mstruct.control_val = enable;
MSafe_CallFunction(MSAFE_OBJECT_PLAYER_CMASK, &mstruct);
}
/*
$$ACTION
Players
[e:Enable/Disable] all player control for [o:PlayerObject]
aTogglePlayerObjAllControls
ToggleAllPlayerControls
Sets a players control either disabled or enabled
Parameters:
Enable/Disable: Enable/Disable the specified control
PlayerObject: The player this affects
$$END
*/
void aTogglePlayerObjAllControls(int enable, int objhandle) {
msafe_struct mstruct;
int controlbit = 0xffffffff;
mstruct.objhandle = objhandle;
mstruct.control_mask = controlbit;
mstruct.control_val = enable ? 1 : 0;
MSafe_CallFunction(MSAFE_OBJECT_PLAYER_CMASK, &mstruct);
}
/*
$$ACTION
Players
Give player [o:PlayerObject] key [o:KeyObject], key number [i:KeyNum=1:1|8], name = [s:KeyName], show HUD message =
[e:Yes/No] aObjectPlayerGiveKey Give player key Gives a player the specified key, and deletes the key object if not
multiplayer
Parameters:
PlayerObject: The player who gets the key
KeyObject: the object that is the key
KeyNum: which key this is (1-8)
KeyName: the name of this key (shown in inventory & on HUD)
Yes/No: should the name of the key be shown on the HUD?
$$END
*/
void aObjectPlayerGiveKey(int player_handle, int key_handle, int key_num, const char *key_name, int show_on_hud) {
msafe_struct mstruct;
mstruct.objhandle = key_handle;
mstruct.ithandle = player_handle;
mstruct.index = key_num;
strncpy(mstruct.message, key_name, sizeof(mstruct.message) - 1);
mstruct.message[sizeof(mstruct.message) - 1] = 0;
MSafe_CallFunction(MSAFE_OBJECT_PLAYER_KEY, &mstruct);
if (show_on_hud)
aShowHUDMessage(key_name);
}
/*
$$ACTION
Players
Give player [o:PlayerObject] invisible key number [i:KeyNum=1:1|8]
aObjectPlayerGiveInvisibleKey
Give player key
Gives a player the specified key, which doesn't show up on the HUD or in the inventory
Parameters:
PlayerObject: The player who gets the key
KeyNum: which key this is (1-8)
$$END
*/
void aObjectPlayerGiveInvisibleKey(int player_handle, int key_num) {
msafe_struct mstruct;
mstruct.objhandle = OBJECT_HANDLE_NONE;
mstruct.ithandle = player_handle;
mstruct.index = key_num;
mstruct.message[0] = 0; // don't think this is used, but just in case
MSafe_CallFunction(MSAFE_OBJECT_PLAYER_KEY, &mstruct);
}
/*
$$QUERY
Objects
f:Object [o:Object] lighting distance
qObjGetLightingDist
Get object lighting distance
Gets the lighting distance for an object
Parameters:
Object: the object to get
$$END
*/
float qObjGetLightingDist(int objhandle) {
msafe_struct mstruct;
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_OBJECT_LIGHT_DIST, &mstruct);
return mstruct.light_distance;
}
/*
$$QUERY
Math
f:[f:Float1] plus [f:Float2]
qMathAddFloat
Add floats
Adds two floating-point numbers and returns the result
Parameters:
Float1, Float2: the numbers to add
$$END
*/
float qMathAddFloat(float f0, float f1) { return f0 + f1; }
/*
$$QUERY
Math
f:[f:Float1] minus [f:Float2]
qMathSubFloat
Subtract floats
Subtracts one floating-point number from another
Parameters:
Float1, Float2: subtracts Float2 from Float1
$$END
*/
float qMathSubFloat(float f0, float f1) { return f0 - f1; }
/*
$$QUERY
Math
f:[f:Float1] times [f:Float2]
qMathMulFloat
Multiply floats
Multiplies two floating-point numbers and returns the result
Parameters:
Float1, Float2: the numbers to multiply
$$END
*/
float qMathMulFloat(float f0, float f1) { return f0 * f1; }
/*
$$QUERY
Math
f:Convert int [i:Int] to float
qMathIntToFloat
Convert Int to Float
Converts an integer value to a floating-point value
Parameters:
Int: the interger that's converted to a float
$$END
*/
float qMathIntToFloat(int i) { return (float)i; }
/*
$$QUERY
Math
p:[p:Percent1] plus [p:Percent2]
qMathAddPercent
Add percentages
Adds two percentages and returns the result, without going above 100%
Parameters:
Percent1, Percent2: the percentages to add
$$END
*/
float qMathAddPercent(float f0, float f1) {
float r = f0 + f1;
return (r > 1.0) ? 1.0 : r;
}
/*
$$QUERY
Math
p:[p:Percent1] minus [p:Percent2]
qMathSubPercent
Subtract percentages
Subtracts one percentage number from another, withing going below 0%
Parameters:
Percent1, Percent2: subtracts Percent2 from Percent1
$$END
*/
float qMathSubPercent(float f0, float f1) {
float r = f0 - f1;
return (r < 0.0) ? 0.0 : r;
}
/*
$$QUERY
Math
i:[i:Integer1] plus [i:Integer2]
qMathAddInt
Add integers
Adds two integer numbers and returns the result
Parameters:
Integer1, Integer2: the numbers to add
$$END
*/
int qMathAddInt(int f0, int f1) { return f0 + f1; }
/*
$$QUERY
Math
i:[i:Integer1] minus [i:Integer2]
qMathSubInt
Subtract integers
Subtracts one integer number from another
Parameters:
Integer1, Integer2: subtracts Integer2 from Integer1
$$END
*/
int qMathSubInt(int f0, int f1) { return f0 - f1; }
/*
$$QUERY
Math
f:[p:Percent] of [f:Float]
qMathPercentage
Percentage of a number
Multiplies a number by a percentage
Parameters:
Percent: how much to scale the number by
Float: the number that's scaled
$$END
*/
float qMathPercentage(float f0, float f1) { return f0 * f1; }
#include <math.h>
/*
$$QUERY
Objects
f:Distance between [o:Object1] and [o:Object2]
qObjGetDistance
Distance between two objects
Gets the distance between two objects
Parameters:
Object1, Object2: the two objects
$$END
*/
float qObjGetDistance(int objhandle0, int objhandle1) {
msafe_struct mstruct;
vector p0;
mstruct.objhandle = objhandle0;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
p0 = mstruct.pos;
mstruct.objhandle = objhandle1;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
return vm_VectorDistance(&p0, &mstruct.pos);
}
/*
$$QUERY
Rooms
b:Forcefield at portal [i:PortalNum] in room [r:Room] is on
qPortalIsOn
Forcefield is on
Checks whether a forcefield is on
Parameters:
Room: The room the forcefield is in
PortalNum: The portal number of the forcefield
$$END
*/
bool qPortalIsOn(int portalnum, int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
mstruct.portalnum = portalnum;
MSafe_GetValue(MSAFE_ROOM_PORTAL_RENDER, &mstruct);
return mstruct.state;
}
/*
$$QUERY
Misc
b:Random chance of [p:Probability]
qRandomChance
Random Chance
Determines whether a random event should happen. Returns true the portion of the time specified.
Parameters:
Probablilty: how likely this query is to return true.
$$END
*/
bool qRandomChance(float prob) {
if (prob == 0.0)
return false;
return ((static_cast<float>(rand()) / static_cast<float>(RAND_MAX)) <= prob);
}
/*
$$QUERY
Math
f:Random value between [f:LowerLimit] and [f:UpperLimit]
qRandomValue
Random Value
Returns a random value between the two specified values
Parameters:
LowerLimit: the returned value will be higher than or equal to this value
UpperLimit: the returned value will be lower than or equal to this value
$$END
*/
float qRandomValue(float low, float high) { return low + (static_cast<float>(rand()) / static_cast<float>(RAND_MAX)) * (high - low); }
/*
$$QUERY
Objects
b:Player is within the [i:Cone=90] degree view cone of [o:Object] at a max distance of [f:Distance]
qObjCanSeePlayer
Can object see a player
Determines if the specified object can see a player
Parameters:
Object: The object doing the looking
Cone: Angle between 0-360 which makes the viewcone that determines if the object can see the other object
Distance: The player must be within this distance for this query to return true
$$END
*/
bool qObjCanSeePlayer(int cone, int handlesrc, float max_distance) {
vector vsource, vtarget, viewvec;
msafe_struct mstruct;
// Get half of the angle that the user specified because they specified a cone, and we want an angle
double cangle = (double)((double)cone / (double)2);
double t = cangle * PI / 180;
double testangle = cos(t);
// Loop though all possible players
for (int p = 0; p < MAX_PLAYERS; p++) {
// Get player position
mstruct.slot = p;
MSafe_GetValue(MSAFE_OBJECT_PLAYER_HANDLE, &mstruct);
// See if this player active
if (mstruct.objhandle == OBJECT_HANDLE_NONE)
continue;
// Get the target position
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vtarget = mstruct.pos;
// Get the viewer position
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vsource = mstruct.pos;
// Get the viewer orientation
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_ORIENT, &mstruct);
// Get the normalized vector from the source to the target
float dist = vm_GetNormalizedDirFast(&viewvec, &vtarget, &vsource);
// Get the angle between the objects
float dot = vm_DotProduct(&viewvec, &mstruct.orient.fvec);
// Check angle and distance
if ((dot > testangle) && (dist < max_distance))
return 1;
}
// Didn't find any in the view cone
return 0;
}
/*
$$QUERY
Objects
b:Player is within the [i:Cone=90] degree view cone of [o:Object] at a max distance of [f:Distance] using flags
[g:FVIHitFlags=1048585:16269119] qObjCanSeePlayerAdvanced Can object see a player Determines if the specified object can
see a player (but allowing some customizability as to what the object can see through)
Parameters:
Object: The object doing the looking
Cone: Angle between 0-360 which makes the viewcone that determines if the object can see the other object
Distance: The player must be within this distance for this query to return true
FVIHitFlags: Flags used to determine visibility
$$END
*/
bool qObjCanSeePlayerAdvanced(int cone, int handlesrc, float max_distance, int fvi_flags) {
vector vsource, vtarget, viewvec;
msafe_struct mstruct;
matrix orient;
int sourceroom;
// Get half of the angle that the user specified because they specified a cone, and we want an angle
double cangle = (double)((double)cone / (double)2);
double t = cangle * PI / 180;
double testangle = cos(t);
// Get the viewer position
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vsource = mstruct.pos;
// Get the viewer orientation
MSafe_GetValue(MSAFE_OBJECT_ORIENT, &mstruct);
orient = mstruct.orient;
// Get the viewer room
MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct);
sourceroom = mstruct.roomnum;
// Loop though all possible players
for (int p = 0; p < MAX_PLAYERS; p++) {
// Get player position
mstruct.slot = p;
MSafe_GetValue(MSAFE_OBJECT_PLAYER_HANDLE, &mstruct);
// See if this player active
if (mstruct.objhandle == OBJECT_HANDLE_NONE)
continue;
// Get the target position
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vtarget = mstruct.pos;
// Get the normalized vector from the source to the target
float dist = vm_GetNormalizedDirFast(&viewvec, &vtarget, &vsource);
// Get the angle between the objects
float dot = vm_DotProduct(&viewvec, &orient.fvec);
// Check angle and distance
if ((dot > testangle) && (dist < max_distance)) {
// see if we can cast a ray to the player
ray_info ray;
fvi_flags |= (FQ_CHECK_OBJS | FQ_ONLY_PLAYER_OBJ);
int fate = FVI_RayCast(handlesrc, &vsource, &vtarget, sourceroom, 0.0f, fvi_flags, &ray);
if (fate == HIT_NONE)
return true;
if (fate == HIT_OBJECT) {
mstruct.objhandle = ray.hit_object;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_PLAYER) {
return 1;
}
return 1;
}
}
}
// Didn't find any in the view cone
return 0;
}
/*
$$QUERY
Objects
b:Player (store in [e:SavedObjectSlot]) is within the [i:Cone=90] degree view cone of [o:Object] at a max distance of
[f:Distance] using flags [g:FVIHitFlags=1048585:16269119] qObjCanSeePlayerAdvancedWithStore Can object see a player
Determines if the specified object can see a player (but allowing some customizability as to what the object can see
through), and if the player can be seen, stores the object in the given object slot.
Parameters:
SavedObjectSlot: the slot to save the seen player object in
Object: The object doing the looking
Cone: Angle between 0-360 which makes the viewcone that determines if the object can see the other object
Distance: The player must be within this distance for this query to return true
FVIHitFlags: Flags used to determine visibility
$$END
*/
bool qObjCanSeePlayerAdvancedWithStore(int slot, int cone, int handlesrc, float max_distance, int fvi_flags) {
vector vsource, vtarget, viewvec;
msafe_struct mstruct;
matrix orient;
int sourceroom;
// Get half of the angle that the user specified because they specified a cone, and we want an angle
double cangle = (double)((double)cone / (double)2);
double t = cangle * PI / 180;
double testangle = cos(t);
// Get the viewer position
mstruct.objhandle = handlesrc;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vsource = mstruct.pos;
// Get the viewer orientation
MSafe_GetValue(MSAFE_OBJECT_ORIENT, &mstruct);
orient = mstruct.orient;
// Get the viewer room
MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct);
sourceroom = mstruct.roomnum;
// Loop though all possible players
for (int p = 0; p < MAX_PLAYERS; p++) {
// Get player position
mstruct.slot = p;
MSafe_GetValue(MSAFE_OBJECT_PLAYER_HANDLE, &mstruct);
// See if this player active
if (mstruct.objhandle == OBJECT_HANDLE_NONE)
continue;
// Get the target position
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
vtarget = mstruct.pos;
// Get the normalized vector from the source to the target
float dist = vm_GetNormalizedDirFast(&viewvec, &vtarget, &vsource);
// Get the angle between the objects
float dot = vm_DotProduct(&viewvec, &orient.fvec);
// Check angle and distance
if ((dot > testangle) && (dist < max_distance)) {
// see if we can cast a ray to the player
ray_info ray;
fvi_flags |= (FQ_CHECK_OBJS | FQ_ONLY_PLAYER_OBJ);
int fate = FVI_RayCast(handlesrc, &vsource, &vtarget, sourceroom, 0.0f, fvi_flags, &ray);
if (fate == HIT_NONE) {
if ((slot >= 0) && (slot < MAX_SAVED_OBJECT_HANDLES))
Saved_object_handles[slot] = mstruct.objhandle;
return true;
}
if (fate == HIT_OBJECT) {
mstruct.objhandle = ray.hit_object;
MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct);
if (mstruct.type == OBJ_PLAYER) {
if ((slot >= 0) && (slot < MAX_SAVED_OBJECT_HANDLES))
Saved_object_handles[slot] = mstruct.objhandle;
return 1;
}
if ((slot >= 0) && (slot < MAX_SAVED_OBJECT_HANDLES))
Saved_object_handles[slot] = mstruct.objhandle;
return 1;
}
}
}
// Didn't find any in the view cone
if ((slot >= 0) && (slot < MAX_SAVED_OBJECT_HANDLES))
Saved_object_handles[slot] = OBJECT_HANDLE_NONE;
return 0;
}
/*
$$QUERY
Rooms
b:A player is in room [r:Room]
qRoomHasPlayer
A player is in the room
Determines if a player is in the specified room
Parameters:
Room: the room to check
$$END
*/
bool qRoomHasPlayer(int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
MSafe_GetValue(MSAFE_ROOM_HAS_PLAYER, &mstruct);
return mstruct.state;
}
/*
$$QUERY
Mission
b:Is the ship [a:Ship] enabled?
qIsShipEnabled
Given the name of a ship, it will return true
if the ship is allowed to be chosen in the single player
ship selection.
Parameters:
Ship: The name of the ship you want to query
$$END
*/
bool qIsShipEnabled(const char *Ship) { return Game_IsShipEnabled(Ship); }
/*
$$QUERY
Rooms
f:Room [r:Room] damage
qRoomGetDamage
Get room damage
Returns the current damage setting for the specified room
Parameters:
Room: The room for which the damage is returned
$$END
*/
float qRoomGetDamage(int roomnum) {
msafe_struct mstruct;
mstruct.roomnum = roomnum;
MSafe_GetValue(MSAFE_ROOM_DAMAGE, &mstruct);
return mstruct.amount;
}
/*
$$QUERY
Objects
o:Saved object handle [e:SavedObjectSlot]
qObjSavedHandle
Saved object handle
Returns the object handle saved in the specified slot
Parameters:
HandleSlot: the slot for which the object handle is returned
$$END
*/
int qObjSavedHandle(int slot) {
if ((slot >= 0) && (slot < MAX_SAVED_OBJECT_HANDLES))
return Saved_object_handles[slot];
else
return OBJECT_HANDLE_NONE;
}
/*
$$QUERY
Triggers
Trigger [t:Trigger] state
qTriggerGetState
Get the enabled/disabled state of a trigger
Determines if a trigger is enabled or disabled
Parameters:
Trigger: which trigger to check
$$END
*/
bool qTriggerGetState(int trigger_num) {
msafe_struct mstruct;
mstruct.trigger_num = trigger_num;
MSafe_GetValue(MSAFE_TRIGGER_SET, &mstruct);
return mstruct.state;
}
/*
$$QUERY
Objects
i:Number of [e:ObjectType] objects of ID = [a:ObjectIDName] in mine
qObjCountTypeID
Get number of objects of a certain type
Counts the number of objects of the specified type
Parameters:
ObjectType: the type of the objects to count
ObjectIDName: the name of the object ID to count
$$END
*/
int qObjCountTypeID(int type, const char *idname) {
int id = Obj_FindID(idname);
if (id != -1) {
msafe_struct mstruct;
mstruct.type = type;
mstruct.id = id;
MSafe_GetValue(MSAFE_OBJECT_COUNT_TYPE, &mstruct);
return mstruct.count;
} else
return 0;
}
/*
$$QUERY
Level Goals
b:All Primary Objectives Complete
qGoalPrimariesComplete
All Primary Objective Complete
Determines if all primary objectives are complete
Parameters:
None.
$$END
*/
bool qGoalPrimariesComplete() {
int flags = LF_ALL_PRIMARIES_DONE;
LGoal_Value(VF_GET, LGV_I_STATUS, &flags);
return (flags != 0);
}
/*
$$QUERY
Level Goals
b:Goal [l:LevelGoal] is enabled
qGoalEnabled
Goal is enabled
Determines if the specified goal is enabled
Parameters:
LevelGoal: the goal to check
$$END
*/
bool qGoalEnabled(int goal_index) {
int flags;
LGoal_Value(VF_GET, LGSV_I_STATUS, &flags, goal_index);
return ((flags & LGF_ENABLED) != 0);
}
/*
$$QUERY
Level Goals
b:Goal [l:LevelGoal] is complete
qGoalCompleted
Goal is enabled
Determines if the specified goal is complete
Parameters:
LevelGoal: the goal to check
$$END
*/
bool qGoalCompleted(int goal_index) {
int flags;
LGoal_Value(VF_GET, LGSV_I_STATUS, &flags, goal_index);
return ((flags & LGF_COMPLETED) != 0);
}
/*
$$QUERY
Level Goals
b:Goal [l:LevelGoal] is failed
qGoalFailed
Goal is failed
Determines if the specified goal is failed
Parameters:
LevelGoal: the goal to check
$$END
*/
bool qGoalFailed(int goal_index) {
int flags;
LGoal_Value(VF_GET, LGSV_I_STATUS, &flags, goal_index);
return ((flags & LGF_FAILED) != 0);
}
/*
$$QUERY
Players
o:Closest player to [o:Object]. Store dist in user var [e:UserVar].
qPlayerClosest
Closest player
Find the closest player to the specified object
Parameters:
Object: the object to check players against
$$END
*/
int qPlayerClosest(int objhandle, int varnum) {
vector objpos;
float closest_dist = FLT_MAX;
int closest_player = OBJECT_HANDLE_NONE;
msafe_struct mstruct;
// Get the object position
mstruct.objhandle = objhandle;
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
objpos = mstruct.pos;
// Loop though all possible players and compute distance
for (int p = 0; p < MAX_PLAYERS; p++) {
// Get player position
mstruct.slot = p;
MSafe_GetValue(MSAFE_OBJECT_PLAYER_HANDLE, &mstruct);
// See if this player active
if (mstruct.objhandle == OBJECT_HANDLE_NONE)
continue;
// Get the target position
MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct);
// Get the normalized vector from the source to the target
float dist = vm_VectorDistanceQuick(&objpos, &mstruct.pos);
if (dist < closest_dist) {
closest_dist = dist;
closest_player = mstruct.objhandle;
}
}
if ((varnum >= 0) && (varnum < MAX_USER_VARS))
User_vars[varnum] = closest_dist;
return closest_player;
}
/*
$$QUERY
Objects
f:[o:WeaponObject=IT] damage
qObjDamage
Object damage
Returns the amount of damage the given weapon object does
Parameters:
WeaponObject: The weapon object whose damage it returned
$$END
*/
float qObjDamage(int handle) {
msafe_struct mstruct;
mstruct.objhandle = handle;
MSafe_GetValue(MSAFE_OBJECT_DAMAGE_AMOUNT, &mstruct);
return mstruct.amount;
}
/*
$$QUERY
Misc
f:Frametime
qFrametime
Game Frametime
Returns the frametime
Parameters:
None
$$END
*/
float qFrametime() { return Game_GetFrameTime(); }
/*
$$QUERY
AI
f:[o:Object] max speed
qAIQueryMaxSpeed
Parameters:
Object: Get object's max speed.
$$END
*/
float qAIQueryMaxSpeed(int objhandle) {
float max_speed = 0.0f;
AI_Value(objhandle, VF_GET, AIV_F_MAX_SPEED, &max_speed);
return max_speed;
}