/// <summary> /// Process the next ACMD command in the queue. /// </summary> /// <returns>True if we should keep processing, False to stop /// for the rest of the frame.</returns> public bool processCommand(ICommand cmd) { Hitbox newHitbox = null; if (TrueFalseSkipLength > 0) { //Skip command since its on a true/false block and the variable is set to the other value TrueFalseSkipLength -= cmd.Parameters.Count + 1; return(true); } switch (cmd.Ident) { case 0x42ACFE7D: // Asynchronous Timer, exact animation frame on which next command should run { float continueOnFrame = (float)cmd.Parameters[0]; // A way of saying strictly greater than or equal to (>=) with better precision if (doubleEquals(currentFrame, continueOnFrame) || currentFrame > continueOnFrame) { return(true); // Timer finished, keep processing ACMD commands } return(false); // Timer hasn't finished yet } case 0x4B7B6E51: // Synchronous Timer, number of animation frames to wait until next command should run { // Formula from ASM is: stopAfterFrames - ((is_active * frameSpeed) + framesSinceSyncTimerStarted) > 0 // THEN the timer has finished. if (framesSinceSyncTimerStarted < 0) { // Interesting to note that the first encounter sets the frames to 0 // in the game's code, while subsequent timer encounters increment it. // Thus a Synchronous_Timer(Frames=0) would always instantly finish. framesSinceSyncTimerStarted = 0; } else { framesSinceSyncTimerStarted += frameSpeed; } float stopAfterFrames = (int)(float)cmd.Parameters[0]; double framesPassed = stopAfterFrames - framesSinceSyncTimerStarted; // A way of saying strictly greater than (>) with better precision if (!doubleEquals(framesPassed, 0d) && framesPassed > 0) { return(false); // Timer hasn't finished yet } // Timer finished, keep processing ACMD commands framesSinceSyncTimerStarted = -1; return(true); } case 0x7172A764: // Set_Frame_Duration, sets Frame_Speed such that Arg0 ACMD frames are processed per in-game frame { if (Runtime.useFrameDuration) { frameSpeed = 1 / (float)cmd.Parameters[0]; } break; } case 0xB2E91D0C: // Used in bayo scripts to set the Frame_Speed to a specific value { if (Runtime.useFrameDuration) { frameSpeed = 1 / (float)cmd.Parameters[0]; } break; } case 0xA546845C: // Frame_Speed_Multiplier, sets Frame_Speed = Arg0 { if (Runtime.useFrameDuration) { frameSpeed = (float)cmd.Parameters[0]; } break; } case 0x9126EBA2: // Subroutine: call another script case 0xFA1BC28A: // Subroutine1: call another script // Try and load the other script. If we can't, then just keep going as per normal uint crc = (uint)int.Parse(cmd.Parameters[0] + ""); if (Runtime.Moveset.Game.Scripts.ContainsKey(crc)) //TODO: { subscripts.Add((ACMDScript)Runtime.Moveset.Game.Scripts[crc]); // Store the return scriptCommandIndex scriptStates.Push(new ScriptState( scriptCommandIndex, loopStart, loopIterations )); // Start fresh in the new script scriptCommandIndex = -1; // This is incremented immediately in the containing loop hence the -1 loopStart = 0; loopIterations = 0; } break; case 0xB738EABD: // hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Part = (int)cmd.Parameters[1]; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; newHitbox.WeightBasedKnockback = (int)cmd.Parameters[6]; newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; addOrOverwriteHitbox(id, newHitbox); break; } case 0x2988D50F: // Extended hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Part = (int)cmd.Parameters[1]; newHitbox.Extended = true; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; newHitbox.WeightBasedKnockback = (int)cmd.Parameters[6]; newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.X2 = (float)cmd.Parameters[24]; newHitbox.Y2 = (float)cmd.Parameters[25]; newHitbox.Z2 = (float)cmd.Parameters[26]; addOrOverwriteHitbox(id, newHitbox); break; } case 0x14FCC7E4: // special hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Part = (int)cmd.Parameters[1]; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; newHitbox.WeightBasedKnockback = (int)cmd.Parameters[6]; newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.FacingRestriction = (int)cmd.Parameters[34]; if (cmd.Parameters.Count > 39) { if ((int)cmd.Parameters[39] == 1) { newHitbox.Type = Hitbox.WINDBOX; } } addOrOverwriteHitbox(id, newHitbox); break; } case 0x7075DC5A: // Extended special hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Extended = true; newHitbox.Part = (int)cmd.Parameters[1]; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; newHitbox.WeightBasedKnockback = (int)cmd.Parameters[6]; newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.FacingRestriction = (int)cmd.Parameters[34]; if ((int)cmd.Parameters[39] == 1) { newHitbox.Type = Hitbox.WINDBOX; } newHitbox.X2 = (float)cmd.Parameters[40]; newHitbox.Y2 = (float)cmd.Parameters[41]; newHitbox.Z2 = (float)cmd.Parameters[42]; addOrOverwriteHitbox(id, newHitbox); break; } case 0xCC7CC705: // collateral hitbox (ignored by character being thrown) { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Part = (int)cmd.Parameters[1]; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; newHitbox.WeightBasedKnockback = (int)cmd.Parameters[6]; newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.Ignore_Throw = true; addOrOverwriteHitbox(id, newHitbox); break; } case 0xED67D5DA: // Extended collateral hitbox (ignored by character being thrown) { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Extended = true; newHitbox.Part = (int)cmd.Parameters[1]; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; newHitbox.WeightBasedKnockback = (int)cmd.Parameters[6]; newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.X2 = (float)cmd.Parameters[24]; newHitbox.Y2 = (float)cmd.Parameters[25]; newHitbox.Z2 = (float)cmd.Parameters[26]; newHitbox.Ignore_Throw = true; addOrOverwriteHitbox(id, newHitbox); break; } case 0x9245E1A8: // clear all hitboxes Hitboxes.Clear(); break; case 0xFF379EB6: // delete hitbox if (Hitboxes.ContainsKey((int)cmd.Parameters[0])) { Hitboxes.Remove((int)cmd.Parameters[0]); } break; case 0x7698BB42: // deactivate previous hitbox Hitboxes.RemoveAt(Hitboxes.Keys.Max()); break; case 0x684264C9: // Change_Hitbox_Size { int id = (int)cmd.Parameters[0]; float size = (float)cmd.Parameters[1]; Hitbox hitboxToChange = null; if (Hitboxes.TryGetValue(id, out hitboxToChange)) { hitboxToChange.Size = size; } else { Console.WriteLine($"Could not find hitbox with ID={id} to change size"); } break; } case 0xDFA4517A: // Change_Hitbox_Damage { int id = (int)cmd.Parameters[0]; float damage = (float)cmd.Parameters[1]; Hitbox hitboxToChange = null; if (Hitboxes.TryGetValue(id, out hitboxToChange)) { hitboxToChange.Damage = damage; } else { Console.WriteLine($"Could not find hitbox with ID={id} to change damage"); } break; } case 0x1AFDA8E6: // Move_Hitbox { int id = (int)cmd.Parameters[0]; Hitbox hitboxToChange = null; if (Hitboxes.TryGetValue(id, out hitboxToChange)) { hitboxToChange.Bone = (int)cmd.Parameters[1]; hitboxToChange.X = (float)cmd.Parameters[2]; hitboxToChange.Y = (float)cmd.Parameters[3]; hitboxToChange.Z = (float)cmd.Parameters[4]; } else { Console.WriteLine($"Could not find hitbox with ID={id} to move position"); } break; } case 0xEB375E3: // Set Loop loopIterations = int.Parse(cmd.Parameters[0] + "") - 1; loopStart = scriptCommandIndex; break; case 0x38A3EC78: // goto if (loopIterations > 0) { scriptCommandIndex = loopStart; loopIterations -= 1; } break; case 0x7B48FE1C: //Extended Grabbox case 0x1EAF840C: //Grabbox 2 (most command grabs) case 0x548F2D4C: //Grabbox (used in tether grabs) case 0xEF787D43: //Extended Grabbox 2 (Mega Man's grab) case 0x323FB9D4: //Special Grabbox (Pikmin's grab) { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.GRABBOX; newHitbox.Bone = int.Parse(cmd.Parameters[1] + ""); newHitbox.Size = (float)cmd.Parameters[2]; newHitbox.X = (float)cmd.Parameters[3]; newHitbox.Y = (float)cmd.Parameters[4]; newHitbox.Z = (float)cmd.Parameters[5]; if (cmd.Parameters.Count > 10) { newHitbox.X2 = float.Parse(cmd.Parameters[8] + ""); newHitbox.Y2 = float.Parse(cmd.Parameters[9] + ""); newHitbox.Z2 = float.Parse(cmd.Parameters[10] + ""); newHitbox.Extended = true; } addOrOverwriteHitbox(id, newHitbox); break; } case 0xF3A464AC: // Terminate_Grab_Collisions { List <int> toDelete = new List <int>(); foreach (KeyValuePair <int, Hitbox> kvp in Hitboxes) { if (kvp.Value.Type == Hitbox.GRABBOX) { toDelete.Add(kvp.Key); } } foreach (int index in toDelete) { Hitboxes.Remove(index); } break; } case 0x2F08F54F: // Delete_Catch_Collision by ID int idToDelete = (int)cmd.Parameters[0]; if (Hitboxes[idToDelete].Type == Hitbox.GRABBOX) { Hitboxes.Remove(idToDelete); } break; case 0x44081C21: //SEARCH { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; if (Hitboxes.ContainsKey(id)) { Hitboxes.Remove(id); } newHitbox.Type = Hitbox.SEARCHBOX; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Size = (float)cmd.Parameters[3]; newHitbox.X = (float)cmd.Parameters[4]; newHitbox.Y = (float)cmd.Parameters[5]; newHitbox.Z = (float)cmd.Parameters[6]; addOrOverwriteHitbox(id, newHitbox); break; } case 0xCD0C1CC9: //Bat Within (it clears WT SEARCH event) case 0x98203AF6: //SRH_CLEAR_ALL { List <int> toDelete = new List <int>(); foreach (KeyValuePair <int, Hitbox> kvp in Hitboxes) { if (kvp.Value.Type == Hitbox.SEARCHBOX) { toDelete.Add(kvp.Key); } } foreach (int index in toDelete) { Hitboxes.Remove(index); } break; } case 0xFAA85333: break; case 0x321297B0: break; case 0x7640AEEB: break; case 0xF13BFE8D: //Bone collision state (intangibility/invincibility) { int bone = (int)cmd.Parameters[0]; int state = (int)cmd.Parameters[1]; switch (state) { case 2: IntangibleBones.Remove(bone); InvincibleBones.Remove(bone); IntangibleBones.Add(bone); break; case 1: IntangibleBones.Remove(bone); InvincibleBones.Remove(bone); InvincibleBones.Add(bone); break; default: IntangibleBones.Remove(bone); InvincibleBones.Remove(bone); break; } break; } case 0xCEDC237E: //Undo Bone collision state { int state = (int)cmd.Parameters[0]; IntangibleBones.Clear(); InvincibleBones.Clear(); break; } case 0xF0D25BDA: //Body_Collision (Full intangibility/invincibility) { int state = (int)cmd.Parameters[0]; switch (state) { case 2: BodyInvincible = false; BodyIntangible = true; break; case 1: BodyInvincible = true; BodyIntangible = false; break; default: BodyInvincible = false; BodyIntangible = false; break; } break; } case 0x2A25155D: // Set_armor - super armor { int state = (int)cmd.Parameters[0]; if (state == 1) { SuperArmor = true; } else { SuperArmor = false; } break; } case 0x661B30DA: // Bit_Variable_Set { uint flag = (uint)((int)cmd.Parameters[0]); if (!ActiveFlags.Contains(flag)) { ActiveFlags.Add(flag); } break; } case 0x17232732: // Bit_Variable_Clear { uint flag = (uint)((int)cmd.Parameters[0]); ActiveFlags.Remove(flag); break; } case 0xA21BC6EA: //If_Bit_Is_Set case 0x34BCD3F7: //If_Compare { if (IfVariableList.ContainsKey((uint)(int)cmd.Parameters[0])) { readTrue = IfVariableList[(uint)(int)cmd.Parameters[0]]; } break; } case 0x477705C2: //unk_477705C2 If_Compare2? { if (IfVariableValueList.ContainsKey((uint)(int)cmd.Parameters[0])) { readTrue = IfVariableValueList[(uint)(int)cmd.Parameters[0]] == (int)cmd.Parameters[2]; } break; } case 0xA5BD4F32: // TRUE { if (!readTrue) { TrueFalseSkipLength = (int)cmd.Parameters[0] - 4; if (TrueFalseSkipLength == 0) { TrueFalseSkipLength = 1; } } break; } case 0x895B9275: // FALSE { if (readTrue) { TrueFalseSkipLength = (int)cmd.Parameters[0] - 2; if (TrueFalseSkipLength == 0) { TrueFalseSkipLength = 1; } } break; } case 0x0F39EC70: // Allow/Disallow Ledgegrab { int type = (int)cmd.Parameters[0]; switch (type) { case 0: LedgeGrabDisallowed = true; FrontLedgeGrabAllowed = false; ReverseLedgeGrabAllowed = false; break; case 1: LedgeGrabDisallowed = false; FrontLedgeGrabAllowed = true; break; case 2: LedgeGrabDisallowed = false; ReverseLedgeGrabAllowed = true; break; } break; } } return(true); }
public int processScriptCommandsAtCurrentFrame(ICommand cmd, int halt, ref int scriptCommandIndex) { Hitbox newHitbox = null; switch (cmd.Ident) { case 0x42ACFE7D: // Asynchronous Timer (specific frame start for next commands) { int frame = (int)(float)cmd.Parameters[0]; halt = frame >= halt + 2 ? frame - 2 : halt; break; } case 0x4B7B6E51: // Synchronous Timer (relative frame start for next commands) { halt += (int)(float)cmd.Parameters[0]; break; } case 0xB738EABD: // hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; //FKB = (float)cmd.Parameters[6] newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; addOrOverwriteHitbox(id, newHitbox); break; } case 0x2988D50F: // Extended hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Extended = true; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; //FKB = (float)cmd.Parameters[6] newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.X2 = (float)cmd.Parameters[24]; newHitbox.Y2 = (float)cmd.Parameters[25]; newHitbox.Z2 = (float)cmd.Parameters[26]; addOrOverwriteHitbox(id, newHitbox); break; } case 0x14FCC7E4: // special hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; //FKB = (float)cmd.Parameters[6] newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; if (cmd.Parameters.Count > 39) { if ((int)cmd.Parameters[39] == 1) { newHitbox.Type = Hitbox.WINDBOX; } } addOrOverwriteHitbox(id, newHitbox); break; } case 0x7075DC5A: // Extended special hitbox { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Extended = true; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; //FKB = (float)cmd.Parameters[6] newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; if ((int)cmd.Parameters[39] == 1) { newHitbox.Type = Hitbox.WINDBOX; } newHitbox.X2 = (float)cmd.Parameters[40]; newHitbox.Y2 = (float)cmd.Parameters[41]; newHitbox.Z2 = (float)cmd.Parameters[42]; addOrOverwriteHitbox(id, newHitbox); break; } case 0xCC7CC705: // collateral hitbox (ignored by character being thrown) { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; //FKB = (float)cmd.Parameters[6] newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.Ignore_Throw = true; addOrOverwriteHitbox(id, newHitbox); break; } case 0xED67D5DA: // Extended collateral hitbox (ignored by character being thrown) { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.HITBOX; newHitbox.Extended = true; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Damage = (float)cmd.Parameters[3]; newHitbox.Angle = (int)cmd.Parameters[4]; newHitbox.KnockbackGrowth = (int)cmd.Parameters[5]; //FKB = (float)cmd.Parameters[6] newHitbox.KnockbackBase = (int)cmd.Parameters[7]; newHitbox.Size = (float)cmd.Parameters[8]; newHitbox.X = (float)cmd.Parameters[9]; newHitbox.Y = (float)cmd.Parameters[10]; newHitbox.Z = (float)cmd.Parameters[11]; newHitbox.X2 = (float)cmd.Parameters[24]; newHitbox.Y2 = (float)cmd.Parameters[25]; newHitbox.Z2 = (float)cmd.Parameters[26]; newHitbox.Ignore_Throw = true; addOrOverwriteHitbox(id, newHitbox); break; } case 0x9245E1A8: // clear all hitboxes Hitboxes.Clear(); break; case 0xFF379EB6: // delete hitbox if (Hitboxes.ContainsKey((int)cmd.Parameters[0])) { Hitboxes.Remove((int)cmd.Parameters[0]); } break; case 0x7698BB42: // deactivate previous hitbox Hitboxes.Remove(Hitboxes.Keys.Max()); break; case 0xEB375E3: // Set Loop iterations = int.Parse(cmd.Parameters[0] + "") - 1; setLoop = scriptCommandIndex; break; case 0x38A3EC78: // goto if (iterations > 0) { // Can fail if a subscript has a goto with no loop starter scriptCommandIndex = setLoop; iterations -= 1; } break; case 0x7B48FE1C: //Extended Grabbox case 0x1EAF840C: //Grabbox 2 (most command grabs) case 0x548F2D4C: //Grabbox (used in tether grabs) case 0xEF787D43: //Extended Grabbox 2 (Mega Man's grab) case 0x323FB9D4: //Special Grabbox (Pikmin's grab) { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; newHitbox.Type = Hitbox.GRABBOX; newHitbox.Bone = int.Parse(cmd.Parameters[1] + ""); newHitbox.Size = (float)cmd.Parameters[2]; newHitbox.X = (float)cmd.Parameters[3]; newHitbox.Y = (float)cmd.Parameters[4]; newHitbox.Z = (float)cmd.Parameters[5]; if (cmd.Parameters.Count > 10) { newHitbox.X2 = float.Parse(cmd.Parameters[8] + ""); newHitbox.Y2 = float.Parse(cmd.Parameters[9] + ""); newHitbox.Z2 = float.Parse(cmd.Parameters[10] + ""); newHitbox.Extended = true; } addOrOverwriteHitbox(id, newHitbox); break; } case 0xF3A464AC: // Terminate_Grab_Collisions { List <int> toDelete = new List <int>(); foreach (KeyValuePair <int, Hitbox> kvp in Hitboxes) { if (kvp.Value.Type == Hitbox.GRABBOX) { toDelete.Add(kvp.Key); } } foreach (int index in toDelete) { Hitboxes.Remove(index); } break; } case 0x2F08F54F: // Delete_Catch_Collision by ID int idToDelete = (int)cmd.Parameters[0]; if (Hitboxes[idToDelete].Type == Hitbox.GRABBOX) { Hitboxes.Remove(idToDelete); } break; case 0x44081C21: //SEARCH { newHitbox = new Hitbox(); int id = (int)cmd.Parameters[0]; if (Hitboxes.ContainsKey(id)) { Hitboxes.Remove(id); } newHitbox.Type = Hitbox.SEARCHBOX; newHitbox.Bone = (int)cmd.Parameters[2]; newHitbox.Size = (float)cmd.Parameters[3]; newHitbox.X = (float)cmd.Parameters[4]; newHitbox.Y = (float)cmd.Parameters[5]; newHitbox.Z = (float)cmd.Parameters[6]; addOrOverwriteHitbox(id, newHitbox); break; } case 0xCD0C1CC9: //Bat Within (it clears WT SEARCH event) case 0x98203AF6: //SRH_CLEAR_ALL { List <int> toDelete = new List <int>(); foreach (KeyValuePair <int, Hitbox> kvp in Hitboxes) { if (kvp.Value.Type == Hitbox.SEARCHBOX) { toDelete.Add(kvp.Key); } } foreach (int index in toDelete) { Hitboxes.Remove(index); } break; } case 0xFA1BC28A: //Subroutine1: call another script halt = processSubscriptCommandsAtCurrentFrame((uint)int.Parse(cmd.Parameters[0] + ""), halt, scriptCommandIndex); break; case 0xFAA85333: break; case 0x321297B0: break; case 0x7640AEEB: break; case 0xA5BD4F32: // TRUE break; case 0x895B9275: // FALSE break; case 0xF13BFE8D: //Bone collision state (intangibility/invincibility) { int bone = VBN.applyBoneThunk((int)cmd.Parameters[0]); int state = (int)cmd.Parameters[1]; switch (state) { case 2: IntangibleBones.Remove(bone); InvincibleBones.Remove(bone); IntangibleBones.Add(bone); break; case 1: IntangibleBones.Remove(bone); InvincibleBones.Remove(bone); InvincibleBones.Add(bone); break; default: IntangibleBones.Remove(bone); InvincibleBones.Remove(bone); break; } break; } case 0xCEDC237E: //Undo Bone collision state { int state = (int)cmd.Parameters[0]; IntangibleBones.Clear(); InvincibleBones.Clear(); break; } case 0xF0D25BDA: //Body_Collision (Full intangibility/invincibility) { int state = (int)cmd.Parameters[0]; switch (state) { case 2: BodyInvincible = false; BodyIntangible = true; break; case 1: BodyInvincible = true; BodyIntangible = false; break; default: BodyInvincible = false; BodyIntangible = false; break; } break; } } if (newHitbox != null) { newHitbox.Bone = VBN.applyBoneThunk(newHitbox.Bone); } return(halt); }