FS2_Open
Open source remastering of the Freespace 2 engine
neblightning.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "debugconsole/console.h"
14 #include "freespace2/freespace.h"
15 #include "gamesnd/gamesnd.h"
16 #include "globalincs/linklist.h"
17 #include "io/timer.h"
18 #include "nebula/neb.h"
19 #include "nebula/neblightning.h"
20 #include "network/multi.h"
21 #include "network/multimsgs.h"
22 #include "parse/parselo.h"
23 #include "render/3d.h"
24 #include "weapon/emp.h"
25 
26 extern int Cmdline_nohtl;
27 
28 // ------------------------------------------------------------------------------------------------------
29 // NEBULA LIGHTNING DEFINES/VARS
30 //
31 
32 // Lightning nodes
33 int Num_lnodes = 0;
35 
38 
39 // nodes in a lightning bolt
40 #define LINK_LEFT 0
41 #define LINK_RIGHT 1
42 #define LINK_CHILD 2
43 
44 // Lightning bolts
45 int Num_lbolts = 0;
47 
48 // Lightning bolt types
50 
51 // Lightning storm types
53 
54 // points on the basic cross section
56  { { { -1.0f, 0.0f, 0.0f } } },
57  { { { 1.0f, 0.70f, 0.0f } } },
58  { { { 1.0f, -0.70f, 0.0f } } }
59 };
60 
61 // pinched off cross-section
63  { { { -0.05f, 0.0f, 0.0f } } },
64  { { { 0.05f, 0.035f, 0.0f } } },
65  { { { 0.05f, -0.035f, 0.0f } } }
66 };
67 
68 // globals used for rendering and generating bolts
69 int Nebl_flash_count = 0; // # of points rendered onscreen for this bolt
70 float Nebl_flash_x = 0.0f; // avg x of the points rendered
71 float Nebl_flash_y = 0.0f; // avg y of the points rendered
72 float Nebl_bang = 0.0; // distance to the viewer object
73 float Nebl_alpha = 0.0f; // alpha to use when rendering the bolt itself
74 float Nebl_glow_alpha = 0.0f; // alpha to use when rendering the bolt glow
75 int Nebl_stamp = -1; // random timestamp for making bolts
76 float Nebl_bolt_len; // length of the current bolt being generated
77 bolt_type *Nebl_type; // bolt type
78 matrix Nebl_bolt_dir; // orientation matrix of the bolt being generated
79 vec3d Nebl_bolt_start; // start point of the bolt being generated
80 vec3d Nebl_bolt_strike; // strike point of the bolt being generated
81 
82 // the type of active storm
83 storm_type *Storm = NULL;
84 
85 // vars
86 DCF(b_scale, "Sets the scale factor for debug nebula bolts")
87 {
88  dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_scale);
89 }
90 DCF(b_rand, "Sets the randomness factor for debug nebula bolts")
91 {
92  dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_rand);
93 }
94 DCF(b_shrink, "Sets the shrink factor for debug nebula bolts")
95 {
96  dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_shrink);
97 }
98 DCF(b_poly_pct, "Sets b_poly_pct")
99 {
100  dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_poly_pct);
101 }
102 DCF(b_add, "Sets b_add")
103 {
104  dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_add);
105 }
106 DCF(b_strikes, "Sets num_strikes")
107 {
108  dc_stuff_int(&Bolt_types[DEBUG_BOLT].num_strikes);
109 }
110 DCF(b_noise, "Sets noise factor")
111 {
112  dc_stuff_float(&Bolt_types[DEBUG_BOLT].noise);
113 }
114 DCF(b_bright, "Sets brightness factor")
115 {
116  dc_stuff_float(&Bolt_types[DEBUG_BOLT].b_bright);
117 }
118 DCF(b_lifetime, "Sets lifetime duration")
119 {
120  dc_stuff_int(&Bolt_types[DEBUG_BOLT].lifetime);
121 }
122 DCF(b_list, "Displays status of debug lightning commands")
123 {
124  dc_printf("Debug lightning bolt settings :\n");
125 
126  dc_printf("b_scale : %f\n", Bolt_types[DEBUG_BOLT].b_scale);
127  dc_printf("b_rand : %f\n", Bolt_types[DEBUG_BOLT].b_rand);
128  dc_printf("b_shrink : %f\n", Bolt_types[DEBUG_BOLT].b_shrink);
129  dc_printf("b_poly_pct : %f\n", Bolt_types[DEBUG_BOLT].b_poly_pct);
130  dc_printf("b_add : %f\n", Bolt_types[DEBUG_BOLT].b_add);
131  dc_printf("b_strikes : %d\n", Bolt_types[DEBUG_BOLT].num_strikes);
132  dc_printf("b_noise : %f\n", Bolt_types[DEBUG_BOLT].noise);
133  dc_printf("b_bright : %f\n", Bolt_types[DEBUG_BOLT].b_bright);
134  dc_printf("b_lifetime : %d\n", Bolt_types[DEBUG_BOLT].lifetime);
135 }
136 
137 // nebula lightning intensity (0.0 to 1.0)
138 float Nebl_intensity = 0.6667f;
139 
140 DCF(lightning_intensity, "Sets lightning intensity between 0.0 and 1.0 (Default is 0.6667)")
141 {
142  float val;
144 
145  CLAMP(val, 0.0f, 1.0f);
146 
147  Nebl_intensity = 1.0f - val;
148 }
149 
150 
151 // ------------------------------------------------------------------------------------------------------
152 // NEBULA LIGHTNING FUNCTIONS
153 //
154 
155 // initialize nebula lightning at game startup
156 void nebl_init()
157 {
158  char name[MAX_FILENAME_LEN];
159 
160  try
161  {
162  // parse the lightning table
163  read_file_text("lightning.tbl", CF_TYPE_TABLES);
164  reset_parse();
165 
166  // parse the individual lightning bolt types
167  required_string("#Bolts begin");
168  while (!optional_string("#Bolts end")){
169  bolt_type new_bolt_type;
170 
171  // bolt title
172  required_string("$Bolt:");
173  stuff_string(new_bolt_type.name, F_NAME, NAME_LENGTH);
174 
175  // b_scale
176  required_string("+b_scale:");
177  stuff_float(&new_bolt_type.b_scale);
178 
179  // b_shrink
180  required_string("+b_shrink:");
181  stuff_float(&new_bolt_type.b_shrink);
182 
183  // b_poly_pct
184  required_string("+b_poly_pct:");
185  stuff_float(&new_bolt_type.b_poly_pct);
186 
187  // child rand
188  required_string("+b_rand:");
189  stuff_float(&new_bolt_type.b_rand);
190 
191  // z add
192  required_string("+b_add:");
193  stuff_float(&new_bolt_type.b_add);
194 
195  // # strikes
196  required_string("+b_strikes:");
197  stuff_int(&new_bolt_type.num_strikes);
198 
199  // lifetime
200  required_string("+b_lifetime:");
201  stuff_int(&new_bolt_type.lifetime);
202 
203  // noise
204  required_string("+b_noise:");
205  stuff_float(&new_bolt_type.noise);
206 
207  // emp effect
208  required_string("+b_emp:");
209  stuff_float(&new_bolt_type.emp_intensity);
210  stuff_float(&new_bolt_type.emp_time);
211 
212  // texture
213  required_string("+b_texture:");
214  stuff_string(name, F_NAME, sizeof(name));
215  if (!Fred_running){
216  new_bolt_type.texture = bm_load(name);
217  }
218 
219  // glow
220  required_string("+b_glow:");
221  stuff_string(name, F_NAME, sizeof(name));
222  if (!Fred_running){
223  new_bolt_type.glow = bm_load(name);
224  }
225 
226  // brightness
227  required_string("+b_bright:");
228  stuff_float(&new_bolt_type.b_bright);
229 
230  Bolt_types.push_back(new_bolt_type);
231  }
232 
233  // parse lightning storm types
234  required_string("#Storms begin");
235  while (!optional_string("#Storms end")){
236  storm_type new_storm_type;
237 
238  // bolt title
239  required_string("$Storm:");
240  stuff_string(new_storm_type.name, F_NAME, NAME_LENGTH);
241 
242  // bolt types
243  while (optional_string("+bolt:")){
244  if (new_storm_type.num_bolt_types < MAX_BOLT_TYPES_PER_STORM){
245  stuff_string(name, F_NAME, sizeof(name));
246 
247  new_storm_type.bolt_types[new_storm_type.num_bolt_types] = nebl_get_bolt_index(name);
248  Assert(new_storm_type.bolt_types[new_storm_type.num_bolt_types] != (size_t)-1);
249 
250  new_storm_type.num_bolt_types++;
251  }
252  }
253 
254  // flavor
255  required_string("+flavor:");
256  stuff_float(&new_storm_type.flavor.xyz.x);
257  stuff_float(&new_storm_type.flavor.xyz.y);
258  stuff_float(&new_storm_type.flavor.xyz.z);
259 
260  // frequencies
261  required_string("+random_freq:");
262  stuff_int(&new_storm_type.min);
263  stuff_int(&new_storm_type.max);
264 
265  // counts
266  required_string("+random_count:");
267  stuff_int(&new_storm_type.min_count);
268  stuff_int(&new_storm_type.max_count);
269 
270  Storm_types.push_back(new_storm_type);
271  }
272  }
273  catch (const parse::ParseException& e)
274  {
275  mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "lightning.tbl", e.what()));
276  return;
277  }
278 }
279 
280 // initialize lightning before entering a level
282 {
283  size_t idx;
284 
285  // zero all lightning bolts
286  for(idx=0; idx<MAX_LIGHTNING_BOLTS; idx++){
287  Nebl_bolts[idx].head = NULL;
288  Nebl_bolts[idx].bolt_life = -1;
289  Nebl_bolts[idx].used = 0;
290  }
291 
292  // initialize node list
293  Num_lnodes = 0;
294  list_init( &Nebl_free_list );
295  list_init( &Nebl_used_list );
296 
297  // Link all object slots into the free list
298  for (idx=0; idx<MAX_LIGHTNING_NODES; idx++) {
299  list_append(&Nebl_free_list, &Nebl_nodes[idx] );
300  }
301 
302  // zero the random timestamp
303  Nebl_stamp = -1;
304 
305  // null the storm. let mission parsing set it up
306  Storm = NULL;
307 }
308 
309 // set the storm (call from mission parse)
310 void nebl_set_storm(char *name)
311 {
312  // sanity
313  Storm = NULL;
314 
315  size_t index = nebl_get_storm_index(name);
316 
317  if(index == (size_t)-1)
318  return;
319 
320  Storm = &Storm_types[index];
321 }
322 
323 // render all lightning bolts
325 {
326  l_bolt *b;
327  bolt_type *bi;
328 
329  // no lightning in non-nebula missions
331  return;
332  }
333 
334  // if we have no storm
335  if(Storm == NULL){
336  return;
337  }
338 
339  // traverse the list
340  for(size_t idx=0; idx<MAX_LIGHTNING_BOLTS; idx++){
341  b = &Nebl_bolts[idx];
342 
343  // if this is being used
344  if(b->used){
345  Assert(b->head != NULL);
346 
347  // bogus bolt
348  if(b->head == NULL){
349  b->used = 0;
350  continue;
351  }
352  if( b->type >= Bolt_types.size() ){
353  b->used = 0;
354  continue;
355  }
356  bi = &Bolt_types[b->type];
357 
358  // if this guy is still on a delay
359  if(b->delay != -1){
360  if(timestamp_elapsed(b->delay)){
361  b->delay = -1;
362  } else {
363  continue;
364  }
365  }
366 
367  // if the timestamp on this guy has expired
368  if((b->bolt_life < 0) || timestamp_elapsed(b->bolt_life)){
369  // if this is a multiple strike bolt, jitter it and reset
370  if(b->strikes_left-1 > 0){
371  b->bolt_life = timestamp(bi->lifetime / bi->num_strikes);
372  b->first_frame = 1;
373  b->strikes_left--;
374  nebl_jitter(b);
375 
376  // by continuing here we skip rendering for one frame, which makes it look more like real lightning
377  continue;
378  }
379  // otherwise he's completely done, so release him
380  else {
381  // maybe free up node data
382  if(b->head != NULL){
383  nebl_release(b->head);
384  b->head = NULL;
385 
386  Num_lbolts--;
387 
388  nprintf(("lightning", "Released bolt. %d used nodes!\n", Num_lnodes));
389  }
390 
391  b->used = 0;
392  }
393  }
394 
395  // pick some cool alpha values
396  Nebl_alpha = frand();
398 
399  // otherwise render him
400  Nebl_flash_count = 0;
401  Nebl_flash_x = 0.0f;
402  Nebl_flash_y = 0.0f;
403  Nebl_bang = 10000000.0f;
404  nebl_render(bi, b->head, b->width);
405 
406  // if this is the first frame he has been rendered, determine if we need to make a flash and sound effect
407  if(b->first_frame){
408  float flash = 0.0f;
409 
410  b->first_frame = 0;
411 
412  // if we rendered any points
413  if(Nebl_flash_count){
416 
417  // quick distance from the center of the screen
418  float x = Nebl_flash_x - (gr_screen.max_w / 2.0f);
419  float y = Nebl_flash_y - (gr_screen.max_h / 2.0f);
420  float dist = fl_sqrt((x * x) + (y * y));
421  if(dist / (gr_screen.max_w / 2.0f) < 1.0f){
422  flash = 1.0f - (dist / (gr_screen.max_w / 2.0f));
423 
424  // scale the flash by bolt type
425  flash *= bi->b_bright;
426 
427  game_flash(flash, flash, flash);
428  }
429 
430  // do some special stuff on the very first strike of the bolt
431  if(b->strikes_left == bi->num_strikes){
432  // play a sound
433  float bang;
434  if(Nebl_bang < 40.0f){
435  bang = 1.0f;
436  } else if(Nebl_bang > 400.0f){
437  bang = 0.0f;
438  } else {
439  bang = 1.0f - (Nebl_bang / 400.0f);
440  }
441  if(frand_range(0.0f, 1.0f) < 0.5f){
443  } else {
445  }
446 
447  // apply em pulse
448  if(bi->emp_intensity > 0.0f){
449  emp_apply(&b->midpoint, 0.0f, vm_vec_dist(&b->start, &b->strike), bi->emp_intensity, bi->emp_time);
450  }
451  }
452  }
453  }
454  }
455  }
456 }
457 
458 // process lightning (randomly generate bolts, etc, etc);
460 {
461  uint num_bolts, idx;
462 
463  // non-nebula mission
465  return;
466  }
467 
468  // non servers in multiplayer don't do this
470  return;
471  }
472 
473  // standalones shouldn't be doing this either
474  if (Is_standalone) {
475  return;
476  }
477 
478  // if there's no chosen storm
479  if(Storm == NULL){
480  return;
481  }
482 
483  // don't process lightning bolts unless we're a few seconds in
484  if(f2fl(Missiontime) < 3.0f){
485  return;
486  }
487 
488  // random stamp
489  if(Nebl_stamp == -1){
490  Nebl_stamp = timestamp((int)frand_range((float)Storm->min, (float)Storm->max));
491  return;
492  }
493 
494  // maybe make a bolt
496  // determine how many bolts to spew
497  num_bolts = (uint)frand_range((float)Storm->min_count, (float)Storm->max_count);
498  for(idx=0; idx<num_bolts; idx++){
499  // hmm. for now just pick a random bolt type and run with it
500  int s1, s2, s3;
501  int e1, e2, e3;
502  do {
503  s1 = (int)frand_range(0.0f, (float)Neb2_slices);
504  s2 = (int)frand_range(0.0f, (float)Neb2_slices);
505  s3 = (int)frand_range(0.0f, (float)Neb2_slices);
506 
507  e1 = (int)frand_range(0.0f, (float)Neb2_slices);
508  e2 = (int)frand_range(0.0f, (float)Neb2_slices);
509  e3 = (int)frand_range(0.0f, (float)Neb2_slices);
510 
511  // never choose the middle cube
512  if((s1 == 2) && (s2 == 2) && (s3 == 2)){
513  s1 = 4;
514  s2 = 0;
515  }
516  if((e1 == 2) && (e2 == 2) && (e3 == 2)){
517  e1 = 0;
518  e2 = 4;
519  }
520 
521  // sanity
522  } while((s1 == e1) && (s2 == e2) && (s3 == e3));
523 
524  vec3d start = Neb2_cubes[s1][s2][s3].pt;
525  vec3d strike = Neb2_cubes[e1][e2][e3].pt;
526 
527  // add some flavor to the bolt. mmmmmmmm, lightning
528  if(!IS_VEC_NULL_SQ_SAFE(&Storm->flavor)){
529  // start with your basic hot sauce. measure how much you have
530  vec3d your_basic_hot_sauce;
531  vm_vec_sub(&your_basic_hot_sauce, &strike, &start);
532  float how_much_hot_sauce = vm_vec_normalize(&your_basic_hot_sauce);
533 
534  // now figure out how much of that good wing sauce to add
535  vec3d wing_sauce = Storm->flavor;
536  if(frand_range(0.0, 1.0f) < 0.5f){
537  vm_vec_scale(&wing_sauce, -1.0f);
538  }
539  float how_much_of_that_good_wing_sauce_to_add = vm_vec_normalize(&wing_sauce);
540 
541  // mix the two together, taking care not to add too much
542  vec3d the_mixture;
543  if(how_much_of_that_good_wing_sauce_to_add > 1000.0f){
544  how_much_of_that_good_wing_sauce_to_add = 1000.0f;
545  }
546  vm_vec_interp_constant(&the_mixture, &your_basic_hot_sauce, &wing_sauce, how_much_of_that_good_wing_sauce_to_add / 1000.0f);
547 
548  // take the final sauce and store it in the proper container
549  vm_vec_scale(&the_mixture, how_much_hot_sauce);
550 
551  // make sure to put it on everything! whee!
552  vm_vec_add(&strike, &start, &the_mixture);
553  }
554 
555  size_t type = (size_t)frand_range(0.0f, (float)(Storm->num_bolt_types-1));
556  nebl_bolt(Storm->bolt_types[type], &start, &strike);
557  }
558 
559  // reset the timestamp
560  Nebl_stamp = timestamp((int)frand_range((float)Storm->min, (float)Storm->max));
561  }
562 }
563 
564 // create a lightning bolt
565 void nebl_bolt(size_t type, vec3d *start, vec3d *strike)
566 {
567  vec3d dir;
568  l_bolt *bolt;
569  l_node *tail;
570  size_t idx;
571  bool found;
572  bolt_type *bi;
573  float bolt_len;
574 
576  return;
577  }
578 
579  // find a free bolt
580  found = 0;
581  for(idx=0; idx<MAX_LIGHTNING_BOLTS; idx++){
582  if(!Nebl_bolts[idx].used){
583  found = 1;
584  break;
585  }
586  }
587  if(!found){
588  return;
589  }
590 
591  if( type >= Bolt_types.size() ){
592  return;
593  }
594  bi = &Bolt_types[type];
595 
596  // get a pointer to the bolt
597  bolt = &Nebl_bolts[idx];
598 
599  // setup bolt into
600  bolt->start = *start;
601  bolt->strike = *strike;
602  bolt->strikes_left = bi->num_strikes;
603  bolt->delay = -1;
604  bolt->type = (char)type;
605  bolt->first_frame = 1;
606  bolt->bolt_life = timestamp(bi->lifetime / bi->num_strikes);
607 
608  Nebl_bolt_start = *start;
609  Nebl_bolt_strike = *strike;
610 
611  // setup fire delay
612  if(bolt->delay != -1){
613  bolt->delay = timestamp(bolt->delay);
614  }
615 
616  // setup the rest of the important bolt data
617  if(vm_vec_same(&Nebl_bolt_start, &Nebl_bolt_strike)){
618  Nebl_bolt_strike.xyz.z += 150.0f;
619  }
620  Nebl_bolt_len = vm_vec_dist(&Nebl_bolt_start, &Nebl_bolt_strike);
621  vm_vec_sub(&dir, &Nebl_bolt_strike, &Nebl_bolt_start);
622 
623  // setup midpoint
624  vm_vec_scale_add(&bolt->midpoint, &Nebl_bolt_start, &dir, 0.5f);
625 
626  bolt_len = vm_vec_normalize(&dir);
627  vm_vector_2_matrix(&Nebl_bolt_dir, &dir, NULL, NULL);
628 
629  // global type for generating the bolt
630  Nebl_type = bi;
631 
632  // try and make the bolt
633  if(!nebl_gen(&Nebl_bolt_start, &Nebl_bolt_strike, 0, 4, 0, &bolt->head, &tail)){
634  if(bolt->head != NULL){
635  nebl_release(bolt->head);
636  }
637 
638  return;
639  }
640 
641  Num_lbolts++;
642 
643  // setup the rest of the data
644  bolt->used = 1;
645  bolt->width = bi->b_poly_pct * bolt_len;
646 
647  // if i'm a multiplayer master, send a bolt packet
648  if(MULTIPLAYER_MASTER){
649  send_lightning_packet(type, start, strike);
650  }
651 }
652 
653 // get the current # of active lightning bolts
655 {
656  return Num_lbolts;
657 }
658 
659 // get the current # of active nodes
661 {
662  return Num_lnodes;
663 }
664 
665 // "new" a lightning node
667 {
668  l_node *lp;
669 
670  // if we're out of nodes
672  nprintf(("lightning", "Out of lightning nodes!\n"));
673  return NULL;
674  }
675 
676  // get a new node off the freelist
677  lp = GET_FIRST(&Nebl_free_list);
678  Assert( lp != &Nebl_free_list ); // shouldn't have the dummy element
679 
680  // remove trailp from the free list
681  list_remove( &Nebl_free_list, lp );
682 
683  // insert trailp onto the end of used list
684  list_append( &Nebl_used_list, lp );
685 
686  // increment counter
687  Num_lnodes++;
688 
689  lp->links[0] = NULL;
690  lp->links[1] = NULL;
691  lp->links[2] = NULL;
692 
693  // return the pointer
694  return lp;
695 }
696 
697 // "delete" a lightning node
699 {
700  // remove objp from the used list
701  list_remove( &Nebl_used_list, lp );
702 
703  // add objp to the end of the free
704  list_append( &Nebl_free_list, lp );
705 
706  // decrement counter
707  Num_lnodes--;
708 }
709 
710 // free a lightning bolt
711 void nebl_release(l_node *whee)
712 {
713  // if we're invalid
714  if(whee == NULL){
715  return;
716  }
717 
718  // release all of our children
719  if(whee->links[LINK_RIGHT] != NULL){
720  nebl_release(whee->links[LINK_RIGHT]);
721  }
722  if(whee->links[LINK_CHILD] != NULL){
723  nebl_release(whee->links[LINK_CHILD]);
724  }
725 
726  // delete this node
727  nebl_delete(whee);
728 }
729 
730 int nebl_gen(vec3d *left, vec3d *right, float depth, float max_depth, int child, l_node **l_left, l_node **l_right)
731 {
732  l_node *child_node = NULL;
733  float d = vm_vec_dist_quick( left, right );
734 
735  // if we've reached the critical point
736  if ( d < 0.30f || (depth > max_depth) ){
737  // generate ne items
738  l_node *new_left = nebl_new();
739  if(new_left == NULL){
740  return 0;
741  }
742  new_left->links[0] = NULL; new_left->links[1] = NULL; new_left->links[2] = NULL;
743  new_left->pos = vmd_zero_vector;
744  l_node *new_right = nebl_new();
745  if(new_right == NULL){
746  nebl_delete(new_left);
747  return 0;
748  }
749  new_right->links[0] = NULL; new_right->links[1] = NULL; new_right->links[2] = NULL;
750  new_right->pos = vmd_zero_vector;
751 
752  // left side
753  new_left->pos = *left;
754  new_left->links[LINK_RIGHT] = new_right;
755  *l_left = new_left;
756 
757  // right side
758  new_right->pos = *right;
759  new_right->links[LINK_LEFT] = new_left;
760  *l_right = new_right;
761 
762  // done
763  return 1;
764  }
765 
766  // divide in half
767  vec3d tmp;
768  vm_vec_avg( &tmp, left, right );
769 
770  // sometimes generate children
771  if(!child && (frand() <= Nebl_type->b_rand)){
772  // get a point on the plane of the strike
773  vec3d tmp2;
774  vm_vec_random_in_circle(&tmp2, &Nebl_bolt_strike, &Nebl_bolt_dir, Nebl_bolt_len * Nebl_type->b_scale, 0);
775 
776  // maybe move away from the plane
777  vec3d dir;
778  vm_vec_sub(&dir, &tmp2, &tmp);
779  vm_vec_scale_add(&tmp2, &tmp, &dir, Nebl_type->b_shrink);
780 
781  // child
782  l_node *argh;
783  if(!nebl_gen(&tmp, &tmp2, 0, 2, 1, &child_node, &argh)){
784  if(child_node != NULL){
785  nebl_release(child_node);
786  }
787  return 0;
788  }
789  }
790 
791  float scaler = 0.30f;
792  tmp.xyz.x += (frand()-0.5f)*d*scaler;
793  tmp.xyz.y += (frand()-0.5f)*d*scaler;
794  tmp.xyz.z += (frand()-0.5f)*d*scaler;
795 
796  // generate left half
797  l_node *ll = NULL;
798  l_node *lr = NULL;
799  if(!nebl_gen( left, &tmp, depth+1, max_depth, child, &ll, &lr )){
800  if(child_node != NULL){
801  nebl_release(child_node);
802  }
803  if(ll != NULL){
804  nebl_release(ll);
805  }
806  return 0;
807  }
808 
809  // generate right half
810  l_node *rl = NULL;
811  l_node *rr = NULL;
812  if(!nebl_gen( &tmp, right, depth+1, max_depth, child, &rl, &rr )){
813  if(child_node != NULL){
814  nebl_release(child_node);
815  }
816  if(ll != NULL){
817  nebl_release(ll);
818  }
819  if(rl != NULL){
820  nebl_release(rl);
821  }
822  return 0;
823  }
824 
825  // splice the two together
826  lr->links[LINK_RIGHT] = rl->links[LINK_RIGHT];
827  lr->links[LINK_RIGHT]->links[LINK_LEFT] = lr;
828  nebl_delete(rl);
829 
830  // if we generated a child, stick him on
831  if(child_node != NULL){
832  lr->links[LINK_CHILD] = child_node;
833  }
834 
835  // return these
836  *l_left = ll;
837  *l_right = rr;
838 
839  return 1;
840 }
841 
842 
843 // output top and bottom vectors
844 // fvec == forward vector (eye viewpoint basically. in world coords)
845 // pos == world coordinate of the point we're calculating "around"
846 // w == width of the diff between top and bottom around pos
847 void nebl_calc_facing_pts_smart( vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, float w, float z_add )
848 {
849  vec3d uvec, rvec;
850  vec3d temp;
851 
852  temp = *pos;
853 
854  vm_vec_sub( &rvec, &Eye_position, &temp );
855  vm_vec_normalize( &rvec );
856 
857  vm_vec_cross(&uvec,fvec,&rvec);
858  vm_vec_normalize(&uvec);
859 
860  vm_vec_scale_add( top, &temp, &uvec, w/2.0f );
861  vm_vec_scale_add( bot, &temp, &uvec, -w/2.0f );
862 
863  vm_vec_scale_add2( top, &rvec, z_add );
864  vm_vec_scale_add2( bot, &rvec, z_add );
865 }
866 
867 // render a section of the bolt
869 {
870  vertex v[4];
871  vertex *verts[4] = {&v[0], &v[1], &v[2], &v[3]};
872 
873  // Sets mode. Returns previous mode.
875 
876  // draw some stuff
877  for(size_t idx=0; idx<2; idx++){
878  v[0] = a->vex[idx];
879  v[0].texture_position.u = 0.0f; v[0].texture_position.v = 0.0f;
880 
881  v[1] = a->vex[idx+1];
882  v[1].texture_position.u = 1.0f; v[1].texture_position.v = 0.0f;
883 
884  v[2] = b->vex[idx+1];
885  v[2].texture_position.u = 1.0f; v[2].texture_position.v = 1.0f;
886 
887  v[3] = b->vex[idx];
888  v[3].texture_position.u = 0.0f; v[3].texture_position.v = 1.0f;
889 
890  // draw
893  }
894 
895  // draw
896  v[0] = a->vex[2];
897  v[0].texture_position.u = 0.0f; v[0].texture_position.v = 0.0f;
898 
899  v[1] = a->vex[0];
900  v[1].texture_position.u = 1.0f; v[1].texture_position.v = 0.0f;
901 
902  v[2] = b->vex[0];
903  v[2].texture_position.u = 1.0f; v[2].texture_position.v = 1.0f;
904 
905  v[3] = b->vex[2];
906  v[3].texture_position.u = 0.0f; v[3].texture_position.v = 1.0f;
907 
910 
911  // draw the glow beam
912  verts[0] = &a->glow_vex[0];
913  verts[0]->texture_position.v = 0.0f; verts[0]->texture_position.u = 0.0f;
914 
915  verts[1] = &a->glow_vex[1];
916  verts[1]->texture_position.v = 1.0f; verts[1]->texture_position.u = 0.0f;
917 
918  verts[2] = &b->glow_vex[1];
919  verts[2]->texture_position.v = 1.0f; verts[2]->texture_position.u = 1.0f;
920 
921  verts[3] = &b->glow_vex[0];
922  verts[3]->texture_position.v = 0.0f; verts[3]->texture_position.u = 1.0f;
923 
926 }
927 
928 // generate a section
929 void nebl_generate_section(bolt_type *bi, float width, l_node *a, l_node *b, l_section *c, l_section *cap, int pinch_a, int pinch_b)
930 {
931  vec3d dir;
932  vec3d dir_normal;
933  matrix m;
934  size_t idx;
935  vec3d temp, pt;
936  vec3d glow_a, glow_b;
937  vertex tempv;
938 
939  // direction matrix
940  vm_vec_sub(&dir, &a->pos, &b->pos);
941  vm_vec_copy_normalize(&dir_normal, &dir);
942  vm_vector_2_matrix(&m, &dir_normal, NULL, NULL);
943 
944  // distance to player
945  float bang_dist = vm_vec_dist_quick(&Eye_position, &a->pos);
946  if(bang_dist < Nebl_bang){
947  Nebl_bang = bang_dist;
948  }
949 
950  // rotate the basic section into world
951  for(idx=0; idx<3; idx++){
952  memset(&tempv, 0, sizeof(tempv));
953 
954  // rotate to world
955  if(pinch_a){
956  vm_vec_rotate(&pt, &Nebl_ring_pinched[idx], &m);
957  } else {
958  vm_vec_copy_scale(&temp, &Nebl_ring[idx], width);
959  vm_vec_rotate(&pt, &temp, &m);
960  }
961  vm_vec_add2(&pt, &a->pos);
962 
963  g3_transfer_vertex(&c->vex[idx], &pt);
964  g3_rotate_vertex(&tempv, &pt);
965  g3_project_vertex(&tempv);
966 
967  // if first frame, keep track of the average screen pos
968  if (tempv.codes == 0) {
969  Nebl_flash_x += tempv.screen.xyw.x;
970  Nebl_flash_y += tempv.screen.xyw.y;
972  }
973 
974  if (Cmdline_nohtl) {
975  memcpy(&c->vex[idx], &tempv, sizeof(vertex));
976  }
977  }
978  // calculate the glow points
979  nebl_calc_facing_pts_smart(&glow_a, &glow_b, &dir_normal, &a->pos, pinch_a ? 0.5f : width * 6.0f, Nebl_type->b_add);
980  if (Cmdline_nohtl) {
981  g3_rotate_vertex(&c->glow_vex[0], &glow_a);
982  g3_rotate_vertex(&c->glow_vex[1], &glow_b);
983  } else {
984  g3_transfer_vertex(&c->glow_vex[0], &glow_a);
985  g3_transfer_vertex(&c->glow_vex[1], &glow_b);
986  }
987 
988  // maybe do a cap
989  if(cap != NULL){
990  // rotate the basic section into world
991  for(idx=0; idx<3; idx++){
992  // rotate to world
993  if(pinch_b){
994  vm_vec_rotate(&pt, &Nebl_ring_pinched[idx], &m);
995  } else {
996  vm_vec_copy_scale(&temp, &Nebl_ring[idx], width);
997  vm_vec_rotate(&pt, &temp, &m);
998  }
999  vm_vec_add2(&pt, &b->pos);
1000 
1001  g3_transfer_vertex(&cap->vex[idx], &pt);
1002  g3_rotate_vertex(&tempv, &pt);
1003  g3_project_vertex(&tempv);
1004 
1005  // if first frame, keep track of the average screen pos
1006  if (tempv.codes == 0) {
1007  Nebl_flash_x += tempv.screen.xyw.x;
1008  Nebl_flash_y += tempv.screen.xyw.y;
1009  Nebl_flash_count++;
1010  }
1011 
1012  if (Cmdline_nohtl) {
1013  memcpy(&cap->vex[idx], &tempv, sizeof(vertex));
1014  }
1015  }
1016 
1017  // calculate the glow points
1018  nebl_calc_facing_pts_smart(&glow_a, &glow_b, &dir_normal, &b->pos, pinch_b ? 0.5f : width * 6.0f, bi->b_add);
1019  if (Cmdline_nohtl) {
1020  g3_rotate_vertex(&cap->glow_vex[0], &glow_a);
1021  g3_rotate_vertex(&cap->glow_vex[1], &glow_b);
1022  } else {
1023  g3_transfer_vertex(&cap->glow_vex[0], &glow_a);
1024  g3_transfer_vertex(&cap->glow_vex[1], &glow_b);
1025  }
1026  }
1027 }
1028 
1029 // render the bolt
1030 void nebl_render(bolt_type *bi, l_node *whee, float width, l_section *prev)
1031 {
1032  l_section start;
1033  l_section end;
1034  l_section child_start;
1035 
1036  // bad
1037  if(whee == NULL){
1038  return;
1039  }
1040 
1041  // if prev is NULL, we're just starting so we need our start point
1042  if(prev == NULL){
1043  Assert(whee->links[LINK_RIGHT] != NULL);
1044  nebl_generate_section(bi, width, whee, whee->links[LINK_RIGHT], &start, NULL, 1, 0);
1045  } else {
1046  start = *prev;
1047  }
1048 
1049  // if we have a child section
1050  if(whee->links[LINK_CHILD]){
1051  // generate section
1052  nebl_generate_section(bi, width * 0.5f, whee, whee->links[LINK_CHILD], &child_start, &end, 0, whee->links[LINK_CHILD]->links[LINK_RIGHT] == NULL ? 1 : 0);
1053 
1054  // render
1055  nebl_render_section(bi, &child_start, &end);
1056 
1057  // maybe continue
1058  if(whee->links[LINK_CHILD]->links[LINK_RIGHT] != NULL){
1059  nebl_render(bi, whee->links[LINK_CHILD], width * 0.5f, &end);
1060  }
1061  }
1062 
1063  // if the next section is an end section
1064  if(whee->links[LINK_RIGHT]->links[LINK_RIGHT] == NULL){
1065  l_section temp;
1066 
1067  // generate section
1068  nebl_generate_section(bi, width, whee, whee->links[LINK_RIGHT], &temp, &end, 0, 1);
1069 
1070  // render the section
1071  nebl_render_section(bi, &start, &end);
1072  }
1073  // a middle section
1074  else if(whee->links[LINK_RIGHT]->links[LINK_RIGHT] != NULL){
1075  // generate section
1076  nebl_generate_section(bi, width, whee->links[LINK_RIGHT], whee->links[LINK_RIGHT]->links[LINK_RIGHT], &end, NULL, 0, 0);
1077 
1078  // render the section
1079  nebl_render_section(bi, &start, &end);
1080 
1081  // recurse through him
1082  nebl_render(bi, whee->links[LINK_RIGHT], width, &end);
1083  }
1084 }
1085 
1086 // given a valid, complete bolt, jitter him based upon his noise
1088 {
1089  matrix m;
1090  vec3d temp;
1091  float length;
1092  l_node *moveup;
1093  bolt_type *bi = NULL;
1094 
1095  // sanity
1096  if(b == NULL){
1097  return;
1098  }
1099  if( b->type >= Bolt_types.size() ){
1100  return;
1101  }
1102  bi = &Bolt_types[b->type];
1103 
1104  // get the bolt direction
1105  vm_vec_sub(&temp, &b->strike, &b->start);
1106  length = vm_vec_normalize_quick(&temp);
1107  vm_vector_2_matrix(&m, &temp, NULL, NULL);
1108 
1109  // jitter all nodes on the main trunk
1110  moveup = b->head;
1111  while(moveup != NULL){
1112  temp = moveup->pos;
1113  vm_vec_random_in_circle(&moveup->pos, &temp, &m, frand_range(0.0f, length * bi->noise), 0);
1114 
1115  // just on the main trunk
1116  moveup = moveup->links[LINK_RIGHT];
1117  }
1118 }
1119 
1120 // return the index of a given bolt type by name
1122 {
1123  for(size_t idx=0; idx<Bolt_types.size(); idx++){
1124  if(!strcmp(name, Bolt_types[idx].name)){
1125  return idx;
1126  }
1127  }
1128 
1129  return (size_t)-1;
1130 }
1131 
1132 // return the index of a given storm type by name
1134 {
1135  if (name == NULL)
1136  return (size_t)-1;
1137 
1138  for(size_t idx=0; idx<Storm_types.size(); idx++){
1139  if(!strcmp(name, Storm_types[idx].name)){
1140  return idx;
1141  }
1142  }
1143 
1144  return (size_t)-1;
1145 }
float b_bright
Definition: neblightning.h:76
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
void game_flash(float r, float g, float b)
Definition: fredstubs.cpp:40
#define gr_zbuffer_set
Definition: 2d.h:817
int timestamp(int delta_ms)
Definition: timer.cpp:226
struct screen3d::@234::@236 xyw
fix Missiontime
Definition: systemvars.cpp:19
float width
Definition: neblightning.h:47
l_node * head
Definition: neblightning.h:37
int nebl_get_active_bolts()
int Game_mode
Definition: systemvars.cpp:24
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
#define MISSION_FLAG_FULLNEB
Definition: missionparse.h:70
float frand_range(float min, float max)
Return a floating point number in the range min..max.
Definition: floating.cpp:50
vec3d Nebl_bolt_strike
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
float v
Definition: pstypes.h:135
l_node Nebl_used_list
GLuint index
Definition: Glext.h:5608
l_node * links[3]
Definition: neblightning.h:30
int Fred_running
Definition: fred.cpp:44
ubyte g3_transfer_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:84
float vm_vec_normalize_quick(vec3d *src)
Definition: vecmat.cpp:529
Assert(pm!=NULL)
int nebl_get_active_nodes()
Definition: pstypes.h:88
#define mprintf(args)
Definition: pstypes.h:238
dc_stuff_float & val
GLint GLint GLsizei GLsizei GLsizei depth
Definition: Glext.h:5180
vec3d Nebl_ring_pinched[3]
#define GR_ZBUFF_FULL
Definition: 2d.h:675
struct vec3d::@225::@227 xyz
int nebl_gen(vec3d *left, vec3d *right, float depth, float max_depth, int child, l_node **l_left, l_node **l_right)
#define TMAP_HTL_3D_UNLIT
Definition: tmapper.h:63
GLclampf f
Definition: Glext.h:7097
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
#define f2fl(fx)
Definition: floating.h:37
size_t bolt_types[MAX_BOLT_TYPES_PER_STORM]
Definition: neblightning.h:83
cube_poof Neb2_cubes[MAX_CPTS][MAX_CPTS][MAX_CPTS]
Definition: neb.cpp:165
#define MAX_LIGHTNING_NODES
Definition: neblightning.h:22
void vm_vec_scale_add2(vec3d *dest, const vec3d *src, float k)
Definition: vecmat.cpp:284
float Nebl_bang
float emp_intensity
Definition: neblightning.h:70
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
float b_shrink
Definition: neblightning.h:61
void nebl_init()
int strikes_left
Definition: neblightning.h:46
void nebl_bolt(size_t type, vec3d *start, vec3d *strike)
GLenum type
Definition: Gl.h:1492
void stuff_float(float *f)
Definition: parselo.cpp:2328
#define IS_VEC_NULL_SQ_SAFE(v)
Definition: vecmat.h:24
GLint GLsizei width
Definition: Gl.h:1505
matrix Nebl_bolt_dir
#define SND_PRIORITY_DOUBLE_INSTANCE
Definition: sound.h:28
#define DEBUG_BOLT
Definition: neblightning.h:25
#define LINK_LEFT
uv_pair texture_position
Definition: pstypes.h:174
vec3d start
Definition: neblightning.h:44
SCP_vector< bolt_type > Bolt_types
int lifetime
Definition: neblightning.h:67
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
matrix * vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
Definition: vecmat.cpp:850
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
#define GR_ALPHABLEND_FILTER
Definition: 2d.h:349
float Nebl_alpha
vec3d strike
Definition: neblightning.h:44
unsigned int uint
Definition: pstypes.h:64
screen3d screen
Definition: pstypes.h:173
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
float noise
Definition: neblightning.h:66
void nebl_process()
#define nprintf(args)
Definition: pstypes.h:239
#define GM_MULTIPLAYER
Definition: systemvars.h:18
char name[NAME_LENGTH]
Definition: neblightning.h:81
int delay
Definition: neblightning.h:45
void nebl_jitter(l_bolt *b)
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
DCF(b_scale,"Sets the scale factor for debug nebula bolts")
void nebl_release(l_node *whee)
void stuff_string(char *outstr, int type, int len, char *terminators)
Definition: parselo.cpp:1189
#define CF_TYPE_TABLES
Definition: cfile.h:50
vec3d Nebl_bolt_start
SCP_vector< storm_type > Storm_types
void nebl_render(bolt_type *bi, l_node *whee, float width, l_section *prev)
Thunder 1 sound in neblua.
Definition: gamesnd.h:253
ubyte used
Definition: neblightning.h:39
ubyte g3_rotate_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:97
int required_string(const char *pstr)
Definition: parselo.cpp:468
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
int Num_lnodes
float Nebl_glow_alpha
float u
Definition: pstypes.h:135
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:355
int optional_string(const char *pstr)
Definition: parselo.cpp:539
ubyte first_frame
Definition: neblightning.h:40
Thunder 2 sound in neblua.
Definition: gamesnd.h:254
vec3d pos
Definition: neblightning.h:29
float b_poly_pct
Definition: neblightning.h:62
vec3d Nebl_ring[3]
CLAMP(val, 0.0f, 1.0f)
int Nebl_flash_count
void emp_apply(vec3d *pos, float inner_radius, float outer_radius, float emp_intensity, float emp_time, bool use_emp_time_for_capship_turrets)
Definition: emp.cpp:103
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
Definition: parselo.cpp:1995
size_t nebl_get_storm_index(char *name)
vertex glow_vex[2]
Definition: neblightning.h:53
int g3_project_vertex(vertex *point)
Definition: 3dmath.cpp:202
int idx
Definition: multiui.cpp:761
int Neb2_slices
Definition: neb.cpp:163
void nebl_level_init()
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
int bolt_life
Definition: neblightning.h:38
int Nebl_stamp
void vm_vec_interp_constant(vec3d *out, const vec3d *v0, const vec3d *v1, float t)
Definition: vecmat.cpp:2401
GLenum cap
Definition: Glext.h:9110
int max_w
Definition: 2d.h:360
vertex vex[3]
Definition: neblightning.h:52
l_node Nebl_free_list
GLuint start
Definition: Gl.h:1502
void vm_vec_copy_scale(vec3d *dest, const vec3d *src, float s)
Definition: vecmat.cpp:257
storm_type * Storm
#define TMAP_FLAG_CORRECT
Definition: tmapper.h:37
void dc_stuff_float(float *f)
Stuffs a float to the given variable.
void vm_vec_random_in_circle(vec3d *out, const vec3d *in, const matrix *orient, float radius, int on_edge)
Definition: vecmat.cpp:2481
float Nebl_bolt_len
void reset_parse(char *text)
Definition: parselo.cpp:3305
void dc_stuff_int(int *i)
Stuffs an int to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats...
GLuint const GLchar * name
Definition: Glext.h:5608
#define MAX_BOLT_TYPES_PER_STORM
Definition: neblightning.h:24
GLdouble GLdouble right
Definition: Glext.h:10330
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
vec3d Eye_position
Definition: 3dsetup.cpp:27
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
void nebl_generate_section(bolt_type *bi, float width, l_node *a, l_node *b, l_section *c, l_section *cap, int pinch_a, int pinch_b)
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
void stuff_int(int *i)
Definition: parselo.cpp:2372
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
#define LINK_RIGHT
ubyte num_bolt_types
Definition: neblightning.h:82
int vm_vec_same(const vec3d *v1, const vec3d *v2)
Definition: vecmat.cpp:1526
void nebl_render_all()
int Cmdline_nohtl
Definition: cmdline.cpp:438
void nebl_render_section(bolt_type *bi, l_section *a, l_section *b)
float vm_vec_dist_quick(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:417
#define NAME_LENGTH
Definition: globals.h:15
float frand()
Return random value in range 0.0..1.0- (1.0- means the closest number less than 1.0)
Definition: floating.cpp:35
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
l_node * nebl_new()
vec3d pt
Definition: neb.h:64
vec3d midpoint
Definition: neblightning.h:44
screen gr_screen
Definition: 2d.cpp:46
float b_rand
Definition: neblightning.h:64
size_t type
Definition: neblightning.h:41
float vm_vec_copy_normalize(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:427
#define fl_sqrt(fl)
Definition: floating.h:29
#define MULTIPLAYER_MASTER
Definition: multi.h:130
#define F_NAME
Definition: parselo.h:34
An overhauled/updated debug console to allow monitoring, testing, and general debugging of new featur...
int num_strikes
Definition: neblightning.h:68
int max_h
Definition: 2d.h:360
vec3d * vm_vec_avg(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:217
#define TMAP_FLAG_TEXTURED
Definition: tmapper.h:36
float Nebl_flash_x
#define timestamp_elapsed(stamp)
Definition: timer.h:102
#define LINK_CHILD
float b_add
Definition: neblightning.h:63
hull_check pos
Definition: lua.cpp:5050
void nebl_delete(l_node *lp)
const GLfloat * m
Definition: Glext.h:10319
GLenum GLuint GLenum GLsizei length
Definition: Glext.h:5156
#define GR_BITBLT_MODE_NORMAL
Definition: 2d.h:351
size_t nebl_get_bolt_index(char *name)
int temp
Definition: lua.cpp:4996
void dc_printf(const char *format,...)
Prints the given char string to the debug console.
Definition: console.cpp:358
void nebl_calc_facing_pts_smart(vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, float w, float z_add)
l_node Nebl_nodes[MAX_LIGHTNING_NODES]
float b_scale
Definition: neblightning.h:60
float Nebl_intensity
ubyte codes
Definition: pstypes.h:177
vec3d * vm_vec_cross(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:645
#define MAX_LIGHTNING_BOLTS
Definition: neblightning.h:23
mission The_mission
vec3d flavor
Definition: neblightning.h:84
int g3_draw_poly(int nv, vertex **pointlist, uint tmap_flags)
Definition: 3ddraw.cpp:207
int Num_lbolts
char name[NAME_LENGTH]
Definition: neblightning.h:58
float emp_time
Definition: neblightning.h:71
vec3d vmd_zero_vector
Definition: vecmat.cpp:24
GLdouble GLdouble GLdouble GLdouble top
Definition: Glext.h:10330
l_bolt Nebl_bolts[MAX_LIGHTNING_BOLTS]
bolt_type * Nebl_type
void vm_vec_add(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:159
const GLdouble * v
Definition: Glext.h:5322
float Nebl_flash_y
const GLubyte * c
Definition: Glext.h:8376
void send_lightning_packet(int bolt_type_internal, vec3d *start, vec3d *strike)
Definition: multimsgs.cpp:8474
void nebl_set_storm(char *name)
GLuint GLuint end
Definition: Gl.h:1502
GLint y
Definition: Gl.h:1505
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460
int Is_standalone
Definition: systemvars.cpp:59
GLint left
Definition: Glext.h:7283