fog.qc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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 float FORCE_SET_FOG = 1;
  16. void stuffcmd_digit( entity client, float f) =
  17. {
  18. float d;
  19. d = floor(f);
  20. d = mod(d, 10);
  21. if(d == 0)
  22. stuffcmd(client, "0");
  23. else if(d == 1)
  24. stuffcmd(client, "1");
  25. else if(d == 2)
  26. stuffcmd(client, "2");
  27. else if(d == 3)
  28. stuffcmd(client, "3");
  29. else if(d == 4)
  30. stuffcmd(client, "4");
  31. else if(d == 5)
  32. stuffcmd(client, "5");
  33. else if(d == 6)
  34. stuffcmd(client, "6");
  35. else if(d == 7)
  36. stuffcmd(client, "7");
  37. else if(d == 8)
  38. stuffcmd(client, "8");
  39. else if(d == 9)
  40. stuffcmd(client, "9");
  41. }
  42. void stuffcmd_int( entity client, float f, float numdigits) =
  43. {
  44. float tmp;
  45. if(f == 0){
  46. stuffcmd( client, "0");
  47. return;
  48. }
  49. if(f < 0){
  50. // Yeah sure.
  51. stuffcmd( client, "-");
  52. f = fabs(f);
  53. }
  54. if(numdigits <= 0){
  55. tmp = f;
  56. numdigits = 1;
  57. while(tmp >= 1){
  58. tmp = tmp / 10;
  59. numdigits = numdigits * 10;
  60. }
  61. }
  62. //I need to do this to get zero-padding to work.
  63. while( numdigits > 1 ){
  64. numdigits = numdigits / 10;
  65. tmp = f / numdigits;
  66. stuffcmd_digit( client, tmp);
  67. }
  68. }
  69. void stuffcmd_float( entity client, float f) =
  70. {
  71. float intpart, decpart, isNegative;
  72. isNegative = FALSE;
  73. if(f == 0){
  74. stuffcmd( client, "0");
  75. return;
  76. }
  77. if(f < 0){
  78. // easier this way
  79. isNegative = TRUE;
  80. f = fabs(f);
  81. }
  82. // 1: stuff the sign.
  83. if(isNegative)
  84. stuffcmd( client, "-");
  85. // 2: stuff the integer part.
  86. intpart = floor(f);
  87. stuffcmd_int( client, intpart, 0);
  88. // 3: stuff the decimal point.
  89. stuffcmd( client, ".");
  90. // 4: stuff the decimal part.
  91. decpart = mod( f, 1);
  92. decpart = decpart * 10000;
  93. stuffcmd_int( client, decpart, 10000);
  94. }
  95. .float fog_density;
  96. .vector fog_color;
  97. .entity fog_active_fog_trigger;
  98. .string fog_info_entity;
  99. void SetFog(entity client, float density, vector color, float transitionTime = 0)
  100. {
  101. client.fog_density = density;
  102. client.fog_color = color;
  103. stuffcmd(client, "\nfog ");
  104. stuffcmd_float(client, density);
  105. stuffcmd(client, " ");
  106. stuffcmd_float(client, color_x);
  107. stuffcmd(client, " ");
  108. stuffcmd_float(client, color_y);
  109. stuffcmd(client, " ");
  110. stuffcmd_float(client, color_z);
  111. if(transitionTime > 0)
  112. {
  113. stuffcmd(client, " ");
  114. stuffcmd_float(client, transitionTime);
  115. }
  116. stuffcmd(client, "\n");
  117. }
  118. entity GetFogInfoEntity(entity e, .string field = fog_info_entity)
  119. {
  120. if(e.field)
  121. {
  122. e = find(world, targetname, e.field);
  123. if(e.classname == "info_fog")
  124. {
  125. return e;
  126. }
  127. }
  128. return world;
  129. }
  130. float FogPushSettingsFrom(entity client, entity source, float transitionTime)
  131. {
  132. if(client.classname != "player") return FALSE;
  133. source = GetFogInfoEntity(source);
  134. if(!source) return FALSE;
  135. if(source.fog_density || source.fog_color || (source.spawnflags & FORCE_SET_FOG))
  136. {
  137. SetFog(client, source.fog_density, source.fog_color, transitionTime);
  138. return TRUE;
  139. }
  140. return FALSE;
  141. }
  142. //////////////////////////////////////////////////////////////////////////////////////////////////////
  143. /*QUAKED info_fog (0.5 .5 .8) (-8 -8 -8) (8 8 8)
  144. Fog value definition
  145. wait: fog density
  146. dest: fog color
  147. */
  148. void info_fog()
  149. {
  150. if(!self.fog_density) self.fog_density = 0.05;
  151. else if(self.fog_color_x > 1.0 || self.fog_color_y > 1.0 || self.fog_color_z > 1.0) //Not in 0..1 range?
  152. {
  153. self.fog_color = self.fog_color * (1.0 / 255);
  154. }
  155. }
  156. //////////////////////////////////////////////////////////////////////////////////////////////////////
  157. void trigger_fog_activate()
  158. {
  159. if(self == other.fog_active_fog_trigger) return;
  160. if (other.classname != "player") // Yoder add, 27/09/2020 to fix crash
  161. return;
  162. other.fog_active_fog_trigger = self;
  163. FogPushSettingsFrom(other, self, self.delay);
  164. }
  165. /*QUAKED trigger_fog (0.5 .5 .8) (? ? ?) (? ? ?)
  166. Trigger to transition fog
  167. fog_info_entity: info_fog that contains values this trigger should use.
  168. delay: time to fade the transition over
  169. */
  170. void trigger_fog()
  171. {
  172. // Fog is set on the server, so transitions and triggers work really bad in multiplayer.
  173. // Just remove ourself if we're in multiplayer.
  174. if(coop || deathmatch)
  175. {
  176. remove(self);
  177. return;
  178. }
  179. if(!self.delay) self.delay = 0.5;
  180. self.use = trigger_fog_activate;
  181. if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
  182. {
  183. self.touch = trigger_fog_activate;
  184. }
  185. InitTrigger ();
  186. }
  187. //////////////////////////////////////////////////////////////////////////////////////////////////////
  188. float trigger_fog_transition_touch_get_tween(entity pl)
  189. {
  190. vector t = pl.origin - self.mins;
  191. vector b = self.size;
  192. float tween;
  193. if(self.style == 0)
  194. {
  195. tween = t_x / b_x;
  196. }
  197. else if(self.style == 1)
  198. {
  199. tween = t_y / b_y;
  200. }
  201. else if(self.style == 2)
  202. {
  203. tween = t_z / b_z;
  204. }
  205. if(tween < 0) tween = 0;
  206. if(tween > 1) tween = 1;
  207. return tween;
  208. }
  209. void trigger_fog_transition_touch()
  210. {
  211. if(other.classname != "player") return;
  212. float tween = trigger_fog_transition_touch_get_tween(other);
  213. entity fog1 = GetFogInfoEntity(self);
  214. entity fog2 = GetFogInfoEntity(self, target);
  215. float density = ((1 - tween) * fog1.fog_density) + (tween * fog2.fog_density);
  216. vector color = ((1 - tween) * fog1.fog_color) + (tween * fog2.fog_color);
  217. SetFog(other, density, color);
  218. }
  219. /*QUAKED trigger_fog_transition (0.5 .5 .8) (? ? ?) (? ? ?)
  220. Trigger to transition fog between two sides.
  221. fog_info_entity: info_fog that contains values this trigger should use on the 'left' side.
  222. target: info_fog that contains values this trigger should use on the 'right' side.
  223. style: Which axis this trigger fades across. 0 = X, 1 = Y, 2 = Z
  224. */
  225. void trigger_fog_transition()
  226. {
  227. // Fog is set on the server, so transitions and triggers work really bad in multiplayer.
  228. // Just remove ourself if we're in multiplayer.
  229. if(coop || deathmatch)
  230. {
  231. remove(self);
  232. return;
  233. }
  234. if(self.style < 0 || self.style > 2)
  235. {
  236. objerror("Invalid style for trigger_fog_transition. Needs to be 0, 1 or 2.");
  237. }
  238. self.touch = trigger_fog_transition_touch;
  239. InitTrigger ();
  240. }