/// <summary> /// /// </summary> /// <param name="frame"></param> public void SetFrame(float frame) { Hitboxes.Clear(); ResetState(); CommandHashes.Clear(); SetFrame(frame, 0, Commands); }
//Använder enums för att se vilken sida om objektet som spelaren befinner sig om //Skapar även nya rektanglar så att se om man är innuti den rektangeln public Hitboxes CheckHitboxes(Rectangle collision, Player player) { if (player.PlayerHitbox.Intersects(new Rectangle(collision.X + ObjectHitbox.Width, collision.Y, ObjectHitbox.Width, ObjectHitbox.Height))) { hitboxes = Hitboxes.Right; return(Hitboxes.Right); } if (player.PlayerHitbox.Intersects(new Rectangle(collision.X, collision.Y - ObjectHitbox.Height, ObjectHitbox.Width, ObjectHitbox.Height))) { hitboxes = Hitboxes.Up; return(Hitboxes.Up); } if (player.PlayerHitbox.Intersects(new Rectangle(collision.X - ObjectHitbox.Width, collision.Y, ObjectHitbox.Width, ObjectHitbox.Height))) { hitboxes = Hitboxes.Left; return(Hitboxes.Left); } else { hitboxes = Hitboxes.Down; return(Hitboxes.Down); } }
Hitbox GetHitbox(int id) { if (Hitboxes == null) { return(null); } return(Hitboxes.Find(h => h.ID == id)); }
public void SetHitBox(Hitboxes val) { if (val != Hitboxes.clear) { localCollider.SetPath(0, colliders[(int)val].GetPath(0)); return; } localCollider.pathCount = 0; }
public void ResetAllHitboxes() { foreach (Hitbox hitbox in Hitboxes.IgnoreNulls()) { if (hitbox.ResetState()) { Log.Info("{0} {1}", this, hitbox); } } }
public void addOrOverwriteHitbox(int id, Hitbox newHitbox) { if (Hitboxes.ContainsKey(id)) { Hitboxes[id] = newHitbox; } else { Hitboxes.Add(id, newHitbox); } }
/// <summary> /// /// </summary> /// <param name="frame"></param> public void SetFrame(float frame) { Hitboxes.Clear(); BoneCollisionStates.Clear(); BodyCollisionState = 0; if (frame == 0) { ResetState(); } SetFrame(frame, 0, Commands); }
public static bool GetClosest(IEnumerable <BasePlayer> to_list, Hitboxes hitbox_to, out BasePlayer enemy, out Vector atAngle) { atAngle = default; enemy = IntPtr.Zero; var best_angle = new Vector(); var min_crosshair_distance = 999d; foreach (var to in to_list) { var toPos = hitbox_to == Hitboxes.HITBOX_HEAD ? to.m_vecEyePos : to.GetHitboxPos(hitbox_to); var crosshair_distance = ~(atAngle = g_LocalPlayer.m_vecEyePos ^ toPos); if (crosshair_distance < min_crosshair_distance) { enemy = to; best_angle = atAngle; min_crosshair_distance = crosshair_distance; } } atAngle = best_angle; return(enemy); }
/// <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 void Render(VBN Skeleton) { if (!Runtime.renderHitboxes || Skeleton == null) { return; } if (Hitboxes.Count <= 0) { return; } GL.Enable(EnableCap.Blend); GL.Disable(EnableCap.CullFace); foreach (var pair in Hitboxes) { var h = pair.Value; if (Runtime.HiddenHitboxes.Contains(h.ID)) { continue; } Bone b = getBone(h.Bone, Skeleton); h.va = Vector3.TransformPosition(new Vector3(h.X, h.Y, h.Z), b.transform.ClearScale()); // Draw angle marker RenderHitboxAngles(h, Skeleton); GL.Color4(h.GetDisplayColor()); // Draw everything to the stencil buffer RenderTools.beginTopLevelStencil(); if (!h.IsSphere()) { h.va2 = new Vector3(h.X2, h.Y2, h.Z2); if (h.Bone != -1) { h.va2 = Vector3.TransformPosition(h.va2, b.transform.ClearScale()); } RenderTools.drawCylinder(h.va, h.va2, h.Size); } else { RenderTools.drawSphere(h.va, h.Size, 30); } // n factorial (n!) algorithm (NOT EFFICIENT) to draw subsequent hitboxes around each other. // Will work fine for the low amounts of hitboxes in smash4. if (Runtime.renderHitboxesNoOverlap) { // Remove the stencil for the already drawn hitboxes RenderTools.beginTopLevelAntiStencil(); foreach (var pair2 in Hitboxes.Reverse()) { if (pair2.Key == pair.Key) { break; // this only works because the list is sorted } var h2 = pair2.Value; if (!Runtime.HiddenHitboxes.Contains(h2.ID)) { Bone b2 = getBone(h2.Bone, Skeleton); var va = Vector3.TransformPosition(new Vector3(h2.X, h2.Y, h2.Z), b2.transform.ClearScale()); if (!h2.IsSphere()) { var va2 = new Vector3(h2.X2, h2.Y2, h2.Z2); if (h2.Bone != -1) { va2 = Vector3.TransformPosition(va2, b2.transform.ClearScale()); } RenderTools.drawCylinder(va, va2, h2.Size); } else { RenderTools.drawSphere(va, h2.Size, 30); } } } } if (Runtime.SelectedHitboxID == h.ID) { GL.Color4(Color.FromArgb(Runtime.hurtboxAlpha, Runtime.hurtboxColorSelected)); if (!h.IsSphere()) { RenderTools.drawWireframeCylinder(h.va, h.va2, h.Size); } else { RenderTools.drawWireframeSphere(h.va, h.Size, 10); } } // End stenciling and draw over all the stenciled bits RenderTools.endTopLevelStencilAndDraw(); } GL.Enable(EnableCap.CullFace); GL.Disable(EnableCap.Blend); }
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); }
private void Read(BinaryReader br, Dictionary <string, BinaryReader> sequenceGroups) { Header = new Header { ID = ID.Idst, Version = Version.Goldsource, Name = br.ReadFixedLengthString(Encoding.ASCII, 64), Size = br.ReadInt32(), EyePosition = br.ReadVector3(), HullMin = br.ReadVector3(), HullMax = br.ReadVector3(), BoundingBoxMin = br.ReadVector3(), BoundingBoxMax = br.ReadVector3(), Flags = br.ReadInt32() }; // Read all the nums/offsets from the header var sections = new int[(int)Section.NumSections][]; for (var i = 0; i < (int)Section.NumSections; i++) { var sec = (Section)i; int indexNum; if (sec == Section.Texture || sec == Section.Skin) { indexNum = 3; } else { indexNum = 2; } sections[i] = new int[indexNum]; for (var j = 0; j < indexNum; j++) { sections[i][j] = br.ReadInt32(); } } // Bones var num = SeekToSection(br, Section.Bone, sections); var numBones = num; for (var i = 0; i < num; i++) { var bone = new Bone { Name = br.ReadFixedLengthString(Encoding.ASCII, 32), Parent = br.ReadInt32(), Flags = br.ReadInt32(), Controllers = br.ReadIntArray(6), Position = br.ReadVector3(), Rotation = br.ReadVector3(), PositionScale = br.ReadVector3(), RotationScale = br.ReadVector3() }; Bones.Add(bone); } // Bone controllers num = SeekToSection(br, Section.BoneController, sections); for (var i = 0; i < num; i++) { var boneController = new BoneController { Bone = br.ReadInt32(), Type = br.ReadInt32(), Start = br.ReadSingle(), End = br.ReadSingle(), Rest = br.ReadInt32(), Index = br.ReadInt32() }; BoneControllers.Add(boneController); } // Hitboxes num = SeekToSection(br, Section.Hitbox, sections); for (var i = 0; i < num; i++) { var hitbox = new Hitbox { Bone = br.ReadInt32(), Group = br.ReadInt32(), Min = br.ReadVector3(), Max = br.ReadVector3() }; Hitboxes.Add(hitbox); } // Sequence groups num = SeekToSection(br, Section.SequenceGroup, sections); for (var i = 0; i < num; i++) { var group = new SequenceGroup { Label = br.ReadFixedLengthString(Encoding.ASCII, 32), Name = br.ReadFixedLengthString(Encoding.ASCII, 64) }; br.ReadBytes(8); // unused SequenceGroups.Add(group); } // Sequences num = SeekToSection(br, Section.Sequence, sections); for (var i = 0; i < num; i++) { var sequence = new Sequence { Name = br.ReadFixedLengthString(Encoding.ASCII, 32), Framerate = br.ReadSingle(), Flags = br.ReadInt32(), Activity = br.ReadInt32(), ActivityWeight = br.ReadInt32(), NumEvents = br.ReadInt32(), EventIndex = br.ReadInt32(), NumFrames = br.ReadInt32(), NumPivots = br.ReadInt32(), PivotIndex = br.ReadInt32(), MotionType = br.ReadInt32(), MotionBone = br.ReadInt32(), LinearMovement = br.ReadVector3(), AutoMovePositionIndex = br.ReadInt32(), AutoMoveAngleIndex = br.ReadInt32(), Min = br.ReadVector3(), Max = br.ReadVector3(), NumBlends = br.ReadInt32(), AnimationIndex = br.ReadInt32(), BlendType = br.ReadIntArray(2), BlendStart = br.ReadSingleArray(2), BlendEnd = br.ReadSingleArray(2), BlendParent = br.ReadInt32(), SequenceGroup = br.ReadInt32(), EntryNode = br.ReadInt32(), ExitNode = br.ReadInt32(), NodeFlags = br.ReadInt32(), NextSequence = br.ReadInt32() }; var seqGroup = SequenceGroups[sequence.SequenceGroup]; // Only load seqence group 0 for now (others are in other files) if (sequence.SequenceGroup == 0) { var pos = br.BaseStream.Position; sequence.Blends = LoadAnimationBlends(br, sequence, numBones); br.BaseStream.Position = pos; } else if (sequenceGroups.ContainsKey(seqGroup.Name)) { var reader = sequenceGroups[seqGroup.Name]; sequence.Blends = LoadAnimationBlends(reader, sequence, numBones); } Sequences.Add(sequence); } // Textures num = SeekToSection(br, Section.Texture, sections); var firstTextureIndex = Textures.Count; for (var i = 0; i < num; i++) { var texture = new Texture { Name = br.ReadFixedLengthString(Encoding.ASCII, 64), Flags = (TextureFlags)br.ReadInt32(), Width = br.ReadInt32(), Height = br.ReadInt32(), Index = br.ReadInt32() }; Textures.Add(texture); } // Texture data for (var i = firstTextureIndex; i < firstTextureIndex + num; i++) { var t = Textures[i]; br.BaseStream.Position = t.Index; t.Data = br.ReadBytes(t.Width * t.Height); t.Palette = br.ReadBytes(256 * 3); Textures[i] = t; } // Skins var skinSection = sections[(int)Section.Skin]; var numSkinRefs = skinSection[0]; var numSkinFamilies = skinSection[1]; br.BaseStream.Seek(skinSection[2], SeekOrigin.Begin); for (var i = 0; i < numSkinFamilies; i++) { var skin = new SkinFamily { Textures = br.ReadShortArray(numSkinRefs) }; Skins.Add(skin); } // Body parts num = SeekToSection(br, Section.BodyPart, sections); for (var i = 0; i < num; i++) { var part = new BodyPart { Name = br.ReadFixedLengthString(Encoding.ASCII, 64), NumModels = br.ReadInt32(), Base = br.ReadInt32(), ModelIndex = br.ReadInt32() }; var pos = br.BaseStream.Position; part.Models = LoadModels(br, part); br.BaseStream.Position = pos; BodyParts.Add(part); } // Attachments num = SeekToSection(br, Section.Attachment, sections); for (var i = 0; i < num; i++) { var attachment = new Attachment { Name = br.ReadFixedLengthString(Encoding.ASCII, 32), Type = br.ReadInt32(), Bone = br.ReadInt32(), Origin = br.ReadVector3(), Vectors = br.ReadVector3Array(3) }; Attachments.Add(attachment); } // Transitions // Sounds & Sound groups aren't used }
/// <summary> /// /// </summary> private float SetFrame(float frame, float time, List <Command> commands) { int loopAmt = 0; int loopPos = 0; for (int i = 0; i < commands.Count; i++) { var cmd = commands[i]; switch (cmd.Action.Code) { case 0: //end script time = int.MaxValue; break; case 1: //synchronous time += cmd.Parameters[0]; break; case 2: //asynchronus time = cmd.Parameters[0]; break; case 3: //start loop loopAmt = cmd.Parameters[0]; loopPos = i; break; case 4: //end loop loopAmt -= 1; if (loopAmt != 0) { i = loopPos; } break; case 5: //subroutine time = SetFrame(frame, time, cmd.ReferenceCommands); break; case 6: //return? break; case 7: //goto time = SetFrame(frame, time, cmd.ReferenceCommands); break; case 11: // Create Hitbox // remove the current hitbox with this id Hitboxes.RemoveAll(e => e.ID == cmd.Parameters[0]); // add hitbox Hitboxes.Add(new Hitbox() { ID = cmd.Parameters[0], BoneID = cmd.Parameters[2], Size = (short)cmd.Parameters[5] / 150f, Point1 = new Vector3((short)cmd.Parameters[8] / 150f, (short)cmd.Parameters[7] / 150f, (short)cmd.Parameters[6] / 150f), }); break; case 13: // adjust size { var hb = Hitboxes.Find(e => e.ID == cmd.Parameters[0]); if (hb != null) { hb.Size = (short)cmd.Parameters[1] / 150f; } } break; case 15: Hitboxes.RemoveAll(e => e.ID == cmd.Parameters[0]); break; case 16: Hitboxes.Clear(); break; case 26: BodyCollisionState = cmd.Parameters[1]; break; case 27: // i don't really know how many bone to assume... for (int j = 0; j < 100; j++) { if (BoneCollisionStates.ContainsKey(j)) { BoneCollisionStates[j] = cmd.Parameters[0]; } else { BoneCollisionStates.Add(j, cmd.Parameters[0]); } } break; case 28: if (BoneCollisionStates.ContainsKey(cmd.Parameters[0])) { BoneCollisionStates[cmd.Parameters[0]] = cmd.Parameters[1]; } else { BoneCollisionStates.Add(cmd.Parameters[0], cmd.Parameters[1]); } break; case 37: CharacterInvisibility = cmd.Parameters[1] == 1; break; case 46: //overlay color if (cmd.Parameters[0] == 1) { OverlayColor = new Vector3(cmd.Parameters[1] / 255f, cmd.Parameters[2] / 255f, cmd.Parameters[3] / 255f); } break; } if (time > frame) { break; } } return(time); }
/// <summary> /// /// </summary> private float SetFrame(float frame, float time, List <Command> commands) { int loopAmt = 0; int loopPos = 0; for (int i = 0; i < commands.Count; i++) { var cmd = commands[i]; switch (cmd.Action.Code) { case 0 << 2: //end script time = int.MaxValue; break; case 1 << 2: //synchronous time += cmd.Parameters[0]; break; case 2 << 2: //asynchronus time = cmd.Parameters[0]; break; case 3 << 2: //start loop loopAmt = cmd.Parameters[0]; loopPos = i; break; case 4 << 2: //end loop loopAmt -= 1; if (loopAmt > 0) { i = loopPos; } break; case 5 << 2: //subroutine time = SetFrame(frame, time, cmd.ReferenceCommands); break; case 6 << 2: //return? return(time); case 7 << 2: //goto time = SetFrame(frame, time, cmd.ReferenceCommands); break; case 11 << 2: // Create Hitbox // remove the current hitbox with this id Hitboxes.RemoveAll(e => e.ID == cmd.Parameters[0]); // add hitbox Hitboxes.Add(new Hitbox() { ID = cmd.Parameters[0], BoneID = cmd.Parameters[2], Size = ((short)cmd.Parameters[5] / 256f), Point1 = new Vector3(cmd.Parameters[6] / 256f, cmd.Parameters[7] / 256f, cmd.Parameters[8] / 256f), Angle = cmd.Parameters[9], Element = cmd.Parameters[15] }); break; case 13 << 2: // adjust size { var hb = Hitboxes.Find(e => e.ID == cmd.Parameters[0]); if (hb != null) { hb.Size = (short)cmd.Parameters[1] / 150f; } } break; case 15 << 2: Hitboxes.RemoveAll(e => e.ID == cmd.Parameters[0]); break; case 16 << 2: Hitboxes.Clear(); break; case 20 << 2: // throw ThrownFighter = true; break; case 26 << 2: BodyCollisionState = cmd.Parameters[0]; break; case 27 << 2: // i don't really know how many bone to assume... for (int j = 0; j < 100; j++) { if (BoneCollisionStates.ContainsKey(j)) { BoneCollisionStates[j] = cmd.Parameters[0]; } else { BoneCollisionStates.Add(j, cmd.Parameters[0]); } } break; case 28 << 2: if (cmd.Parameters.Length > 1) { if (BoneCollisionStates.ContainsKey(cmd.Parameters[0])) { BoneCollisionStates[cmd.Parameters[0]] = cmd.Parameters[1]; } else { BoneCollisionStates.Add(cmd.Parameters[0], cmd.Parameters[1]); } } break; case 31 << 2: // struct vis change UpdateVISMethod(cmd.Parameters[0], cmd.Parameters[2]); break; case 37 << 2: CharacterInvisibility = cmd.Parameters[1] == 1; break; case 40 << 2: AnimateMaterialMethod(cmd.Parameters[1], cmd.Parameters[3], cmd.Parameters[0], cmd.Parameters[2]); break; case 41 << 2: AnimateModelMethod(cmd.Parameters[0], cmd.Parameters[1]); break; case 46 << 2: //overlay color if (cmd.Parameters[0] == 1) { OverlayColor = new Vector3(cmd.Parameters[1] / 255f, cmd.Parameters[2] / 255f, cmd.Parameters[3] / 255f); } break; } if (time > frame) { break; } } return(time); }