use crate::cclocallevels::gdobj::{
Event, GDObjConfig, GDObject, GDValue, MoveEasing,
ids::{objects::*, properties::*},
structs::*,
};
pub fn move_trigger(
config: &GDObjConfig,
move_config: MoveMode,
time: f64,
target_group: i16,
silent: bool,
dynamic: bool,
easing: Option<(MoveEasing, f64)>,
) -> GDObject {
let mut properties = vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(time)),
(SMALL_STEP, GDValue::Bool(true)),
(DYNAMIC_MOVE, GDValue::Bool(dynamic)),
(SILENT_MOVE, GDValue::Bool(silent)),
];
add_easing(&mut properties, easing);
match move_config {
MoveMode::Default(config) => {
if let Some(lock) = config.x_lock {
properties.push((
match lock {
MoveLock::Player => FOLLOW_PLAYERS_X_MOVEMENT,
MoveLock::Camera => FOLLOW_CAMERAS_X_MOVEMENT,
},
GDValue::Int(1),
));
properties.push((X_MOVEMENT_MULTIPLIER, GDValue::Float(config.dx)));
} else {
properties.push((MOVE_UNITS_X, GDValue::Int(config.dx as i32)));
}
if let Some(lock) = config.y_lock {
properties.push((
match lock {
MoveLock::Player => FOLLOW_PLAYERS_Y_MOVEMENT,
MoveLock::Camera => FOLLOW_CAMERAS_Y_MOVEMENT,
},
GDValue::Int(1),
));
properties.push((Y_MOVEMENT_MULTIPLIER, GDValue::Float(config.dy)));
} else {
properties.push((MOVE_UNITS_Y, GDValue::Int(config.dy as i32)));
}
}
MoveMode::Targeting(config) => {
properties.push((TARGET_MOVE_MODE, GDValue::Int(1)));
if let Some(id) = config.center_group_id {
properties.push((CENTER_GROUP_ID, GDValue::Group(id)));
}
if let Some(axis) = config.axis_only {
properties.push((TARGET_MOVE_MODE_AXIS_LOCK, GDValue::Int(axis as i32)));
}
match config.target_group_id {
MoveTarget::Player1 => properties.push((CONTROLLING_PLAYER_1, GDValue::Int(1))),
MoveTarget::Player2 => properties.push((CONTROLLING_PLAYER_2, GDValue::Int(1))),
MoveTarget::Group(id) => properties.push((TARGET_ITEM_2, GDValue::Group(id))),
};
}
MoveMode::Directional(config) => {
if let Some(id) = config.center_group_id {
properties.push((CENTER_GROUP_ID, GDValue::Group(id)));
}
match config.target_group_id {
MoveTarget::Player1 => properties.push((CONTROLLING_PLAYER_1, GDValue::Int(1))),
MoveTarget::Player2 => properties.push((CONTROLLING_PLAYER_2, GDValue::Int(1))),
MoveTarget::Group(id) => properties.push((TARGET_ITEM_2, GDValue::Group(id))),
};
properties.push((DIRECTIONAL_MOVE_MODE, GDValue::Int(1)));
properties.push((DIRECTIONAL_MODE_DISTANCE, GDValue::Int(config.distance)));
}
}
GDObject::new(TRIGGER_MOVE, config, properties)
}
pub fn start_pos(
config: &GDObjConfig,
gameplay_settings: StartposConfig,
target_order: i32,
target_channel: i32,
disabled: bool,
) -> GDObject {
GDObject::new(
START_POS,
config,
vec![
(
STARTING_SPEED,
GDValue::Int(gameplay_settings.start_speed as i32),
),
(
STARTING_GAMEMODE,
GDValue::Int(gameplay_settings.starting_gamemode as i32),
),
(
STARTING_IN_MINI_MODE,
GDValue::Bool(gameplay_settings.starting_as_mini),
),
(
STARTING_IN_DUAL_MODE,
GDValue::Bool(gameplay_settings.starting_as_dual),
),
(IS_DISABLED, GDValue::Bool(disabled)),
(
STARTING_IN_MIRROR_MODE,
GDValue::Bool(gameplay_settings.starting_mirrored),
),
(
ROTATE_GAMEPLAY,
GDValue::Bool(gameplay_settings.rotate_gameplay),
),
(
REVERSE_GAMEPLAY,
GDValue::Bool(gameplay_settings.reverse_gameplay),
),
(TARGET_ORDER, GDValue::Int(target_order)),
(TARGET_CHANNEL, GDValue::Int(target_channel)),
(RESET_CAMERA, GDValue::Bool(gameplay_settings.reset_camera)),
(10010, GDValue::Int(0)),
(10011, GDValue::String(String::new())),
(10022, GDValue::Int(0)),
(10023, GDValue::Int(0)),
(10024, GDValue::Int(0)),
(10027, GDValue::Int(1)),
(10031, GDValue::Int(1)),
(10032, GDValue::Int(1)),
(10033, GDValue::Int(1)),
(10034, GDValue::Int(1)),
(10036, GDValue::Int(0)),
(10037, GDValue::Int(1)),
(10038, GDValue::Int(1)),
(10039, GDValue::Int(1)),
(10040, GDValue::Int(1)),
(10041, GDValue::Int(1)),
(10042, GDValue::Int(1)),
(10043, GDValue::Int(0)),
(10044, GDValue::Int(0)),
(10045, GDValue::Int(1)),
(10046, GDValue::Int(0)),
(10009, GDValue::Int(1)),
],
)
}
pub fn colour_trigger(
config: &GDObjConfig,
colour_cfg: ColourTriggerConfig,
fade_time: f64,
copy_colour: Option<CopyColourConfig>,
) -> GDObject {
let mut properties = vec![
(RED, GDValue::Int(colour_cfg.colour.red as i32)),
(GREEN, GDValue::Int(colour_cfg.colour.green as i32)),
(BLUE, GDValue::Int(colour_cfg.colour.blue as i32)),
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(fade_time)),
(
USING_PLAYER_COLOUR_1,
GDValue::Bool(colour_cfg.use_player_col_1),
),
(
USING_PLAYER_COLOUR_2,
GDValue::Bool(colour_cfg.use_player_col_2),
),
(COLOUR_CHANNEL, GDValue::Short(colour_cfg.channel.into())),
(OPACITY, GDValue::Float(colour_cfg.opacity)),
(BLENDING_ENABLED, GDValue::Bool(colour_cfg.blending)),
];
if let Some(config) = copy_colour {
let cfg_string = config.hsv_config.to_string();
if !config.use_legacy_hsv {
properties.push((NO_LEGACY_HSV, GDValue::Bool(true)));
}
properties.push((COPY_OPACITY, GDValue::Bool(config.copy_opacity)));
properties.push((COPY_COLOUR_SPECS, GDValue::String(cfg_string)));
properties.push((
COPY_COLOUR_FROM_CHANNEL,
GDValue::ColourChannel(config.original_ch),
));
}
GDObject::new(TRIGGER_COLOUR, config, properties)
}
pub fn pulse_trigger(
config: &GDObjConfig,
pulse_fade_in_time: f64,
pulse_hold_time: f64,
pulse_fade_out_time: f64,
exclusive_pulse: bool,
pulse_target: &PulseTarget,
pulse_mode: PulseMode,
) -> GDObject {
let mut properties = vec![
(PULSE_FADE_IN_TIME, GDValue::Float(pulse_fade_in_time)),
(PULSE_HOLD_TIME, GDValue::Float(pulse_hold_time)),
(PULSE_FADE_OUT_TIME, GDValue::Float(pulse_fade_out_time)),
(EXCLUSIVE_PULSE_MODE, GDValue::Bool(exclusive_pulse)),
];
match pulse_target {
PulseTarget::Channel(c) => properties.push((TARGET_ITEM, GDValue::Group(c.channel_id))),
PulseTarget::Group(g) => {
properties.extend_from_slice(&[
(
PULSE_DETAIL_COLOUR_ONLY,
GDValue::Bool(g.detail_colour_only),
),
(PULSE_MAIN_COLOUR_ONLY, GDValue::Bool(g.main_colour_only)),
(PULSE_GROUP, GDValue::Group(g.group_id)),
]);
}
}
match pulse_mode {
PulseMode::Colour(c) => {
properties.extend_from_slice(&[
(RED, GDValue::Int(c.red as i32)),
(GREEN, GDValue::Int(c.green as i32)),
(BLUE, GDValue::Int(c.blue as i32)),
]);
}
PulseMode::HSV(h) => {
properties.extend_from_slice(&[
(NO_LEGACY_HSV, GDValue::Bool(h.use_static_hsv)),
(COPY_COLOUR_SPECS, GDValue::String(h.hsv_config.to_string())),
(
COPY_COLOUR_FROM_CHANNEL,
GDValue::ColourChannel(h.colour_id),
),
]);
}
}
GDObject::new(TRIGGER_PULSE, config, properties)
}
#[inline]
pub fn stop_trigger(
config: &GDObjConfig,
target_group: i16,
stop_mode: StopMode,
use_control_id: bool,
) -> GDObject {
GDObject::new(
TRIGGER_STOP,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(USE_CONTROL_ID, GDValue::Bool(use_control_id)),
(STOP_MODE, GDValue::Int(stop_mode.to_num())),
],
)
}
#[inline]
pub fn alpha_trigger(
config: &GDObjConfig,
target_group: i16,
opacity: f64,
fade_time: f64,
) -> GDObject {
GDObject::new(
1007,
config,
vec![
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(fade_time)),
(OPACITY, GDValue::Float(opacity)),
(TARGET_ITEM, GDValue::Group(target_group)),
],
)
}
#[inline]
pub fn toggle_trigger(config: &GDObjConfig, target_group: i16, activate_group: bool) -> GDObject {
GDObject::new(
TRIGGER_TOGGLE,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(ACTIVATE_GROUP, GDValue::Bool(activate_group)),
],
)
}
pub fn transition_object(
config: &GDObjConfig,
transition: TransitionType,
mode: TransitionMode,
target_channel: Option<i32>,
) -> GDObject {
let mut properties = vec![];
if mode != TransitionMode::Both {
properties.push((ENTEREXIT_TRANSITION_CONFIG, GDValue::Int(mode.to_num())));
}
if let Some(channel) = target_channel {
properties.push((TARGET_TRANSITION_CHANNEL, GDValue::Int(channel)));
}
GDObject::new(transition as i32, config, properties)
}
#[inline]
pub fn reverse_gameplay(config: &GDObjConfig) -> GDObject {
GDObject::new(TRIGGER_REVERSE_GAMEPLAY, config, vec![])
}
#[inline]
pub fn link_visible(config: &GDObjConfig, target_group: i16) -> GDObject {
GDObject::new(
TRIGGER_LINK_VISIBLE,
config,
vec![(TARGET_ITEM, GDValue::Group(target_group))],
)
}
#[inline]
pub fn timewarp(config: &GDObjConfig, time_scale: f64) -> GDObject {
GDObject::new(
TRIGGER_TIME_WARP,
config,
vec![(TIMEWARP_AMOUNT, GDValue::Float(time_scale))],
)
}
#[inline]
pub fn show_player(config: &GDObjConfig) -> GDObject {
GDObject::new(1613, config, vec![])
}
#[inline]
pub fn hide_player(config: &GDObjConfig) -> GDObject {
GDObject::new(1612, config, vec![])
}
#[inline]
pub fn show_player_trail(config: &GDObjConfig) -> GDObject {
GDObject::new(ENABLE_PLAYER_TRAIL, config, vec![])
}
#[inline]
pub fn hide_player_trail(config: &GDObjConfig) -> GDObject {
GDObject::new(DISABLE_PLAYER_TRAIL, config, vec![])
}
#[inline]
pub fn bg_effect_on(config: &GDObjConfig) -> GDObject {
GDObject::new(BG_EFFECT_ON, config, vec![])
}
#[inline]
pub fn bg_effect_off(config: &GDObjConfig) -> GDObject {
GDObject::new(BG_EFFECT_OFF, config, vec![])
}
#[inline]
pub fn group_reset(config: &GDObjConfig, target_group: i16) -> GDObject {
GDObject::new(
TRIGGER_RESET_GROUP,
config,
vec![(TARGET_ITEM, GDValue::Group(target_group))],
)
}
#[inline]
pub fn shake_trigger(
config: &GDObjConfig,
strength: i32,
interval: f64,
duration: f64,
) -> GDObject {
GDObject::new(
TRIGGER_SHAKE,
config,
vec![
(SHAKE_STRENGTH, GDValue::Int(strength)),
(SHAKE_INTERVAL, GDValue::Float(interval)),
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(duration)),
],
)
}
#[inline]
pub fn bg_speed(config: &GDObjConfig, mod_x: f64, mod_y: f64) -> GDObject {
GDObject::new(
BG_SPEED_CONFIG,
config,
vec![
(X_MOVEMENT_MULTIPLIER, GDValue::Float(mod_x)),
(Y_MOVEMENT_MULTIPLIER, GDValue::Float(mod_y)),
],
)
}
#[inline]
pub fn mg_speed(config: &GDObjConfig, mod_x: f64, mod_y: f64) -> GDObject {
GDObject::new(
MG_SPEED_CONFIG,
config,
vec![
(X_MOVEMENT_MULTIPLIER, GDValue::Float(mod_x)),
(Y_MOVEMENT_MULTIPLIER, GDValue::Float(mod_y)),
],
)
}
#[inline]
pub fn player_control(
config: &GDObjConfig,
p1: bool,
p2: bool,
stop_jump: bool,
stop_move: bool,
stop_rotation: bool,
stop_slide: bool,
) -> GDObject {
GDObject::new(
TRIGGER_PLAYER_CONTROL,
config,
vec![
(CONTROLLING_PLAYER_1, GDValue::Bool(p1)),
(CONTROLLING_PLAYER_2, GDValue::Bool(p2)),
(STOP_PLAYER_JUMP, GDValue::Bool(stop_jump)),
(STOP_PLAYER_MOVEMENT, GDValue::Bool(stop_move)),
(STOP_PLAYER_ROTATION, GDValue::Bool(stop_rotation)),
(STOP_PLAYER_SLIDING, GDValue::Bool(stop_slide)),
],
)
}
pub fn gravity_trigger(
config: &GDObjConfig,
gravity: f64,
target_player: Option<TargetPlayer>,
) -> GDObject {
let mut properties = vec![(GRAVITY, GDValue::Float(gravity))];
if let Some(player) = target_player {
properties.push((player as u16, GDValue::Bool(true)));
}
GDObject::new(TRIGGER_GRAVITY, config, properties)
}
pub fn end_trigger(
config: &GDObjConfig,
spawn_id: Option<i16>,
target_pos: Option<i16>,
no_effects: bool,
instant: bool,
no_sfx: bool,
) -> GDObject {
let mut properties = vec![
(NO_END_EFFECTS, GDValue::Bool(no_effects)),
(INSTANT_END, GDValue::Bool(instant)),
(NO_END_SOUND_EFFECTS, GDValue::Bool(no_sfx)),
];
if let Some(id) = spawn_id {
properties.push((TARGET_ITEM, GDValue::Group(id)));
}
if let Some(pos) = target_pos {
properties.push((TARGET_ITEM_2, GDValue::Group(pos)));
}
GDObject::new(TRIGGER_END, config, properties)
}
pub fn counter_object(
config: &GDObjConfig,
item: Item,
align: ItemAlign,
seconds_only: bool,
) -> GDObject {
let mut properties = vec![
(SECONDS_ONLY, GDValue::Bool(seconds_only)),
(COUNTER_ALIGNMENT, GDValue::Int(align.to_num())),
];
match item {
Item::Attempts | Item::MainTime | Item::Points => {
properties.push((
SPECIAL_COUNTER_MODE,
GDValue::Int(item.as_special_mode_i32().unwrap()),
));
}
Item::Counter(c) => {
properties.push((INPUT_ITEM_1, GDValue::Item(c)));
}
Item::Timer(t) => {
properties.extend_from_slice(&[
(INPUT_ITEM_1, GDValue::Item(t)),
(IS_TIMER, GDValue::Bool(true)),
]);
}
}
GDObject::new(COUNTER, config, properties)
}
#[allow(clippy::too_many_arguments)]
pub fn item_edit(
config: &GDObjConfig,
operand1: Option<Item>,
operand2: Option<Item>,
target: Item,
modifier: f64,
assign_op: Op,
multiply_mod: bool,
id_op: Option<Op>,
id_rounding: RoundMode,
result_rounding: RoundMode,
id_sign: SignMode,
result_sign: SignMode,
) -> GDObject {
let mod_op = match multiply_mod {
true => Op::Mul,
false => Op::Div,
};
let id_op = match id_op {
Some(op) => op,
None => Op::Add,
};
let mut properties = vec![
(TARGET_ITEM, GDValue::Item(target.id())),
(TARGET_ITEM_TYPE, GDValue::Int(target.get_type_as_i32())),
(MODIFIER, GDValue::Float(modifier)),
(LEFT_OPERATOR, GDValue::Int(assign_op.to_num())),
(RIGHT_OPERATOR, GDValue::Int(id_op.to_num())),
(COMPARE_OPERATOR, GDValue::Int(mod_op.to_num())),
(LEFT_ROUND_MODE, GDValue::Int(id_rounding as i32)),
(RIGHT_ROUND_MODE, GDValue::Int(result_rounding as i32)),
(LEFT_SIGN_MODE, GDValue::Int(id_sign as i32)),
(RIGHT_SIGN_MODE, GDValue::Int(result_sign as i32)),
];
if let Some(item) = operand1 {
properties.extend_from_slice(&[
(INPUT_ITEM_1, GDValue::Item(item.id())),
(FIRST_ITEM_TYPE, GDValue::Int(item.get_type_as_i32())),
]);
}
if let Some(item) = operand2 {
properties.extend_from_slice(&[
(INPUT_ITEM_2, GDValue::Item(item.id())),
(SECOND_ITEM_TYPE, GDValue::Int(item.get_type_as_i32())),
]);
}
GDObject::new(TRIGGER_ITEM_EDIT, config, properties)
}
pub fn item_compare(
config: &GDObjConfig,
true_id: i16,
false_id: i16,
lhs: CompareOperand,
rhs: CompareOperand,
compare_op: CompareOp,
tolerance: f64,
) -> GDObject {
let properties = vec![
(TARGET_ITEM, GDValue::Item(true_id)),
(TARGET_ITEM_2, GDValue::Item(false_id)),
(INPUT_ITEM_1, GDValue::Item(lhs.operand_item.id())),
(INPUT_ITEM_2, GDValue::Item(rhs.operand_item.id())),
(
FIRST_ITEM_TYPE,
GDValue::Int(lhs.operand_item.get_type_as_i32()),
),
(
SECOND_ITEM_TYPE,
GDValue::Int(rhs.operand_item.get_type_as_i32()),
),
(MODIFIER, GDValue::Float(lhs.modifier)),
(SECOND_MODIFIER, GDValue::Float(rhs.modifier)),
(LEFT_OPERATOR, GDValue::Int(lhs.mod_op.to_num())),
(RIGHT_OPERATOR, GDValue::Int(rhs.mod_op.to_num())),
(COMPARE_OPERATOR, GDValue::Int(compare_op.to_num())),
(TOLERANCE, GDValue::Float(tolerance)),
(LEFT_ROUND_MODE, GDValue::Int(lhs.rounding as i32)),
(RIGHT_ROUND_MODE, GDValue::Int(rhs.rounding as i32)),
(LEFT_SIGN_MODE, GDValue::Int(lhs.sign as i32)),
(RIGHT_SIGN_MODE, GDValue::Int(rhs.sign as i32)),
];
GDObject::new(TRIGGER_ITEM_COMPARE, config, properties)
}
pub fn persistent_item(
config: &GDObjConfig,
item_id: i16,
timer: bool,
persistent: bool,
target_all: bool,
reset: bool,
) -> GDObject {
GDObject::new(
TRIGGER_PERSISTENT_ITEM,
config,
vec![
(TARGET_ITEM, GDValue::Item(item_id)),
(SET_PERSISTENT_ITEM, GDValue::Bool(persistent)),
(TARGET_ALL_PERSISTENT_ITEMS, GDValue::Bool(target_all)),
(RESET_ITEM_TO_0, GDValue::Bool(reset)),
(TIMER, GDValue::Bool(timer)),
],
)
}
pub fn random_trigger(
config: &GDObjConfig,
chance: f64,
target_group1: i16,
target_group2: i16,
) -> GDObject {
GDObject::new(
TRIGGER_RANDOM,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group1)),
(TARGET_ITEM_2, GDValue::Group(target_group2)),
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(chance)),
],
)
}
pub fn spawn_trigger(
config: &GDObjConfig,
spawn_id: i16,
delay: f64,
delay_variation: f64,
reset_remap: bool,
spawn_ordered: bool,
preview_disable: bool,
spawn_remap: Vec<(i16, i16)>,
) -> GDObject {
GDObject::new(
TRIGGER_SPAWN,
config,
vec![
(TARGET_ITEM, GDValue::Group(spawn_id)),
(SPAWN_DELAY, GDValue::Float(delay)),
(DISABLE_PREVIEW, GDValue::Bool(preview_disable)),
(SPAWN_ORDERED, GDValue::Bool(spawn_ordered)),
(SPAWN_DELAY_VARIATION, GDValue::Float(delay_variation)),
(RESET_REMAP, GDValue::Bool(reset_remap)),
(SPAWN_ID_REMAPS, GDValue::from_spawn_remaps(spawn_remap)),
],
)
}
#[inline]
pub fn on_death(config: &GDObjConfig, target_group: i16, activate_group: bool) -> GDObject {
GDObject::new(
TRIGGER_ON_DEATH,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(ACTIVATE_GROUP, GDValue::Bool(activate_group)),
],
)
}
pub fn spawn_particle(
config: &GDObjConfig,
particle_group: i16,
position_group: i16,
spawn_cfg: ParticleSpawnConfig,
) -> GDObject {
let mut properties = vec![
(TARGET_ITEM, GDValue::Group(particle_group)),
(TARGET_ITEM_2, GDValue::Group(position_group)),
(
MATCH_ROTATION_OF_SPAWNED_PARTICLES,
GDValue::Bool(spawn_cfg.match_rotation),
),
];
if let Some((x, y)) = spawn_cfg.position_offsets {
properties.push((X_OFFSET_OF_SPAWNED_PARTICLES, GDValue::Int(x)));
properties.push((Y_OFFSET_OF_SPAWNED_PARTICLES, GDValue::Int(y)));
}
if let Some((x, y)) = spawn_cfg.position_variation {
properties.push((X_OFFSET_VARIATION_OF_SPAWNED_PARTICLES, GDValue::Int(x)));
properties.push((Y_OFFSET_VARIATION_OF_SPAWNED_PARTICLES, GDValue::Int(y)));
}
if let Some((rot, var)) = spawn_cfg.rotation_config {
properties.push((ROTATION_OF_SPAWNED_PARTICLES, GDValue::Int(rot)));
properties.push((ROTATION_VARIATION_OF_SPAWNED_PARTICLES, GDValue::Int(var)));
}
if let Some((scale, var)) = spawn_cfg.scale_config {
properties.push((SCALE_OF_SPAWNED_PARTICLES, GDValue::Float(scale)));
properties.push((SCALE_VARIATION_OF_SPAWNED_PARTICLES, GDValue::Float(var)));
}
GDObject::new(TRIGGER_SPAWN_PARTICLE, config, properties)
}
#[inline]
pub fn collision_block(config: &GDObjConfig, id: i16, dynamic: bool) -> GDObject {
GDObject::new(
COLLISION_BLOCK,
config,
vec![
(INPUT_ITEM_1, GDValue::Item(id)),
(DYNAMIC_BLOCK, GDValue::Bool(dynamic)),
],
)
}
#[inline]
pub fn toggle_block(
config: &GDObjConfig,
target_group: i16,
activate_group: bool,
claim_touch: bool,
multi_activate: bool,
spawn_only: bool,
) -> GDObject {
GDObject::new(
TOGGLE_BLOCK,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(ACTIVATE_GROUP, GDValue::Bool(activate_group)),
(MULTI_ACTIVATE, GDValue::Bool(multi_activate)),
(CLAIM_TOUCH, GDValue::Bool(claim_touch)),
(SPAWN_ONLY, GDValue::Bool(spawn_only)),
],
)
}
#[inline]
pub fn state_block(config: &GDObjConfig, state_on: i16, state_off: i16) -> GDObject {
GDObject::new(
COLLISION_STATE_BLOCK,
config,
vec![
(TARGET_ITEM, GDValue::Group(state_on)),
(TARGET_ITEM_2, GDValue::Group(state_off)),
],
)
}
#[inline]
pub fn collision_trigger(
config: &GDObjConfig,
collider_cfg: ColliderConfig,
target_id: i16,
activate_group: bool,
trigger_on_exit: bool,
) -> GDObject {
GDObject::new(
TRIGGER_COLLISION,
config,
vec![
(INPUT_ITEM_1, GDValue::Item(collider_cfg.collider1)),
(INPUT_ITEM_2, GDValue::Item(collider_cfg.collider2)),
(TARGET_ITEM, GDValue::Item(target_id)),
(
CONTROLLING_PLAYER_1,
GDValue::Bool(collider_cfg.collide_player1),
),
(
CONTROLLING_PLAYER_2,
GDValue::Bool(collider_cfg.collide_player2),
),
(
CONTROLLING_TARGET_PLAYER,
GDValue::Bool(collider_cfg.collide_both_players),
),
(ACTIVATE_GROUP, GDValue::Bool(activate_group)),
(TRIGGER_ON_EXIT, GDValue::Bool(trigger_on_exit)),
],
)
}
#[inline]
pub fn instant_coll_trigger(
config: &GDObjConfig,
collider_cfg: ColliderConfig,
true_id: i16,
false_id: i16,
) -> GDObject {
GDObject::new(
TRIGGER_COLLISION,
config,
vec![
(INPUT_ITEM_1, GDValue::Item(collider_cfg.collider1)),
(INPUT_ITEM_2, GDValue::Item(collider_cfg.collider2)),
(TARGET_ITEM, GDValue::Item(true_id)),
(TARGET_ITEM_2, GDValue::Item(false_id)),
(
CONTROLLING_PLAYER_1,
GDValue::Bool(collider_cfg.collide_player1),
),
(
CONTROLLING_PLAYER_2,
GDValue::Bool(collider_cfg.collide_player2),
),
(
CONTROLLING_TARGET_PLAYER,
GDValue::Bool(collider_cfg.collide_both_players),
),
],
)
}
pub fn time_trigger(
config: &GDObjConfig,
time_cfg: TimeTriggerConfig,
target_group: i16,
) -> GDObject {
GDObject::new(
TRIGGER_TIME,
config,
vec![
(START_TIME, GDValue::Float(time_cfg.start_time)),
(TARGET_TIME, GDValue::Float(time_cfg.stop_time)),
(
PAUSE_AT_TARGET_TIME,
GDValue::Bool(time_cfg.pause_when_reached),
),
(TIME_VALUE_MULTIPLER, GDValue::Float(time_cfg.time_mod)),
(INPUT_ITEM_1, GDValue::Item(time_cfg.timer_id)),
(TARGET_ITEM, GDValue::Group(target_group)),
(IGNORE_TIMEWARP, GDValue::Bool(time_cfg.ignore_timewarp)),
(START_PAUSED_TIMER, GDValue::Bool(time_cfg.start_paused)),
(DONT_OVERRIDE, GDValue::Bool(time_cfg.dont_override)),
],
)
}
#[inline]
pub fn time_control(config: &GDObjConfig, id: i16, stop: bool) -> GDObject {
GDObject::new(
TRIGGER_TIME_CONTROL,
config,
vec![
(INPUT_ITEM_1, GDValue::Item(id)),
(STOP_TIME_COUNTER, GDValue::Bool(stop)),
],
)
}
#[inline]
pub fn time_event(
config: &GDObjConfig,
id: i16,
target_group: i16,
target_time: f64,
multi_activate: bool,
) -> GDObject {
GDObject::new(
TRIGGER_TIME_EVENT,
config,
vec![
(INPUT_ITEM_1, GDValue::Group(id)),
(TARGET_ITEM, GDValue::Group(target_group)),
(TARGET_TIME, GDValue::Float(target_time)),
(MULTIACTIVATABLE_TIME_EVENT, GDValue::Bool(multi_activate)),
],
)
}
pub fn camera_zoom(
config: &GDObjConfig,
zoom: f64,
time: f64,
easing: Option<(MoveEasing, f64)>,
) -> GDObject {
let mut properties = vec![
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(time)),
(CAMERA_ZOOM, GDValue::Float(zoom)),
];
if let Some((easing, rate)) = easing {
properties.push((MOVE_EASING, GDValue::Int(easing as i32)));
properties.push((EASING_RATE, GDValue::Float(rate)));
}
GDObject::new(TRIGGER_CAMERA_ZOOM, config, properties)
}
#[inline]
pub fn camera_guide(
config: &GDObjConfig,
zoom: f64,
offset_x: i32,
offset_y: i32,
opacity: f64,
) -> GDObject {
GDObject::new(
CAMERA_GUIDE,
config,
vec![
(MOVE_UNITS_X, GDValue::Int(offset_x)),
(MOVE_UNITS_Y, GDValue::Int(offset_y)),
(CAMERA_ZOOM, GDValue::Float(zoom)),
(CAMERA_GUIDE_PREVIEW_OPACITY, GDValue::Float(opacity)),
],
)
}
#[inline]
pub fn follow_trigger(
config: &GDObjConfig,
x_mod: f64,
y_mod: f64,
follow_time: f64,
target_group: i16,
follow_group: i16,
) -> GDObject {
GDObject::new(
TRIGGER_FOLLOW,
config,
vec![
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(follow_time)),
(XAXIS_FOLLOW_MOD, GDValue::Float(x_mod)),
(YAXIS_FOLLOW_MOD, GDValue::Float(y_mod)),
(TARGET_ITEM, GDValue::Group(target_group)),
(TARGET_ITEM_2, GDValue::Group(follow_group)),
],
)
}
#[inline]
pub fn animate_trigger(config: &GDObjConfig, target_group: i16, animation: Anim) -> GDObject {
GDObject::new(
TRIGGER_ANIMATE,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(ANIMATION_ID, GDValue::Int(animation.into())),
],
)
}
#[inline]
pub fn count_trigger(
config: &GDObjConfig,
item_id: i16,
target_id: i16,
target_count: i32,
activate_group: bool,
multi_activate: bool,
) -> GDObject {
GDObject::new(
TRIGGER_COUNT,
config,
vec![
(INPUT_ITEM_1, GDValue::Item(item_id)),
(TARGET_ITEM, GDValue::Group(target_id)),
(TARGET_COUNT, GDValue::Int(target_count)),
(ACTIVATE_GROUP, GDValue::Bool(activate_group)),
(MULTI_ACTIVATE, GDValue::Bool(multi_activate)),
],
)
}
#[inline]
pub fn advanced_random_trigger(config: &GDObjConfig, probabilities: Vec<(i16, i32)>) -> GDObject {
GDObject::new(
TRIGGER_ADVANCED_RANDOM,
config,
vec![(
RANDOM_PROBABILITIES_LIST,
GDValue::from_prob_list(probabilities),
)],
)
}
#[inline]
pub fn ui_config_trigger(
config: &GDObjConfig,
target_group: i16,
ui_reference_obj: i16,
x_reference: UIReferencePos,
y_reference: UIReferencePos,
x_ref_relative: bool,
y_ref_relative: bool,
) -> GDObject {
GDObject::new(
UI_CONFIG,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(TARGET_ITEM_2, GDValue::Group(ui_reference_obj)),
(X_REFERENCE_POSITION, GDValue::Int(x_reference as i32)),
(Y_REFERENCE_POSITION, GDValue::Int(y_reference as i32 + 4)),
(X_REFERENCE_IS_RELATIVE, GDValue::Bool(x_ref_relative)),
(Y_REFERENCE_IS_RELATIVE, GDValue::Bool(y_ref_relative)),
],
)
}
pub fn rotate_trigger(
config: &GDObjConfig,
move_time: f64,
rotation_cfg: RotationConfig,
easing: Option<(MoveEasing, f64)>,
target_group: i16,
center_group_id: i16,
bounding_box: Option<(i16, i16, i16, i16)>,
) -> GDObject {
let mut properties = vec![
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(move_time)),
(DYNAMIC_MOVE, GDValue::Bool(rotation_cfg.dynamic_mode)),
(
LOCK_OBJECT_ROTATION,
GDValue::Bool(rotation_cfg.lock_object_rotation),
),
(TARGET_ITEM, GDValue::Group(target_group)),
(TARGET_ITEM_2, GDValue::Group(center_group_id)),
];
match rotation_cfg.mode {
RotationMode::Aim(cfg) => {
properties.extend_from_slice(&[
(TARGET_MOVE_MODE, GDValue::Bool(true)),
(ROTATION_TARGET_ID, GDValue::Group(cfg.aim_target)),
(ROTATION_OFFSET, GDValue::Float(cfg.rot_offset)),
]);
if let Some(player) = cfg.player_target {
properties.push(match player {
RotationPlayerTarget::Player1 => (CONTROLLING_PLAYER_1, GDValue::Bool(true)),
RotationPlayerTarget::Player2 => (CONTROLLING_PLAYER_2, GDValue::Bool(true)),
});
}
}
RotationMode::Follow(cfg) => {
properties.extend_from_slice(&[
(DIRECTIONAL_MOVE_MODE, GDValue::Bool(true)),
(ROTATION_TARGET_ID, GDValue::Group(cfg.aim_target)),
(ROTATION_OFFSET, GDValue::Float(cfg.rot_offset)),
]);
if let Some(player) = cfg.player_target {
properties.push(match player {
RotationPlayerTarget::Player1 => (CONTROLLING_PLAYER_1, GDValue::Bool(true)),
RotationPlayerTarget::Player2 => (CONTROLLING_PLAYER_2, GDValue::Bool(true)),
});
}
}
RotationMode::Default(cfg) => {
properties.extend_from_slice(&[
(ROTATE_DEGREES, GDValue::Float(cfg.degrees)),
(ROTATE_X360, GDValue::Int(cfg.x360)),
]);
}
}
add_easing(&mut properties, easing);
if let Some((min_x, min_y, max_x, max_y)) = bounding_box {
properties.extend_from_slice(&[
(MINX_ID, GDValue::Group(min_x)),
(MINY_ID, GDValue::Group(min_y)),
(MAXX_ID, GDValue::Group(max_x)),
(MAXY_ID, GDValue::Group(max_y)),
]);
}
GDObject::new(TRIGGER_ROTATION, config, properties)
}
pub fn scale_trigger(
config: &GDObjConfig,
scale_config: ScaleConfig,
easing: Option<(MoveEasing, f64)>,
center_group_id: i16,
target_group: i16,
duration: f64,
) -> GDObject {
let mut properties = vec![
(NEW_X_SCALE, GDValue::Float(scale_config.x_scale)),
(NEW_Y_SCALE, GDValue::Float(scale_config.y_scale)),
(DIV_BY_VALUE_X, GDValue::Bool(scale_config.div_by_value_x)),
(DIV_BY_VALUE_Y, GDValue::Bool(scale_config.div_by_value_y)),
(TARGET_ITEM, GDValue::Group(target_group)),
(TARGET_ITEM_2, GDValue::Group(center_group_id)),
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(duration)),
(ONLY_MOVE, GDValue::Bool(scale_config.only_move)),
(RELATIVE_SCALE, GDValue::Bool(scale_config.relative_scale)),
(
RELATIVE_ROTATION,
GDValue::Bool(scale_config.relative_rotation),
),
];
add_easing(&mut properties, easing);
GDObject::new(TRIGGER_SCALE, config, properties)
}
#[inline]
pub fn follow_player_y(
config: &GDObjConfig,
speed: f64,
delay: f64,
offset: i32,
max_speed: f64,
move_time: f64,
target_group: i16,
) -> GDObject {
GDObject::new(
TRIGGER_FOLLOW_PLAYER_Y,
config,
vec![
(FOLLOW_SPEED, GDValue::Float(speed)),
(FOLLOW_DELAY, GDValue::Float(delay)),
(FOLLOW_OFFSET, GDValue::Int(offset)),
(MAX_FOLLOW_SPEED, GDValue::Float(max_speed)),
(DURATION_GROUP_TRIGGER_CHANCE, GDValue::Float(move_time)),
(TARGET_ITEM, GDValue::Group(target_group)),
],
)
}
#[inline]
pub fn mg_config(
config: &GDObjConfig,
offset_y: i32,
easing: Option<(MoveEasing, f64)>,
) -> GDObject {
let mut properties = vec![(MOVE_UNITS_Y, GDValue::Int(offset_y))];
add_easing(&mut properties, easing);
GDObject::new(TRIGGER_MIDDLEGROUND_CONFIG, config, properties)
}
fn add_easing(properties: &mut Vec<(u16, GDValue)>, easing: Option<(MoveEasing, f64)>) {
if let Some((easing, rate)) = easing {
properties.extend_from_slice(&[
(MOVE_EASING, GDValue::Easing(easing)),
(EASING_RATE, GDValue::Float(rate)),
]);
}
}
pub fn event_trigger(
config: &GDObjConfig,
target_group: i16,
events: Vec<Event>,
extra_id: i16,
extra_id2: ExtraID2,
) -> GDObject {
GDObject::new(
TRIGGER_EVENT,
config,
vec![
(IS_INTERACTABLE, GDValue::Bool(true)),
(TARGET_ITEM, GDValue::Group(target_group)),
(EVENT_LISTENERS, GDValue::Events(events)),
(EVENT_EXTRA_ID, GDValue::Group(extra_id)),
(EVENT_EXTRA_ID_2, GDValue::Int(extra_id2 as i32)),
],
)
}
pub fn middle_ground_trigger(config: &GDObjConfig, middleground: MiddleGround) -> GDObject {
GDObject::new(
TRIGGER_MIDDLEGROUND_CHANGE,
config,
vec![(MIDDLEGROUND, GDValue::Int(middleground as i32))],
)
}
pub fn touch_trigger(
config: &GDObjConfig,
target_group: i16,
hold_mode: bool,
dual_mode: bool,
toggle: TouchToggle,
target_player: OptionalPlayerTarget,
) -> GDObject {
GDObject::new(
TRIGGER_TOUCH,
config,
vec![
(TARGET_ITEM, GDValue::Group(target_group)),
(TOUCH_HOLD_MODE, GDValue::Bool(hold_mode)),
(TOUCH_DUAL_MODE, GDValue::Bool(dual_mode)),
(TOUCH_TOGGLE_ONOFF, GDValue::Int(toggle as i32)),
(TOUCH_PLAYER_ONLY, GDValue::Int(target_player as i32)),
],
)
}
pub fn area_stop(config: &GDObjConfig, effect_id: i16) -> GDObject {
GDObject::new(
TRIGGER_AREA_STOP,
config,
vec![(TARGET_ITEM, GDValue::Short(effect_id))],
)
}