@@ -26,6 +26,11 @@ static xVec3 sPoint[5];
2626static F32 sSize [5 ];
2727
2828const char * lightning_type_names[4 ] = { " Line" , " Rotating" , " Zeus" , " Func" };
29+ #define LYT_TYPE_LINE 0
30+ #define LYT_TYPE_ROTATING 1
31+ #define LYT_TYPE_ZEUS 2
32+ #define LYT_TYPE_FUNC 3
33+
2934static zParEmitter* sSparkEmitter ;
3035static RwRaster* sLightningRaster ;
3136static F32 sLFuncJerkTime ;
@@ -192,6 +197,224 @@ void zLightningInit()
192197 xDebugAddTweak (" Lightning|Randomness|Rand Radius" , &gLightningTweakAddInfo .rand_radius , 0 .0f , 1000000000 .0f , NULL , NULL , 0x2 );
193198}
194199
200+ static zLightning* FindFreeLightning ()
201+ {
202+ for (int i = 0 ; i != (sizeof (sLightning ) / sizeof (zLightning*)); i++)
203+ {
204+ if (sLightning [i] != NULL )
205+ {
206+ if (!(sLightning [i]->flags & 1 ))
207+ {
208+ return sLightning [i];
209+ }
210+ }
211+ else
212+ {
213+ sLightning [i] = (zLightning*)xMemAlloc (gActiveHeap , 0x234 , 0 );
214+ return sLightning [i];
215+ }
216+ }
217+
218+ return 0 ;
219+ }
220+
221+ // FIXME: Logic is nearly perfect but there are some incorrect values used causing register mismatches
222+ // inside the loop logic, as well as incorrect r1 local offsets throughout
223+ zLightning* zLightningAdd (_tagLightningAdd* add)
224+ {
225+ zLightning* new_lightning;
226+ if (!(new_lightning = FindFreeLightning ()))
227+ {
228+ return NULL ;
229+ }
230+
231+ new_lightning->type = add->type ;
232+ new_lightning->flags = add->flags | 0x41 ;
233+ new_lightning->color = add->color ;
234+
235+ if (new_lightning->type != LYT_TYPE_FUNC)
236+ {
237+ new_lightning->legacy .total_points = add->total_points ;
238+ new_lightning->legacy .end_points = add->end_points ;
239+ new_lightning->legacy .arc_height = add->arc_height ;
240+ new_lightning->legacy .rand_radius = add->rand_radius ;
241+
242+ S32 zeusOnStraightPoint = TRUE ;
243+ F32 currot = 0 .0f ;
244+
245+ switch (new_lightning->type )
246+ {
247+ case LYT_TYPE_LINE:
248+ break ;
249+ case LYT_TYPE_ROTATING:
250+ new_lightning->legacy .rot .degrees = add->move_degrees ;
251+ new_lightning->legacy .rot .height = add->rot_radius ;
252+ break ;
253+ case LYT_TYPE_ZEUS:
254+ new_lightning->legacy .zeus .normal_offset = add->zeus_normal_offset ;
255+ new_lightning->legacy .zeus .back_offset = add->zeus_back_offset ;
256+ new_lightning->legacy .zeus .side_offset = add->zeus_side_offset ;
257+ break ;
258+ }
259+
260+ xVec3 dir;
261+ if (add->flags & 0x80 )
262+ {
263+ if (add->end_points - 1 < 0 )
264+ {
265+ xVec3Sub (&dir, &add->start [add->total_points - 1 ], add->start );
266+ }
267+ else
268+ {
269+ xVec3Sub (&dir, &add->end [add->end_points - 1 ], add->start );
270+ }
271+ }
272+ else
273+ {
274+ xVec3Sub (&dir, add->end , add->start );
275+ }
276+
277+ xVec3Normalize (&dir, &dir);
278+
279+ if (dir.y > 0 .999f || dir.y < -0 .999f )
280+ {
281+ xVec3Init (&new_lightning->legacy .arc_normal , 1 .0f , 0 .0f , 0 .0f );
282+ }
283+ else
284+ {
285+ new_lightning->legacy .arc_normal .x = -(dir.x * dir.y );
286+ new_lightning->legacy .arc_normal .y = dir.z * dir.z + dir.x * dir.x ;
287+ new_lightning->legacy .arc_normal .z = -(dir.z * dir.y );
288+ xVec3Normalize (&new_lightning->legacy .arc_normal , &new_lightning->legacy .arc_normal );
289+ }
290+
291+ xVec3 arc_orthogonal;
292+ xVec3Cross (&arc_orthogonal, &new_lightning->legacy .arc_normal , &dir);
293+
294+ F32 pos = 0 .0f ;
295+ F32 inc = 1 .0f / (new_lightning->legacy .total_points - 1 .0f );
296+
297+ S32 i;
298+ S32 j = 0 ;
299+ for (i = 0 ; i < new_lightning->legacy .total_points ; i++)
300+ {
301+
302+ new_lightning[i].legacy .thickness [0 ] = add->thickness * 0 .5f ;
303+
304+ if (add->flags & 0x400 )
305+ {
306+ new_lightning[i].legacy .thickness [0 ] *= 1 .0f - pos;
307+ }
308+
309+ if (add->flags & 0x800 )
310+ {
311+ new_lightning[i].legacy .thickness [0 ] *= pos;
312+ }
313+
314+ if ((add->flags & 0x400 ) && (add->flags & 0x800 ))
315+ {
316+ new_lightning[i].legacy .thickness [0 ] *= 4 .0f ;
317+ }
318+
319+ if (add->flags & 0x80 )
320+ {
321+ if (i - (add->total_points - add->end_points ) < 0 )
322+ {
323+ new_lightning[i].legacy .point [0 ] = add->start [j];
324+ }
325+ else
326+ {
327+ new_lightning[i].legacy .point [0 ] = add->end [i - (add->total_points - add->end_points )];
328+ }
329+ }
330+ else
331+ {
332+ xVec3Lerp (&new_lightning[i].legacy .point [0 ], add->start , add->end , pos);
333+ }
334+
335+ switch (new_lightning->type )
336+ {
337+ case LYT_TYPE_LINE:
338+ break ;
339+ case LYT_TYPE_ROTATING:
340+ new_lightning[i].legacy .rot .deg [0 ] = currot;
341+
342+ while (new_lightning[i].legacy .rot .deg [0 ] > 180 .0f )
343+ {
344+ new_lightning[i].legacy .rot .deg [0 ] -= 360 .0f ;
345+ }
346+
347+ while (new_lightning[i].legacy .rot .deg [0 ] < -180 .0f )
348+ {
349+ new_lightning[i].legacy .rot .deg [0 ] += 360 .0f ;
350+ }
351+
352+ currot += add->setup_degrees ;
353+ break ;
354+ case LYT_TYPE_ZEUS:
355+ if (i != 0 && i == new_lightning[i].legacy .total_points - 1 )
356+ {
357+ break ;
358+ }
359+
360+ xVec3 unk_r1_20;
361+ if (zeusOnStraightPoint)
362+ {
363+ xVec3Copy (&unk_r1_20, new_lightning[i].legacy .point );
364+ zeusOnStraightPoint = FALSE ;
365+ }
366+ else
367+ {
368+ xVec3Copy (new_lightning[i].legacy .point , &unk_r1_20);
369+ xVec3AddScaled (new_lightning->legacy .point , &new_lightning->legacy .arc_normal , new_lightning->legacy .zeus .normal_offset );
370+ xVec3AddScaled (new_lightning->legacy .point , &arc_orthogonal, -new_lightning->legacy .zeus .back_offset );
371+ xVec3AddScaled (new_lightning->legacy .point , &dir, -new_lightning->legacy .zeus .side_offset );
372+
373+ zeusOnStraightPoint = TRUE ;
374+ }
375+
376+ break ;
377+ }
378+
379+ if (new_lightning->flags & 0x20 )
380+ {
381+ F32 scalar = 4 .0f * pos + pos * pos * -4 .0f ;
382+ if (scalar > 0 .0f )
383+ {
384+ xVec3AddScaled (&new_lightning[j].legacy .base_point [0 ], &new_lightning->legacy .arc_normal , scalar * new_lightning->legacy .arc_height );
385+ }
386+ }
387+
388+ new_lightning->legacy .base_point [0 ] = new_lightning->legacy .point [0 ];
389+
390+ pos += inc;
391+ j++;
392+ }
393+ }
394+ else
395+ {
396+ zLightningModifyEndpoints (new_lightning, add->start , add->end );
397+
398+ new_lightning->func .endParam [0 ] = 10 .0f * xurand ();
399+ new_lightning->func .endParam [1 ] = 10 .0f * xurand ();
400+ new_lightning->func .endVel [0 ] = -1 .0f ;
401+ new_lightning->func .endVel [1 ] = 1 .0f ;
402+ new_lightning->func .width = add->thickness ;
403+ new_lightning->func .arc_height = add->arc_height ;
404+ }
405+
406+ if (new_lightning->flags & 0x10 )
407+ {
408+ new_lightning->time_left = new_lightning->time_total = 0 .1f ;
409+ }
410+ else
411+ {
412+ new_lightning->time_left = new_lightning->time_total = add->time ;
413+ }
414+
415+ return new_lightning;
416+ }
417+
195418static void lightningTweakStart (const tweak_info& t)
196419{
197420 xVec3 s, e;
@@ -296,24 +519,3 @@ void zLightningKill(zLightning* l)
296519{
297520 l->flags &= 0xfffffefe ;
298521}
299-
300- static zLightning* FindFreeLightning ()
301- {
302- for (int i = 0 ; i != (sizeof (sLightning ) / sizeof (zLightning*)); i++)
303- {
304- if (sLightning [i] != NULL )
305- {
306- if (!(sLightning [i]->flags & 1 ))
307- {
308- return sLightning [i];
309- }
310- }
311- else
312- {
313- sLightning [i] = (zLightning*)xMemAlloc (gActiveHeap , 0x234 , 0 );
314- return sLightning [i];
315- }
316- }
317-
318- return 0 ;
319- }
0 commit comments