/**
* @module group
*/
/**
* @typedef {object} group
* @property {function} remap Remaps multiple IDs inside of the group to others
* @property {function} move Moves the group
* @property {function} call Calls the group
* @property {function} alpha Alpha trigger implementation
* @property {function} lock_to_player Locks group to player
* @property {function} stop Stops the current group
* @property {function} toggle_on Toggles the group on
* @property {function} toggle_off Toggles the group off
* @property {function} rotate Rotates the group
* @property {function} follow Makes the group follow another
* @property {function} follow_lerp Keeps an object's position proportionally between 2 others
* @property {function} follow_player_y Follows player Y
* @property {function} move_to Move target implementation
* @property {function} move_to_xy Moves group to specific coordinate
* @property {function} pulse_hsv Pulses group w/ HSV
* @property {function} pulse Pulses group
*/
/**
* Representation of groups
* @class
* @constructor
* @public
*/
class $group {
/**
* Creates a group from a number
* @param {number} number Group ID
* @param {boolean} [specific=true] Whether to disallow G.js from using that specific group again
*/
constructor(a, specific = true) {
this.value = a;
this.type = 'group';
if (specific && !all_known.groups.includes(a)) all_known.groups.push(a);
}
/**
* Remaps multiple IDs inside of the group to others
* @param {...array} remaps Array of groups to remap, e.g. remap([group(1), group(2)], [group(4), group(3)]) is valid
*/
remap(...mps) {
mps = mps.map(x => (x[0].value ? x[0].value : x[0]) + '.' + (x[1].value ? x[1].value : x[1])).join('.');
this.remaps = mps;
return this;
}
/**
* Moves the group
* @param {number} x Movement on X axis
* @param {number} y Movement on Y axis
* @param {number} duration Duration for move trigger
* @param {easing} easing How smoothly object moves
* @param {number} easing_rate Easing rate for move trigger
* @param {number} x_multiplier How much to multiply the amount by on X axis
* @param {number} y_multiplier How much to multiply the amount by on Y axis
* @param {boolean} multiply Whether to fit the amount of units moved into GD units (multiplying by 3 does this)
* * @param {boolean} silent Make move trigger take no time
*/
move(x, y, duration = 0, easing = NONE, easing_rate = 2, x_multiplier = 1, y_multiplier = 1, multiply = true, silent = false) {
$.add(object({
OBJ_ID: 901,
TARGET: this,
MOVE_X: multiply ? x * 3 * x_multiplier : x * x_multiplier,
MOVE_Y: multiply ? y * 3 * y_multiplier : y * y_multiplier,
DURATION: duration,
EASING: easing,
EASING_RATE: easing_rate,
}).with(544, silent));
wait(duration);
}
/**
* Scales the group
* @param {group} center Center of group for scaling
* @param {number} scale_x Scaling on X axis
* @param {number} scale_y Scaling on Y axis
* @param {number} [duration=0] Duration for scale trigger
* @param {easing} [easing=NONE] How smoothly object gets scaled
* @param {number} [easing_rate=2] Easing rate for scale trigger
* @param {boolean} [x_divide=false] Whether to divide the current scaling by scale_x
* @param {boolean} [y_divide=false] Whether to divide the current scaling by scale_y
* @param {boolean} [move_only=false] Whether to emulate the effect of scaling without actually scaling the group by moving the group instead
* @param {boolean} [relative_scale=false] Bases scaling on the reference object
* @param {boolean} [relative_rot=false] Whether to rotate the X and Y axis
*/
scale(center, scale_x, scale_y, duration = 0, easing = NONE, easing_rate = 2, x_divide = false, y_divide = false, move_only = false, relative_scale = false, relative_rot = false) {
$.add(object({
OBJ_ID: 2067,
CENTER: center,
DURATION: duration,
EASING_RATE: easing_rate,
SCALE_X_BY: scale_x,
SCALE_Y_BY: scale_y,
DIV_BY_X: x_divide,
DIV_BY_Y: y_divide,
ONLY_MOVE: move_only,
RELATIVE_SCALE: relative_scale,
RELATIVE_ROT: relative_rot,
}))
}
/**
* Animate trigger implementation
* @param {number} [anim_id=0] Animation ID (can also use `animations.[monster].[animation name]`, check index module for more info about animation IDs)
*/
animate(anim_id = 0) {
$.add(object({
OBJ_ID: 1585,
TARGET: this,
ANIMATION_GID: anim_id
}));
}
/**
* Calls the group
* @param {number} delay How long to delay the group being called
*/
call(delay = 0) {
let tr = spawn_trigger(this, delay);
if (this.remaps) tr.obj_props.REMAPS = this.remaps;
$.add(tr);
}
/**
* Alpha trigger implementation
* @param {number} opacity Changed opacity
* @param {number} duration How long it takes for the opacity to change
*/
alpha(opacity = 1, duration = 0) {
$.add(object({
OBJ_ID: 1007,
TARGET: this,
OPACITY: opacity,
DURATION: duration,
}));
wait(duration);
}
/**
* Locks group to player
* @param {boolean} [lock_x=true] Whether to lock to X axis of player
* @param {boolean} [lock_y=true] Whether to lock to Y axis of player
* @param {number} [duration=999] How long group is locked to player
*/
lock_to_player(lock_x = true, lock_y = true, duration = 999) {
$.add(object({
OBJ_ID: 901,
TARGET: this,
DURATION: duration,
LOCK_TO_PLAYER_X: lock_x,
LOCK_TO_PLAYER_Y: lock_y,
}));
}
/**
* Stops the current group
*/
stop() {
$.add(object({
OBJ_ID: 1616,
TARGET: this,
}));
}
/**
* Pauses the current group
*/
pause() {
$.add(object({
OBJ_ID: 1616,
TARGET: this,
STOP_PAUSE_RESUME: 1
}));
}
/**
* Resumes the current group
*/
resume() {
$.add(object({
OBJ_ID: 1616,
TARGET: this,
STOP_PAUSE_RESUME: 2
}));
}
/**
* Toggles the group on
*/
toggle_on() {
$.add(object({
OBJ_ID: 1049,
TARGET: this,
ACTIVATE_GROUP: true,
}));
}
/**
* Toggles the group off
*/
toggle_off() {
$.add(object({
OBJ_ID: 1049,
TARGET: this,
ACTIVATE_GROUP: false,
}));
}
/**
* Rotates the group
* @param {group} center Group to rotate around
* @param {number} degrees How many degrees to rotate
* @param {number} [duration=0] How long it takes for the group to rotate
* @param {easing} [easing=NONE] How smoothly the object rotates
* @param {number} [easing_rate=2] Easing rate of rotation
* @param {boolean} [lock_object_rotation=false] Whether to turn on "lock object rotation"
*/
rotate(center, degrees, duration = 0, easing = NONE, easing_rate = 2, lock_object_rotation = false) {
$.add(object({
OBJ_ID: 1346,
TARGET: this,
CENTER: center,
ROTATE_DEGREES: degrees,
DURATION: duration,
EASING: easing.id,
EASING_RATE: easing_rate,
LOCK_OBJECT_ROTATION: lock_object_rotation
}));
wait(duration);
}
/**
* Makes the group follow another
* @param {group} other Group to follow
* @param {number} x_mod How much to speed up/slow down movement on X axis
* @param {number} y_mod How much to speed up/slow down movement on Y axis
* @param {number} duration How long to follow other group
*/
follow(other, x_mod = 1, y_mod = 1, duration = 999) {
$.add(object({
OBJ_ID: 1347,
X_MOD: x_mod,
Y_MOD: y_mod,
DURATION: duration,
TARGET: this,
FOLLOW: other,
}));
}
/**
* Keeps an object's position proportionally between 2 others
* @param {group} groupA Group of object A to follow
* @param {group} groupB Group of object B to follow
* @param {number} weight How much of the way the group should be kept in
* @param {number} duration How long to follow
*/
follow_lerp(groupA, groupB, weight = 0.5, duration = 999) {
this.follow(groupA, 1 - weight, 1 - weight, duration);
this.follow(groupB, weight, weight, duration)
}
/**
* Follows player Y
* @param {number} [speed=0] How fast group snaps to player Y position
* @param {number} [delay=0] Delay of movement
* @param {number} [offset=0] Offset of group
* @param {number} [max_speed=0] How fast movement of group can be
* @param {number} [duration=0] How long the group is locked to player Y axis
*/
follow_player_y(speed = 1, delay = 0, offset = 0, max_speed = 0, duration = 999) {
$.add(object({
OBJ_ID: 1814,
SPEED: speed,
DELAY: delay,
Y_OFFSET: offset,
MAX_SPEED: max_speed,
TARGET: this,
DURATION: duration,
}));
}
/**
* Move target implementation
* @param {group} target Group to move to
* @param {number} duration How long it takes to move to target
* @param {boolean} x_only Whether to only move on X axis
* @param {boolean} y_only Whether to only move on Y axis
* @param {easing} easing Easing of movement
* @param {number} easing_rate Easing rate of movement
*/
move_to(target, duration = 0, x_only = false, y_only = false, easing = NONE, easing_rate = 2) {
$.add(object({
OBJ_ID: 901,
TARGET: this,
USE_TARGET: true,
TARGET_POS_AXES: x_only && y_only ? 0 : (x_only ? 1 : (y_only ? 2 : 0)),
TARGET_POS: target,
DURATION: duration,
EASING: easing,
EASING_RATE: easing_rate,
}));
wait(duration);
}
/**
* Moves group to specific coordinate
* @param {number} x X coordinate
* @param {number} y Y coordinate
* @param {number} [duration=0] Duration of movement
* @param {easing} [easing=0] Easing of movement
* @param {number} [easing_rate=2] Easing rate of movement
*/
move_to_xy(x, y, duration = 0, easing = NONE, easing_rate = 2) {
if (!x && !y) throw new Error("At least one coordinate must be specified!");
let target = unknown_g();
$.add(object({
OBJ_ID: 1765,
X: x ? x : 0,
Y: y ? y : 0,
GROUPS: target,
}));
$.add(object({
OBJ_ID: 1007,
X: 0,
Y: 75 * 30,
TARGET: target,
OPACITY: 0,
DURATION: 0,
}));
this.move_to(target, duration, !y, !x, easing, easing_rate);
}
/**
* Pulses group w/ HSV
* @param {number} h Hue
* @param {number} s Saturation
* @param {number} b Brightness
* @param {boolean} [s_checked=false] Saturation is checked
* @param {boolean} [b_checked=false] Brightness is checked
* @param {number} [fade_in=0] Fade in
* @param {number} [hold=0] Hold
* @param {number} [fade_out=0] Fade out
* @param {number} [exclusive=false] Whether to prioritize over simultaneous pulses
*/
pulse_hsv(h, s, b, s_checked = false, b_checked = false, fade_in = 0, hold = 0, fade_out = 0, exclusive = false) {
$.add(object({
OBJ_ID: 1006,
COPIED_COLOR_HVS: [h, s, b, +s_checked, +b_checked].join("a"),
EXCLUSIVE: exclusive,
FADE_IN: fade_in,
HOLD: hold,
FADE_OUT: fade_out,
TARGET: this,
PULSE_HSV: true,
TARGET_TYPE: 1,
}));
wait(fade_in + hold + fade_out);
}
/**
* Pulses group
* @param {array} color RGB color to pulse
* @param {number} [fade_in=0] Fade in
* @param {number} [hold=0] Hold
* @param {number} [fade_out=0] Fade out
* @param {number} [exclusive=false] Whether to prioritize over simultaneous pulses
*/
pulse(c, fade_in = 0, hold = 0, fade_out = 0, exclusive = false) {
$.add(object({
OBJ_ID: 1006,
TRIGGER_RED: c[0],
TRIGGER_GREEN: c[1],
TRIGGER_BLUE: c[2],
EXCLUSIVE: exclusive,
FADE_IN: fade_in,
HOLD: hold,
FADE_OUT: fade_out,
TARGET: this,
PULSE_HSV: false,
TARGET_TYPE: 1,
}));
wait(fade_in + hold + fade_out);
}
}
module.exports = $group