iw6-scripts-dev/common_scripts/_createfxmenu.gsc
2024-12-11 11:28:08 +01:00

755 lines
18 KiB
Plaintext

#include common_scripts\utility;
#include common_scripts\_createfx;
//---------------------------------------------------------
// Menu init/loop section
//---------------------------------------------------------
init_menu()
{
level._createfx.options = [];
// each option has a type, a name its stored under, a description, a default, and a mask it uses to determine
// which types of fx can have this option
addOption( "string", "fxid", "FX id", "nil", "fx" );
addOption( "float", "delay", "Repeat rate/start delay", 0.5, "fx" );
addOption( "string", "flag", "Flag", "nil", "exploder" );
if( !level.mp_createfx )
{
addOption( "string", "firefx", "2nd FX id", "nil", "exploder" );
addOption( "float", "firefxdelay", "2nd FX id repeat rate", 0.5, "exploder" );
addOption( "float", "firefxtimeout", "2nd FX timeout", 5, "exploder" );
addOption( "string", "firefxsound", "2nd FX soundalias", "nil", "exploder" );
addOption( "float", "damage", "Radius damage", 150, "exploder" );
addOption( "float", "damage_radius", "Radius of radius damage", 250, "exploder" );
addOption( "string", "earthquake", "Earthquake", "nil", "exploder" );
addOption( "string", "ender", "Level notify for ending 2nd FX", "nil", "exploder" );
}
addOption( "float", "delay_min", "Minimimum time between repeats", 1, "soundfx_interval" );
addOption( "float", "delay_max", "Maximum time between repeats", 2, "soundfx_interval" );
addOption( "int", "repeat", "Number of times to repeat", 5, "exploder" );
addOption( "string", "exploder", "Exploder", "1", "exploder" );
addOption( "string", "soundalias", "Soundalias", "nil", "all" );
addOption( "string", "loopsound", "Loopsound", "nil", "exploder" );
addOption( "int", "reactive_radius", "Reactive Radius", 100, "reactive_fx", ::input_reactive_radius );
if( !level.mp_createfx )
{
addOption( "string", "rumble", "Rumble", "nil", "exploder" );
addOption( "int", "stoppable", "Can be stopped from script", "1", "all" );
}
level.effect_list_offset = 0;
level.effect_list_offset_max = 10;
// creates mask groups. For example if the above says its mask is "fx", then all the types under "fx" can use the option
level.createfxMasks = [];
level.createfxMasks[ "all" ] = [];
level.createfxMasks[ "all" ][ "exploder" ] = true;
level.createfxMasks[ "all" ][ "oneshotfx" ] = true;
level.createfxMasks[ "all" ][ "loopfx" ] = true;
level.createfxMasks[ "all" ][ "soundfx" ] = true;
level.createfxMasks[ "all" ][ "soundfx_interval" ] = true;
level.createfxMasks[ "all" ][ "reactive_fx" ] = true;
level.createfxMasks[ "fx" ] = [];
level.createfxMasks[ "fx" ][ "exploder" ] = true;
level.createfxMasks[ "fx" ][ "oneshotfx" ] = true;
level.createfxMasks[ "fx" ][ "loopfx" ] = true;
level.createfxMasks[ "exploder" ] = [];
level.createfxMasks[ "exploder" ][ "exploder" ] = true;
level.createfxMasks[ "loopfx" ] = [];
level.createfxMasks[ "loopfx" ][ "loopfx" ] = true;
level.createfxMasks[ "oneshotfx" ] = [];
level.createfxMasks[ "oneshotfx" ][ "oneshotfx" ] = true;
level.createfxMasks[ "soundfx" ] = [];
level.createfxMasks[ "soundfx" ][ "soundalias" ] = true;
level.createfxMasks[ "soundfx_interval" ] = [];
level.createfxMasks[ "soundfx_interval" ][ "soundfx_interval" ] = true;
level.createfxMasks[ "reactive_fx" ] = [];
level.createfxMasks[ "reactive_fx" ][ "reactive_fx" ] = true;
// Mainly used for input of a menu
menus = [];
menus[ "creation" ] = ::menu_create_select;
menus[ "create_oneshot" ] = ::menu_create;
menus[ "create_loopfx" ] = ::menu_create;
menus[ "change_fxid" ] = ::menu_create;
menus[ "none" ] = ::menu_none;
menus[ "add_options" ] = ::menu_add_options;
menus[ "select_by_name" ] = ::menu_select_by_name;
level._createfx.menus = menus;
}
menu( name )
{
return level.create_fx_menu == name;
}
setmenu( name )
{
level.create_fx_menu = name;
}
create_fx_menu()
{
if ( button_is_clicked( "escape", "x" ) )
{
_exit_menu();
return;
}
if ( IsDefined( level._createfx.menus[ level.create_fx_menu ] ) )
{
[[ level._createfx.menus[ level.create_fx_menu ] ]]();
}
}
menu_create_select()
{
if ( button_is_clicked( "1" ) )
{
setmenu( "create_oneshot" );
draw_effects_list();
return;
}
else if ( button_is_clicked( "2" ) )
{
setmenu( "create_loopsound" );
ent = createLoopSound();
finish_creating_entity( ent );
return;
}
else if ( button_is_clicked( "3" ) )
{
setmenu( "create_exploder" );
ent = createNewExploder();
finish_creating_entity( ent );
return;
}
else if ( button_is_clicked( "4" ) )
{
setmenu( "create_interval_sound" );
ent = createIntervalSound();
finish_creating_entity( ent );
return;
}
else if ( button_is_clicked( "5" ) )
{
ent = createReactiveEnt();
finish_creating_entity( ent );
return;
}
}
menu_create()
{
if ( next_button() )
{
increment_list_offset();
draw_effects_list();
}
else if ( previous_button() )
{
decrement_list_offset();
draw_effects_list();
}
menu_fx_creation();
}
menu_none()
{
if ( button_is_clicked( "m" ) )
increment_list_offset();
// change selected entities
menu_change_selected_fx();
// if there's a selected ent then display the info on the last one to be selected
if ( entities_are_selected() )
{
last_selected_ent = get_last_selected_ent();
// only update hudelems when we have new info
if ( !IsDefined( level.last_displayed_ent ) || last_selected_ent != level.last_displayed_ent )
{
display_fx_info( last_selected_ent );
level.last_displayed_ent = last_selected_ent;
}
if ( button_is_clicked( "a" ) )
{
clear_settable_fx();
setMenu( "add_options" );
}
}
else
{
level.last_displayed_ent = undefined;
}
}
menu_add_options()
{
if ( !entities_are_selected() )
{
clear_fx_hudElements();
setMenu( "none" );
return;
}
display_fx_add_options( get_last_selected_ent() );
if ( next_button() )
{
increment_list_offset();
// draw_effects_list();
}
}
menu_select_by_name()
{
if ( next_button() )
{
increment_list_offset();
draw_effects_list( "Select by name" );
}
else if ( previous_button() )
{
decrement_list_offset();
draw_effects_list( "Select by name" );
}
select_by_name();
}
next_button()
{
return button_is_clicked( "rightarrow" );
}
previous_button()
{
return button_is_clicked( "leftarrow" );
}
_exit_menu()
{
clear_fx_hudElements();
clear_entity_selection();
update_selected_entities();
setmenu( "none" );
}
//---------------------------------------------------------
// Create FX Section (button presses)
//---------------------------------------------------------
menu_fx_creation()
{
count = 0;
picked_fx = undefined;
keys = func_get_level_fx();
for ( i = level.effect_list_offset; i < keys.size; i++ )
{
count = count + 1;
button_to_check = count;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
picked_fx = keys[ i ];
break;
}
if ( count > level.effect_list_offset_max )
break;
}
if ( !isdefined( picked_fx ) )
return;
if ( menu( "change_fxid" ) )
{
apply_option_to_selected_fx( get_option( "fxid" ), picked_fx );
level.effect_list_offset = 0;
clear_fx_hudElements();
setMenu( "none" );
return;
}
ent = undefined;
if ( menu( "create_loopfx" ) )
ent = createLoopEffect( picked_fx );
if ( menu( "create_oneshot" ) )
ent = createOneshotEffect( picked_fx );
finish_creating_entity( ent );
}
finish_creating_entity( ent )
{
assert( isdefined( ent ) );
ent.v[ "angles" ] = vectortoangles( ( ent.v[ "origin" ] + ( 0, 0, 100 ) ) - ent.v[ "origin" ] );
ent post_entity_creation_function();// for createfx dev purposes
clear_entity_selection();
select_last_entity();
move_selection_to_cursor();
update_selected_entities();
setMenu( "none" );
}
entities_are_selected()
{
return level._createfx.selected_fx_ents.size > 0;
}
menu_change_selected_fx()
{
if ( !level._createfx.selected_fx_ents.size )
{
return;
}
count = 0;
drawnCount = 0;
ent = get_last_selected_ent();
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( !isdefined( ent.v[ option[ "name" ] ] ) )
continue;
count++ ;
if ( count < level.effect_list_offset )
continue;
drawnCount++ ;
button_to_check = drawnCount;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
prepare_option_for_change( option, drawnCount );
break;
}
if ( drawnCount > level.effect_list_offset_max )
{
more = true;
break;
}
}
}
prepare_option_for_change( option, drawnCount )
{
if ( option[ "name" ] == "fxid" )
{
setMenu( "change_fxid" );
draw_effects_list();
return;
}
level.createfx_inputlocked = true;
level._createfx.hudelems[ drawnCount + 3 ][ 0 ].color = ( 1, 1, 0 );
if ( IsDefined( option[ "input_func" ] ) )
{
thread [[ option[ "input_func" ] ]]( drawnCount + 3 );
}
else
{
createfx_centerprint( "To change " + option[ "description" ] + " on selected entities, type /fx newvalue" );
}
set_option_index( option[ "name" ] );
setdvar( "fx", "nil" );
}
menu_fx_option_set()
{
if ( getdvar( "fx" ) == "nil" )
return;
option = get_selected_option();
setting = undefined;
if ( option[ "type" ] == "string" )
setting = getdvar( "fx" );
if ( option[ "type" ] == "int" )
setting = getdvarint( "fx" );
if ( option[ "type" ] == "float" )
setting = getdvarfloat( "fx" );
apply_option_to_selected_fx( option, setting );
}
apply_option_to_selected_fx( option, setting )
{
for ( i = 0; i < level._createfx.selected_fx_ents.size; i++ )
{
ent = level._createfx.selected_fx_ents[ i ];
if ( mask( option[ "mask" ], ent.v[ "type" ] ) )
ent.v[ option[ "name" ] ] = setting;
}
level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
update_selected_entities();
clear_settable_fx();
}
set_option_index( name )
{
for ( i = 0; i < level._createfx.options.size; i++ )
{
if ( level._createfx.options[ i ][ "name" ] != name )
continue;
level._createfx.selected_fx_option_index = i;
return;
}
}
get_selected_option()
{
return level._createfx.options[ level._createfx.selected_fx_option_index ];
}
mask( type, name )
{
return isdefined( level.createfxMasks[ type ][ name ] );
}
addOption( type, name, description, defaultSetting, mask, input_func )
{
option = [];
option[ "type" ] = type;
option[ "name" ] = name;
option[ "description" ] = description;
option[ "default" ] = defaultSetting;
option[ "mask" ] = mask;
if ( IsDefined( input_func ) )
{
option[ "input_func" ] = input_func;
}
level._createfx.options[ level._createfx.options.size ] = option;
}
get_option( name )
{
for ( i = 0; i < level._createfx.options.size; i++ )
{
if ( level._createfx.options[ i ][ "name" ] == name )
return level._createfx.options[ i ];
}
}
//---------------------------------------------------------
// Reactive Radius
//---------------------------------------------------------
input_reactive_radius( menu_index )
{
level._createfx.hudelems[ menu_index ][ 0 ] SetDevText( "Reactive Radius, Press: + OR -" );
while ( 1 )
{
wait( 0.05 );
if ( level.player ButtonPressed( "escape" ) || level.player ButtonPressed( "x" ) )
break;
val = 0;
if ( level.player ButtonPressed( "-" ) )
val = -10;
else if ( level.player ButtonPressed( "=" ) )
val = 10;
if ( val != 0 )
{
foreach ( ent in level._createfx.selected_fx_ents )
{
if ( IsDefined( ent.v[ "reactive_radius" ] ) )
{
ent.v[ "reactive_radius" ] += val;
ent.v[ "reactive_radius" ] = Clamp( ent.v[ "reactive_radius" ], 10, 1000 );
}
}
}
}
level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
update_selected_entities();
clear_settable_fx();
}
//---------------------------------------------------------
// Display FX Add Options
//---------------------------------------------------------
display_fx_add_options( ent )
{
// are we doing the create fx menu right now?
assert( menu( "add_options" ) );
assert( entities_are_selected() );
clear_fx_hudElements();
set_fx_hudElement( "Name: " + ent.v[ "fxid" ] );
set_fx_hudElement( "Type: " + ent.v[ "type" ] );
set_fx_hudElement( "Origin: " + ent.v[ "origin" ] );
set_fx_hudElement( "Angles: " + ent.v[ "angles" ] );
// if entities are selected then we make the entity stats modifiable
count = 0;
drawnCount = 0;
more = false;
if ( level.effect_list_offset >= level._createfx.options.size )
level.effect_list_offset = 0;
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( isdefined( ent.v[ option[ "name" ] ] ) )
continue;
// does this type of effect get this kind of option?
if ( !mask( option[ "mask" ], ent.v[ "type" ] ) )
continue;
count++ ;
if ( count < level.effect_list_offset )
continue;
if ( drawnCount >= level.effect_list_offset_max )
continue;
drawnCount++ ;
button_to_check = drawnCount;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
add_option_to_selected_entities( option );
// prepare_option_for_change( option, drawnCount );
menuNone();
level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
return;
}
set_fx_hudElement( button_to_check + ". " + option[ "description" ] );
}
if ( count > level.effect_list_offset_max )
set_fx_hudElement( "(->) More >" );
set_fx_hudElement( "(x) Exit >" );
}
add_option_to_selected_entities( option )
{
setting = undefined;
for ( i = 0; i < level._createfx.selected_fx_ents.size; i++ )
{
ent = level._createfx.selected_fx_ents[ i ];
if ( mask( option[ "mask" ], ent.v[ "type" ] ) )
ent.v[ option[ "name" ] ] = option[ "default" ];
}
}
menuNone()
{
level.effect_list_offset = 0;
clear_fx_hudElements();
setMenu( "none" );
}
//---------------------------------------------------------
// Display FX info
//---------------------------------------------------------
display_fx_info( ent )
{
// are we doing the create fx menu right now?
if ( !menu( "none" ) )
return;
clear_fx_hudElements();
set_fx_hudElement( "Name: " + ent.v[ "fxid" ] );
set_fx_hudElement( "Type: " + ent.v[ "type" ] );
set_fx_hudElement( "Origin: " + ent.v[ "origin" ] );
set_fx_hudElement( "Angles: " + ent.v[ "angles" ] );
if ( entities_are_selected() )
{
// if entities are selected then we make the entity stats modifiable
count = 0;
drawnCount = 0;
more = false;
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( !isdefined( ent.v[ option[ "name" ] ] ) )
continue;
count++ ;
if ( count < level.effect_list_offset )
continue;
drawnCount++ ;
set_fx_hudElement( drawnCount + ". " + option[ "description" ] + ": " + ent.v[ option[ "name" ] ] );
if ( drawnCount > level.effect_list_offset_max )
{
more = true;
break;
}
}
if ( count > level.effect_list_offset_max )
set_fx_hudElement( "(->) More >" );
set_fx_hudElement( "(a) Add >" );
set_fx_hudElement( "(x) Exit >" );
}
else
{
count = 0;
more = false;
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( !isdefined( ent.v[ option[ "name" ] ] ) )
continue;
count++ ;
set_fx_hudElement( option[ "description" ] + ": " + ent.v[ option[ "name" ] ] );
if ( count > level._createfx.hudelem_count )
break;
}
}
}
//---------------------------------------------------------
// Draw Effects Section
//---------------------------------------------------------
draw_effects_list( title )
{
clear_fx_hudElements();
count = 0;
more = false;
keys = func_get_level_fx();
if( !IsDefined( title ) )
{
title = "Pick an effect";
}
set_fx_hudElement( title + " [" + level.effect_list_offset + " - " + keys.size + "]:" );
// if ( level.effect_list_offset >= keys.size )
// level.effect_list_offset = 0;
for ( i = level.effect_list_offset; i < keys.size; i++ )
{
count = count + 1;
set_fx_hudElement( count + ". " + keys[ i ] );
if ( count >= level.effect_list_offset_max )
{
more = true;
break;
}
}
if ( keys.size > level.effect_list_offset_max )
{
set_fx_hudElement( "(->) More >" );
set_fx_hudElement( "(<-) Previous >" );
}
}
increment_list_offset()
{
keys = func_get_level_fx();
if ( level.effect_list_offset >= keys.size - level.effect_list_offset_max )
{
level.effect_list_offset = 0;
}
else
{
level.effect_list_offset += level.effect_list_offset_max;
}
}
decrement_list_offset()
{
level.effect_list_offset -= level.effect_list_offset_max;
if ( level.effect_list_offset < 0 )
{
keys = func_get_level_fx();
level.effect_list_offset = keys.size - level.effect_list_offset_max;
}
}
//---------------------------------------------------------
// Select by Name Section
//---------------------------------------------------------
select_by_name()
{
count = 0;
picked_fx = undefined;
keys = func_get_level_fx();
for ( i = level.effect_list_offset; i < keys.size; i++ )
{
count = count + 1;
button_to_check = count;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
picked_fx = keys[ i ];
break;
}
if ( count > level.effect_list_offset_max )
break;
}
if ( !IsDefined( picked_fx ) )
return;
index_array = [];
foreach ( i, ent in level.createFXent )
{
if ( IsSubStr( ent.v[ "fxid" ], picked_fx ) )
{
index_array[ index_array.size ] = i;
}
}
deselect_all_ents();
select_index_array( index_array );
level._createfx.select_by_name = true;
}
//---------------------------------------------------------
// Utility Section
//---------------------------------------------------------
get_last_selected_ent()
{
return level._createfx.selected_fx_ents[ level._createfx.selected_fx_ents.size - 1 ];
}