So, I solved it. Turns out I just needed to get away from the problem a bit.
Just in case anyone else wants to replicate this, I got it working and I made a function in C# (Although it should be really easy to transpose it to any other language) that solves 2D arms. Arms being assumed to be made up of two segments with shoulder and elbow joints. All angles are in radians. It could probably be done better but this is what I've got in my test program:
public Vector2 SolveLimb(Vector2 startPosition, Vector2 endPosition, float length)
//startPosition is the where the first joint is. e.g. The shoulder.
//endPosition is where the desired final position is for the last joint. e.g Where the hand should end up
//length is the length of each arm segment. Could use separate values if you want arm segments of different lengths
//Get the direction vector between the hand and shoulder
Vector2 dir = endPosition - startPosition;
//Measure the distance between hand and shoulder to get length of one side of the triangle
//The other two sides we already know because they're the lengths of the arm segments
float distToEnd = Vector2.Distance(startPosition, endPosition);
distToEnd = MathHelper.Clamp(distToEnd, 0, length * 2);
float ShoulderToHand = distToEnd;
float ShoulderToElbow = ArmTexture.Width;
float ElbowToHand = ArmTexture.Width;
//Use the Law of Cosines to figure out what the two angles are that we want.
//Helpful links: https://www.mathsisfun.com/algebra/trig-solving-sss-triangles.html
//Math.Acos(angle) == Cos^1(angle)
float ElbowA = (Square(ShoulderToElbow) + Square(ElbowToHand) - Square(ShoulderToHand)) / (2 * (ShoulderToElbow * ElbowToHand));
float ElbowAngle = (float)Math.Acos(ElbowA);
float ShoulderA = (Square(ShoulderToElbow) + Square(ShoulderToHand) - Square(ElbowToHand)) / (2 * (ShoulderToElbow * ShoulderToHand));
float ShoulderAngle = (float)Math.Acos(ShoulderA);
//Additional rotation that needs to be made to both arm segments
float rot = (float)Math.Atan2(dir.Y, dir.X);
//Return the angles for the Shoulder and Elbow.
//I used a Vector2 to return both numbers at the same time. x = Shoulder, y = Elbow
//Added Pi to the elbow rotation to fix a problem where it was rotated 180 degrees incorrectly.
//Probably messed up somewhere else, but it works
result = new Vector2(ShoulderAngle + rot, ElbowAngle + ShoulderAngle + rot + (float)Math.PI);
The rotation of the torso is really simple. I just did this:
Torso.Rotation = Gun.Rotation * 0.8f;
Hope this helps someone who stumbles across this.