script_macros_common.hpp 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810
  1. /*
  2. Header: script_macros_common.hpp
  3. Description:
  4. A general set of useful macro functions for use by CBA itself or by any module that uses CBA.
  5. Authors:
  6. Sickboy <sb_at_dev-heaven.net> and Spooner
  7. */
  8. /* ****************************************************
  9. New - Should be exported to general addon
  10. Aim:
  11. - Simplify (shorten) the amount of characters required for repetitive tasks
  12. - Provide a solid structure that can be dynamic and easy editable (Which sometimes means we cannot adhere to Aim #1 ;-)
  13. An example is the path that is built from defines. Some available in this file, others in mods and addons.
  14. Follows Standard:
  15. Object variables: PREFIX_COMPONENT
  16. Main-object variables: PREFIX_main
  17. Paths: MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\SCRIPTNAME.sqf
  18. e.g: x\six\addons\sys_menu\fDate.sqf
  19. Usage:
  20. define PREFIX and COMPONENT, then include this file
  21. (Note, you could have a main addon for your mod, define the PREFIX in a macros.hpp,
  22. and include this script_macros_common.hpp file.
  23. Then in your addons, add a component.hpp, define the COMPONENT,
  24. and include your mod's script_macros.hpp
  25. In your scripts you can then include the addon's component.hpp with relative path)
  26. TODO:
  27. - Try only to use 1 string type " vs '
  28. - Evaluate double functions, and simplification
  29. - Evaluate naming scheme; current = prototype
  30. - Evaluate "Debug" features..
  31. - Evaluate "create mini function per precompiled script, that will load the script on first usage, rather than on init"
  32. - Also saw "Namespace" typeName, evaluate which we need :P
  33. - Single/Multi player gamelogics? (Incase of MP, you would want only 1 gamelogic per component, which is pv'ed from server, etc)
  34. */
  35. #ifndef MAINPREFIX
  36. #define MAINPREFIX x
  37. #endif
  38. #ifndef SUBPREFIX
  39. #define SUBPREFIX addons
  40. #endif
  41. #ifndef MAINLOGIC
  42. #define MAINLOGIC main
  43. #endif
  44. #ifndef VERSION
  45. #define VERSION 0
  46. #endif
  47. #ifndef VERSION_AR
  48. #define VERSION_AR VERSION
  49. #endif
  50. #ifndef VERSION_CONFIG
  51. #define VERSION_CONFIG version = VERSION; versionStr = QUOTE(VERSION); versionAr[] = {VERSION_AR}
  52. #endif
  53. #define ADDON DOUBLES(PREFIX,COMPONENT)
  54. #define MAIN_ADDON DOUBLES(PREFIX,main)
  55. /* -------------------------------------------
  56. Group: Debugging
  57. ------------------------------------------- */
  58. /* -------------------------------------------
  59. Macros: DEBUG_MODE_x
  60. Managing debugging based on debug level.
  61. According to the *highest* level of debugging that has been defined *before* script_macros_common.hpp is included,
  62. only the appropriate debugging commands will be functional. With no level explicitely defined, assume DEBUG_MODE_NORMAL.
  63. DEBUG_MODE_FULL - Full debugging output.
  64. DEBUG_MODE_NORMAL - All debugging except <TRACE_n()> and <LOG()> (Default setting if none specified).
  65. DEBUG_MODE_MINIMAL - Only <ERROR()> and <ERROR_WITH_TITLE()> enabled.
  66. Examples:
  67. In order to turn on full debugging for a single file,
  68. (begin example)
  69. // Top of individual script file.
  70. #define DEBUG_MODE_FULL
  71. #include "script_component.hpp"
  72. (end)
  73. In order to force minimal debugging for a single component,
  74. (begin example)
  75. // Top of addons\<component>\script_component.hpp
  76. // Ensure that any FULL and NORMAL setting from the individual files are undefined and MINIMAL is set.
  77. #ifdef DEBUG_MODE_FULL
  78. #undef DEBUG_MODE_FULL
  79. #endif
  80. #ifdef DEBUG_MODE_NORMAL
  81. #undef DEBUG_MODE_NORMAL
  82. #endif
  83. #ifndef DEBUG_MODE_MINIMAL
  84. #define DEBUG_MODE_MINIMAL
  85. #endif
  86. #include "script_macros.hpp"
  87. (end)
  88. In order to turn on full debugging for a whole addon,
  89. (begin example)
  90. // Top of addons\main\script_macros.hpp
  91. #ifndef DEBUG_MODE_FULL
  92. #define DEBUG_MODE_FULL
  93. #endif
  94. #include "\x\cba\addons\main\script_macros_common.hpp"
  95. (end)
  96. Author:
  97. Spooner
  98. ------------------------------------------- */
  99. // If DEBUG_MODE_FULL, then also enable DEBUG_MODE_NORMAL.
  100. #ifdef DEBUG_MODE_FULL
  101. #define DEBUG_MODE_NORMAL
  102. #endif
  103. // If DEBUG_MODE_NORMAL, then also enable DEBUG_MODE_MINIMAL.
  104. #ifdef DEBUG_MODE_NORMAL
  105. #define DEBUG_MODE_MINIMAL
  106. #endif
  107. // If no debug modes specified, use DEBUG_MODE_NORMAL (+ DEBUG_MODE_MINIMAL).
  108. #ifndef DEBUG_MODE_MINIMAL
  109. #define DEBUG_MODE_NORMAL
  110. #define DEBUG_MODE_MINIMAL
  111. #endif
  112. #define LOG_SYS_FORMAT(LEVEL,MESSAGE) format ['[%1] (%2) %3: %4', toUpper 'PREFIX', 'COMPONENT', LEVEL, MESSAGE]
  113. #ifdef DEBUG_SYNCHRONOUS
  114. #define LOG_SYS(LEVEL,MESSAGE) diag_log text LOG_SYS_FORMAT(LEVEL,MESSAGE)
  115. #else
  116. #define LOG_SYS(LEVEL,MESSAGE) LOG_SYS_FORMAT(LEVEL,MESSAGE) call CBA_fnc_log
  117. #endif
  118. #define LOG_SYS_FILELINENUMBERS(LEVEL,MESSAGE) LOG_SYS(LEVEL,format [ARR_4('%1 %2:%3',MESSAGE,__FILE__,__LINE__ + 1)])
  119. /* -------------------------------------------
  120. Macro: LOG()
  121. Log a debug message into the RPT log.
  122. Only run if <DEBUG_MODE_FULL> is defined.
  123. Parameters:
  124. MESSAGE - Message to record <STRING>
  125. Example:
  126. (begin example)
  127. LOG("Initiated clog-dancing simulator.");
  128. (end)
  129. Author:
  130. Spooner
  131. ------------------------------------------- */
  132. #ifdef DEBUG_MODE_FULL
  133. #define LOG(MESSAGE) LOG_SYS_FILELINENUMBERS('LOG',MESSAGE)
  134. #define LOG_1(MESSAGE,ARG1) LOG(FORMAT_1(MESSAGE,ARG1))
  135. #define LOG_2(MESSAGE,ARG1,ARG2) LOG(FORMAT_2(MESSAGE,ARG1,ARG2))
  136. #define LOG_3(MESSAGE,ARG1,ARG2,ARG3) LOG(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
  137. #define LOG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) LOG(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
  138. #define LOG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) LOG(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
  139. #define LOG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) LOG(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
  140. #define LOG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) LOG(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
  141. #define LOG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) LOG(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
  142. #else
  143. #define LOG(MESSAGE) /* disabled */
  144. #define LOG_1(MESSAGE,ARG1) /* disabled */
  145. #define LOG_2(MESSAGE,ARG1,ARG2) /* disabled */
  146. #define LOG_3(MESSAGE,ARG1,ARG2,ARG3) /* disabled */
  147. #define LOG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) /* disabled */
  148. #define LOG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) /* disabled */
  149. #define LOG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) /* disabled */
  150. #define LOG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) /* disabled */
  151. #define LOG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) /* disabled */
  152. #endif
  153. /* -------------------------------------------
  154. Macro: INFO()
  155. Record a message without file and line number in the RPT log.
  156. Parameters:
  157. MESSAGE - Message to record <STRING>
  158. Example:
  159. (begin example)
  160. INFO("Mod X is loaded, do Y");
  161. (end)
  162. Author:
  163. commy2
  164. ------------------------------------------- */
  165. #define INFO(MESSAGE) LOG_SYS('INFO',MESSAGE)
  166. #define INFO_1(MESSAGE,ARG1) INFO(FORMAT_1(MESSAGE,ARG1))
  167. #define INFO_2(MESSAGE,ARG1,ARG2) INFO(FORMAT_2(MESSAGE,ARG1,ARG2))
  168. #define INFO_3(MESSAGE,ARG1,ARG2,ARG3) INFO(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
  169. #define INFO_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) INFO(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
  170. #define INFO_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) INFO(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
  171. #define INFO_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) INFO(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
  172. #define INFO_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) INFO(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
  173. #define INFO_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) INFO(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
  174. /* -------------------------------------------
  175. Macro: WARNING()
  176. Record a non-critical error in the RPT log.
  177. Only run if <DEBUG_MODE_NORMAL> or higher is defined.
  178. Parameters:
  179. MESSAGE - Message to record <STRING>
  180. Example:
  181. (begin example)
  182. WARNING("This function has been deprecated. Please don't use it in future!");
  183. (end)
  184. Author:
  185. Spooner
  186. ------------------------------------------- */
  187. #ifdef DEBUG_MODE_NORMAL
  188. #define WARNING(MESSAGE) LOG_SYS_FILELINENUMBERS('WARNING',MESSAGE)
  189. #define WARNING_1(MESSAGE,ARG1) WARNING(FORMAT_1(MESSAGE,ARG1))
  190. #define WARNING_2(MESSAGE,ARG1,ARG2) WARNING(FORMAT_2(MESSAGE,ARG1,ARG2))
  191. #define WARNING_3(MESSAGE,ARG1,ARG2,ARG3) WARNING(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
  192. #define WARNING_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) WARNING(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
  193. #define WARNING_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) WARNING(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
  194. #define WARNING_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) WARNING(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
  195. #define WARNING_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) WARNING(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
  196. #define WARNING_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) WARNING(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
  197. #else
  198. #define WARNING(MESSAGE) /* disabled */
  199. #define WARNING_1(MESSAGE,ARG1) /* disabled */
  200. #define WARNING_2(MESSAGE,ARG1,ARG2) /* disabled */
  201. #define WARNING_3(MESSAGE,ARG1,ARG2,ARG3) /* disabled */
  202. #define WARNING_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) /* disabled */
  203. #define WARNING_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) /* disabled */
  204. #define WARNING_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) /* disabled */
  205. #define WARNING_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) /* disabled */
  206. #define WARNING_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) /* disabled */
  207. #endif
  208. /* -------------------------------------------
  209. Macro: ERROR()
  210. Record a critical error in the RPT log.
  211. Parameters:
  212. MESSAGE - Message to record <STRING>
  213. Example:
  214. (begin example)
  215. ERROR("value of frog not found in config ...yada...yada...");
  216. (end)
  217. Author:
  218. Spooner
  219. ------------------------------------------- */
  220. #define ERROR(MESSAGE) LOG_SYS_FILELINENUMBERS('ERROR',MESSAGE)
  221. #define ERROR_1(MESSAGE,ARG1) ERROR(FORMAT_1(MESSAGE,ARG1))
  222. #define ERROR_2(MESSAGE,ARG1,ARG2) ERROR(FORMAT_2(MESSAGE,ARG1,ARG2))
  223. #define ERROR_3(MESSAGE,ARG1,ARG2,ARG3) ERROR(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
  224. #define ERROR_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) ERROR(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
  225. #define ERROR_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) ERROR(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
  226. #define ERROR_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ERROR(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
  227. #define ERROR_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ERROR(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
  228. #define ERROR_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ERROR(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
  229. /* -------------------------------------------
  230. Macro: ERROR_MSG()
  231. Record a critical error in the RPT log and display on screen error message.
  232. Newlines (\n) in the MESSAGE will be put on separate lines.
  233. Parameters:
  234. MESSAGE - Message to record <STRING>
  235. Example:
  236. (begin example)
  237. ERROR_MSG("value of frog not found in config ...yada...yada...");
  238. (end)
  239. Author:
  240. commy2
  241. ------------------------------------------- */
  242. #define ERROR_MSG(MESSAGE) ['PREFIX', 'COMPONENT', nil, MESSAGE, __FILE__, __LINE__ + 1] call CBA_fnc_error
  243. #define ERROR_MSG_1(MESSAGE,ARG1) ERROR_MSG(FORMAT_1(MESSAGE,ARG1))
  244. #define ERROR_MSG_2(MESSAGE,ARG1,ARG2) ERROR_MSG(FORMAT_2(MESSAGE,ARG1,ARG2))
  245. #define ERROR_MSG_3(MESSAGE,ARG1,ARG2,ARG3) ERROR_MSG(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
  246. #define ERROR_MSG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) ERROR_MSG(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
  247. #define ERROR_MSG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) ERROR_MSG(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
  248. #define ERROR_MSG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ERROR_MSG(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
  249. #define ERROR_MSG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ERROR_MSG(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
  250. #define ERROR_MSG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ERROR_MSG(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
  251. /* -------------------------------------------
  252. Macro: ERROR_WITH_TITLE()
  253. Record a critical error in the RPT log.
  254. The title can be specified (in <ERROR()> the heading is always just "ERROR")
  255. Newlines (\n) in the MESSAGE will be put on separate lines.
  256. Parameters:
  257. TITLE - Title of error message <STRING>
  258. MESSAGE - Body of error message <STRING>
  259. Example:
  260. (begin example)
  261. ERROR_WITH_TITLE("Value not found","Value of frog not found in config ...yada...yada...");
  262. (end)
  263. Author:
  264. Spooner
  265. ------------------------------------------- */
  266. #define ERROR_WITH_TITLE(TITLE,MESSAGE) ['PREFIX', 'COMPONENT', TITLE, MESSAGE, __FILE__, __LINE__ + 1] call CBA_fnc_error
  267. #define ERROR_WITH_TITLE_1(TITLE,MESSAGE,ARG1) ERROR_WITH_TITLE(TITLE,FORMAT_1(MESSAGE,ARG1))
  268. #define ERROR_WITH_TITLE_2(TITLE,MESSAGE,ARG1,ARG2) ERROR_WITH_TITLE(TITLE,FORMAT_2(MESSAGE,ARG1,ARG2))
  269. #define ERROR_WITH_TITLE_3(TITLE,MESSAGE,ARG1,ARG2,ARG3) ERROR_WITH_TITLE(TITLE,FORMAT_3(MESSAGE,ARG1,ARG2,ARG3))
  270. #define ERROR_WITH_TITLE_4(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4) ERROR_WITH_TITLE(TITLE,FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4))
  271. #define ERROR_WITH_TITLE_5(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) ERROR_WITH_TITLE(TITLE,FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5))
  272. #define ERROR_WITH_TITLE_6(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ERROR_WITH_TITLE(TITLE,FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6))
  273. #define ERROR_WITH_TITLE_7(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ERROR_WITH_TITLE(TITLE,FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7))
  274. #define ERROR_WITH_TITLE_8(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ERROR_WITH_TITLE(TITLE,FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8))
  275. /* -------------------------------------------
  276. Macro: MESSAGE_WITH_TITLE()
  277. Record a single line in the RPT log.
  278. Parameters:
  279. TITLE - Title of log message <STRING>
  280. MESSAGE - Body of message <STRING>
  281. Example:
  282. (begin example)
  283. MESSAGE_WITH_TITLE("Value found","Value of frog found in config <someconfig>");
  284. (end)
  285. Author:
  286. Killswitch
  287. ------------------------------------------- */
  288. #define MESSAGE_WITH_TITLE(TITLE,MESSAGE) LOG_SYS_FILELINENUMBERS(TITLE,MESSAGE)
  289. /* -------------------------------------------
  290. Macro: RETDEF()
  291. If a variable is undefined, return the default value. Otherwise, return the
  292. variable itself.
  293. Parameters:
  294. VARIABLE - the variable to check
  295. DEFAULT_VALUE - the default value to use if variable is undefined
  296. Example:
  297. (begin example)
  298. // _var is undefined
  299. hintSilent format ["_var=%1", RETDEF(_var,5)]; // "_var=5"
  300. _var = 7;
  301. hintSilent format ["_var=%1", RETDEF(_var,5)]; // "_var=7"
  302. (end example)
  303. Author:
  304. 654wak654
  305. ------------------------------------------- */
  306. #define RETDEF(VARIABLE,DEFAULT_VALUE) (if (isNil {VARIABLE}) then [{DEFAULT_VALUE}, {VARIABLE}])
  307. /* -------------------------------------------
  308. Macro: RETNIL()
  309. If a variable is undefined, return the value nil. Otherwise, return the
  310. variable itself.
  311. Parameters:
  312. VARIABLE - the variable to check
  313. Example:
  314. (begin example)
  315. // _var is undefined
  316. hintSilent format ["_var=%1", RETNIL(_var)]; // "_var=any"
  317. (end example)
  318. Author:
  319. Alef (see CBA issue #8514)
  320. ------------------------------------------- */
  321. #define RETNIL(VARIABLE) RETDEF(VARIABLE,nil)
  322. /* -------------------------------------------
  323. Macros: TRACE_n()
  324. Log a message and 1-8 variables to the RPT log.
  325. Only run if <DEBUG_MODE_FULL> is defined.
  326. TRACE_1(MESSAGE,A) - Log 1 variable.
  327. TRACE_2(MESSAGE,A,B) - Log 2 variables.
  328. TRACE_3(MESSAGE,A,B,C) - Log 3 variables.
  329. TRACE_4(MESSAGE,A,B,C,D) - Log 4 variables.
  330. TRACE_5(MESSAGE,A,B,C,D,E) - Log 5 variables.
  331. TRACE_6(MESSAGE,A,B,C,D,E,F) - Log 6 variables.
  332. TRACE_7(MESSAGE,A,B,C,D,E,F,G) - Log 7 variables.
  333. TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) - Log 8 variables.
  334. TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) - Log 9 variables.
  335. Parameters:
  336. MESSAGE - Message to add to the trace [String]
  337. A..H - Variable names to log values of [Any]
  338. Example:
  339. (begin example)
  340. TRACE_3("After takeoff",_vehicle player,getPos (_vehicle player), getPosASL (_vehicle player));
  341. (end)
  342. Author:
  343. Spooner
  344. ------------------------------------------- */
  345. #define PFORMAT_1(MESSAGE,A) \
  346. format ['%1: A=%2', MESSAGE, RETNIL(A)]
  347. #define PFORMAT_2(MESSAGE,A,B) \
  348. format ['%1: A=%2, B=%3', MESSAGE, RETNIL(A), RETNIL(B)]
  349. #define PFORMAT_3(MESSAGE,A,B,C) \
  350. format ['%1: A=%2, B=%3, C=%4', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C)]
  351. #define PFORMAT_4(MESSAGE,A,B,C,D) \
  352. format ['%1: A=%2, B=%3, C=%4, D=%5', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D)]
  353. #define PFORMAT_5(MESSAGE,A,B,C,D,E) \
  354. format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E)]
  355. #define PFORMAT_6(MESSAGE,A,B,C,D,E,F) \
  356. format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F)]
  357. #define PFORMAT_7(MESSAGE,A,B,C,D,E,F,G) \
  358. format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7, G=%8', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F), RETNIL(G)]
  359. #define PFORMAT_8(MESSAGE,A,B,C,D,E,F,G,H) \
  360. format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7, G=%8, H=%9', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F), RETNIL(G), RETNIL(H)]
  361. #define PFORMAT_9(MESSAGE,A,B,C,D,E,F,G,H,I) \
  362. format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7, G=%8, H=%9, I=%10', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F), RETNIL(G), RETNIL(H), RETNIL(I)]
  363. #ifdef DEBUG_MODE_FULL
  364. #define TRACE_1(MESSAGE,A) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_1(str diag_frameNo + ' ' + (MESSAGE),A))
  365. #define TRACE_2(MESSAGE,A,B) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_2(str diag_frameNo + ' ' + (MESSAGE),A,B))
  366. #define TRACE_3(MESSAGE,A,B,C) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_3(str diag_frameNo + ' ' + (MESSAGE),A,B,C))
  367. #define TRACE_4(MESSAGE,A,B,C,D) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_4(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D))
  368. #define TRACE_5(MESSAGE,A,B,C,D,E) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_5(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E))
  369. #define TRACE_6(MESSAGE,A,B,C,D,E,F) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_6(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F))
  370. #define TRACE_7(MESSAGE,A,B,C,D,E,F,G) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_7(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G))
  371. #define TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_8(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G,H))
  372. #define TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_9(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G,H,I))
  373. #else
  374. #define TRACE_1(MESSAGE,A) /* disabled */
  375. #define TRACE_2(MESSAGE,A,B) /* disabled */
  376. #define TRACE_3(MESSAGE,A,B,C) /* disabled */
  377. #define TRACE_4(MESSAGE,A,B,C,D) /* disabled */
  378. #define TRACE_5(MESSAGE,A,B,C,D,E) /* disabled */
  379. #define TRACE_6(MESSAGE,A,B,C,D,E,F) /* disabled */
  380. #define TRACE_7(MESSAGE,A,B,C,D,E,F,G) /* disabled */
  381. #define TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) /* disabled */
  382. #define TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) /* disabled */
  383. #endif
  384. /* -------------------------------------------
  385. Group: General
  386. ------------------------------------------- */
  387. // *************************************
  388. // Internal Functions
  389. #define DOUBLES(var1,var2) ##var1##_##var2
  390. #define TRIPLES(var1,var2,var3) ##var1##_##var2##_##var3
  391. #define QUOTE(var1) #var1
  392. #ifdef MODULAR
  393. #define COMPONENT_T DOUBLES(t,COMPONENT)
  394. #define COMPONENT_M DOUBLES(m,COMPONENT)
  395. #define COMPONENT_S DOUBLES(s,COMPONENT)
  396. #define COMPONENT_C DOUBLES(c,COMPONENT)
  397. #define COMPONENT_F COMPONENT_C
  398. #else
  399. #define COMPONENT_T COMPONENT
  400. #define COMPONENT_M COMPONENT
  401. #define COMPONENT_S COMPONENT
  402. #define COMPONENT_F COMPONENT
  403. #define COMPONENT_C COMPONENT
  404. #endif
  405. /* -------------------------------------------
  406. Macro: INC()
  407. Description:
  408. Increase a number by one.
  409. Parameters:
  410. VAR - Variable to increment [Number]
  411. Example:
  412. (begin example)
  413. _counter = 0;
  414. INC(_counter);
  415. // _counter => 1
  416. (end)
  417. Author:
  418. Spooner
  419. ------------------------------------------- */
  420. #define INC(var) var = (var) + 1
  421. /* -------------------------------------------
  422. Macro: DEC()
  423. Description:
  424. Decrease a number by one.
  425. Parameters:
  426. VAR - Variable to decrement [Number]
  427. Example:
  428. (begin example)
  429. _counter = 99;
  430. DEC(_counter);
  431. // _counter => 98
  432. (end)
  433. Author:
  434. Spooner
  435. ------------------------------------------- */
  436. #define DEC(var) var = (var) - 1
  437. /* -------------------------------------------
  438. Macro: ADD()
  439. Description:
  440. Add a value to a variable. Variable and value should be both Numbers or both Strings.
  441. Parameters:
  442. VAR - Variable to add to [Number or String]
  443. VALUE - Value to add [Number or String]
  444. Examples:
  445. (begin example)
  446. _counter = 2;
  447. ADD(_counter,3);
  448. // _counter => 5
  449. (end)
  450. (begin example)
  451. _str = "hello";
  452. ADD(_str," ");
  453. ADD(_str,"Fred");
  454. // _str => "hello Fred"
  455. (end)
  456. Author:
  457. Sickboy
  458. ------------------------------------------- */
  459. #define ADD(var1,var2) var1 = (var1) + (var2)
  460. /* -------------------------------------------
  461. Macro: SUB()
  462. Description:
  463. Subtract a value from a number variable. VAR and VALUE should both be Numbers.
  464. Parameters:
  465. VAR - Variable to subtract from [Number]
  466. VALUE - Value to subtract [Number]
  467. Examples:
  468. (begin example)
  469. _numChickens = 2;
  470. SUB(_numChickens,3);
  471. // _numChickens => -1
  472. (end)
  473. ------------------------------------------- */
  474. #define SUB(var1,var2) var1 = (var1) - (var2)
  475. /* -------------------------------------------
  476. Macro: REM()
  477. Description:
  478. Remove an element from an array each time it occurs.
  479. This recreates the entire array, so use BIS_fnc_removeIndex if modification of the original array is required
  480. or if only one of the elements that matches ELEMENT needs to be removed.
  481. Parameters:
  482. ARRAY - Array to modify [Array]
  483. ELEMENT - Element to remove [Any]
  484. Examples:
  485. (begin example)
  486. _array = [1, 2, 3, 4, 3, 8];
  487. REM(_array,3);
  488. // _array = [1, 2, 4, 8];
  489. (end)
  490. Author:
  491. Spooner
  492. ------------------------------------------- */
  493. #define REM(var1,var2) SUB(var1,[var2])
  494. /* -------------------------------------------
  495. Macro: PUSH()
  496. Description:
  497. Appends a single value onto the end of an ARRAY. Change is made to the ARRAY itself, not creating a new array.
  498. Parameters:
  499. ARRAY - Array to push element onto [Array]
  500. ELEMENT - Element to push [Any]
  501. Examples:
  502. (begin example)
  503. _fish = ["blue", "green", "smelly"];
  504. PUSH(_fish,"monkey-flavoured");
  505. // _fish => ["blue", "green", "smelly", "monkey-flavoured"]
  506. (end)
  507. Author:
  508. Spooner
  509. ------------------------------------------- */
  510. #define PUSH(var1,var2) (var1) pushBack (var2)
  511. /* -------------------------------------------
  512. Macro: MAP()
  513. Description:
  514. Applies given code to each element of the array, then assigns the
  515. resulting array to the original
  516. Parameters:
  517. ARRAY - Array to be modified
  518. CODE - Code that'll be applied to each element of the array.
  519. Example:
  520. (begin example)
  521. _array = [1, 2, 3, 4, 3, 8];
  522. MAP(_array,_x + 1);
  523. // _array is now [2, 3, 4, 5, 4, 9];
  524. (end)
  525. Author:
  526. 654wak654
  527. ------------------------------------------- */
  528. #define MAP(ARR,CODE) ARR = ARR apply {CODE}
  529. /* -------------------------------------------
  530. Macro: FILTER()
  531. Description:
  532. Filters an array based on given code, then assigns the resulting array
  533. to the original
  534. Parameters:
  535. ARRAY - Array to be filtered
  536. CODE - Condition to pick elements
  537. Example:
  538. (begin example)
  539. _array = [1, 2, 3, 4, 3, 8];
  540. FILTER(_array,_x % 2 == 0)
  541. // _array is now [2, 4, 8];
  542. (end)
  543. Author:
  544. Commy2
  545. ------------------------------------------- */
  546. #define FILTER(ARR,CODE) ARR = ARR select {CODE}
  547. /* -------------------------------------------
  548. Macro: UNIQUE()
  549. Description:
  550. Removes duplicate values in given array
  551. Parameters:
  552. ARRAY - The array to be modified
  553. Example:
  554. (begin example)
  555. _someArray = [4, 4, 5, 5, 5, 2];
  556. UNIQUE(_someArray);
  557. // _someArray is now [4, 5, 2]
  558. (end)
  559. Author:
  560. Commy2
  561. ------------------------------------------- */
  562. #define UNIQUE(ARR) ARR = ARR arrayIntersect ARR
  563. /* -------------------------------------------
  564. Macro: INTERSECTION()
  565. Description:
  566. Finds unique common elements between two arrays and assigns them
  567. to the first array
  568. Parameters:
  569. ARRAY0 - The array to be modified
  570. ARRAY1 - The array to find intersections with
  571. Example:
  572. (begin example)
  573. _someArray = [1, 2, 3, 4, 5, 5];
  574. _anotherArray = [4, 5, 6, 7];
  575. INTERSECTION(_someArray,_anotherArray);
  576. // _someArray is now [4, 5]
  577. (end)
  578. Author:
  579. 654wak654
  580. ------------------------------------------- */
  581. #define INTERSECTION(ARG0,ARG1) ARG0 = ARG0 arrayIntersect (ARG1)
  582. /* -------------------------------------------
  583. Macro: ISNILS()
  584. Description:
  585. Sets a variable with a value, but only if it is undefined.
  586. Parameters:
  587. VARIABLE - Variable to set [Any, not nil]
  588. DEFAULT_VALUE - Value to set VARIABLE to if it is undefined [Any, not nil]
  589. Examples:
  590. (begin example)
  591. // _fish is undefined
  592. ISNILS(_fish,0);
  593. // _fish => 0
  594. (end)
  595. (begin example)
  596. _fish = 12;
  597. // ...later...
  598. ISNILS(_fish,0);
  599. // _fish => 12
  600. (end)
  601. Author:
  602. Sickboy
  603. ------------------------------------------- */
  604. #define ISNILS(VARIABLE,DEFAULT_VALUE) if (isNil #VARIABLE) then { ##VARIABLE = ##DEFAULT_VALUE }
  605. #define ISNILS2(var1,var2,var3,var4) ISNILS(TRIPLES(var1,var2,var3),var4)
  606. #define ISNILS3(var1,var2,var3) ISNILS(DOUBLES(var1,var2),var3)
  607. #define ISNIL(var1,var2) ISNILS2(PREFIX,COMPONENT,var1,var2)
  608. #define ISNILMAIN(var1,var2) ISNILS3(PREFIX,var1,var2)
  609. #define CREATELOGICS(var1,var2) ##var1##_##var2## = ([sideLogic] call CBA_fnc_getSharedGroup) createUnit ["LOGIC", [0, 0, 0], [], 0, "NONE"]
  610. #define CREATELOGICLOCALS(var1,var2) ##var1##_##var2## = "LOGIC" createVehicleLocal [0, 0, 0]
  611. #define CREATELOGICGLOBALS(var1,var2) ##var1##_##var2## = ([sideLogic] call CBA_fnc_getSharedGroup) createUnit ["LOGIC", [0, 0, 0], [], 0, "NONE"]; publicVariable QUOTE(DOUBLES(var1,var2))
  612. #define CREATELOGICGLOBALTESTS(var1,var2) ##var1##_##var2## = ([sideLogic] call CBA_fnc_getSharedGroup) createUnit [QUOTE(DOUBLES(ADDON,logic)), [0, 0, 0], [], 0, "NONE"]
  613. #define GETVARS(var1,var2,var3) (##var1##_##var2 getVariable #var3)
  614. #define GETVARMAINS(var1,var2) GETVARS(var1,MAINLOGIC,var2)
  615. #ifndef PATHTO_SYS
  616. #define PATHTO_SYS(var1,var2,var3) \MAINPREFIX\##var1\SUBPREFIX\##var2\##var3.sqf
  617. #endif
  618. #ifndef PATHTOF_SYS
  619. #define PATHTOF_SYS(var1,var2,var3) \MAINPREFIX\##var1\SUBPREFIX\##var2\##var3
  620. #endif
  621. #ifndef PATHTOF2_SYS
  622. #define PATHTOF2_SYS(var1,var2,var3) MAINPREFIX\##var1\SUBPREFIX\##var2\##var3
  623. #endif
  624. #define PATHTO_R(var1) PATHTOF2_SYS(PREFIX,COMPONENT_C,var1)
  625. #define PATHTO_T(var1) PATHTOF_SYS(PREFIX,COMPONENT_T,var1)
  626. #define PATHTO_M(var1) PATHTOF_SYS(PREFIX,COMPONENT_M,var1)
  627. #define PATHTO_S(var1) PATHTOF_SYS(PREFIX,COMPONENT_S,var1)
  628. #define PATHTO_C(var1) PATHTOF_SYS(PREFIX,COMPONENT_C,var1)
  629. #define PATHTO_F(var1) PATHTO_SYS(PREFIX,COMPONENT_F,var1)
  630. // Already quoted ""
  631. #define QPATHTO_R(var1) QUOTE(PATHTO_R(var1))
  632. #define QPATHTO_T(var1) QUOTE(PATHTO_T(var1))
  633. #define QPATHTO_M(var1) QUOTE(PATHTO_M(var1))
  634. #define QPATHTO_S(var1) QUOTE(PATHTO_S(var1))
  635. #define QPATHTO_C(var1) QUOTE(PATHTO_C(var1))
  636. #define QPATHTO_F(var1) QUOTE(PATHTO_F(var1))
  637. // This only works for binarized configs after recompiling the pbos
  638. // TODO: Reduce amount of calls / code..
  639. #define COMPILE_FILE2_CFG_SYS(var1) compile preprocessFileLineNumbers var1
  640. #define COMPILE_FILE2_SYS(var1) COMPILE_FILE2_CFG_SYS(var1)
  641. #define COMPILE_FILE_SYS(var1,var2,var3) COMPILE_FILE2_SYS('PATHTO_SYS(var1,var2,var3)')
  642. #define COMPILE_FILE_CFG_SYS(var1,var2,var3) COMPILE_FILE2_CFG_SYS('PATHTO_SYS(var1,var2,var3)')
  643. #define SETVARS(var1,var2) ##var1##_##var2 setVariable
  644. #define SETVARMAINS(var1) SETVARS(var1,MAINLOGIC)
  645. #define GVARMAINS(var1,var2) ##var1##_##var2##
  646. #define CFGSETTINGSS(var1,var2) configFile >> "CfgSettings" >> #var1 >> #var2
  647. //#define SETGVARS(var1,var2,var3) ##var1##_##var2##_##var3 =
  648. //#define SETGVARMAINS(var1,var2) ##var1##_##var2 =
  649. // Compile-Once, JIT: On first use.
  650. // #define PREPMAIN_SYS(var1,var2,var3) ##var1##_fnc_##var3 = { ##var1##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3)); if (isNil "_this") then { call ##var1##_fnc_##var3 } else { _this call ##var1##_fnc_##var3 } }
  651. // #define PREP_SYS(var1,var2,var3) ##var1##_##var2##_fnc_##var3 = { ##var1##_##var2##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3)); if (isNil "_this") then { call ##var1##_##var2##_fnc_##var3 } else { _this call ##var1##_##var2##_fnc_##var3 } }
  652. // #define PREP_SYS2(var1,var2,var3,var4) ##var1##_##var2##_fnc_##var4 = { ##var1##_##var2##_fnc_##var4 = COMPILE_FILE_SYS(var1,var3,DOUBLES(fnc,var4)); if (isNil "_this") then { call ##var1##_##var2##_fnc_##var4 } else { _this call ##var1##_##var2##_fnc_##var4 } }
  653. // Compile-Once, at Macro. As opposed to Compile-Once, on first use.
  654. #define PREPMAIN_SYS(var1,var2,var3) ##var1##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3))
  655. #define PREP_SYS(var1,var2,var3) ##var1##_##var2##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3))
  656. #define PREP_SYS2(var1,var2,var3,var4) ##var1##_##var2##_fnc_##var4 = COMPILE_FILE_SYS(var1,var3,DOUBLES(fnc,var4))
  657. #define LSTR(var1) TRIPLES(ADDON,STR,var1)
  658. #ifndef DEBUG_SETTINGS
  659. #define DEBUG_SETTINGS [false, true, false]
  660. #endif
  661. #define MSG_INIT QUOTE(Initializing: ADDON version: VERSION)
  662. // *************************************
  663. // User Functions
  664. #define CFGSETTINGS CFGSETTINGSS(PREFIX,COMPONENT)
  665. #define PATHTO(var1) PATHTO_SYS(PREFIX,COMPONENT_F,var1)
  666. #define PATHTOF(var1) PATHTOF_SYS(PREFIX,COMPONENT,var1)
  667. #define PATHTOEF(var1,var2) PATHTOF_SYS(PREFIX,var1,var2)
  668. #define QPATHTOF(var1) QUOTE(PATHTOF(var1))
  669. #define QPATHTOEF(var1,var2) QUOTE(PATHTOEF(var1,var2))
  670. #define COMPILE_FILE(var1) COMPILE_FILE_SYS(PREFIX,COMPONENT_F,var1)
  671. #define COMPILE_FILE_CFG(var1) COMPILE_FILE_CFG_SYS(PREFIX,COMPONENT_F,var1)
  672. #define COMPILE_FILE2(var1) COMPILE_FILE2_SYS('var1')
  673. #define COMPILE_FILE2_CFG(var1) COMPILE_FILE2_CFG_SYS('var1')
  674. #define VERSIONING_SYS(var1) class CfgSettings \
  675. { \
  676. class CBA \
  677. { \
  678. class Versioning \
  679. { \
  680. class var1 \
  681. { \
  682. }; \
  683. }; \
  684. }; \
  685. };
  686. #define VERSIONING VERSIONING_SYS(PREFIX)
  687. /* -------------------------------------------
  688. Macro: GVAR()
  689. Get full variable identifier for a global variable owned by this component.
  690. Parameters:
  691. VARIABLE - Partial name of global variable owned by this component [Any].
  692. Example:
  693. (begin example)
  694. GVAR(frog) = 12;
  695. // In SPON_FrogDancing component, equivalent to SPON_FrogDancing_frog = 12
  696. (end)
  697. Author:
  698. Sickboy
  699. ------------------------------------------- */
  700. #define GVAR(var1) DOUBLES(ADDON,var1)
  701. #define EGVAR(var1,var2) TRIPLES(PREFIX,var1,var2)
  702. #define QGVAR(var1) QUOTE(GVAR(var1))
  703. #define QEGVAR(var1,var2) QUOTE(EGVAR(var1,var2))
  704. #define QQGVAR(var1) QUOTE(QGVAR(var1))
  705. #define QQEGVAR(var1,var2) QUOTE(QEGVAR(var1,var2))
  706. /* -------------------------------------------
  707. Macro: GVARMAIN()
  708. Get full variable identifier for a global variable owned by this addon.
  709. Parameters:
  710. VARIABLE - Partial name of global variable owned by this addon [Any].
  711. Example:
  712. (begin example)
  713. GVARMAIN(frog) = 12;
  714. // In SPON_FrogDancing component, equivalent to SPON_frog = 12
  715. (end)
  716. Author:
  717. Sickboy
  718. ------------------------------------------- */
  719. #define GVARMAIN(var1) GVARMAINS(PREFIX,var1)
  720. #define QGVARMAIN(var1) QUOTE(GVARMAIN(var1))
  721. #define QQGVARMAIN(var1) QUOTE(QGVARMAIN(var1))
  722. // TODO: What's this?
  723. #define SETTINGS DOUBLES(PREFIX,settings)
  724. #define CREATELOGIC CREATELOGICS(PREFIX,COMPONENT)
  725. #define CREATELOGICGLOBAL CREATELOGICGLOBALS(PREFIX,COMPONENT)
  726. #define CREATELOGICGLOBALTEST CREATELOGICGLOBALTESTS(PREFIX,COMPONENT)
  727. #define CREATELOGICLOCAL CREATELOGICLOCALS(PREFIX,COMPONENT)
  728. #define CREATELOGICMAIN CREATELOGICS(PREFIX,MAINLOGIC)
  729. #define GETVAR(var1) GETVARS(PREFIX,COMPONENT,var1)
  730. #define SETVAR SETVARS(PREFIX,COMPONENT)
  731. #define SETVARMAIN SETVARMAINS(PREFIX)
  732. #define IFCOUNT(var1,var2,var3) if (count ##var1 > ##var2) then { ##var3 = ##var1 select ##var2 };
  733. /* -------------------------------------------
  734. Macro: PREP()
  735. Description:
  736. Defines a function.
  737. Full file path:
  738. '\MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\fnc_<FNC>.sqf'
  739. Resulting function name:
  740. 'PREFIX_COMPONENT_<FNC>'
  741. The PREP macro should be placed in a script run by a XEH preStart and XEH preInit event.
  742. The PREP macro allows for CBA function caching, which drastically speeds up load times.
  743. Beware though that function caching is enabled by default and as such to disable it, you need to
  744. #define DISABLE_COMPILE_CACHE above your #include "script_components.hpp" include!
  745. The function will be defined in ui and mission namespace. It can not be overwritten without
  746. a mission restart.
  747. Parameters:
  748. FUNCTION NAME - Name of the function, unquoted <STRING>
  749. Examples:
  750. (begin example)
  751. PREP(banana);
  752. call FUNC(banana);
  753. (end)
  754. Author:
  755. dixon13
  756. ------------------------------------------- */
  757. //#define PREP(var1) PREP_SYS(PREFIX,COMPONENT_F,var1)
  758. #ifdef DISABLE_COMPILE_CACHE
  759. #define PREP(var1) TRIPLES(ADDON,fnc,var1) = compile preProcessFileLineNumbers 'PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))'
  760. #define PREPMAIN(var1) TRIPLES(PREFIX,fnc,var1) = compile preProcessFileLineNumbers 'PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))'
  761. #else
  762. #define PREP(var1) ['PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))', 'TRIPLES(ADDON,fnc,var1)'] call SLX_XEH_COMPILE_NEW
  763. #define PREPMAIN(var1) ['PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))', 'TRIPLES(PREFIX,fnc,var1)'] call SLX_XEH_COMPILE_NEW
  764. #endif
  765. /* -------------------------------------------
  766. Macro: PATHTO_FNC()
  767. Description:
  768. Defines a function inside CfgFunctions.
  769. Full file path in addons:
  770. '\MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\fnc_<FNC>.sqf'
  771. Define 'RECOMPILE' to enable recompiling.
  772. Define 'SKIP_FUNCTION_HEADER' to skip adding function header.
  773. Parameters:
  774. FUNCTION NAME - Name of the function, unquoted <STRING>
  775. Examples:
  776. (begin example)
  777. // file name: fnc_addPerFrameHandler.sqf
  778. class CfgFunctions {
  779. class CBA {
  780. class Misc {
  781. PATHTO_FNC(addPerFrameHandler);
  782. };
  783. };
  784. };
  785. // -> CBA_fnc_addPerFrameHandler
  786. (end)
  787. Author:
  788. dixon13, commy2
  789. ------------------------------------------- */
  790. #ifdef RECOMPILE
  791. #undef RECOMPILE
  792. #define RECOMPILE recompile = 1
  793. #else
  794. #define RECOMPILE recompile = 0
  795. #endif
  796. // Set function header type: -1 - no header; 0 - default header; 1 - system header.
  797. #ifdef SKIP_FUNCTION_HEADER
  798. #define CFGFUNCTION_HEADER headerType = -1
  799. #else
  800. #define CFGFUNCTION_HEADER headerType = 0
  801. #endif
  802. #define PATHTO_FNC(func) class func {\
  803. file = QPATHTOF(DOUBLES(fnc,func).sqf);\
  804. CFGFUNCTION_HEADER;\
  805. RECOMPILE;\
  806. }
  807. #define FUNC(var1) TRIPLES(ADDON,fnc,var1)
  808. #define FUNCMAIN(var1) TRIPLES(PREFIX,fnc,var1)
  809. #define FUNC_INNER(var1,var2) TRIPLES(DOUBLES(PREFIX,var1),fnc,var2)
  810. #define EFUNC(var1,var2) FUNC_INNER(var1,var2)
  811. #define QFUNC(var1) QUOTE(FUNC(var1))
  812. #define QFUNCMAIN(var1) QUOTE(FUNCMAIN(var1))
  813. #define QFUNC_INNER(var1,var2) QUOTE(FUNC_INNER(var1,var2))
  814. #define QEFUNC(var1,var2) QUOTE(EFUNC(var1,var2))
  815. #define QQFUNC(var1) QUOTE(QFUNC(var1))
  816. #define QQFUNCMAIN(var1) QUOTE(QFUNCMAIN(var1))
  817. #define QQFUNC_INNER(var1,var2) QUOTE(QFUNC_INNER(var1,var2))
  818. #define QQEFUNC(var1,var2) QUOTE(QEFUNC(var1,var2))
  819. #ifndef PRELOAD_ADDONS
  820. #define PRELOAD_ADDONS class CfgAddons \
  821. { \
  822. class PreloadAddons \
  823. { \
  824. class ADDON \
  825. { \
  826. list[]={ QUOTE(ADDON) }; \
  827. }; \
  828. }; \
  829. }
  830. #endif
  831. /* -------------------------------------------
  832. Macros: ARG_#()
  833. Select from list of array arguments
  834. Parameters:
  835. VARIABLE(1-8) - elements for the list
  836. Author:
  837. Rommel
  838. ------------------------------------------- */
  839. #define ARG_1(A,B) ((A) select (B))
  840. #define ARG_2(A,B,C) (ARG_1(ARG_1(A,B),C))
  841. #define ARG_3(A,B,C,D) (ARG_1(ARG_2(A,B,C),D))
  842. #define ARG_4(A,B,C,D,E) (ARG_1(ARG_3(A,B,C,D),E))
  843. #define ARG_5(A,B,C,D,E,F) (ARG_1(ARG_4(A,B,C,D,E),F))
  844. #define ARG_6(A,B,C,D,E,F,G) (ARG_1(ARG_5(A,B,C,D,E,F),G))
  845. #define ARG_7(A,B,C,D,E,F,G,H) (ARG_1(ARG_6(A,B,C,D,E,E,F,G),H))
  846. #define ARG_8(A,B,C,D,E,F,G,H,I) (ARG_1(ARG_7(A,B,C,D,E,E,F,G,H),I))
  847. /* -------------------------------------------
  848. Macros: ARR_#()
  849. Create list from arguments. Useful for working around , in macro parameters.
  850. 1-8 arguments possible.
  851. Parameters:
  852. VARIABLE(1-8) - elements for the list
  853. Author:
  854. Nou
  855. ------------------------------------------- */
  856. #define ARR_1(ARG1) ARG1
  857. #define ARR_2(ARG1,ARG2) ARG1, ARG2
  858. #define ARR_3(ARG1,ARG2,ARG3) ARG1, ARG2, ARG3
  859. #define ARR_4(ARG1,ARG2,ARG3,ARG4) ARG1, ARG2, ARG3, ARG4
  860. #define ARR_5(ARG1,ARG2,ARG3,ARG4,ARG5) ARG1, ARG2, ARG3, ARG4, ARG5
  861. #define ARR_6(ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ARG1, ARG2, ARG3, ARG4, ARG5, ARG6
  862. #define ARR_7(ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7
  863. #define ARR_8(ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8
  864. /* -------------------------------------------
  865. Macros: FORMAT_#(STR, ARG1)
  866. Format - Useful for working around , in macro parameters.
  867. 1-8 arguments possible.
  868. Parameters:
  869. STRING - string used by format
  870. VARIABLE(1-8) - elements for usage in format
  871. Author:
  872. Nou & Sickboy
  873. ------------------------------------------- */
  874. #define FORMAT_1(STR,ARG1) format[STR, ARG1]
  875. #define FORMAT_2(STR,ARG1,ARG2) format[STR, ARG1, ARG2]
  876. #define FORMAT_3(STR,ARG1,ARG2,ARG3) format[STR, ARG1, ARG2, ARG3]
  877. #define FORMAT_4(STR,ARG1,ARG2,ARG3,ARG4) format[STR, ARG1, ARG2, ARG3, ARG4]
  878. #define FORMAT_5(STR,ARG1,ARG2,ARG3,ARG4,ARG5) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5]
  879. #define FORMAT_6(STR,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6]
  880. #define FORMAT_7(STR,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7]
  881. #define FORMAT_8(STR,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8]
  882. // CONTROL(46) 12
  883. #define DISPLAY(A) (findDisplay A)
  884. #define CONTROL(A) DISPLAY(A) displayCtrl
  885. /* -------------------------------------------
  886. Macros: IS_x()
  887. Checking the data types of variables.
  888. IS_ARRAY() - Array
  889. IS_BOOL() - Boolean
  890. IS_BOOLEAN() - UI display handle(synonym for <IS_BOOL()>)
  891. IS_CODE() - Code block (i.e a compiled function)
  892. IS_CONFIG() - Configuration
  893. IS_CONTROL() - UI control handle.
  894. IS_DISPLAY() - UI display handle.
  895. IS_FUNCTION() - A compiled function (synonym for <IS_CODE()>)
  896. IS_GROUP() - Group.
  897. IS_INTEGER() - Is a number a whole number?
  898. IS_LOCATION() - World location.
  899. IS_NUMBER() - A floating point number (synonym for <IS_SCALAR()>)
  900. IS_OBJECT() - World object.
  901. IS_SCALAR() - Floating point number.
  902. IS_SCRIPT() - A script handle (as returned by execVM and spawn commands).
  903. IS_SIDE() - Game side.
  904. IS_STRING() - World object.
  905. IS_TEXT() - Structured text.
  906. Parameters:
  907. VARIABLE - Variable to check if it is of a particular type [Any, not nil]
  908. Author:
  909. Spooner
  910. ------------------------------------------- */
  911. #define IS_META_SYS(VAR,TYPE) (if (isNil {VAR}) then {false} else {(VAR) isEqualType TYPE})
  912. #define IS_ARRAY(VAR) IS_META_SYS(VAR,[])
  913. #define IS_BOOL(VAR) IS_META_SYS(VAR,false)
  914. #define IS_CODE(VAR) IS_META_SYS(VAR,{})
  915. #define IS_CONFIG(VAR) IS_META_SYS(VAR,configNull)
  916. #define IS_CONTROL(VAR) IS_META_SYS(VAR,controlNull)
  917. #define IS_DISPLAY(VAR) IS_META_SYS(VAR,displayNull)
  918. #define IS_GROUP(VAR) IS_META_SYS(VAR,grpNull)
  919. #define IS_OBJECT(VAR) IS_META_SYS(VAR,objNull)
  920. #define IS_SCALAR(VAR) IS_META_SYS(VAR,0)
  921. #define IS_SCRIPT(VAR) IS_META_SYS(VAR,scriptNull)
  922. #define IS_SIDE(VAR) IS_META_SYS(VAR,west)
  923. #define IS_STRING(VAR) IS_META_SYS(VAR,"STRING")
  924. #define IS_TEXT(VAR) IS_META_SYS(VAR,text "")
  925. #define IS_LOCATION(VAR) IS_META_SYS(VAR,locationNull)
  926. #define IS_BOOLEAN(VAR) IS_BOOL(VAR)
  927. #define IS_FUNCTION(VAR) IS_CODE(VAR)
  928. #define IS_INTEGER(VAR) (if (IS_SCALAR(VAR)) then {floor (VAR) == (VAR)} else {false})
  929. #define IS_NUMBER(VAR) IS_SCALAR(VAR)
  930. #define FLOAT_TO_STRING(num) (if (_this == 0) then {"0"} else {str parseNumber (str (_this % _this) + str floor abs _this) + "." + (str (abs _this - floor abs _this) select [2]) + "0"})
  931. /* -------------------------------------------
  932. Macro: SCRIPT()
  933. Sets name of script (relies on PREFIX and COMPONENT values being #defined).
  934. Define 'SKIP_SCRIPT_NAME' to skip adding scriptName.
  935. Parameters:
  936. NAME - Name of script [Indentifier]
  937. Example:
  938. (begin example)
  939. SCRIPT(eradicateMuppets);
  940. (end)
  941. Author:
  942. Spooner
  943. ------------------------------------------- */
  944. #ifndef SKIP_SCRIPT_NAME
  945. #define SCRIPT(NAME) scriptName 'PREFIX\COMPONENT\NAME'
  946. #else
  947. #define SCRIPT(NAME) /* nope */
  948. #endif
  949. /* -------------------------------------------
  950. Macros: EXPLODE_n()
  951. DEPRECATED - Use param/params commands added in Arma 3 1.48
  952. Splitting an ARRAY into a number of variables (A, B, C, etc).
  953. Note that this NOT does make the created variables private.
  954. _PVT variants do.
  955. EXPLODE_1(ARRAY,A,B) - Split a 1-element array into separate variable.
  956. EXPLODE_2(ARRAY,A,B) - Split a 2-element array into separate variables.
  957. EXPLODE_3(ARRAY,A,B,C) - Split a 3-element array into separate variables.
  958. EXPLODE_4(ARRAY,A,B,C,D) - Split a 4-element array into separate variables.
  959. EXPLODE_5(ARRAY,A,B,C,D,E) - Split a 5-element array into separate variables.
  960. EXPLODE_6(ARRAY,A,B,C,D,E,F) - Split a 6-element array into separate variables.
  961. EXPLODE_7(ARRAY,A,B,C,D,E,F,G) - Split a 7-element array into separate variables.
  962. EXPLODE_8(ARRAY,A,B,C,D,E,F,G,H) - Split a 8-element array into separate variables.
  963. EXPLODE_9(ARRAY,A,B,C,D,E,F,G,H,I) - Split a 9-element array into separate variables.
  964. Parameters:
  965. ARRAY - Array to read from [Array]
  966. A..H - Names of variables to set from array [Identifier]
  967. Example:
  968. (begin example)
  969. _array = ["fred", 156.8, 120.9];
  970. EXPLODE_3(_array,_name,_height,_weight);
  971. (end)
  972. Author:
  973. Spooner
  974. ------------------------------------------- */
  975. #define EXPLODE_1_SYS(ARRAY,A) A = ARRAY param [0]
  976. #define EXPLODE_1(ARRAY,A) EXPLODE_1_SYS(ARRAY,A); TRACE_1("EXPLODE_1, " + QUOTE(ARRAY),A)
  977. #define EXPLODE_1_PVT(ARRAY,A) ARRAY params [#A]; TRACE_1("EXPLODE_1, " + QUOTE(ARRAY),A)
  978. #define EXPLODE_2_SYS(ARRAY,A,B) EXPLODE_1_SYS(ARRAY,A); B = ARRAY param [1]
  979. #define EXPLODE_2(ARRAY,A,B) EXPLODE_2_SYS(ARRAY,A,B); TRACE_2("EXPLODE_2, " + QUOTE(ARRAY),A,B)
  980. #define EXPLODE_2_PVT(ARRAY,A,B) ARRAY params [#A,#B]; TRACE_2("EXPLODE_2, " + QUOTE(ARRAY),A,B)
  981. #define EXPLODE_3_SYS(ARRAY,A,B,C) EXPLODE_2_SYS(ARRAY,A,B); C = ARRAY param [2]
  982. #define EXPLODE_3(ARRAY,A,B,C) EXPLODE_3_SYS(ARRAY,A,B,C); TRACE_3("EXPLODE_3, " + QUOTE(ARRAY),A,B,C)
  983. #define EXPLODE_3_PVT(ARRAY,A,B,C) ARRAY params [#A,#B,#C]; TRACE_3("EXPLODE_3, " + QUOTE(ARRAY),A,B,C)
  984. #define EXPLODE_4_SYS(ARRAY,A,B,C,D) EXPLODE_3_SYS(ARRAY,A,B,C); D = ARRAY param [3]
  985. #define EXPLODE_4(ARRAY,A,B,C,D) EXPLODE_4_SYS(ARRAY,A,B,C,D); TRACE_4("EXPLODE_4, " + QUOTE(ARRAY),A,B,C,D)
  986. #define EXPLODE_4_PVT(ARRAY,A,B,C,D) ARRAY params [#A,#B,#C,#D]; TRACE_4("EXPLODE_4, " + QUOTE(ARRAY),A,B,C,D)
  987. #define EXPLODE_5_SYS(ARRAY,A,B,C,D,E) EXPLODE_4_SYS(ARRAY,A,B,C,D); E = ARRAY param [4]
  988. #define EXPLODE_5(ARRAY,A,B,C,D,E) EXPLODE_5_SYS(ARRAY,A,B,C,D,E); TRACE_5("EXPLODE_5, " + QUOTE(ARRAY),A,B,C,D,E)
  989. #define EXPLODE_5_PVT(ARRAY,A,B,C,D,E) ARRAY params [#A,#B,#C,#D,#E]; TRACE_5("EXPLODE_5, " + QUOTE(ARRAY),A,B,C,D,E)
  990. #define EXPLODE_6_SYS(ARRAY,A,B,C,D,E,F) EXPLODE_5_SYS(ARRAY,A,B,C,D,E); F = ARRAY param [5]
  991. #define EXPLODE_6(ARRAY,A,B,C,D,E,F) EXPLODE_6_SYS(ARRAY,A,B,C,D,E,F); TRACE_6("EXPLODE_6, " + QUOTE(ARRAY),A,B,C,D,E,F)
  992. #define EXPLODE_6_PVT(ARRAY,A,B,C,D,E,F) ARRAY params [#A,#B,#C,#D,#E,#F]; TRACE_6("EXPLODE_6, " + QUOTE(ARRAY),A,B,C,D,E,F)
  993. #define EXPLODE_7_SYS(ARRAY,A,B,C,D,E,F,G) EXPLODE_6_SYS(ARRAY,A,B,C,D,E,F); G = ARRAY param [6]
  994. #define EXPLODE_7(ARRAY,A,B,C,D,E,F,G) EXPLODE_7_SYS(ARRAY,A,B,C,D,E,F,G); TRACE_7("EXPLODE_7, " + QUOTE(ARRAY),A,B,C,D,E,F,G)
  995. #define EXPLODE_7_PVT(ARRAY,A,B,C,D,E,F,G) ARRAY params [#A,#B,#C,#D,#E,#F,#G]; TRACE_7("EXPLODE_7, " + QUOTE(ARRAY),A,B,C,D,E,F,G)
  996. #define EXPLODE_8_SYS(ARRAY,A,B,C,D,E,F,G,H) EXPLODE_7_SYS(ARRAY,A,B,C,D,E,F,G); H = ARRAY param [7]
  997. #define EXPLODE_8(ARRAY,A,B,C,D,E,F,G,H) EXPLODE_8_SYS(ARRAY,A,B,C,D,E,F,G,H); TRACE_8("EXPLODE_8, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H)
  998. #define EXPLODE_8_PVT(ARRAY,A,B,C,D,E,F,G,H) ARRAY params [#A,#B,#C,#D,#E,#F,#G,#H]; TRACE_8("EXPLODE_8, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H)
  999. #define EXPLODE_9_SYS(ARRAY,A,B,C,D,E,F,G,H,I) EXPLODE_8_SYS(ARRAY,A,B,C,D,E,F,G,H); I = ARRAY param [8]
  1000. #define EXPLODE_9(ARRAY,A,B,C,D,E,F,G,H,I) EXPLODE_9_SYS(ARRAY,A,B,C,D,E,F,G,H,I); TRACE_9("EXPLODE_9, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H,I)
  1001. #define EXPLODE_9_PVT(ARRAY,A,B,C,D,E,F,G,H,I) ARRAY params [#A,#B,#C,#D,#E,#F,#G,#H,#I]; TRACE_9("EXPLODE_9, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H,I)
  1002. /* -------------------------------------------
  1003. Macro: xSTRING()
  1004. Get full string identifier from a stringtable owned by this component.
  1005. Parameters:
  1006. VARIABLE - Partial name of global variable owned by this component [Any].
  1007. Example:
  1008. ADDON is CBA_Balls.
  1009. (begin example)
  1010. // Localized String (localize command must still be used with it)
  1011. LSTRING(Example); // STR_CBA_Balls_Example;
  1012. // Config String (note the $)
  1013. CSTRING(Example); // $STR_CBA_Balls_Example;
  1014. (end)
  1015. Author:
  1016. Jonpas
  1017. ------------------------------------------- */
  1018. #ifndef STRING_MACROS_GUARD
  1019. #define STRING_MACROS_GUARD
  1020. #define LSTRING(var1) QUOTE(TRIPLES(STR,ADDON,var1))
  1021. #define ELSTRING(var1,var2) QUOTE(TRIPLES(STR,DOUBLES(PREFIX,var1),var2))
  1022. #define CSTRING(var1) QUOTE(TRIPLES($STR,ADDON,var1))
  1023. #define ECSTRING(var1,var2) QUOTE(TRIPLES($STR,DOUBLES(PREFIX,var1),var2))
  1024. #define LLSTRING(var1) localize QUOTE(TRIPLES(STR,ADDON,var1))
  1025. #define LELSTRING(var1,var2) localize QUOTE(TRIPLES(STR,DOUBLES(PREFIX,var1),var2))
  1026. #endif
  1027. /* -------------------------------------------
  1028. Group: Managing Function Parameters
  1029. ------------------------------------------- */
  1030. /* -------------------------------------------
  1031. Macros: PARAMS_n()
  1032. DEPRECATED - Use param/params commands added in Arma 3 1.48
  1033. Setting variables based on parameters passed to a function.
  1034. Each parameter is defines as private and set to the appropriate value from _this.
  1035. PARAMS_1(A) - Get 1 parameter from the _this array (or _this if it's not an array).
  1036. PARAMS_2(A,B) - Get 2 parameters from the _this array.
  1037. PARAMS_3(A,B,C) - Get 3 parameters from the _this array.
  1038. PARAMS_4(A,B,C,D) - Get 4 parameters from the _this array.
  1039. PARAMS_5(A,B,C,D,E) - Get 5 parameters from the _this array.
  1040. PARAMS_6(A,B,C,D,E,F) - Get 6 parameters from the _this array.
  1041. PARAMS_7(A,B,C,D,E,F,G) - Get 7 parameters from the _this array.
  1042. PARAMS_8(A,B,C,D,E,F,G,H) - Get 8 parameters from the _this array.
  1043. Parameters:
  1044. A..H - Name of variable to read from _this [Identifier]
  1045. Example:
  1046. A function called like this:
  1047. (begin example)
  1048. [_name,_address,_telephone] call recordPersonalDetails;
  1049. (end)
  1050. expects 3 parameters and those variables could be initialised at the start of the function definition with:
  1051. (begin example)
  1052. recordPersonalDetails = {
  1053. PARAMS_3(_name,_address,_telephone);
  1054. // Rest of function follows...
  1055. };
  1056. (end)
  1057. Author:
  1058. Spooner
  1059. ------------------------------------------- */
  1060. #define PARAMS_1(A) EXPLODE_1_PVT(_this,A)
  1061. #define PARAMS_2(A,B) EXPLODE_2_PVT(_this,A,B)
  1062. #define PARAMS_3(A,B,C) EXPLODE_3_PVT(_this,A,B,C)
  1063. #define PARAMS_4(A,B,C,D) EXPLODE_4_PVT(_this,A,B,C,D)
  1064. #define PARAMS_5(A,B,C,D,E) EXPLODE_5_PVT(_this,A,B,C,D,E)
  1065. #define PARAMS_6(A,B,C,D,E,F) EXPLODE_6_PVT(_this,A,B,C,D,E,F)
  1066. #define PARAMS_7(A,B,C,D,E,F,G) EXPLODE_7_PVT(_this,A,B,C,D,E,F,G)
  1067. #define PARAMS_8(A,B,C,D,E,F,G,H) EXPLODE_8_PVT(_this,A,B,C,D,E,F,G,H)
  1068. #define PARAMS_9(A,B,C,D,E,F,G,H,I) EXPLODE_9_PVT(_this,A,B,C,D,E,F,G,H,I)
  1069. /* -------------------------------------------
  1070. Macro: DEFAULT_PARAM()
  1071. DEPRECATED - Use param/params commands added in Arma 3 1.48
  1072. Getting a default function parameter. This may be used together with <PARAMS_n()> to have a mix of required and
  1073. optional parameters.
  1074. Parameters:
  1075. INDEX - Index of parameter in _this [Integer, 0+]
  1076. NAME - Name of the variable to set [Identifier]
  1077. DEF_VALUE - Default value to use in case the array is too short or the value at INDEX is nil [Any]
  1078. Example:
  1079. A function called with optional parameters:
  1080. (begin example)
  1081. [_name] call myFunction;
  1082. [_name, _numberOfLegs] call myFunction;
  1083. [_name, _numberOfLegs, _hasAHead] call myFunction;
  1084. (end)
  1085. 1 required parameter and 2 optional parameters. Those variables could be initialised at the start of the function
  1086. definition with:
  1087. (begin example)
  1088. myFunction = {
  1089. PARAMS_1(_name);
  1090. DEFAULT_PARAM(1,_numberOfLegs,2);
  1091. DEFAULT_PARAM(2,_hasAHead,true);
  1092. // Rest of function follows...
  1093. };
  1094. (end)
  1095. Author:
  1096. Spooner
  1097. ------------------------------------------- */
  1098. #define DEFAULT_PARAM(INDEX,NAME,DEF_VALUE) \
  1099. private [#NAME,"_this"]; \
  1100. ISNILS(_this,[]); \
  1101. NAME = _this param [INDEX, DEF_VALUE]; \
  1102. TRACE_3("DEFAULT_PARAM",INDEX,NAME,DEF_VALUE)
  1103. /* -------------------------------------------
  1104. Macro: KEY_PARAM()
  1105. Get value from key in _this list, return default when key is not included in list.
  1106. Parameters:
  1107. KEY - Key name [String]
  1108. NAME - Name of the variable to set [Identifier]
  1109. DEF_VALUE - Default value to use in case key not found [ANY]
  1110. Example:
  1111. Author:
  1112. Muzzleflash
  1113. ------------------------------------------- */
  1114. #define KEY_PARAM(KEY,NAME,DEF_VALUE) \
  1115. private #NAME; \
  1116. NAME = [toLower KEY, toUpper KEY, DEF_VALUE, RETNIL(_this)] call CBA_fnc_getArg; \
  1117. TRACE_3("KEY_PARAM",KEY,NAME,DEF_VALUE)
  1118. /* -------------------------------------------
  1119. Group: Assertions
  1120. ------------------------------------------- */
  1121. #define ASSERTION_ERROR(MESSAGE) ERROR_WITH_TITLE("Assertion failed!",MESSAGE)
  1122. /* -------------------------------------------
  1123. Macro: ASSERT_TRUE()
  1124. Asserts that a CONDITION is true. When an assertion fails, an error is raised with the given MESSAGE.
  1125. Parameters:
  1126. CONDITION - Condition to assert as true [Boolean]
  1127. MESSSAGE - Message to display if (A OPERATOR B) is false [String]
  1128. Example:
  1129. (begin example)
  1130. ASSERT_TRUE(_frogIsDead,"The frog is alive");
  1131. (end)
  1132. Author:
  1133. Spooner
  1134. ------------------------------------------- */
  1135. #define ASSERT_TRUE(CONDITION,MESSAGE) \
  1136. if (not (CONDITION)) then \
  1137. { \
  1138. ASSERTION_ERROR('Assertion (CONDITION) failed!\n\n' + (MESSAGE)); \
  1139. }
  1140. /* -------------------------------------------
  1141. Macro: ASSERT_FALSE()
  1142. Asserts that a CONDITION is false. When an assertion fails, an error is raised with the given MESSAGE.
  1143. Parameters:
  1144. CONDITION - Condition to assert as false [Boolean]
  1145. MESSSAGE - Message to display if (A OPERATOR B) is true [String]
  1146. Example:
  1147. (begin example)
  1148. ASSERT_FALSE(_frogIsDead,"The frog died");
  1149. (end)
  1150. Author:
  1151. Spooner
  1152. ------------------------------------------- */
  1153. #define ASSERT_FALSE(CONDITION,MESSAGE) \
  1154. if (CONDITION) then \
  1155. { \
  1156. ASSERTION_ERROR('Assertion (not (CONDITION)) failed!\n\n' + (MESSAGE)) \
  1157. }
  1158. /* -------------------------------------------
  1159. Macro: ASSERT_OP()
  1160. Asserts that (A OPERATOR B) is true. When an assertion fails, an error is raised with the given MESSAGE.
  1161. Parameters:
  1162. A - First value [Any]
  1163. OPERATOR - Binary operator to use [Operator]
  1164. B - Second value [Any]
  1165. MESSSAGE - Message to display if (A OPERATOR B) is false. [String]
  1166. Example:
  1167. (begin example)
  1168. ASSERT_OP(_fish,>,5,"Too few fish!");
  1169. (end)
  1170. Author:
  1171. Spooner
  1172. ------------------------------------------- */
  1173. #define ASSERT_OP(A,OPERATOR,B,MESSAGE) \
  1174. if (not ((A) OPERATOR (B))) then \
  1175. { \
  1176. ASSERTION_ERROR('Assertion (A OPERATOR B) failed!\n' + 'A: ' + (str (A)) + '\n' + 'B: ' + (str (B)) + "\n\n" + (MESSAGE)); \
  1177. }
  1178. /* -------------------------------------------
  1179. Macro: ASSERT_DEFINED()
  1180. Asserts that a VARIABLE is defined. When an assertion fails, an error is raised with the given MESSAGE..
  1181. Parameters:
  1182. VARIABLE - Variable to test if defined [String or Function].
  1183. MESSAGE - Message to display if variable is undefined [String].
  1184. Examples:
  1185. (begin example)
  1186. ASSERT_DEFINED("_anUndefinedVar","Too few fish!");
  1187. ASSERT_DEFINED({ obj getVariable "anUndefinedVar" },"Too many fish!");
  1188. (end)
  1189. Author:
  1190. Spooner
  1191. ------------------------------------------- */
  1192. #define ASSERT_DEFINED(VARIABLE,MESSAGE) \
  1193. if (isNil VARIABLE) then \
  1194. { \
  1195. ASSERTION_ERROR('Assertion (VARIABLE is defined) failed!\n\n' + (MESSAGE)); \
  1196. }
  1197. /* -------------------------------------------
  1198. Group: Unit tests
  1199. ------------------------------------------- */
  1200. #define TEST_SUCCESS(MESSAGE) MESSAGE_WITH_TITLE("Test OK",MESSAGE)
  1201. #define TEST_FAIL(MESSAGE) ERROR_WITH_TITLE("Test FAIL",MESSAGE)
  1202. /* -------------------------------------------
  1203. Macro: TEST_TRUE()
  1204. Tests that a CONDITION is true.
  1205. If the condition is not true, an error is raised with the given MESSAGE.
  1206. Parameters:
  1207. CONDITION - Condition to assert as true [Boolean]
  1208. MESSSAGE - Message to display if (A OPERATOR B) is false [String]
  1209. Example:
  1210. (begin example)
  1211. TEST_TRUE(_frogIsDead,"The frog is alive");
  1212. (end)
  1213. Author:
  1214. Killswitch
  1215. ------------------------------------------- */
  1216. #define TEST_TRUE(CONDITION, MESSAGE) \
  1217. if (CONDITION) then \
  1218. { \
  1219. TEST_SUCCESS('(CONDITION)'); \
  1220. } \
  1221. else \
  1222. { \
  1223. TEST_FAIL('(CONDITION) ' + (MESSAGE)); \
  1224. }
  1225. /* -------------------------------------------
  1226. Macro: TEST_FALSE()
  1227. Tests that a CONDITION is false.
  1228. If the condition is not false, an error is raised with the given MESSAGE.
  1229. Parameters:
  1230. CONDITION - Condition to test as false [Boolean]
  1231. MESSSAGE - Message to display if (A OPERATOR B) is true [String]
  1232. Example:
  1233. (begin example)
  1234. TEST_FALSE(_frogIsDead,"The frog died");
  1235. (end)
  1236. Author:
  1237. Killswitch
  1238. ------------------------------------------- */
  1239. #define TEST_FALSE(CONDITION, MESSAGE) \
  1240. if (not (CONDITION)) then \
  1241. { \
  1242. TEST_SUCCESS('(not (CONDITION))'); \
  1243. } \
  1244. else \
  1245. { \
  1246. TEST_FAIL('(not (CONDITION)) ' + (MESSAGE)); \
  1247. }
  1248. /* -------------------------------------------
  1249. Macro: TEST_OP()
  1250. Tests that (A OPERATOR B) is true.
  1251. If the test fails, an error is raised with the given MESSAGE.
  1252. Parameters:
  1253. A - First value [Any]
  1254. OPERATOR - Binary operator to use [Operator]
  1255. B - Second value [Any]
  1256. MESSSAGE - Message to display if (A OPERATOR B) is false. [String]
  1257. Example:
  1258. (begin example)
  1259. TEST_OP(_fish,>,5,"Too few fish!");
  1260. (end)
  1261. Author:
  1262. Killswitch
  1263. ------------------------------------------- */
  1264. #define TEST_OP(A,OPERATOR,B,MESSAGE) \
  1265. if ((A) OPERATOR (B)) then \
  1266. { \
  1267. TEST_SUCCESS('(A OPERATOR B)') \
  1268. } \
  1269. else \
  1270. { \
  1271. TEST_FAIL('(A OPERATOR B)') \
  1272. };
  1273. /* -------------------------------------------
  1274. Macro: TEST_DEFINED_AND_OP()
  1275. Tests that A and B are defined and (A OPERATOR B) is true.
  1276. If the test fails, an error is raised with the given MESSAGE.
  1277. Parameters:
  1278. A - First value [Any]
  1279. OPERATOR - Binary operator to use [Operator]
  1280. B - Second value [Any]
  1281. MESSSAGE - Message to display [String]
  1282. Example:
  1283. (begin example)
  1284. TEST_OP(_fish,>,5,"Too few fish!");
  1285. (end)
  1286. Author:
  1287. Killswitch, PabstMirror
  1288. ------------------------------------------- */
  1289. #define TEST_DEFINED_AND_OP(A,OPERATOR,B,MESSAGE) \
  1290. if (isNil #A) then { \
  1291. TEST_FAIL('(A is not defined) ' + (MESSAGE)); \
  1292. } else { \
  1293. if (isNil #B) then { \
  1294. TEST_FAIL('(B is not defined) ' + (MESSAGE)); \
  1295. } else { \
  1296. if ((A) OPERATOR (B)) then { \
  1297. TEST_SUCCESS('(A OPERATOR B) ' + (MESSAGE)) \
  1298. } else { \
  1299. TEST_FAIL('(A OPERATOR B) ' + (MESSAGE)) \
  1300. }; }; };
  1301. /* -------------------------------------------
  1302. Macro: TEST_DEFINED()
  1303. Tests that a VARIABLE is defined.
  1304. Parameters:
  1305. VARIABLE - Variable to test if defined [String or Function].
  1306. MESSAGE - Message to display if variable is undefined [String].
  1307. Examples:
  1308. (begin example)
  1309. TEST_DEFINED("_anUndefinedVar","Too few fish!");
  1310. TEST_DEFINED({ obj getVariable "anUndefinedVar" },"Too many fish!");
  1311. (end)
  1312. Author:
  1313. Killswitch
  1314. ------------------------------------------- */
  1315. #define TEST_DEFINED(VARIABLE,MESSAGE) \
  1316. if (not isNil VARIABLE) then \
  1317. { \
  1318. TEST_SUCCESS('(' + VARIABLE + ' is defined)'); \
  1319. } \
  1320. else \
  1321. { \
  1322. TEST_FAIL('(' + VARIABLE + ' is not defined)' + (MESSAGE)); \
  1323. }
  1324. /* -------------------------------------------
  1325. Group: Managing Deprecation
  1326. ------------------------------------------- */
  1327. /* -------------------------------------------
  1328. Macro: DEPRECATE_SYS()
  1329. Allow deprecation of a function that has been renamed.
  1330. Replaces an old OLD_FUNCTION (which will have PREFIX_ prepended) with a NEW_FUNCTION
  1331. (PREFIX_ prepended) with the intention that the old function will be disabled in the future.
  1332. Shows a warning in RPT each time the deprecated function is used, but runs the new function.
  1333. Parameters:
  1334. OLD_FUNCTION - Full name of old function [Identifier for function that does not exist any more]
  1335. NEW_FUNCTION - Full name of new function [Function]
  1336. Example:
  1337. (begin example)
  1338. // After renaming CBA_fnc_frog as CBA_fnc_fish
  1339. DEPRECATE_SYS(CBA_fnc_frog,CBA_fnc_fish);
  1340. (end)
  1341. Author:
  1342. Sickboy
  1343. ------------------------------------------- */
  1344. #define DEPRECATE_SYS(OLD_FUNCTION,NEW_FUNCTION) \
  1345. OLD_FUNCTION = { \
  1346. WARNING('Deprecated function used: OLD_FUNCTION (new: NEW_FUNCTION) in ADDON'); \
  1347. if (isNil "_this") then { call NEW_FUNCTION } else { _this call NEW_FUNCTION }; \
  1348. }
  1349. /* -------------------------------------------
  1350. Macro: DEPRECATE()
  1351. Allow deprecation of a function, in the current component, that has been renamed.
  1352. Replaces an OLD_FUNCTION (which will have PREFIX_ prepended) with a NEW_FUNCTION
  1353. (PREFIX_ prepended) with the intention that the old function will be disabled in the future.
  1354. Shows a warning in RPT each time the deprecated function is used, but runs the new function.
  1355. Parameters:
  1356. OLD_FUNCTION - Name of old function, assuming PREFIX [Identifier for function that does not exist any more]
  1357. NEW_FUNCTION - Name of new function, assuming PREFIX [Function]
  1358. Example:
  1359. (begin example)
  1360. // After renaming CBA_fnc_frog as CBA_fnc_fish
  1361. DEPRECATE(fnc_frog,fnc_fish);
  1362. (end)
  1363. Author:
  1364. Sickboy
  1365. ------------------------------------------- */
  1366. #define DEPRECATE(OLD_FUNCTION,NEW_FUNCTION) \
  1367. DEPRECATE_SYS(DOUBLES(PREFIX,OLD_FUNCTION),DOUBLES(PREFIX,NEW_FUNCTION))
  1368. /* -------------------------------------------
  1369. Macro: OBSOLETE_SYS()
  1370. Replace a function that has become obsolete.
  1371. Replace an obsolete OLD_FUNCTION with a simple COMMAND_FUNCTION, with the intention that anyone
  1372. using the function should replace it with the simple command, since the function will be disabled in the future.
  1373. Shows a warning in RPT each time the deprecated function is used, and runs the command function.
  1374. Parameters:
  1375. OLD_FUNCTION - Full name of old function [Identifier for function that does not exist any more]
  1376. COMMAND_CODE - Code to replace the old function [Function]
  1377. Example:
  1378. (begin example)
  1379. // In Arma2, currentWeapon command made the CBA_fMyWeapon function obsolete:
  1380. OBSOLETE_SYS(CBA_fMyWeapon,{ currentWeapon player });
  1381. (end)
  1382. Author:
  1383. Spooner
  1384. ------------------------------------------- */
  1385. #define OBSOLETE_SYS(OLD_FUNCTION,COMMAND_CODE) \
  1386. OLD_FUNCTION = { \
  1387. WARNING('Obsolete function used: (use: OLD_FUNCTION) in ADDON'); \
  1388. if (isNil "_this") then { call COMMAND_CODE } else { _this call COMMAND_CODE }; \
  1389. }
  1390. /* -------------------------------------------
  1391. Macro: OBSOLETE()
  1392. Replace a function, in the current component, that has become obsolete.
  1393. Replace an obsolete OLD_FUNCTION (which will have PREFIX_ prepended) with a simple
  1394. COMMAND_CODE, with the intention that anyone using the function should replace it with the simple
  1395. command.
  1396. Shows a warning in RPT each time the deprecated function is used.
  1397. Parameters:
  1398. OLD_FUNCTION - Name of old function, assuming PREFIX [Identifier for function that does not exist any more]
  1399. COMMAND_CODE - Code to replace the old function [Function]
  1400. Example:
  1401. (begin example)
  1402. // In Arma2, currentWeapon command made the CBA_fMyWeapon function obsolete:
  1403. OBSOLETE(fMyWeapon,{ currentWeapon player });
  1404. (end)
  1405. Author:
  1406. Spooner
  1407. ------------------------------------------- */
  1408. #define OBSOLETE(OLD_FUNCTION,COMMAND_CODE) \
  1409. OBSOLETE_SYS(DOUBLES(PREFIX,OLD_FUNCTION),COMMAND_CODE)
  1410. #define BWC_CONFIG(NAME) class NAME { \
  1411. units[] = {}; \
  1412. weapons[] = {}; \
  1413. requiredVersion = REQUIRED_VERSION; \
  1414. requiredAddons[] = {}; \
  1415. version = VERSION; \
  1416. }
  1417. // XEH Specific
  1418. #define XEH_CLASS CBA_Extended_EventHandlers
  1419. #define XEH_CLASS_BASE DOUBLES(XEH_CLASS,base)
  1420. #define XEH_DISABLED class EventHandlers { class XEH_CLASS {}; }; SLX_XEH_DISABLED = 1
  1421. #define XEH_ENABLED class EventHandlers { class XEH_CLASS { EXTENDED_EVENTHANDLERS }; }; SLX_XEH_DISABLED = 0
  1422. // TODO: These are actually outdated; _Once ?
  1423. #define XEH_PRE_INIT QUOTE(call COMPILE_FILE(XEH_PreInit_Once))
  1424. #define XEH_PRE_CINIT QUOTE(call COMPILE_FILE(XEH_PreClientInit_Once))
  1425. #define XEH_PRE_SINIT QUOTE(call COMPILE_FILE(XEH_PreServerInit_Once))
  1426. #define XEH_POST_INIT QUOTE(call COMPILE_FILE(XEH_PostInit_Once))
  1427. #define XEH_POST_CINIT QUOTE(call COMPILE_FILE(XEH_PostClientInit_Once))
  1428. #define XEH_POST_SINIT QUOTE(call COMPILE_FILE(XEH_PostServerInit_Once))
  1429. /* -------------------------------------------
  1430. Macro: IS_ADMIN
  1431. Check if the local machine is an admin in the multiplayer environment.
  1432. Reports 'true' for logged and voted in admins.
  1433. Parameters:
  1434. None
  1435. Example:
  1436. (begin example)
  1437. // print "true" if player is admin
  1438. systemChat str IS_ADMIN;
  1439. (end)
  1440. Author:
  1441. commy2
  1442. ------------------------------------------- */
  1443. #define IS_ADMIN_SYS(x) x##kick
  1444. #define IS_ADMIN serverCommandAvailable 'IS_ADMIN_SYS(#)'
  1445. /* -------------------------------------------
  1446. Macro: IS_ADMIN_LOGGED
  1447. Check if the local machine is a logged in admin in the multiplayer environment.
  1448. Reports 'false' if the player was voted to be the admin.
  1449. Parameters:
  1450. None
  1451. Example:
  1452. (begin example)
  1453. // print "true" if player is admin and entered in the server password
  1454. systemChat str IS_ADMIN_LOGGED;
  1455. (end)
  1456. Author:
  1457. commy2
  1458. ------------------------------------------- */
  1459. #define IS_ADMIN_LOGGED_SYS(x) x##shutdown
  1460. #define IS_ADMIN_LOGGED serverCommandAvailable 'IS_ADMIN_LOGGED_SYS(#)'
  1461. /* -------------------------------------------
  1462. Macro: FILE_EXISTS
  1463. Check if a file exists on machines with interface
  1464. Reports "false" if the file does not exist and throws an error in RPT.
  1465. Parameters:
  1466. FILE - Path to the file
  1467. Example:
  1468. (begin example)
  1469. // print "true" if file exists
  1470. systemChat str FILE_EXISTS("\A3\ui_f\data\igui\cfg\cursors\weapon_ca.paa");
  1471. (end)
  1472. Author:
  1473. commy2
  1474. ------------------------------------------- */
  1475. #define FILE_EXISTS(FILE) (call {\
  1476. private _return = false;\
  1477. isNil {\
  1478. private _control = (uiNamespace getVariable ["RscDisplayMain", displayNull]) ctrlCreate ["RscHTML", -1];\
  1479. if (isNull _control) then {\
  1480. _return = loadFile (FILE) != "";\
  1481. } else {\
  1482. _control htmlLoad (FILE);\
  1483. _return = ctrlHTMLLoaded _control;\
  1484. ctrlDelete _control;\
  1485. };\
  1486. };\
  1487. _return\
  1488. })