@@ -3,10 +3,11 @@ HumanFunctions = {};
3
3
function HumanFunctions .DoAlternativeGib (actor )
4
4
-- Detach limbs instead of regular gibbing
5
5
if actor .detachWoundLimit or actor .detachImpulseLimit then
6
- if actor .detachWoundLimit and actor .WoundCount > actor .detachWoundLimit then
7
- actor .detachWoundLimit = actor .WoundCount + 1 ;
6
+ local torsoWoundCount = actor :GetWoundCount (false , false , false );
7
+ if actor .detachWoundLimit and torsoWoundCount > actor .detachWoundLimit then
8
+ actor .detachWoundLimit = torsoWoundCount + 1 ;
8
9
9
- local parts = {actor .BGArm , actor .BGLeg , actor .FGArm , actor . FGLeg , actor .Head }; -- Priority order
10
+ local parts = {actor .BGArm , actor .BGLeg , actor .FGLeg , actor .Head }; -- Priority order (Never detach FG Arm)
10
11
local mostWounds , detachLimb ;
11
12
-- Pick the limb with most wounds and detach it
12
13
for _ , limb in pairs (parts ) do
@@ -16,12 +17,12 @@ function HumanFunctions.DoAlternativeGib(actor)
16
17
end
17
18
end
18
19
if detachLimb then
19
- detachLimb . JointStrength = - 1 ;
20
+ actor : RemoveAttachable ( detachLimb , true , true ) ;
20
21
end
21
22
end
22
- if actor .detachImpulseLimit and actor .TravelImpulse .Magnitude > actor .detachImpulseLimit then
23
- local parts = {actor .BGLeg , actor .BGArm , actor .FGLeg , actor .FGArm , actor . Head }; -- Priority order
24
- local impulsePoint = actor .Pos - actor .TravelImpulse / ( actor .Mass == 0 and 0.0001 or actor . Mass ) ;
23
+ if actor .detachImpulseLimit and actor .TravelImpulse .Magnitude > actor .detachImpulseLimit and actor . Mass > 0 then
24
+ local parts = {actor .BGLeg , actor .BGArm , actor .FGLeg , actor .Head }; -- Priority order (Never detach FG Arm)
25
+ local impulsePoint = actor .Pos - actor .TravelImpulse / actor .Mass ;
25
26
local closestDist , detachLimb ;
26
27
-- Pick the limb closest to the direction of impulse
27
28
for _ , limb in pairs (parts ) do
@@ -34,10 +35,10 @@ function HumanFunctions.DoAlternativeGib(actor)
34
35
end
35
36
end
36
37
end
37
- if detachLimb then
38
- local limbImpulse = actor .TravelImpulse .Magnitude / ( detachLimb .Mass == 0 and 0.0001 or detachLimb . Mass ) ;
38
+ if detachLimb and detachLimb . Mass > 0 then
39
+ local limbImpulse = actor .TravelImpulse .Magnitude / detachLimb .Mass ;
39
40
if limbImpulse > detachLimb .JointStrength then
40
- detachLimb . JointStrength = - 1 ;
41
+ actor : RemoveAttachable ( detachLimb , true , true ) ;
41
42
if math.random () * limbImpulse > detachLimb .GibImpulseLimit then
42
43
detachLimb :GibThis ();
43
44
end
@@ -57,124 +58,139 @@ function HumanFunctions.DoAlternativeGib(actor)
57
58
end
58
59
59
60
function HumanFunctions .DoAutomaticEquip (actor )
60
- -- Equip a weapon automatically if the one held by a player is destroyed
61
- if actor : IsPlayerControlled () and actor .EquippedItem == nil and actor . InventorySize > 0 and not actor .controller :IsState (Controller .WEAPON_FIRE ) then
61
+ -- Equip a weapon automatically if the one held by a player is destroyed (To-do: move this to cpp?)
62
+ if actor .EquippedItem == nil and not actor .controller :IsState (Controller .WEAPON_FIRE ) and ( actor : IsPlayerControlled () or actor : UnequipBGArm () ) then
62
63
actor :EquipFirearm (true );
63
64
end
64
65
end
65
66
66
67
function HumanFunctions .DoArmSway (actor , pushStrength )
67
- -- Control arm movements
68
68
local aimAngle = actor :GetAimAngle (false );
69
- if not actor .lastHandPos then -- Initialize
70
- actor . lastAngle = aimAngle ;
71
- actor .lastHandPos = { actor . Pos , actor . Pos } ;
69
+ if actor .weight then
70
+ actor : RemoveAttachable ( actor . weight ) ;
71
+ actor .weight = nil ;
72
72
end
73
- -- Flail around if aiming around too fast
74
- local angleMovement = actor .lastAngle - aimAngle ;
75
- actor .AngularVel = actor .AngularVel - (2 * angleMovement * actor .FlipFactor )/ (math.abs (actor .AngularVel ) * 0.1 + 1 );
76
- actor .lastAngle = aimAngle ;
77
- -- Shove when unarmed
78
- if actor :IsInventoryEmpty () and actor .controller :IsState (Controller .WEAPON_FIRE ) and (actor .FGArm or actor .BGArm ) and not (actor .EquippedItem or actor .EquippedBGItem ) and actor .Status == Actor .STABLE then
79
- actor .AngularVel = actor .AngularVel / (actor .shoved and 1.3 or 3 ) + (aimAngle - actor .RotAngle * actor .FlipFactor - 1.57 ) * (actor .shoved and 0.3 or 3 ) * actor .FlipFactor / (1 + math.abs (actor .RotAngle ));
80
- if not actor .shoved then
81
- actor .Vel = actor .Vel + Vector (2 / (1 + actor .Vel .Magnitude ), 0 ):RadRotate (actor :GetAimAngle (true )) * math.abs (math.cos (actor :GetAimAngle (true )));
82
- actor .shoved = true ;
73
+ if actor .Status == Actor .STABLE and actor .lastHandPos then
74
+ -- Unequip weapons by pressing both weapon switch keys at once
75
+ if actor .controller :IsState (Controller .WEAPON_CHANGE_NEXT ) and actor .controller :IsState (Controller .WEAPON_CHANGE_PREV ) then
76
+ local item = CreateHeldDevice (" Null Item" );
77
+ actor :AddInventoryItem (item );
78
+ actor :EquipNamedDevice (" Null Item" , true );
79
+ item .ToDelete = true ;
83
80
end
84
- else
85
- actor .shoved = false ;
86
- end
87
- local armPairs = {{actor .FGArm , actor .FGLeg , actor .BGLeg }, {actor .BGArm , actor .BGLeg , actor .FGLeg }};
88
- for i = 1 , # armPairs do
89
- local arm = armPairs [i ][1 ];
90
- if arm then
91
- arm = ToArm (arm );
92
-
93
- local armLength = ToMOSprite (arm ):GetSpriteWidth ();
94
- local rotAng = actor .RotAngle - (1.57 * actor .FlipFactor );
95
- local legMain = armPairs [i ][2 ];
96
- local legAlt = armPairs [i ][3 ];
97
-
98
- if actor .controller :IsState (Controller .MOVE_LEFT ) or actor .controller :IsState (Controller .MOVE_RIGHT ) then
99
- rotAng = (legAlt and legAlt .RotAngle ) or (legMain and (- legMain .RotAngle + math.pi ) or rotAng );
100
- elseif legMain then
101
- rotAng = legMain .RotAngle ;
102
- end
103
- -- Flail arms in tandem with leg movement or raise them them up for a push if aiming
104
- if actor .controller :IsState (Controller .AIM_SHARP ) then
105
- arm .IdleOffset = Vector (0 , 1 ):RadRotate (aimAngle );
106
- else
107
- arm .IdleOffset = Vector (0 , (armLength + arm .SpriteOffset .X ) * 1.1 ):RadRotate (rotAng * actor .FlipFactor + 1.5 + (i * 0.2 ));
81
+ -- Control arm movements
82
+ -- Flail around if aiming around too fast
83
+ local angleMovement = actor .lastAngle - aimAngle ;
84
+ actor .AngularVel = actor .AngularVel - (2 * angleMovement * actor .FlipFactor )/ (math.abs (actor .AngularVel ) * 0.1 + 1 );
85
+ -- Shove when unarmed
86
+ if actor .controller :IsState (Controller .WEAPON_FIRE ) and (actor .FGArm or actor .BGArm ) and not (actor .EquippedItem or actor .EquippedBGItem ) then
87
+ actor .AngularVel = actor .AngularVel / (actor .shoved and 1.3 or 3 ) + (aimAngle - actor .RotAngle * actor .FlipFactor - 1.57 ) * (actor .shoved and 0.3 or 3 ) * actor .FlipFactor / (1 + math.abs (actor .RotAngle ));
88
+ if not actor .shoved then
89
+ actor .Vel = actor .Vel + Vector (2 / (1 + actor .Vel .Magnitude ), 0 ):RadRotate (actor :GetAimAngle (true )) * math.abs (math.cos (actor :GetAimAngle (true )));
90
+ actor .shoved = true ;
108
91
end
109
- if actor .shoved or (actor .EquippedItem and IsTDExplosive (actor .EquippedItem ) and actor .controller :IsState (Controller .WEAPON_FIRE )) then
110
- arm .IdleOffset = Vector (armLength + (pushStrength * armLength ), 0 ):RadRotate (aimAngle );
111
- local handVector = SceneMan :ShortestDistance (actor .lastHandPos [i ], arm .HandPos , SceneMan .SceneWrapsX );
112
- -- Diminish hand relocation vector to potentially prevent post-superhuman pushing powers
113
- handVector :SetMagnitude (handVector .Magnitude / (1 + handVector .Magnitude * 0.01 ));
114
- -- Emphasize the first frames that signify contracted arm = highest potential energy
115
- local dots = math.sqrt (arm .Radius )/ (1 + arm .Frame / arm .FrameCount );
116
- local armStrength = (arm .Mass + arm .Material .StructuralIntegrity ) * pushStrength ;
117
- for i = 1 , dots do
118
- local part = CreateMOPixel (" Smack Particle Light" );
119
- part .Pos = arm .HandPos - Vector (handVector .X * 0.5 , handVector .Y * 0.5 );
120
- part .Vel = Vector (handVector .X , handVector .Y ):RadRotate (RangeRand (- 0.1 , 0.1 )) + Vector (0 , - 0.5 );
121
- part .Mass = armStrength ; part .Sharpness = math.random () * 0.1 ;
122
- part .Team = actor .Team ; part .IgnoresTeamHits = true ;
123
- MovableMan :AddParticle (part );
92
+ else
93
+ actor .shoved = false ;
94
+ end
95
+ local shove = {};
96
+ local armPairs = {{actor .FGArm , actor .FGLeg , actor .BGLeg }, {actor .BGArm , actor .BGLeg , actor .FGLeg }};
97
+ for i = 1 , # armPairs do
98
+ local arm = armPairs [i ][1 ];
99
+ if arm then
100
+ arm = ToArm (arm );
101
+
102
+ local armLength = ToMOSprite (arm ):GetSpriteWidth ();
103
+ local rotAng = actor .RotAngle - (1.57 * actor .FlipFactor );
104
+ local legMain = armPairs [i ][2 ];
105
+ local legAlt = armPairs [i ][3 ];
106
+
107
+ if actor .controller :IsState (Controller .MOVE_LEFT ) or actor .controller :IsState (Controller .MOVE_RIGHT ) then
108
+ rotAng = (legAlt and legAlt .RotAngle ) or (legMain and (- legMain .RotAngle + math.pi ) or rotAng );
109
+ elseif legMain then
110
+ rotAng = legMain .RotAngle ;
111
+ end
112
+ -- Flail arms in tandem with leg movement or raise them them up for a push if aiming
113
+ if actor .controller :IsState (Controller .AIM_SHARP ) then
114
+ arm .IdleOffset = Vector (0 , 1 ):RadRotate (aimAngle );
115
+ else
116
+ arm .IdleOffset = Vector (0 , (armLength + arm .SpriteOffset .X ) * 1.1 ):RadRotate (rotAng * actor .FlipFactor + 1.5 + (i * 0.2 ));
124
117
end
125
- -- Apply some additional forces if the travel vector of the moving hand is half an arms length
126
- if handVector .Magnitude > (armLength * 0.5 ) then
127
- local moCheck = SceneMan :GetMOIDPixel (arm .HandPos .X , arm .HandPos .Y )
128
- if moCheck ~= rte .NoMOID then
129
- local mo = MovableMan :GetMOFromID (MovableMan :GetMOFromID (moCheck ).RootID );
130
- if mo and mo .Team ~= actor .Team and IsActor (mo ) and actor .Mass > (mo .Mass * 0.5 ) then
131
- mo :AddForce (handVector * (actor .Mass * 0.5 ), Vector ());
132
- ToActor (mo ).Status = Actor .UNSTABLE ;
118
+ if actor .shoved or (actor .EquippedItem and IsTDExplosive (actor .EquippedItem ) and actor .controller :IsState (Controller .WEAPON_FIRE )) then
119
+ arm .IdleOffset = Vector (armLength + (pushStrength * armLength ), 0 ):RadRotate (aimAngle );
120
+ local handVector = SceneMan :ShortestDistance (actor .lastHandPos [i ], arm .HandPos , SceneMan .SceneWrapsX );
121
+ -- Diminish hand relocation vector to prevent superhuman pushing powers
122
+ handVector :SetMagnitude (math.min (handVector .Magnitude , 1 + armLength * 0.1 ));
123
+ local armStrength = (arm .Mass + arm .Material .StructuralIntegrity * 0.5 ) * pushStrength ;
124
+
125
+ shove .Pos = shove .Pos and shove .Pos + SceneMan :ShortestDistance (shove .Pos , arm .HandPos , SceneMan .SceneWrapsX ) * 0.5 or arm .HandPos ;
126
+ shove .Power = shove .Power and shove .Power + armStrength or armStrength ;
127
+ shove .Vector = shove .Vector and shove .Vector + handVector * 0.5 or handVector * 0.5 ;
128
+ end
129
+ actor .lastHandPos [i ] = arm .HandPos ;
130
+ end
131
+ end
132
+ if shove .Pos then
133
+ -- local moCheck = SceneMan:GetMOIDPixel(shove.Pos.X + actor.FlipFactor, shove.Pos.Y - 1);
134
+ local moCheck = SceneMan :CastMORay (shove .Pos , shove .Vector , actor .ID , actor .Team , rte .airID , false , shove .Vector .Magnitude - 1 );
135
+ if moCheck ~= rte .NoMOID then
136
+ local mo = MovableMan :GetMOFromID (MovableMan :GetMOFromID (moCheck ).RootID );
137
+ if mo and mo .Team ~= actor .Team and IsActor (mo ) then
138
+ if actor .Mass > mo .Mass then
139
+ ToActor (mo ).Status = Actor .UNSTABLE ;
140
+ -- Simulate target actor weight with an attachable
141
+ if not actor .weight then
142
+ actor .weight = CreateAttachable (" Null Attachable" );
143
+ actor .weight .Mass = mo .Mass ;
144
+ actor :AddAttachable (actor .weight );
133
145
end
146
+ local shoveVel = shove .Vector / rte .PxTravelledPerFrame ;
147
+ mo .Vel = mo .Vel * 0.5 + shoveVel :SetMagnitude (math.min (shoveVel .Magnitude , math.sqrt (actor .IndividualDiameter ))) - SceneMan .GlobalAcc * GetMPP () * rte .PxTravelledPerFrame ;
148
+ mo .AngularVel = (aimAngle - actor .lastAngle ) * actor .FlipFactor * math.pi ;
149
+ else
150
+ mo :AddForce (shove .Vector * (actor .Mass * 0.5 ) * shove .Power , Vector ());
134
151
end
135
152
end
136
153
end
137
- actor .lastHandPos [i ] = arm .HandPos ;
138
154
end
155
+ actor .lastAngle = aimAngle ;
156
+ else
157
+ actor .lastAngle = aimAngle ;
158
+ actor .lastHandPos = {actor .Pos , actor .Pos };
139
159
end
140
160
end
141
161
142
162
function HumanFunctions .DoVisibleInventory (actor , showAll )
143
163
-- Visualize inventory with primitive bitmaps
144
- if actor .Status < Actor .DYING and not actor : IsInventoryEmpty () then
164
+ if actor .Status < Actor .DYING then
145
165
local heldCount , thrownCount , largestItem = 0 , 0 , 0 ;
146
- for i = 1 , actor .InventorySize do
147
- local item = actor :Inventory ();
148
- if item then
149
- if item .ClassName == " TDExplosive" then
150
- thrownCount = thrownCount + 1 ;
151
- elseif item .ClassName == " HDFirearm" or item .ClassName == " HeldDevice" then
152
- if showAll or item .Diameter + item .Mass > largestItem then
153
- item = ToMOSprite (item );
154
- largestItem = item .Diameter + item .Mass ;
155
- heldCount = heldCount + 1 ;
156
- local itemCount = math.sqrt (heldCount );
166
+ for item in actor .Inventory do
167
+ if item .ClassName == " TDExplosive" then
168
+ thrownCount = thrownCount + 1 ;
169
+ elseif item .ClassName == " HDFirearm" or item .ClassName == " HeldDevice" then
170
+ if showAll or item .Diameter + item .Mass > largestItem then
171
+ item = ToMOSprite (item );
172
+ largestItem = item .Diameter + item .Mass ;
173
+ heldCount = heldCount + 1 ;
174
+ local itemCount = math.sqrt (heldCount );
157
175
158
- local actorBack = Vector (ToMOSprite (actor ):GetSpriteWidth () + actor .SpriteOffset .X , ToMOSprite (actor ):GetSpriteHeight () + actor .SpriteOffset .Y );
159
- local stackX = item .Radius * 0.2 + itemCount ;
160
- -- Bigger actors carry weapons higher up, smaller weapons are carried lower down
161
- local drawPos = actor .Pos + Vector ((- actorBack .X * 0.5 - stackX ) * actor .FlipFactor , - actorBack .Y * 0.75 ):RadRotate (actor .RotAngle );
162
- -- Display tall objects upright
163
- local widthToHeightRatio = item :GetSpriteWidth ()/ item :GetSpriteHeight ();
164
- local orientation = widthToHeightRatio > 1 and 1.57 * actor .FlipFactor or 0 ;
176
+ local actorBack = Vector (ToMOSprite (actor ):GetSpriteWidth () + actor .SpriteOffset .X , ToMOSprite (actor ):GetSpriteHeight () + actor .SpriteOffset .Y );
177
+ local stackX = item .Radius * 0.2 + itemCount ;
178
+ -- Bigger actors carry weapons higher up, smaller weapons are carried lower down
179
+ local drawPos = actor .Pos + Vector ((- actorBack .X * 0.5 - stackX ) * actor .FlipFactor , - actorBack .Y * 0.75 ):RadRotate (actor .RotAngle );
180
+ -- Display tall objects upright
181
+ local widthToHeightRatio = item :GetSpriteWidth ()/ item :GetSpriteHeight ();
182
+ local orientation = widthToHeightRatio > 1 and 1.57 * actor .FlipFactor or 0 ;
165
183
166
- local tilt = (itemCount / item .Radius ) * widthToHeightRatio * actor .FlipFactor ;
167
- local rotAng = actor .RotAngle + orientation + (tilt * 2 ) - tilt * (itemCount - 1 );
184
+ local tilt = (itemCount / item .Radius ) * widthToHeightRatio * actor .FlipFactor ;
185
+ local rotAng = actor .RotAngle + orientation + (tilt * 2 ) - tilt * (itemCount - 1 );
168
186
169
- for player = Activity .PLAYER_1 , Activity .MAXPLAYERCOUNT - 1 do
170
- local screen = ActivityMan :GetActivity ():ScreenOfPlayer (player );
171
- if screen ~= - 1 and not SceneMan :IsUnseen (drawPos .X , drawPos .Y , ActivityMan :GetActivity ():GetTeamOfPlayer (player )) then
172
- PrimitiveMan :DrawBitmapPrimitive (screen , drawPos , item , rotAng , item .Frame , actor .HFlipped , true );
173
- end
187
+ for player = Activity .PLAYER_1 , Activity .MAXPLAYERCOUNT - 1 do
188
+ local screen = ActivityMan :GetActivity ():ScreenOfPlayer (player );
189
+ if screen ~= - 1 and not SceneMan :IsUnseen (drawPos .X , drawPos .Y , ActivityMan :GetActivity ():GetTeamOfPlayer (player )) then
190
+ PrimitiveMan :DrawBitmapPrimitive (screen , drawPos , item , rotAng , item .Frame , actor .HFlipped , true );
174
191
end
175
192
end
176
193
end
177
- actor :SwapNextInventory (item , true );
178
194
end
179
195
end
180
196
end
0 commit comments