mirror of
https://github.com/thug1src/thug.git
synced 2025-01-21 21:33:46 +00:00
947 lines
28 KiB
C++
947 lines
28 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// NxParticle.cpp
|
||
|
|
||
|
#include <core/defines.h>
|
||
|
#include <core/singleton.h>
|
||
|
#include <core/math.h>
|
||
|
#include <gfx/NxParticle.h>
|
||
|
#include <gel/scripting/struct.h>
|
||
|
#include <gel/scripting/script.h>
|
||
|
#include <sk/modules/frontend/frontend.h>
|
||
|
#include <gel/components/suspendcomponent.h>
|
||
|
#include <gfx/nx.h>
|
||
|
#include <gfx/debuggfx.h>
|
||
|
#include <sys/replay/replay.h>
|
||
|
|
||
|
#define next_random() ((((float)rand() / RAND_MAX ) * 2.0f ) - 1.0f)
|
||
|
|
||
|
//NsVector pright;
|
||
|
//NsVector pup;
|
||
|
//NsVector pat;
|
||
|
|
||
|
namespace Nx
|
||
|
{
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CParticle::plat_render( void )
|
||
|
{
|
||
|
printf ("STUB: plat_render\n");
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CParticle::plat_get_position( int entry, int list, float * x, float * y, float * z )
|
||
|
{
|
||
|
printf ("STUB: plat_get_position\n");
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CParticle::plat_set_position( int entry, int list, float x, float y, float z )
|
||
|
{
|
||
|
printf ("STUB: plat_set_position\n");
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CParticle::plat_add_position( int entry, int list, float x, float y, float z )
|
||
|
{
|
||
|
printf ("STUB: plat_add_position\n");
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CParticle::plat_set_active( bool active )
|
||
|
{
|
||
|
// PS2 & Gamecube do nothing here.
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CParticle::plat_build_path( void )
|
||
|
{
|
||
|
printf ("STUB: plat_build_path\n");
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
int CParticle::plat_get_num_particle_colors( void ) { printf ("STUB: plat_get_num_particle_colors\n"); return 0; };
|
||
|
int CParticle::plat_get_num_vertex_lists( void ) { printf ("STUB: plat_get_num_vertex_lists\n"); return 0; };
|
||
|
void CParticle::plat_set_sr( int entry, uint8 value ) { printf ("STUB: plat_set_sr\n"); }
|
||
|
void CParticle::plat_set_sg( int entry, uint8 value ) { printf ("STUB: plat_set_sg\n"); }
|
||
|
void CParticle::plat_set_sb( int entry, uint8 value ) { printf ("STUB: plat_set_sb\n"); }
|
||
|
void CParticle::plat_set_sa( int entry, uint8 value ) { printf ("STUB: plat_set_sa\n"); }
|
||
|
void CParticle::plat_set_mr( int entry, uint8 value ) { printf ("STUB: plat_set_mr\n"); }
|
||
|
void CParticle::plat_set_mg( int entry, uint8 value ) { printf ("STUB: plat_set_mg\n"); }
|
||
|
void CParticle::plat_set_mb( int entry, uint8 value ) { printf ("STUB: plat_set_mb\n"); }
|
||
|
void CParticle::plat_set_ma( int entry, uint8 value ) { printf ("STUB: plat_set_ma\n"); }
|
||
|
void CParticle::plat_set_er( int entry, uint8 value ) { printf ("STUB: plat_set_er\n"); }
|
||
|
void CParticle::plat_set_eg( int entry, uint8 value ) { printf ("STUB: plat_set_eg\n"); }
|
||
|
void CParticle::plat_set_eb( int entry, uint8 value ) { printf ("STUB: plat_set_eb\n"); }
|
||
|
void CParticle::plat_set_ea( int entry, uint8 value ) { printf ("STUB: plat_set_ea\n"); }
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CParticleEntry::CParticleEntry()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CParticleEntry::~CParticleEntry()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
void CParticle::set_defaults( void )
|
||
|
{
|
||
|
#define px 0x800 //0x4a1;
|
||
|
#define py 0x90 //-0x117; //0xfffffee9;
|
||
|
#define pz -0x3a0 //0xb96;
|
||
|
|
||
|
mp_emit_script = NULL;
|
||
|
mp_update_script = NULL;
|
||
|
mp_params = NULL;
|
||
|
m_life_set = false;
|
||
|
m_end_set = false;
|
||
|
|
||
|
|
||
|
// Temp: Set up some debug values.
|
||
|
m_pos[X] = px;
|
||
|
m_pos[Y] = py;
|
||
|
m_pos[Z] = pz;
|
||
|
|
||
|
m_sw = 2.0f;
|
||
|
m_sh = 2.0f;
|
||
|
m_ew = 2.0f;
|
||
|
m_eh = 2.0f;
|
||
|
|
||
|
m_life_min = 2.0f;
|
||
|
m_life_max = 2.0f;
|
||
|
|
||
|
m_emit_w = 1.0f; //16.0f;
|
||
|
m_emit_h = 1.0f; //16.0f;
|
||
|
m_emit_angle_spread = 0.5f; //0.5f;
|
||
|
|
||
|
m_fx = 0.0f;
|
||
|
m_fy = -0.02f;
|
||
|
m_fz = 0.0f;
|
||
|
|
||
|
m_tx = 0.0f; // Default target: straight up.
|
||
|
m_ty = 1.0f;
|
||
|
m_tz = 0.0f;
|
||
|
|
||
|
m_ax = 0.0f; // Default angles: No rotation.
|
||
|
m_ay = 0.0f;
|
||
|
m_az = 0.0f;
|
||
|
|
||
|
m_speed_min = 1.0f;
|
||
|
m_speed_max = 2.0f;
|
||
|
|
||
|
m_random_angle = false;
|
||
|
m_circular_emit = true;
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CParticle::CParticle()
|
||
|
{
|
||
|
set_defaults();
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CParticle::CParticle( uint32 checksum )
|
||
|
{
|
||
|
set_defaults();
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CParticle::CParticle( uint32 checksum, int maxParticles )
|
||
|
{
|
||
|
set_defaults();
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
CParticle::~CParticle()
|
||
|
{
|
||
|
if ( mp_emit_script )
|
||
|
{
|
||
|
delete mp_emit_script;
|
||
|
}
|
||
|
if ( mp_update_script )
|
||
|
{
|
||
|
delete mp_update_script;
|
||
|
}
|
||
|
if ( mp_params )
|
||
|
{
|
||
|
delete mp_params;
|
||
|
}
|
||
|
CEngine::sGetParticleTable()->FlushItem( m_checksum ); // remove reference from hash table
|
||
|
// printf ("\nJust Deleted 0x%x, contenets are now:\n",m_checksum);
|
||
|
// CEngine::sGetParticleTable()->PrintContents();
|
||
|
}
|
||
|
|
||
|
void CParticle::process( float delta_time )
|
||
|
{
|
||
|
int lp;
|
||
|
CParticleEntry* p_particle;
|
||
|
|
||
|
// If flagged for deletion, check if the particle system is empty and delete if it is.
|
||
|
if ( m_delete_when_empty )
|
||
|
{
|
||
|
if ( !m_num_particles )
|
||
|
{
|
||
|
// removing reference is sone in the destructor
|
||
|
//CEngine::sGetParticleTable()->FlushItem( m_checksum ); // remove reference from hash table
|
||
|
delete this;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Don't process if paused.
|
||
|
if (Mdl::FrontEnd::Instance()->GamePaused() && !Replay::RunningReplay())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (Replay::Paused())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( GetSuspendComponent()->SkipLogic( ) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Script updates.
|
||
|
if ( mp_update_script )
|
||
|
{
|
||
|
mp_update_script->Update();
|
||
|
}
|
||
|
|
||
|
// We can't check for off screen or not until we've run the update script
|
||
|
// as that might change the position (like for sparks)
|
||
|
|
||
|
// Don't process if off screen
|
||
|
// if (!Nx::CEngine::sIsVisible(m_pos,m_bounding_radius))
|
||
|
// {
|
||
|
// //printf ("Off - process\n");
|
||
|
// Gfx::AddDebugLine(m_pos,Mth::Vector(0,0,0),0x0000ff,0x0000ff,100); // where is it?
|
||
|
// return;
|
||
|
// }
|
||
|
|
||
|
|
||
|
if ( mp_emit_script )
|
||
|
{
|
||
|
mp_emit_script->Update();
|
||
|
// if ( mp_emit_script->Update() == Script::ESCRIPTRETURNVAL_FINISHED )
|
||
|
// {
|
||
|
// m_delete_when_empty = true;
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// If life was not set, assume we're a screen-facing system.
|
||
|
if ( !m_life_set ) return;
|
||
|
|
||
|
// Physics update.
|
||
|
for ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )
|
||
|
{
|
||
|
// Update time/life.
|
||
|
p_particle->m_time += delta_time;
|
||
|
|
||
|
// Apply force to velocity.
|
||
|
p_particle->m_vx += p_particle->m_fx;
|
||
|
p_particle->m_vy += p_particle->m_fy;
|
||
|
p_particle->m_vz += p_particle->m_fz;
|
||
|
|
||
|
// Copy history.
|
||
|
float x, y, z;
|
||
|
for ( int lp2 = ( plat_get_num_vertex_lists() - 1 ); lp2 > 0; lp2-- )
|
||
|
{
|
||
|
plat_get_position( lp, lp2 - 1, &x, &y, &z );
|
||
|
plat_set_position( lp, lp2, x, y, z );
|
||
|
}
|
||
|
|
||
|
// Apply velocity to position.
|
||
|
plat_add_position( lp, 0, p_particle->m_vx, p_particle->m_vy, p_particle->m_vz );
|
||
|
}
|
||
|
|
||
|
// Delete old particles.
|
||
|
for ( lp = 0, p_particle = mp_particle_array; lp < m_num_particles; lp++, p_particle++ )
|
||
|
{
|
||
|
if ( p_particle->m_time > p_particle->m_life )
|
||
|
{
|
||
|
// Delete old particles by copying last entry to entry that is being deleted.
|
||
|
m_num_particles--;
|
||
|
memcpy( p_particle, &mp_particle_array[m_num_particles], sizeof( CParticleEntry ) );
|
||
|
|
||
|
float x, y, z;
|
||
|
for ( int lp2 = 0; lp2 < plat_get_num_vertex_lists(); lp2++ )
|
||
|
{
|
||
|
plat_get_position( m_num_particles, lp2, &x, &y, &z );
|
||
|
plat_set_position( lp, lp2, x, y, z );
|
||
|
plat_set_position( m_num_particles, lp2, 1024.0f, 1024.0f, 1024.0f );
|
||
|
}
|
||
|
|
||
|
// Since we copied the last one to the current slot, decrement lp counter & particle
|
||
|
// pointer so that the copied entry gets checked for deletion as well.
|
||
|
p_particle--;
|
||
|
lp--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CParticle::render( void )
|
||
|
{
|
||
|
|
||
|
if ( GetSuspendComponent()->SkipRender( ) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
plat_render();
|
||
|
}
|
||
|
|
||
|
void CParticle::emit( int count )
|
||
|
{
|
||
|
int first, last;
|
||
|
|
||
|
// Do nothing here if flagged for deletion.
|
||
|
if ( m_delete_when_empty )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Calculate the range of array entries to emit to.
|
||
|
first = m_num_particles;
|
||
|
if ( ( m_num_particles + count ) <= m_max_particles )
|
||
|
{
|
||
|
m_num_particles += count;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_num_particles = m_max_particles;
|
||
|
}
|
||
|
last = m_num_particles;
|
||
|
|
||
|
// Build matrix to rotate the particle to the target.
|
||
|
Mth::Matrix mt;
|
||
|
|
||
|
mt.GetPos().Set();
|
||
|
mt.GetAt().Set( m_tx, m_ty, m_tz );
|
||
|
mt.GetAt().Normalize();
|
||
|
|
||
|
Mth::Vector temp;
|
||
|
temp.Set( 0.0f, 1.0f, 0.0f );
|
||
|
if ( ( fabs( mt.GetAt()[Y] ) > fabs( mt.GetAt()[X] ) ) && ( fabs( mt.GetAt()[Y] ) > fabs( mt.GetAt()[Z] ) ) )
|
||
|
{
|
||
|
// Y Major - use Z as up.
|
||
|
temp.Set( 0.0f, 0.0f, 1.0f );
|
||
|
}
|
||
|
|
||
|
mt.GetRight() = Mth::CrossProduct( temp, mt.GetAt() );
|
||
|
mt.GetRight().Normalize();
|
||
|
mt.GetUp() = Mth::CrossProduct( mt.GetRight(), mt.GetAt() );
|
||
|
mt.GetUp().Normalize();
|
||
|
|
||
|
// Add on rotation.
|
||
|
mt.RotateX( Mth::DegToRad(m_ax) );
|
||
|
mt.RotateY( Mth::DegToRad(m_ay) );
|
||
|
mt.RotateZ( Mth::DegToRad(m_az) );
|
||
|
|
||
|
// pright.set( mt.GetRight()[X], mt.GetRight()[Y], mt.GetRight()[Z] );
|
||
|
// pup.set( mt.GetUp()[X], mt.GetUp()[Y], mt.GetUp()[Z] );
|
||
|
// pat.set( mt.GetAt()[X], mt.GetAt()[Y], mt.GetAt()[Z] );
|
||
|
|
||
|
// Emit particles.
|
||
|
for ( int lp = first; lp < last; lp++ )
|
||
|
{
|
||
|
if ( m_life_set )
|
||
|
{
|
||
|
// Random values for this emission.
|
||
|
float rx = next_random();
|
||
|
float ry = next_random();
|
||
|
|
||
|
// Calculate emission initial velocity.
|
||
|
Mth::Vector velocity;
|
||
|
velocity[X] = rx * ( Mth::PI * ( m_emit_angle_spread / 4.0f ) );
|
||
|
velocity[Y] = ry * ( Mth::PI * ( m_emit_angle_spread / 4.0f ) );
|
||
|
velocity[Z] = 1.0f - (( velocity[X] * velocity[X] ) + ( velocity[Y] * velocity[Y] ));
|
||
|
velocity[W] = 1.0f;
|
||
|
|
||
|
float speed_mul = ( ( m_speed_max - m_speed_min ) * ((float)rand() / RAND_MAX ) ) + m_speed_min;
|
||
|
velocity[X] *= speed_mul;
|
||
|
velocity[Y] *= speed_mul;
|
||
|
velocity[Z] *= speed_mul;
|
||
|
|
||
|
// Get new rx, ry to make the particles cross over one another.
|
||
|
if ( m_random_angle )
|
||
|
{
|
||
|
rx = next_random();
|
||
|
ry = next_random();
|
||
|
}
|
||
|
|
||
|
// Normalize rx, ry to make a circular emission.
|
||
|
if ( m_circular_emit )
|
||
|
{
|
||
|
float l = 1.0f / sqrtf( ( rx * rx ) + ( ry * ry ) );
|
||
|
rx = rx * ( l * (float)fabs( rx ) ); // Note: length is scaled by random factor.
|
||
|
ry = ry * ( l * (float)fabs( ry ) );
|
||
|
}
|
||
|
|
||
|
// Set position around emitter width/height.
|
||
|
Mth::Vector pos;
|
||
|
pos[X] = m_emit_w * rx;
|
||
|
pos[Y] = m_emit_h * ry;
|
||
|
pos[Z] = 0.0f;
|
||
|
pos[W] = 1.0f;
|
||
|
|
||
|
// Set force.
|
||
|
mp_particle_array[lp].m_fx = m_fx;
|
||
|
mp_particle_array[lp].m_fy = m_fy;
|
||
|
mp_particle_array[lp].m_fz = m_fz;
|
||
|
|
||
|
// Set particle w/h
|
||
|
mp_particle_array[lp].m_sw = m_sw;
|
||
|
mp_particle_array[lp].m_sh = m_sh;
|
||
|
mp_particle_array[lp].m_ew = m_ew;
|
||
|
mp_particle_array[lp].m_eh = m_eh;
|
||
|
|
||
|
// Set time & life.
|
||
|
mp_particle_array[lp].m_time = 0.0f;
|
||
|
mp_particle_array[lp].m_life = ( ( m_life_max - m_life_min ) * ((float)rand() / RAND_MAX ) ) + m_life_min;
|
||
|
|
||
|
// Orient the particles to the target.
|
||
|
Mth::Vector v;
|
||
|
v = mt.Transform( velocity );
|
||
|
mp_particle_array[lp].m_vx = v[X];
|
||
|
mp_particle_array[lp].m_vy = v[Y];
|
||
|
mp_particle_array[lp].m_vz = v[Z];
|
||
|
|
||
|
v = mt.Transform( pos );
|
||
|
|
||
|
for ( int lp2 = 0; lp2 < plat_get_num_vertex_lists(); lp2++ )
|
||
|
{
|
||
|
plat_set_position( lp, lp2, v[X], v[Y], v[Z] );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Set particle w/h
|
||
|
mp_particle_array[lp].m_sw = m_sw;
|
||
|
mp_particle_array[lp].m_sh = m_sh;
|
||
|
mp_particle_array[lp].m_ew = m_ew;
|
||
|
mp_particle_array[lp].m_eh = m_eh;
|
||
|
|
||
|
// Set time & life.
|
||
|
mp_particle_array[lp].m_time = 0.0f;
|
||
|
mp_particle_array[lp].m_life = ( ( m_life_max - m_life_min ) * ((float)rand() / RAND_MAX ) ) + m_life_min;
|
||
|
|
||
|
// Screen-facing poly. Just set to 0,0,0.
|
||
|
for ( int lp2 = 0; lp2 < plat_get_num_vertex_lists(); lp2++ )
|
||
|
{
|
||
|
plat_set_position( lp, lp2, 0, 0, 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CParticle::set_emit_script( uint32 checksum, Script::CStruct* pParams )
|
||
|
{
|
||
|
if ( checksum )
|
||
|
{
|
||
|
if ( !mp_emit_script )
|
||
|
{
|
||
|
mp_emit_script = new Script::CScript();
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
mp_emit_script->SetCommentString("Created in CParticle::set_emit_script(...)");
|
||
|
#endif
|
||
|
}
|
||
|
if ( !mp_params )
|
||
|
{
|
||
|
mp_params = new Script::CStruct;
|
||
|
}
|
||
|
mp_params->AppendStructure( pParams );
|
||
|
mp_emit_script->SetScript( checksum, mp_params, this );
|
||
|
// mp_emit_script->Update();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CParticle::set_update_script( uint32 checksum, Script::CStruct* pParams )
|
||
|
{
|
||
|
if ( checksum )
|
||
|
{
|
||
|
if ( !mp_update_script )
|
||
|
{
|
||
|
mp_update_script = new Script::CScript();
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
mp_update_script->SetCommentString("Created in CParticle::set_update_script(...)");
|
||
|
#endif
|
||
|
}
|
||
|
if ( !mp_params )
|
||
|
{
|
||
|
mp_params = new Script::CStruct;
|
||
|
}
|
||
|
mp_params->AppendStructure( pParams );
|
||
|
mp_update_script->SetScript( checksum, mp_params, this );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Refresh a particle system after things like position have changed
|
||
|
|
||
|
void CParticle::Refresh()
|
||
|
{
|
||
|
plat_build_path();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CParticle::SetActive( bool active )
|
||
|
{
|
||
|
m_active = active;
|
||
|
plat_set_active( active );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* CParticle::CallMemberFunction */
|
||
|
/* Call a member function, based on a checksum */
|
||
|
/* This is usually the checksum of the name of the function */
|
||
|
/* but can actually be any number, as it just uses a switch */
|
||
|
/* note this is a virtual function, so the same checksum */
|
||
|
/* can do differnet things for different objects */
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
bool CParticle::CallMemberFunction( uint32 Checksum, Script::CStruct *pParams, Script::CScript *pScript )
|
||
|
{
|
||
|
|
||
|
Dbg_MsgAssert(pScript,("NULL pScript"));
|
||
|
|
||
|
switch(Checksum)
|
||
|
{
|
||
|
// @script | SetPos | Sets the position of the particle system.
|
||
|
// @parmopt vector | pos | world position.
|
||
|
// @parmopt float | x | x world position.
|
||
|
// @parmopt float | y | y world position.
|
||
|
// @parmopt float | z | z world position.
|
||
|
case 0x99cd17b: // SetPos
|
||
|
{
|
||
|
Mth::Vector pos;
|
||
|
float x = 0.0f;
|
||
|
float y = 0.0f;
|
||
|
float z = 0.0f;
|
||
|
if ( pParams->GetVector(CRCD(0x7f261953,"pos"),&pos) )
|
||
|
{
|
||
|
x = pos[X];
|
||
|
y = pos[Y];
|
||
|
z = pos[Z];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pParams->GetFloat(CRCD(0x7323e97c,"x"),&x);
|
||
|
pParams->GetFloat(CRCD(0x424d9ea,"y"),&y);
|
||
|
pParams->GetFloat(CRCD(0x9d2d8850,"z"),&z);
|
||
|
}
|
||
|
|
||
|
set_pos( x, y, z );
|
||
|
}
|
||
|
break;
|
||
|
// @script | SetSpeedRange | Sets the min & max speed of the particles upon emission.
|
||
|
// @parm float | min | minimum speed. If only min is provided, all speeds will be set to min.
|
||
|
// @parmopt float | max | maximum speed.
|
||
|
case 0x63274395: // SetSpeedRange
|
||
|
{
|
||
|
float min = 0.0f;
|
||
|
pParams->GetFloat(CRCD(0x5e84e22f,"min"),&min);
|
||
|
float max = min;
|
||
|
pParams->GetFloat(CRCD(0x6289dd76,"max"),&max);
|
||
|
|
||
|
set_speed_range( min, max );
|
||
|
}
|
||
|
break;
|
||
|
// @script | SetEmitRange | Sets the emission range (width and height).
|
||
|
// @parm float | width | Width of emission area. If only width is provided, height will be set to width.
|
||
|
// @parmopt float | height | Height of emission area.
|
||
|
case 0x8ffdef38: // SetEmitRange
|
||
|
{
|
||
|
float width = 0.0f;
|
||
|
pParams->GetFloat(CRCD(0x73e5bad0,"width"),&width);
|
||
|
float height = width;
|
||
|
pParams->GetFloat(CRCD(0xab21af0,"height"),&height);
|
||
|
|
||
|
set_emit_range( width, height );
|
||
|
}
|
||
|
break;
|
||
|
// @script | SetAngleSpread | Sets the angle spread for particle emissions.
|
||
|
// @parm float | spread | Angle spread. 0=No spread. 1=Full spread (180 degrees).
|
||
|
case 0x7911855b: // SetAngleSpread
|
||
|
{
|
||
|
float spread = 0.0f;
|
||
|
pParams->GetFloat(CRCD(0x834a5f87,"spread"),&spread);
|
||
|
|
||
|
set_emit_angle_spread( spread );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
// @script | SetRandomAngle | Sets whether the emission angle is random or not.
|
||
|
// @parm int | random | 1 means choose a random angle regardless of the emission position. 0 means use the emission position to define the emission angle.
|
||
|
case 0xdb8621f7: // SetRandomAngle
|
||
|
{
|
||
|
int random = 0;
|
||
|
pParams->GetInteger("random",(int*)&random);
|
||
|
|
||
|
set_random_angle( random > 0 );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// @script | SetCircularEmit | Sets whether the emission area is circular or square.
|
||
|
// @parm int | circular | 1 means use a circular emission area. 0 means use a square emission area.
|
||
|
case 0xe985a9a6: // SetCircularEmit
|
||
|
{
|
||
|
int circular = 0;
|
||
|
pParams->GetInteger("circular",(int*)&circular);
|
||
|
|
||
|
set_circular_emit( circular > 0 );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// @script | SetForce | Sets the force acting on the particles.
|
||
|
// @parmopt vector | force | Force.
|
||
|
// @parmopt float | x | x force.
|
||
|
// @parmopt float | y | y force.
|
||
|
// @parmopt float | z | z force.
|
||
|
case 0xa075ee45: // SetForce
|
||
|
{
|
||
|
Mth::Vector force;
|
||
|
float x = 0.0f;
|
||
|
float y = 0.0f;
|
||
|
float z = 0.0f;
|
||
|
if ( pParams->GetVector("force",&force) )
|
||
|
{
|
||
|
x = force[X];
|
||
|
y = force[Y];
|
||
|
z = force[Z];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pParams->GetFloat("x",&x);
|
||
|
pParams->GetFloat("y",&y);
|
||
|
pParams->GetFloat("z",&z);
|
||
|
}
|
||
|
|
||
|
set_force( x, y, z );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// @script | SetParticleSize | Sets the size of the particles.
|
||
|
// @parm float | sw | Start width of the particle. If only width is provided, height is set to width.
|
||
|
// @parmopt float | sh | Start height of the particle.
|
||
|
// @parm float | ew | End width of the particle. If only width is provided, height is set to width.
|
||
|
// @parmopt float | eh | End height of the particle.
|
||
|
case 0x2a479569: // SetParticleSize
|
||
|
{
|
||
|
float sw = 0.0f;
|
||
|
pParams->GetFloat("sw",&sw);
|
||
|
float sh = sw;
|
||
|
pParams->GetFloat("sh",&sh);
|
||
|
|
||
|
set_particle_start_size( sw, sh );
|
||
|
|
||
|
float ew = sw;
|
||
|
float eh;
|
||
|
if ( pParams->GetFloat("ew",&ew) )
|
||
|
{
|
||
|
eh = ew;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
eh = sh;
|
||
|
}
|
||
|
pParams->GetFloat("eh",&eh);
|
||
|
|
||
|
set_particle_end_size( ew, eh );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// @script | SetLife | Sets the life of the particles in seconds.
|
||
|
// @parm float | min | Minimum life of the particle. 1.0 = 1 second.
|
||
|
// @parmopt float | max | Maximum life of the particle. 1.0 = 1 second. If not specified, will be set to same as min.
|
||
|
case 0xd3f1d333: // SetLife
|
||
|
{
|
||
|
float min = 0.0f;
|
||
|
pParams->GetFloat("min",&min);
|
||
|
float max = min;
|
||
|
pParams->GetFloat("max",&max);
|
||
|
|
||
|
set_particle_life( min, max );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// @script | SetEmitTarget | Sets the target position that the particle system will emit particles towards.
|
||
|
// @parmopt vector | target | Target.
|
||
|
// @parmopt float | x | x target.
|
||
|
// @parmopt float | y | y target.
|
||
|
// @parmopt float | z | z target.
|
||
|
case 0xb373fb6e: // SetEmitTarget
|
||
|
{
|
||
|
Mth::Vector target;
|
||
|
float x = 0.0f;
|
||
|
float y = 0.0f;
|
||
|
float z = 0.0f;
|
||
|
if ( pParams->GetVector("target",&target) )
|
||
|
{
|
||
|
x = target[X];
|
||
|
y = target[Y];
|
||
|
z = target[Z];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pParams->GetFloat("x",&x);
|
||
|
pParams->GetFloat("y",&y);
|
||
|
pParams->GetFloat("z",&z);
|
||
|
}
|
||
|
|
||
|
// If it's just 0,1,0, then rotate it by the angles of the node
|
||
|
if (x == 0.0f && y == 1.0f && z == 0.0f)
|
||
|
{
|
||
|
// not done here though....
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
set_emit_target( x, y, z );
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
// @script | SetEmitAngle | Sets the emission angle. This is done after the target, so you can set a target as well as angles to rotate in addition to the target angle. Target defaults to 0,1,0 (straight up), so all angles rotate from there.
|
||
|
// @parmopt vector | angle | Angle (in degrees).
|
||
|
// @parmopt float | x | x angle.
|
||
|
// @parmopt float | y | y angle.
|
||
|
// @parmopt float | z | z angle.
|
||
|
case 0x1cfbf078: // SetEmitAngle
|
||
|
{
|
||
|
Mth::Vector angle;
|
||
|
float x = 0.0f;
|
||
|
float y = 0.0f;
|
||
|
float z = 0.0f;
|
||
|
if ( pParams->GetVector("angle",&angle) )
|
||
|
{
|
||
|
x = angle[X];
|
||
|
y = angle[Y];
|
||
|
z = angle[Z];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pParams->GetFloat("x",&x);
|
||
|
pParams->GetFloat("y",&y);
|
||
|
pParams->GetFloat("z",&z);
|
||
|
}
|
||
|
|
||
|
set_emit_angle( x, y, z );
|
||
|
}
|
||
|
break;
|
||
|
// CreateParticleSystem colorentries=n // default 2.
|
||
|
// SetColorEntry slot=n r=n g=n b=n
|
||
|
|
||
|
|
||
|
// @script | SetColor | Sets the color for the next particle emission.
|
||
|
// @parmopt int | corner | | The corner to set. Omitting this paramter means set all corners.
|
||
|
// @parmopt int | sr | | Start red color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | sg | | Start green color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | sb | | Start blue color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | sa | | Start alpha color element to set (0-255). 255 is opaque, 0 is invisible.
|
||
|
// @parmopt int | mr | | Mid red color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | mg | | Mid green color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | mb | | Mid blue color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | ma | | Mid alpha color element to set (0-255). 255 is opaque, 0 is invisible.
|
||
|
// @parmopt int | er | | End red color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | eg | | End green color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | eb | | End blue color element to set (0-255). 128 is normal.
|
||
|
// @parmopt int | ea | | End alpha color element to set (0-255). 255 is opaque, 0 is invisible.
|
||
|
// @parmopt int | midtime | | Sets the % through the particle's life that the mid color is reached.
|
||
|
// 0.5 means halfway through. Use values from 0-1. By default, the mid color is not used. By setting
|
||
|
// the mid time, the middle color will be used.
|
||
|
case 0x514b2584: // SetColor
|
||
|
{
|
||
|
int corner;
|
||
|
int first = 0;
|
||
|
int last = 0;
|
||
|
if ( pParams->GetInteger("corner",&corner) )
|
||
|
{
|
||
|
first = last = corner;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
first = 0;
|
||
|
last = plat_get_num_particle_colors() - 1;
|
||
|
}
|
||
|
if ( ( first < plat_get_num_particle_colors() ) && ( last < plat_get_num_particle_colors() ) )
|
||
|
{
|
||
|
for ( int entry = first; entry < ( last + 1 ); entry++ )
|
||
|
{
|
||
|
if ( entry < plat_get_num_particle_colors() )
|
||
|
{
|
||
|
int elem;
|
||
|
if ( pParams->GetInteger("er",&elem) )
|
||
|
{
|
||
|
plat_set_er( entry, elem );
|
||
|
m_end_set = true;
|
||
|
}
|
||
|
if ( pParams->GetInteger("eg",&elem) )
|
||
|
{
|
||
|
plat_set_eg( entry, elem );
|
||
|
m_end_set = true;
|
||
|
}
|
||
|
if ( pParams->GetInteger("eb",&elem) )
|
||
|
{
|
||
|
plat_set_eb( entry, elem );
|
||
|
m_end_set = true;
|
||
|
}
|
||
|
if ( pParams->GetInteger("ea",&elem) )
|
||
|
{
|
||
|
plat_set_ea( entry, elem );
|
||
|
m_end_set = true;
|
||
|
}
|
||
|
if ( pParams->GetInteger("mr",&elem) )
|
||
|
{
|
||
|
plat_set_mr( entry, elem );
|
||
|
}
|
||
|
if ( pParams->GetInteger("mg",&elem) )
|
||
|
{
|
||
|
plat_set_mg( entry, elem );
|
||
|
}
|
||
|
if ( pParams->GetInteger("mb",&elem) )
|
||
|
{
|
||
|
plat_set_mb( entry, elem );
|
||
|
}
|
||
|
if ( pParams->GetInteger("ma",&elem) )
|
||
|
{
|
||
|
plat_set_ma( entry, elem );
|
||
|
}
|
||
|
if ( pParams->GetInteger("sr",&elem) )
|
||
|
{
|
||
|
plat_set_sr( entry, elem );
|
||
|
if ( !m_end_set ) plat_set_er( entry, elem );
|
||
|
}
|
||
|
if ( pParams->GetInteger("sg",&elem) )
|
||
|
{
|
||
|
plat_set_sg( entry, elem );
|
||
|
if ( !m_end_set ) plat_set_eg( entry, elem );
|
||
|
}
|
||
|
if ( pParams->GetInteger("sb",&elem) )
|
||
|
{
|
||
|
plat_set_sb( entry, elem );
|
||
|
if ( !m_end_set ) plat_set_eb( entry, elem );
|
||
|
}
|
||
|
if ( pParams->GetInteger("sa",&elem) )
|
||
|
{
|
||
|
plat_set_sa( entry, elem );
|
||
|
if ( !m_end_set ) plat_set_ea( entry, elem );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
pParams->GetFloat("midtime",&m_mid_time);
|
||
|
}
|
||
|
break;
|
||
|
// @script | Emit | Emits the specified number of particles.
|
||
|
// @parm int | num | Number of particles to emit.
|
||
|
case 0x711b1a6a: // Emit
|
||
|
{
|
||
|
int num = 1; // Defaults to 1 particle emitted.
|
||
|
pParams->GetInteger("num",&num);
|
||
|
|
||
|
emit( num );
|
||
|
}
|
||
|
break;
|
||
|
// @script | EmitRate | Emits at the specified rate - 1=1 particle per frame.
|
||
|
// @parm float | rate | The rate to emit at.
|
||
|
case 0x35b65bd4: // EmitRate
|
||
|
{
|
||
|
float rate = 1.0f; // Defaults to 1 particle emitted per frame.
|
||
|
pParams->GetFloat("rate",&rate);
|
||
|
|
||
|
set_emit_rate( rate );
|
||
|
}
|
||
|
break;
|
||
|
// @script | BuildPath | Builds a path based on the current physics data.
|
||
|
case 0xa8699e0e: // BuildPath
|
||
|
{
|
||
|
plat_build_path();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// @script | EmptySystem | Empties the particle system immediately (sets number of particles to 0.
|
||
|
case 0x482482c6: // EmptySystem
|
||
|
{
|
||
|
m_num_particles = 0;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return Obj::CMovingObject::CallMemberFunction( Checksum, pParams, pScript );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|