lights.qc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /* Copyright (C) 1996-2022 id Software LLC
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  13. See file, 'COPYING', for details.
  14. */
  15. const string LightStyles[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
  16. const float LightStyles_MAX = LightStyles.length - 1;
  17. const string LightStylesHalf[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"};
  18. const float LightStylesHalf_MAX = LightStylesHalf.length - 1;
  19. //============================================================================
  20. // No special functionality, just to hold dynamic shadowcasting lights for KEX
  21. const float DYNAMICLIGHT_NOT_IN_COOP = 1;
  22. void dynamiclight()
  23. {
  24. if(coop && self.spawnflags & DYNAMICLIGHT_NOT_IN_COOP)
  25. {
  26. remove(self);
  27. }
  28. }
  29. //============================================================================
  30. void InitLightStyles()
  31. {
  32. //
  33. // Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
  34. //
  35. // 0 normal
  36. lightstyle(0, "m");
  37. // 1 FLICKER (first variety)
  38. lightstyle(1, "mmnmmommommnonmmonqnmmo");
  39. // 2 SLOW STRONG PULSE
  40. lightstyle(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");
  41. // 3 CANDLE (first variety)
  42. lightstyle(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");
  43. // 4 FAST STROBE
  44. lightstyle(4, "ma");
  45. // 5 GENTLE PULSE 1
  46. lightstyle(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");
  47. // 6 FLICKER (second variety)
  48. lightstyle(6, "nmonqnmomnmomomno");
  49. // 7 CANDLE (second variety)
  50. lightstyle(7, "mmmaaaabcdefgmmmmaaaammmaamm");
  51. // 8 CANDLE (third variety)
  52. lightstyle(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");
  53. // 9 SLOW STROBE (fourth variety)
  54. lightstyle(9, "aaaaaaaazzzzzzzz");
  55. // 10 FLUORESCENT FLICKER
  56. lightstyle(10, "mmamammmmammamamaaamammma");
  57. // 11 SLOW PULSE NOT FADE TO BLACK
  58. lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
  59. // New styles under here if needed:
  60. // styles 32-62 are assigned by the light program for switchable lights
  61. // 63 testing
  62. lightstyle(63, "a");
  63. }
  64. //============================================================================
  65. string LightFractionToStyle(float frac)
  66. {
  67. if(frac <= 0) return LightStyles[0];
  68. if(frac >= 1) return LightStyles[LightStyles_MAX];
  69. frac*= LightStyles.length;
  70. frac = floor(frac);
  71. return LightStyles[frac];
  72. }
  73. string LightFractionToStyleHalf(float frac)
  74. {
  75. if(frac <= 0) return LightStylesHalf[0];
  76. if(frac >= 1) return LightStylesHalf[LightStylesHalf_MAX];
  77. frac*= LightStylesHalf.length;
  78. frac = floor(frac);
  79. return LightStylesHalf[frac];
  80. }
  81. enum : int
  82. {
  83. LightRampStateOff,
  84. LightRampStateFadeUp,
  85. LightRampStateOn,
  86. LightRampStateFadeDown
  87. };
  88. float LIGHTRAMP_FULLRANGE = 1;
  89. void target_lightramp_setlight(float style, float frac)
  90. {
  91. if(self.spawnflags & LIGHTRAMP_FULLRANGE)
  92. lightstyle(style, LightFractionToStyle(frac));
  93. else
  94. lightstyle(style, LightFractionToStyleHalf(frac));
  95. }
  96. void target_lightramp_tick(float dt)
  97. {
  98. float diff = dt * self.delay;
  99. switch(self.state)
  100. {
  101. case LightRampStateFadeDown:
  102. self.cnt-= diff;
  103. break;
  104. case LightRampStateFadeUp:
  105. self.cnt+= diff;
  106. break;
  107. }
  108. target_lightramp_setlight(self.owner.style, self.cnt);
  109. if(self.cnt >= 1)
  110. {
  111. self.cnt = 1;
  112. self.state = LightRampStateOn;
  113. RemoveFrameTickEntity(self);
  114. }
  115. if(self.cnt <= 0)
  116. {
  117. self.cnt = 0;
  118. self.state = LightRampStateOff;
  119. RemoveFrameTickEntity(self);
  120. }
  121. }
  122. void target_lightramp_use()
  123. {
  124. switch(self.state)
  125. {
  126. case LightRampStateFadeDown:
  127. self.state = LightRampStateFadeUp;
  128. return;
  129. case LightRampStateOff:
  130. self.state = LightRampStateFadeUp;
  131. RegisterFrameTickEntity(self);
  132. return;
  133. case LightRampStateOn:
  134. self.state = LightRampStateFadeDown;
  135. RegisterFrameTickEntity(self);
  136. return;
  137. case LightRampStateFadeUp:
  138. self.state = LightRampStateFadeDown;
  139. return;
  140. }
  141. }
  142. void target_lightramp_init()
  143. {
  144. self.think = SUB_Null;
  145. if(!self.target) objerror("\n\ntarget_lightramp with no target.\n\n");
  146. if(!self.targetname) objerror("\n\ntarget_lightramp with no targetname.\n\n");
  147. self.owner = find(world, targetname, self.target);
  148. if(!self.owner) objerror("\n\ntarget_lightramp with unmatched target.\n\n");
  149. if(self.owner.spawnflags & START_OFF)
  150. {
  151. self.state = LightRampStateOff;
  152. self.cnt = 0;
  153. }
  154. else
  155. {
  156. self.state = LightRampStateOn;
  157. self.cnt = 1;
  158. }
  159. self.use = target_lightramp_use;
  160. self.tick = target_lightramp_tick;
  161. }
  162. void target_lightramp()
  163. {
  164. if(!self.delay) self.delay = 1;
  165. self.delay = 1 / self.delay;
  166. self.think = target_lightramp_init;
  167. self.nextthink = time + 0.1;
  168. }
  169. //============================================================================
  170. const float LIGHT_TARGETNAME_IS_STYLE = 2;
  171. void() light_use =
  172. {
  173. if (self.spawnflags & START_OFF)
  174. {
  175. lightstyle(self.style, "m");
  176. self.spawnflags = self.spawnflags - START_OFF;
  177. }
  178. else
  179. {
  180. lightstyle(self.style, "a");
  181. self.spawnflags = self.spawnflags + START_OFF;
  182. }
  183. };
  184. /*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
  185. Non-displayed light.
  186. Default light value is 300
  187. Default style is 0
  188. If targeted, it will toggle between on or off.
  189. */
  190. void() light =
  191. {
  192. if (!self.targetname)
  193. { // inert light
  194. remove(self);
  195. return;
  196. }
  197. if (self.style >= 32)
  198. {
  199. if(self.spawnflags & LIGHT_TARGETNAME_IS_STYLE)
  200. {
  201. lightstyle(self.style, self.targetname);
  202. remove(self);
  203. return;
  204. }
  205. self.use = light_use;
  206. if (self.spawnflags & START_OFF)
  207. lightstyle(self.style, "a");
  208. else
  209. lightstyle(self.style, "m");
  210. }
  211. };
  212. /*QUAKED light_fluoro (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
  213. Non-displayed light.
  214. Default light value is 300
  215. Default style is 0
  216. If targeted, it will toggle between on or off.
  217. Makes steady fluorescent humming sound
  218. */
  219. void() light_fluoro =
  220. {
  221. if (self.style >= 32)
  222. {
  223. self.use = light_use;
  224. if (self.spawnflags & START_OFF)
  225. lightstyle(self.style, "a");
  226. else
  227. lightstyle(self.style, "m");
  228. }
  229. precache_sound ("ambience/fl_hum1.wav");
  230. ambientsound (self.origin, "ambience/fl_hum1.wav", 0.5, ATTN_STATIC);
  231. };
  232. /*QUAKED light_fluorospark (0 1 0) (-8 -8 -8) (8 8 8)
  233. Non-displayed light.
  234. Default light value is 300
  235. Default style is 10
  236. Makes sparking, broken fluorescent sound
  237. */
  238. void() light_fluorospark =
  239. {
  240. if (!self.style)
  241. self.style = 10;
  242. precache_sound ("ambience/buzz1.wav");
  243. ambientsound (self.origin, "ambience/buzz1.wav", 0.5, ATTN_STATIC);
  244. };
  245. /*QUAKED light_globe (0 1 0) (-8 -8 -8) (8 8 8)
  246. Sphere globe light.
  247. Default light value is 300
  248. Default style is 0
  249. */
  250. void() light_globe =
  251. {
  252. precache_model ("progs/s_light.spr");
  253. setmodel (self, "progs/s_light.spr");
  254. makestatic (self);
  255. };
  256. void() FireAmbient =
  257. {
  258. precache_sound ("ambience/fire1.wav");
  259. // attenuate fast
  260. ambientsound (self.origin, "ambience/fire1.wav", 0.5, ATTN_STATIC);
  261. };
  262. const float UPSIDEDOWN = 4;
  263. /*QUAKED light_torch_small_walltorch (0 .5 0) (-10 -10 -20) (10 10 20)
  264. Short wall torch
  265. Default light value is 200
  266. Default style is 0
  267. */
  268. void() light_torch_small_walltorch =
  269. {
  270. precache_model ("progs/flame.mdl");
  271. setmodel (self, "progs/flame.mdl");
  272. if (self.spawnflags & UPSIDEDOWN)
  273. self.angles = '180 0 0';
  274. FireAmbient ();
  275. makestatic (self);
  276. };
  277. /*QUAKED light_flame_large_yellow (0 1 0) (-10 -10 -12) (12 12 18)
  278. Large yellow flame ball
  279. */
  280. void() light_flame_large_yellow =
  281. {
  282. precache_model ("progs/flame2.mdl");
  283. setmodel (self, "progs/flame2.mdl");
  284. self.frame = 1;
  285. if (self.spawnflags & UPSIDEDOWN)
  286. self.angles = '180 0 0';
  287. FireAmbient ();
  288. makestatic (self);
  289. };
  290. /*QUAKED light_flame_small_yellow (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
  291. Small yellow flame ball
  292. */
  293. void() light_flame_small_yellow =
  294. {
  295. precache_model ("progs/flame2.mdl");
  296. setmodel (self, "progs/flame2.mdl");
  297. if (self.spawnflags & UPSIDEDOWN)
  298. self.angles = '180 0 0';
  299. FireAmbient ();
  300. makestatic (self);
  301. };
  302. /*QUAKED light_flame_small_white (0 1 0) (-10 -10 -40) (10 10 40) START_OFF
  303. Small white flame ball
  304. */
  305. void() light_flame_small_white =
  306. {
  307. precache_model ("progs/flame2.mdl");
  308. setmodel (self, "progs/flame2.mdl");
  309. if (self.spawnflags & UPSIDEDOWN)
  310. self.angles = '180 0 0';
  311. FireAmbient ();
  312. makestatic (self);
  313. };
  314. /*QUAKED light_flame_gas (0 1 0) (-10 -10 -40) (10 10 40) START_OFF
  315. Gas flare (spawns two entites)
  316. */
  317. void() light_flame_gas =
  318. {
  319. precache_model ("progs/flame3.mdl");
  320. setmodel (self, "progs/flame3.mdl");
  321. self.alpha = 0.6;
  322. entity s = spawn();
  323. setorigin(s, self.origin);
  324. setmodel (s, "progs/flame3.mdl");
  325. s.alpha = 0.4;
  326. s.frame = 1;
  327. };
  328. /*QUAKED light_candle (0 .5 0) (-4 -4 -10) (4 4 10)
  329. Candle
  330. Default light value is 200
  331. Default style is 0
  332. */
  333. void() light_candle =
  334. {
  335. precache_model ("progs/candle.mdl");
  336. setmodel (self, "progs/candle.mdl");
  337. makestatic (self);
  338. };