Update FancyHandwork, add BrutalHandwork
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animNode>
|
||||
<m_Name>AttackDefaultL</m_Name>
|
||||
<m_AnimName>Bob_Attack1Hand01_Hit_L</m_AnimName>
|
||||
<m_Priority>4</m_Priority>
|
||||
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
|
||||
<m_Looped>false</m_Looped>
|
||||
<m_EarlyTransitionOut>true</m_EarlyTransitionOut>
|
||||
<m_SpeedScale>LCombatSpeed</m_SpeedScale>
|
||||
<m_BlendTime>0.15</m_BlendTime>
|
||||
<m_BlendOutTime>0.25</m_BlendOutTime>
|
||||
<m_Conditions>
|
||||
<m_Name>PerformingAction</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>LAttack</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>LAttackType</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>bash</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Transitions>
|
||||
<m_Target>Idle</m_Target>
|
||||
<m_AnimName>Bob_AimToIdle_1Hand</m_AnimName>
|
||||
<m_blendInTime>0.5</m_blendInTime>
|
||||
<m_blendOutTime>0.5</m_blendOutTime>
|
||||
<m_speedScale>1.3</m_speedScale>
|
||||
</m_Transitions>
|
||||
<m_Events>
|
||||
<m_EventName>AttackCollisionCheck</m_EventName>
|
||||
<m_TimePc>0.25</m_TimePc>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>BlockMovement</m_EventName>
|
||||
<m_TimePc>0.75</m_TimePc>
|
||||
<m_ParameterValue>TRUE</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>StartAttack</m_EventName>
|
||||
<m_Time>Start</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>EndAttack</m_EventName>
|
||||
<m_Time>End</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>SetVariable</m_EventName>
|
||||
<m_TimePc>0.1</m_TimePc>
|
||||
<m_ParameterValue>ZombieHitReaction=HeadRight</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine1</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Neck</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_BackPack</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Prop2</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine</boneName>
|
||||
<includeDescendants>false</includeDescendants>
|
||||
</m_SubStateBoneWeights>
|
||||
</animNode>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animNode>
|
||||
<m_Name>BH_LeftPunch1</m_Name>
|
||||
<m_AnimName>Bob_BH_AttackPunch01_L_Hit</m_AnimName>
|
||||
<m_Priority>4</m_Priority>
|
||||
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
|
||||
<m_Looped>false</m_Looped>
|
||||
<m_EarlyTransitionOut>true</m_EarlyTransitionOut>
|
||||
<m_SpeedScale>LCombatSpeed</m_SpeedScale>
|
||||
<m_BlendTime>0.15</m_BlendTime>
|
||||
<m_BlendOutTime>0.25</m_BlendOutTime>
|
||||
<m_Conditions>
|
||||
<m_Name>PerformingAction</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>LAttack</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>LAttackType</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>lpunch1</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Transitions>
|
||||
<m_Target>Idle</m_Target>
|
||||
<m_AnimName>Bob_AimToIdle_1Hand</m_AnimName>
|
||||
<m_blendInTime>0.5</m_blendInTime>
|
||||
<m_blendOutTime>0.5</m_blendOutTime>
|
||||
<m_speedScale>1.3</m_speedScale>
|
||||
</m_Transitions>
|
||||
<m_Events>
|
||||
<m_EventName>AttackCollisionCheck</m_EventName>
|
||||
<m_TimePc>0.25</m_TimePc>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>BlockMovement</m_EventName>
|
||||
<m_TimePc>0.75</m_TimePc>
|
||||
<m_ParameterValue>TRUE</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>StartAttack</m_EventName>
|
||||
<m_Time>Start</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>EndAttack</m_EventName>
|
||||
<m_Time>End</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>SetVariable</m_EventName>
|
||||
<m_TimePc>0.1</m_TimePc>
|
||||
<m_ParameterValue>ZombieHitReaction=HeadRight</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine1</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Neck</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_BackPack</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine</boneName>
|
||||
<includeDescendants>false</includeDescendants>
|
||||
</m_SubStateBoneWeights>
|
||||
</animNode>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animNode>
|
||||
<m_Name>BH_LeftPunch1</m_Name>
|
||||
<m_AnimName>Bob_BH_AttackPunch02_L_Hit</m_AnimName>
|
||||
<m_Priority>4</m_Priority>
|
||||
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
|
||||
<m_Looped>false</m_Looped>
|
||||
<m_EarlyTransitionOut>true</m_EarlyTransitionOut>
|
||||
<m_SpeedScale>LCombatSpeed</m_SpeedScale>
|
||||
<m_BlendTime>0.15</m_BlendTime>
|
||||
<m_BlendOutTime>0.25</m_BlendOutTime>
|
||||
<m_Conditions>
|
||||
<m_Name>PerformingAction</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>LAttack</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>LAttackType</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>lpunch2</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Transitions>
|
||||
<m_Target>Idle</m_Target>
|
||||
<m_AnimName>Bob_AimToIdle_1Hand</m_AnimName>
|
||||
<m_blendInTime>0.5</m_blendInTime>
|
||||
<m_blendOutTime>0.5</m_blendOutTime>
|
||||
<m_speedScale>1.3</m_speedScale>
|
||||
</m_Transitions>
|
||||
<m_Events>
|
||||
<m_EventName>AttackCollisionCheck</m_EventName>
|
||||
<m_TimePc>0.25</m_TimePc>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>BlockMovement</m_EventName>
|
||||
<m_TimePc>0.75</m_TimePc>
|
||||
<m_ParameterValue>TRUE</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>StartAttack</m_EventName>
|
||||
<m_Time>Start</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>EndAttack</m_EventName>
|
||||
<m_Time>End</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>SetVariable</m_EventName>
|
||||
<m_TimePc>0.1</m_TimePc>
|
||||
<m_ParameterValue>ZombieHitReaction=Uppercut</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine1</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Neck</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_BackPack</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine</boneName>
|
||||
<includeDescendants>false</includeDescendants>
|
||||
</m_SubStateBoneWeights>
|
||||
</animNode>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animNode>
|
||||
<m_Name>BH_RightPunch1</m_Name>
|
||||
<m_AnimName>Bob_BH_AttackPunch01_R_Hit</m_AnimName>
|
||||
<m_Priority>4</m_Priority>
|
||||
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
|
||||
<m_Looped>false</m_Looped>
|
||||
<m_EarlyTransitionOut>true</m_EarlyTransitionOut>
|
||||
<m_SpeedScale>LCombatSpeed</m_SpeedScale>
|
||||
<m_BlendTime>0.15</m_BlendTime>
|
||||
<m_BlendOutTime>0.25</m_BlendOutTime>
|
||||
<m_Conditions>
|
||||
<m_Name>PerformingAction</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>LAttack</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>LAttackType</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>rpunch1</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Transitions>
|
||||
<m_Target>Idle</m_Target>
|
||||
<m_AnimName>Bob_AimToIdle_1Hand</m_AnimName>
|
||||
<m_blendInTime>0.5</m_blendInTime>
|
||||
<m_blendOutTime>0.5</m_blendOutTime>
|
||||
<m_speedScale>1.3</m_speedScale>
|
||||
</m_Transitions>
|
||||
<m_Events>
|
||||
<m_EventName>AttackCollisionCheck</m_EventName>
|
||||
<m_TimePc>0.25</m_TimePc>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>BlockMovement</m_EventName>
|
||||
<m_TimePc>0.75</m_TimePc>
|
||||
<m_ParameterValue>TRUE</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>StartAttack</m_EventName>
|
||||
<m_Time>Start</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>EndAttack</m_EventName>
|
||||
<m_Time>End</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>SetVariable</m_EventName>
|
||||
<m_TimePc>0.1</m_TimePc>
|
||||
<m_ParameterValue>ZombieHitReaction=HeadLeft</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine1</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Neck</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_BackPack</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine</boneName>
|
||||
<includeDescendants>false</includeDescendants>
|
||||
</m_SubStateBoneWeights>
|
||||
</animNode>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animNode>
|
||||
<m_Name>BH_RightPunch1</m_Name>
|
||||
<m_AnimName>Bob_BH_AttackPunch02_R_Hit</m_AnimName>
|
||||
<m_Priority>4</m_Priority>
|
||||
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
|
||||
<m_Looped>false</m_Looped>
|
||||
<m_EarlyTransitionOut>true</m_EarlyTransitionOut>
|
||||
<m_SpeedScale>LCombatSpeed</m_SpeedScale>
|
||||
<m_BlendTime>0.15</m_BlendTime>
|
||||
<m_BlendOutTime>0.25</m_BlendOutTime>
|
||||
<m_Conditions>
|
||||
<m_Name>PerformingAction</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>LAttack</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>LAttackType</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>rpunch2</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Transitions>
|
||||
<m_Target>Idle</m_Target>
|
||||
<m_AnimName>Bob_AimToIdle_1Hand</m_AnimName>
|
||||
<m_blendInTime>0.5</m_blendInTime>
|
||||
<m_blendOutTime>0.5</m_blendOutTime>
|
||||
<m_speedScale>1.3</m_speedScale>
|
||||
</m_Transitions>
|
||||
<m_Events>
|
||||
<m_EventName>AttackCollisionCheck</m_EventName>
|
||||
<m_TimePc>0.25</m_TimePc>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>BlockMovement</m_EventName>
|
||||
<m_TimePc>0.75</m_TimePc>
|
||||
<m_ParameterValue>TRUE</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>StartAttack</m_EventName>
|
||||
<m_Time>Start</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>EndAttack</m_EventName>
|
||||
<m_Time>End</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>SetVariable</m_EventName>
|
||||
<m_TimePc>0.1</m_TimePc>
|
||||
<m_ParameterValue>ZombieHitReaction=Uppercut</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine1</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Neck</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_BackPack</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine</boneName>
|
||||
<includeDescendants>false</includeDescendants>
|
||||
</m_SubStateBoneWeights>
|
||||
</animNode>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animNode>
|
||||
<m_Name>KnifeDefaultL</m_Name>
|
||||
<m_AnimName>Bob_AttackKnife01_Hit_L</m_AnimName>
|
||||
<m_Priority>1</m_Priority>
|
||||
<m_DeferredBoneName>Bip01</m_DeferredBoneName>
|
||||
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
|
||||
<m_maxTorsoTwist>70.0</m_maxTorsoTwist>
|
||||
<m_Looped>false</m_Looped>
|
||||
<m_EarlyTransitionOut>true</m_EarlyTransitionOut>
|
||||
<m_SpeedScale>LCombatSpeed</m_SpeedScale>
|
||||
<m_BlendTime>0.15</m_BlendTime>
|
||||
<m_BlendOutTime>0.25</m_BlendOutTime>
|
||||
<m_Conditions>
|
||||
<m_Name>PerformingAction</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>LAttack</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>LAttackType</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>knife</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Transitions>
|
||||
<m_Target>Idle</m_Target>
|
||||
<m_AnimName>Bob_AimToIdle_1Hand</m_AnimName>
|
||||
<m_blendInTime>0.5</m_blendInTime>
|
||||
<m_blendOutTime>0.5</m_blendOutTime>
|
||||
<m_speedScale>1.3</m_speedScale>
|
||||
</m_Transitions>
|
||||
<m_Events>
|
||||
<m_EventName>AttackCollisionCheck</m_EventName>
|
||||
<m_TimePc>0.25</m_TimePc>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>BlockMovement</m_EventName>
|
||||
<m_TimePc>0.6</m_TimePc>
|
||||
<m_ParameterValue>TRUE</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>StartAttack</m_EventName>
|
||||
<m_Time>Start</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>EndAttack</m_EventName>
|
||||
<m_Time>End</m_Time>
|
||||
<m_ParameterValue></m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_Events>
|
||||
<m_EventName>SetVariable</m_EventName>
|
||||
<m_TimePc>0.1</m_TimePc>
|
||||
<m_ParameterValue>ZombieHitReaction=Uppercut</m_ParameterValue>
|
||||
</m_Events>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01</boneName>
|
||||
<weight>0.0</weight>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine1</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Neck</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_BackPack</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Prop2</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Spine</boneName>
|
||||
<includeDescendants>false</includeDescendants>
|
||||
</m_SubStateBoneWeights>
|
||||
</animNode>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animNode>
|
||||
<m_Name>BHUnarmedAimMask</m_Name>
|
||||
<m_AnimName>Bob_BH_UnarmedAim</m_AnimName>
|
||||
<m_Priority>10</m_Priority>
|
||||
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
|
||||
<m_SyncTrackingEnabled>false</m_SyncTrackingEnabled>
|
||||
<m_SpeedScale>0.80</m_SpeedScale>
|
||||
<m_BlendTime>0.20</m_BlendTime>
|
||||
<m_Conditions>
|
||||
<m_Name>RightHandMask</m_Name>
|
||||
<m_Type>STRING</m_Type>
|
||||
<m_StringValue>bhunarmedaim</m_StringValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>FHDoingAction</m_Name>
|
||||
<m_Type>BOOL</m_Type>
|
||||
<m_BoolValue>false</m_BoolValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>Aim</m_Name>
|
||||
<m_Type>BOOL</m_Type>
|
||||
<m_BoolValue>true</m_BoolValue>
|
||||
</m_Conditions>
|
||||
<m_Conditions>
|
||||
<m_Name>bShoveAiming</m_Name>
|
||||
<m_Type>BOOL</m_Type>
|
||||
<m_BoolValue>false</m_BoolValue>
|
||||
</m_Conditions>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_Neck</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_R_Clavicle</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
<m_SubStateBoneWeights>
|
||||
<boneName>Bip01_L_Clavicle</boneName>
|
||||
</m_SubStateBoneWeights>
|
||||
</animNode>
|
||||
12731
BrutalHandwork/Contents/mods/BrutalHandwork/media/anims_X/Bob/Bob_Attack1Hand01_Hit_L.x
Executable file
12731
BrutalHandwork/Contents/mods/BrutalHandwork/media/anims_X/Bob/Bob_Attack1Hand01_Hit_L.x
Executable file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
15942
BrutalHandwork/Contents/mods/BrutalHandwork/media/anims_X/Bob/Bob_BH_UnarmedAim.x
Executable file
15942
BrutalHandwork/Contents/mods/BrutalHandwork/media/anims_X/Bob/Bob_BH_UnarmedAim.x
Executable file
File diff suppressed because it is too large
Load Diff
797
BrutalHandwork/Contents/mods/BrutalHandwork/media/lua/client/BrutalAttack.lua
Executable file
797
BrutalHandwork/Contents/mods/BrutalHandwork/media/lua/client/BrutalAttack.lua
Executable file
@@ -0,0 +1,797 @@
|
||||
-- BrutalAttack is intended to be a module that can be used by anyone
|
||||
--- This is a more-or-less port of the Java functions to find and perform attacks
|
||||
--- Not everything is exposed to us that is used, so some liberties were taken
|
||||
local BrutalAttack = {}
|
||||
|
||||
-- for caching, let's reuse these
|
||||
local checkValid = function(player, weapon)
|
||||
return (player and instanceof(weapon, "HandWeapon"))
|
||||
end
|
||||
|
||||
local function clamp(low, n, high) return math.min(math.max(n, low), high) end
|
||||
|
||||
BrutalAttack.SplitValueString = function(str)
|
||||
local t = {}
|
||||
for k, v in string.gmatch(str, "(%w+)=(%w+)") do
|
||||
t[k] = v
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
-- WARNING
|
||||
---- This ONLY returns the available count, as the objects this returns are not exported for use in Lua
|
||||
BrutalAttack.GetAvailableTargetCount = function(player, weapon)
|
||||
local prone = ArrayList.new()
|
||||
local stand = ArrayList.new()
|
||||
-- we want a player, and a hand weapon
|
||||
if not checkValid(player, weapon) then return end
|
||||
|
||||
SwipeStatePlayer.instance():calcValidTargets(player, weapon, true, prone, stand)
|
||||
local pC = prone:size()
|
||||
local sC = stand:size()
|
||||
|
||||
--prone:clear()
|
||||
--stand:clear()
|
||||
|
||||
return pC, sC
|
||||
end
|
||||
|
||||
local moodleOffset = {
|
||||
0.5, 0.2, 0.1, 0.05
|
||||
}
|
||||
|
||||
local weaponLevelOffset = {
|
||||
0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3
|
||||
}
|
||||
|
||||
BrutalAttack.GetWeaponLevel = function(player, weapon)
|
||||
local lvl = -1
|
||||
if weapon and player then
|
||||
local cats = weapon:getCategories()
|
||||
if cats:contains("Axe") then
|
||||
lvl = lvl + player:getPerkLevel(Perks.Axe)
|
||||
end
|
||||
if cats:contains("Spear") then
|
||||
lvl = lvl + player:getPerkLevel(Perks.Spear)
|
||||
end
|
||||
|
||||
if cats:contains("SmallBlade") then
|
||||
lvl = lvl + player:getPerkLevel(Perks.SmallBlade)
|
||||
end
|
||||
if cats:contains("LongBlade") then
|
||||
lvl = lvl + player:getPerkLevel(Perks.LongBlade)
|
||||
end
|
||||
if cats:contains("Blunt") then
|
||||
lvl = lvl + player:getPerkLevel(Perks.Blunt)
|
||||
end
|
||||
if cats:contains("SmallBlunt") then
|
||||
lvl = lvl + player:getPerkLevel(Perks.SmallBlunt)
|
||||
end
|
||||
-- if cats:contains("Unarmed") then
|
||||
-- lvl = lvl + player:getPerkLevel(Perks.Unarmed)
|
||||
-- end
|
||||
end
|
||||
|
||||
return (lvl == -1 and 0) or lvl
|
||||
end
|
||||
|
||||
|
||||
-- Yea, you see all this here? This is the FULL damage code ported from Java to Lua, made weapon agnostic.
|
||||
---- This doesn't fucking work in MP though, as there is NO method to get a zombie remotely.
|
||||
---- So, I cannot accurately sync hit reactions. This causes zombies to fall for you, and walk in place for others
|
||||
---- I could fix this if I could just get a zombie by its online id or something. But noooooooooooo. I can't have nice things......
|
||||
-- BrutalAttack.processHitDamage = function(weapon, player, target, damage, ignoreDamage, delta)
|
||||
-- local dmg = damage * delta
|
||||
-- local dmg2 = (ignoreDamage and dmg/2.7) or dmg
|
||||
|
||||
-- local force = dmg2 * player:getShovingMod()
|
||||
-- if force > 1.0 then force = 1.0 end
|
||||
|
||||
-- if not weapon:isRanged() then
|
||||
-- force = (player:HasTrait("Strong") and force*1.4) or (player:HasTrait("Weak") and force*0.6) or force
|
||||
-- end
|
||||
|
||||
-- local dist = 1.0 - ((target:DistTo(player) - weapon:getMinRange())/weapon:getMaxRange(player))
|
||||
-- if dist > 1.0 then dist = 1.0 end
|
||||
|
||||
-- -- Apparently, this is supposed to be modified by knockbackAttackMod, but this always seems to be 1
|
||||
-- local endurance = player:getStats():getEndurance()
|
||||
-- if endurance < 0.5 then
|
||||
-- endurance = endurance * 1.3
|
||||
-- if endurance < 0.4 then
|
||||
-- endurance = 0.4
|
||||
-- end
|
||||
-- end
|
||||
-- force = force * endurance
|
||||
|
||||
|
||||
-- if not weapon:isRangeFalloff() then
|
||||
-- dist = 1.0
|
||||
-- end
|
||||
-- if not weapon:isShareDamage() then
|
||||
-- damage = 1.0
|
||||
-- end
|
||||
|
||||
-- if not ignoreDamage then
|
||||
-- force = force * 2.0
|
||||
-- end
|
||||
|
||||
-- if player:isDoShove() then
|
||||
-- local vec = Vector2.new()
|
||||
-- vec:set(target:getX() - player:getX(), target:getY() - player:getY())
|
||||
-- vec:normalize()
|
||||
-- local vec2 = Vector2.new()
|
||||
-- vec2:set(player:getX(), player:getY())
|
||||
-- vec2 = target:getVectorFromDirection(vec2)
|
||||
-- local dir = vec:dot(vec2)
|
||||
-- if dir > -0.3 then
|
||||
-- dmg = dmg * 1.5
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- dmg = (instanceof(target, "IsoPlayer") and dmg * 0.4) or dmg * 1.5
|
||||
|
||||
-- dmg = dmg * (weaponLevelOffset[BrutalAttack.GetWeaponLevel(player, weapon)] or 0.3)
|
||||
|
||||
-- if player:isAimAtFloor() and not player:isDoShove() and not ignoreDamage then
|
||||
-- dmg = dmg * (math.max(5.0, weapon:getCritDmgMultiplier()))
|
||||
-- end
|
||||
|
||||
-- if player:isCriticalHit() and not ignoreDamage then
|
||||
-- dmg = dmg * math.max(2.0, weapon:getCritDmgMultiplier())
|
||||
-- end
|
||||
|
||||
-- if weapon:isTwoHandWeapon() and not player:isItemInBothHands(weapon) then
|
||||
-- dmg = dmg * 0.5
|
||||
-- end
|
||||
|
||||
-- return dmg
|
||||
-- end
|
||||
|
||||
-- local basehitConsequences = function(weapon, player, target, ignoreDamage, damage)
|
||||
-- if not ignoreDamage then
|
||||
-- if weapon:isAimedFirearm() then
|
||||
-- target:setHealth(target:getHealth() - damage * 0.7)
|
||||
-- else
|
||||
-- target:setHealth(target:getHealth() - damage * 0.15)
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if target:isDead() then
|
||||
-- if target:isOnKillDone() and target:shouldDoInventory() then
|
||||
-- target:Kill(player)
|
||||
-- end
|
||||
-- if target:isZombie() then
|
||||
-- player:setZombieKills(player:getZombieKills() + 1)
|
||||
-- end
|
||||
-- else
|
||||
-- if weapon:isSplatBloodOnNoDeath() then
|
||||
-- target:splatBlood(2, 0.2)
|
||||
-- end
|
||||
-- if (weapon:isKnockBackOnNoDeath()) then
|
||||
-- player:getXp():AddXP(Perks.Strength, 2.0)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- local zedhitConsequences = function(weapon, player, target, ignoreDamage, damage)
|
||||
-- if not target:isOnlyJawStab() or target:isCloseKilled() then
|
||||
-- basehitConsequences(weapon, player, target, ignoreDamage, damage)
|
||||
-- end
|
||||
-- if getDebug() then
|
||||
-- print("BRUTAL: Zombie #" .. tostring(target:getOnlineID()) .. " got hit for " .. tostring(damage))
|
||||
-- end
|
||||
|
||||
-- target:reportEvent("wasHit")
|
||||
-- if not ignoreDamage then
|
||||
-- local react = player:getVariableString("ZombieHitReaction") or ""
|
||||
-- local cats = weapon:getCategories()
|
||||
-- if react == "Shot" then
|
||||
-- -- Shot
|
||||
-- elseif cats:contains("Blunt") or cats:contains("BHUnarmed") then
|
||||
-- target:addBlood(BloodBodyPartType.FromIndex(ZombRand(BloodBodyPartType.MAX:index())), false, false, true)
|
||||
-- elseif not cats:contains("Unarmed") then
|
||||
-- target:addBlood(BloodBodyPartType.FromIndex(ZombRand(BloodBodyPartType.MAX:index())), false, true, true)
|
||||
-- end
|
||||
|
||||
-- if react == "ShotHeadFwd" and ZombRand(2) == 0 then
|
||||
-- react = "ShotHeadFwd02"
|
||||
-- end
|
||||
|
||||
-- if target:getEatBodyTarget() ~= nil then
|
||||
-- if target:getVariableBoolean("onknees") then
|
||||
-- react = "OnKnees"
|
||||
-- else
|
||||
-- react = "Eating"
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if string.lower(react) == "floor" and target:isCurrentState(ZombieGetUpState.instance()) and target:isFallOnFront() then
|
||||
-- react = "GettingUpFront"
|
||||
-- end
|
||||
|
||||
-- if react ~= "" then
|
||||
-- target:setHitReaction(react)
|
||||
-- else
|
||||
-- target:setStaggerBack(true)
|
||||
-- target:setHitReaction("")
|
||||
-- if target:getPlayerAttackPosition() == "LEFT" or target:getPlayerAttackPosition() == "RIGHT" then
|
||||
-- player:setCriticalHit(false)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- local tgt = target:getTarget()
|
||||
-- if not tgt or tgt == player or target:DistToSquared(player) < 10.0 then
|
||||
-- target:setTarget(player)
|
||||
-- end
|
||||
|
||||
-- if player:isLocalPlayer() and not target:isRemoteZombie() then
|
||||
-- target:setKnockedDown(player:isCriticalHit() or target:isOnFloor() or target:isAlwaysKnockedDown())
|
||||
-- end
|
||||
|
||||
-- if not target:isOnFloor() then
|
||||
-- local windowFence = function(x,y)
|
||||
-- local dir = target:getDir()
|
||||
-- if dir == IsoDirections.W then
|
||||
-- target:setX(x + 0.9)
|
||||
-- target:setLx(target:getX())
|
||||
-- elseif dir == IsoDirections.E then
|
||||
-- target:setX(x + 0.1)
|
||||
-- target:setLx(target:getX())
|
||||
-- elseif dir == IsoDirections.N then
|
||||
-- target:setY(y + 0.9)
|
||||
-- target:setLy(target:getY())
|
||||
-- elseif dir == IsoDirections.S then
|
||||
-- target:setY(y + 0.1)
|
||||
-- target:setLy(target:getY())
|
||||
-- end
|
||||
|
||||
-- target:setStaggerBack(false);
|
||||
-- target:setKnockedDown(true);
|
||||
-- target:setOnFloor(true);
|
||||
-- target:setFallOnFront(true);
|
||||
-- target:setHitReaction("FenceWindow");
|
||||
-- end
|
||||
|
||||
-- if target:isCurrentState(ClimbOverFenceState.instance()) and target:getVariableBoolean("ClimbFenceStarted") and not target:isVariable("ClimbFenceOutcome", "fall") and not target:getVariableBoolean("ClimbFenceFlopped") then
|
||||
-- local map = target:getStateMachineParams(ClimbOverFenceState.instance())
|
||||
-- windowFence(map:get(3), map:get(4))
|
||||
-- elseif target:isCurrentState(ClimbThroughWindowState.instance()) and target:getVariableBoolean("ClimbWindowStarted") and not target:isVariable("ClimbWindowOutcome", "fall") and not target:getVariableBoolean("ClimbWindowFlopped") then
|
||||
-- local map = target:getStateMachineParams(ClimbThroughWindowState.instance())
|
||||
-- windowFence(map:get(12), map:get(13))
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- local crawler = false
|
||||
-- if target:isBecomeCrawler() then
|
||||
-- crawler = true
|
||||
-- elseif target:isCrawling() or BrutalAttack.isLastStand or target:isDead() or target:isCloseKilled() then
|
||||
-- crawler = false
|
||||
-- else
|
||||
-- if not player:isAimAtFloor() and player:isDoShove() then
|
||||
-- crawler = false
|
||||
-- elseif player:isAimAtFloor() and player:isDoShove() then
|
||||
-- crawler = (ZombRand((target:isHitLegsWhileOnFloor() and 7) or 15) % 2) == 0
|
||||
-- end
|
||||
-- end
|
||||
-- if crawler then
|
||||
-- target:setBecomeCrawler(true)
|
||||
-- end
|
||||
|
||||
-- end
|
||||
|
||||
-- local playerhitConsequences = function(weapon, player, target, ignoreDamage, damage)
|
||||
-- end
|
||||
|
||||
-- BrutalAttack.hitConsequences = function(weapon, player, target, ignoreDamage, damage)
|
||||
-- if instanceof(target, "IsoPlayer") then
|
||||
-- playerhitConsequences(weapon, player, target, ignoreDamage, damage)
|
||||
-- else
|
||||
-- zedhitConsequences(weapon, player, target, ignoreDamage, damage)
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- BrutalAttack.OnWeaponHitCharacter = function(player, target, weapon, damage)
|
||||
-- if not instanceof(weapon, "HandWeapon") or not instanceof(player, "IsoPlayer") or not instanceof(target, "IsoGameCharacter") then return false end
|
||||
-- if weapon:isRanged() then return false end -- not implemented
|
||||
-- local vec2 = Vector2.new()
|
||||
-- vec2:set(target:getX()-player:getX(), target:getY()-player:getY())
|
||||
-- local delta = BrutalAttack.calcDelta(player, weapon, vec2)
|
||||
-- BrutalAttack.weaponHitCharacter(player, target, weapon, damage, false, delta)
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
-- BrutalAttack.weaponHitCharacter = function(player, target, weapon, damage, ignoreDamage ,delta)
|
||||
-- if target:avoidDamage() then
|
||||
-- target:setAvoidDamage(false)
|
||||
-- return 0
|
||||
-- end
|
||||
-- local ignoreDamage = target:getNoDamage()
|
||||
-- if ignoreDamage then
|
||||
-- target:setNoDamage(false)
|
||||
-- end
|
||||
|
||||
-- if instanceof(target, "IsoSurvivor") then
|
||||
-- local enemyList = target:getEnemyList()
|
||||
-- if enemyList and not enemyList:contains(player) then
|
||||
-- enemyList:add(player)
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- target:setStaggerTimeMod(weapon:getPushBackMod() * weapon:getKnockbackMod(player) * player:getShovingMod())
|
||||
|
||||
-- player:addWorldSoundUnlessInvisible(5, 1, false)
|
||||
|
||||
-- local vec2 = Vector2.new()
|
||||
-- vec2:set(target:getX() - player:getX(), target:getY() - player:getY())
|
||||
-- vec2:normalize()
|
||||
-- vec2:set(vec2:getX() * weapon:getPushBackMod(), vec2:getY() * weapon:getPushBackMod())
|
||||
-- -- Literally everything that I can find uses -30 for the HitAngleMod, including modded items. This parameter does not have a 'get', so lets just use -30
|
||||
-- vec2:rotate(-30)
|
||||
-- target:setHitDir(vec2)
|
||||
|
||||
-- target:setAttackedBy(player)
|
||||
|
||||
-- local finalDamage = BrutalAttack.processHitDamage(weapon, player, target, damage, ignoreDamage, delta)
|
||||
-- local weight = 0
|
||||
-- if weapon:isTwoHandWeapon() and player:isItemInBothHands(weapon) then
|
||||
-- weight = weapon:getWeight()/0.15
|
||||
-- end
|
||||
-- weight = (weapon:getWeight() * 0.28 * weapon:getFatigueMod(player) * target:getFatigueMod() * weapon:getEnduranceMod() * 0.30 + weight) * 0.04
|
||||
|
||||
-- if instanceof(player, "IsoPlayer") and player:isAimAtFloor() and player:isDoShove() then
|
||||
-- weight = weight * 2.0
|
||||
-- end
|
||||
|
||||
-- local enduranceDmg = finalDamage * ((weapon:isAimedFirearm() and 0.7) or 0.15)
|
||||
-- enduranceDmg = ((target:getHealth() < enduranceDmg and target:getHealth()) or enduranceDmg)/weapon:getMaxDamage()
|
||||
-- if enduranceDmg > 1.0 then enduranceDmg = 1.0 end
|
||||
-- enduranceDmg = (target:isCloseKilled() and 0.2) or enduranceDmg
|
||||
|
||||
-- if weapon:isUseEndurance() then
|
||||
-- enduranceDmg = ((finalDamage <= 0) and 1.0) or enduranceDmg
|
||||
-- player:getStats():setEndurance(player:getStats():getEndurance() - (weight * enduranceDmg))
|
||||
-- end
|
||||
|
||||
-- --BrutalAttack.hitConsequences(weapon, player, target, ignoreDamage, finalDamage)
|
||||
-- target:hitConsequences(weapon, player, ignoreDamage, finalDamage, false)
|
||||
|
||||
-- if target:isZombie() then
|
||||
-- if not target:isRemoteZombie() then
|
||||
-- target:addAggro(player, finalDamage)
|
||||
-- end
|
||||
|
||||
-- target:setTargetSeenTime(0)
|
||||
-- if not target:isDead() and not target:isOnFloor() and not ignoreDamage and weapon:getScriptItem():getCategories():contains("Blade") then
|
||||
-- target:setHitForce(0.5)
|
||||
-- target:changeState(StaggerBackState.instance())
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- return finalDamage
|
||||
-- end
|
||||
|
||||
-- BrutalAttack.Hit = function(weapon, player, target, damage, ignoreDamage, delta)
|
||||
-- if not instanceof(weapon, "HandWeapon") or not instanceof(player, "IsoPlayer") or not instanceof(target, "IsoGameCharacter") then return end
|
||||
-- if not ignoreDamage and target:isZombie() then
|
||||
-- target:setHitTime(target:getHitTime()+1)
|
||||
-- if target:getHitTime() >= 4 then
|
||||
-- damage = damage * ((target:getHitTime()-2) * 1.50)
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- -- Set the shove damage. probably un-needed, but lets do it anyways
|
||||
-- if player:isDoShove() and not player:isAimAtFloor() then
|
||||
-- ignoreDamage = true
|
||||
-- delta = delta * 1.5
|
||||
-- end
|
||||
|
||||
-- triggerEvent("OnWeaponHitCharacter", player, target, weapon, damage)
|
||||
-- triggerEvent("OnPlayerGetDamage", target, "WEAPONHIT", damage)
|
||||
|
||||
-- BrutalAttack.weaponHitCharacter(player, target, weapon, damage, ignoreDamage, delta)
|
||||
|
||||
-- triggerEvent("OnWeaponHitXp", player, weapon, target, damage)
|
||||
-- end
|
||||
|
||||
BrutalAttack.calcDelta = function(player, weapon, vec2)
|
||||
local delta = 1.0
|
||||
if weapon:isRangeFalloff() then
|
||||
delta = 1.0
|
||||
elseif weapon:isRanged() then
|
||||
delta = 0.5
|
||||
else
|
||||
delta = vec2:getLength() / weapon:getMaxRange(player)
|
||||
end
|
||||
delta = delta * 2.0
|
||||
if delta < 0.3 then delta = 1 end
|
||||
|
||||
-- I'm tired. I've written 3 methods for calculating damage, only to run into an issue.
|
||||
--- So we're just going to correct it using math and the `delta` parameter
|
||||
---- We must correct for the offhand weapon skill here
|
||||
---- first, we divide by the primary hand's skill offset; later, this is counter-acted by the offset being multiplied
|
||||
delta = delta / (weaponLevelOffset[BrutalAttack.GetWeaponLevel(player, player:getPrimaryHandItem())] or 0.3)
|
||||
-- then we multiply the real skill offset
|
||||
delta = delta * (weaponLevelOffset[BrutalAttack.GetWeaponLevel(player, weapon)] or 0.3)
|
||||
|
||||
return delta
|
||||
end
|
||||
|
||||
BrutalAttack.calcDamage = function(player, weapon, target, count)
|
||||
local vec2 = Vector2.new()
|
||||
vec2:set(target:getX()-player:getX(), target:getY()-player:getY())
|
||||
local delta = BrutalAttack.calcDelta(player, weapon, vec2)
|
||||
|
||||
local minDamage = weapon:getMinDamage() -- var50
|
||||
local maxDamage = weapon:getMaxDamage() -- var28
|
||||
local deltaDamage = maxDamage - minDamage -- var52
|
||||
local twoHand = not weapon:isTwoHandWeapon() or player:isItemInBothHands(weapon) -- var54
|
||||
|
||||
local initDamage = 0 -- var51
|
||||
if deltaDamage == 0.0 then
|
||||
initDamage = minDamage
|
||||
else
|
||||
initDamage = minDamage + (ZombRand(maxDamage*1000.0)/1000.0)
|
||||
end
|
||||
|
||||
if not weapon:isRanged() then
|
||||
initDamage = initDamage * weapon:getDamageMod(player) * player:getHittingMod()
|
||||
if not twoHand and maxDamage > minDamage then
|
||||
initDamage = initDamage - minDamage
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- local damage = 0 --var34
|
||||
-- local forward = target:getForwardDirection()
|
||||
-- vec2:normalize()
|
||||
-- forward:normalize()
|
||||
-- damage = vec2.dot(forward)
|
||||
-- local fromBehind = damage > 0.50
|
||||
|
||||
local damage = 0
|
||||
for i=0,BodyPartType.ToIndex(BodyPartType.MAX) - 1 do
|
||||
damage = damage + player:getBodyDamage():getBodyParts():get(i):getPain()
|
||||
end
|
||||
if damage > 10.0 then
|
||||
initDamage = initDamage/clamp(damage/10.0, 1.0, 30.0)
|
||||
end
|
||||
|
||||
if player:HasTrait("Underweight") then
|
||||
initDamage = initDamage * 0.8
|
||||
end
|
||||
|
||||
if player:HasTrait("VeryUnderweight") then
|
||||
initDamage = initDamage * 0.6
|
||||
end
|
||||
|
||||
if player:HasTrait("Emaciated") then
|
||||
initDamage = initDamage * 0.4
|
||||
end
|
||||
|
||||
-- this way, the other items hit get less damage, i get it
|
||||
damage = initDamage/(count/2.0)
|
||||
|
||||
if player:isAttackWasSuperAttack() then
|
||||
damage = damage * 5.0
|
||||
end
|
||||
|
||||
if weapon:isRanged() and player:getPerkLevel(Perks.Aiming) < 6 and player:getMoodles():getMoodleLevel(MoodleType.Panic) > 2 then
|
||||
damage = damage - (player:getMoodles():getMoodleLevel(MoodleType.Panic) * 0.2)
|
||||
end
|
||||
|
||||
if not weapon:isRanged() and player:getMoodles():getMoodleLevel(MoodleType.Panic) > 1 then
|
||||
damage = damage - (player:getMoodles():getMoodleLevel(MoodleType.Panic) * 0.1)
|
||||
end
|
||||
|
||||
if player:getMoodles():getMoodleLevel(MoodleType.Stress) > 1 then
|
||||
damage = damage - (player:getMoodles():getMoodleLevel(MoodleType.Stress) * 0.1)
|
||||
end
|
||||
|
||||
if damage < 0 then damage = 0.1 end
|
||||
|
||||
if not weapon:isRanged() then
|
||||
damage = damage * (moodleOffset[player:getMoodles():getMoodleLevel(MoodleType.Endurance)] or 1.0)
|
||||
damage = damage * (moodleOffset[player:getMoodles():getMoodleLevel(MoodleType.Tired)] or 1.0)
|
||||
end
|
||||
|
||||
-- local part = ZombRand(BodyPartType.ToIndex(BodyPartType.Hand_L), BodyPartType.ToIndex(BodyPartType.Neck) + 1)
|
||||
-- local def = target:getBodyPartClothingDefense(part, false, weapon:isRanged())/2.0
|
||||
-- def = def + target:getBodyPartClothingDefense(part, true, weapon:isRanged())
|
||||
-- if def > 70.0 then def = 70.0 end
|
||||
-- damage = damage * math.abs(1.0-def/100.0)
|
||||
|
||||
-- triggerEvent("OnHitZombie", target, player, part, weapon)
|
||||
|
||||
return damage, delta
|
||||
end
|
||||
|
||||
local addToHitList = function(list, obj, player, weapon, extraRange, vec)
|
||||
if obj and obj:isZombie() and obj:isAlive() then
|
||||
obj:getPosition(vec)
|
||||
if player:IsAttackRange(weapon, obj, vec, extraRange) then
|
||||
-- Add our zed, cache the distance to the player
|
||||
list[#list+1] = { obj = obj, dist = obj:DistTo(player) }
|
||||
if isDebugEnabled() then
|
||||
print("Found: " .. tostring(#list) .. " | Distance: " .. tostring(list[#list].dist))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local directions = {
|
||||
[0] = IsoDirections.N,
|
||||
[1] = IsoDirections.NW,
|
||||
[2] = IsoDirections.W,
|
||||
[3] = IsoDirections.SW,
|
||||
[4] = IsoDirections.S,
|
||||
[5] = IsoDirections.SE,
|
||||
[6] = IsoDirections.E,
|
||||
[7] = IsoDirections.NE,
|
||||
}
|
||||
|
||||
local getAttackSquares = function(player)
|
||||
local psquare = player:getSquare()
|
||||
if not psquare then return nil end
|
||||
local squares = {psquare}
|
||||
local currentDir = player:getDir():index()
|
||||
local leftIndex = currentDir+1
|
||||
if leftIndex > 7 then leftIndex=0 end
|
||||
--local middleIndex = currentDir
|
||||
local rightIndex = currentDir-1
|
||||
if rightIndex < 0 then rightIndex=7 end
|
||||
-- this should collect any additional squares, only if we nothing is in the way
|
||||
local sq = psquare:getAdjacentSquare(directions[leftIndex])
|
||||
if sq and not sq:isBlockedTo(psquare) then
|
||||
squares[#squares+1] = sq
|
||||
end
|
||||
sq = psquare:getAdjacentSquare(directions[currentDir])
|
||||
if sq and not sq:isBlockedTo(psquare) then
|
||||
squares[#squares+1] = sq
|
||||
end
|
||||
sq = psquare:getAdjacentSquare(directions[rightIndex])
|
||||
if sq and not sq:isBlockedTo(psquare) then
|
||||
squares[#squares+1] = sq
|
||||
end
|
||||
return squares
|
||||
end
|
||||
|
||||
-- Finds and performs the attack on players in weapon range
|
||||
BrutalAttack.FindAndAttackTargets = function(player, weapon, extraRange)
|
||||
-- we want a player, and a hand weapon
|
||||
if not checkValid(player, weapon) then return end
|
||||
|
||||
-- honor the max hit
|
||||
local maxHit = (SandboxVars.MultiHitZombies and weapon:getMaxHitCount()) or 1
|
||||
|
||||
-- this seems to be the default sooooooooo
|
||||
if extraRange == nil then extraRange = true end
|
||||
|
||||
-- We do everything so we can attack non-zeds too
|
||||
--local objs = getCell():getObjectList()
|
||||
local found = {}
|
||||
local psquare = player:getSquare()
|
||||
if not psquare then return end -- can't attack
|
||||
local attackSquares = getAttackSquares(player)
|
||||
if not attackSquares then return end -- no squares?
|
||||
local vec = Vector3.new() -- reuse this
|
||||
for i=1, #attackSquares do
|
||||
local objs = attackSquares[i]:getMovingObjects()
|
||||
if objs then
|
||||
for j=0, objs:size()-1 do
|
||||
addToHitList(found, objs:get(j), player, weapon, extraRange, vec)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #found > 0 then
|
||||
-- sort our found list by the closest zed
|
||||
table.sort(found, function(a,b)
|
||||
if a.obj:isZombie() then return true end
|
||||
if b.obj:isZombie() then return false end
|
||||
return a.dist < b.dist
|
||||
end)
|
||||
local count = 1
|
||||
local sound = false
|
||||
for _,v in ipairs(found) do
|
||||
-- hit em!
|
||||
local damage, dmgDelta = BrutalAttack.calcDamage(player, weapon, v.obj, count)
|
||||
if isDebugEnabled() then
|
||||
print("Damage: " .. tostring(damage) .. " | Delta: " .. tostring(dmgDelta))
|
||||
end
|
||||
v.obj:Hit(weapon, player, damage, false, dmgDelta)
|
||||
|
||||
--v.zed:splatBloodFloor()
|
||||
if not sound then
|
||||
-- if we haven't played the sound yet, do so
|
||||
sound = true
|
||||
local zSound = weapon:getZombieHitSound()
|
||||
if zSound then v.obj:playSound(zSound) end
|
||||
end
|
||||
|
||||
-- stop at maxhit
|
||||
if count >= maxHit then break end
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
luautils.weaponLowerCondition(weapon, player)
|
||||
else
|
||||
-- Swing and collide with anything not a zed
|
||||
SwipeStatePlayer.instance():ConnectSwing(player, weapon)
|
||||
end
|
||||
end
|
||||
|
||||
BrutalAttack.CalcCombatSpeed = function(player, weapon, right)
|
||||
|
||||
-- we want a player, and a hand weapon
|
||||
if not checkValid(player, weapon) then return nil end
|
||||
local speed = weapon:getBaseSpeed()
|
||||
|
||||
local other
|
||||
if right then
|
||||
other = player:getSecondaryHandItem()
|
||||
else
|
||||
other = player:getPrimaryHandItem()
|
||||
end
|
||||
|
||||
if weapon:isTwoHandWeapon() and weapon ~= other then
|
||||
speed = speed * 0.77
|
||||
end
|
||||
|
||||
if player:HasTrait("Axeman") and weapon:getCategories():contains("Axe") then
|
||||
speed = speed * player:getChopTreeSpeed()
|
||||
end
|
||||
|
||||
speed = speed - (player:getMoodles():getMoodleLevel(MoodleType.Endurance) * 0.07)
|
||||
speed = speed - (player:getMoodles():getMoodleLevel(MoodleType.HeavyLoad) * 0.07)
|
||||
speed = speed + (player:getWeaponLevel() * 0.03)
|
||||
speed = speed + (player:getPerkLevel(Perks.Fitness) * 0.02)
|
||||
|
||||
if instanceof(other, "InventoryContainer") then
|
||||
speed = speed * 0.95
|
||||
end
|
||||
|
||||
local md = player:getModData()
|
||||
-- our calculation is still just a bit too fast. So lets actually reduce it a bit instead of increasing:
|
||||
speed = speed * ZombRandFloat(1.1, 1.2)
|
||||
speed = speed * ((md.BrutalHandwork and md.BrutalHandwork.CombatSpeed) or 1)
|
||||
speed = speed * BrutalAttack.getArmsInjurySpeedModifier(player, right)
|
||||
|
||||
if player:getBodyDamage() and player:getBodyDamage():getThermoregulator() then
|
||||
speed = speed * player:getBodyDamage():getThermoregulator():getCombatModifier()
|
||||
end
|
||||
|
||||
speed = math.min(1.6, speed)
|
||||
speed = math.max(0.8, speed)
|
||||
|
||||
speed = speed * GameTime.getAnimSpeedFix()
|
||||
|
||||
return speed
|
||||
end
|
||||
|
||||
BrutalAttack.calcInjurySpeed = function(part, pain)
|
||||
if part:haveBullet() then return 1.0 end
|
||||
|
||||
local scratch = part:getScratchSpeedModifier()
|
||||
local cut = part:getCutSpeedModifier()
|
||||
local burn = part:getBurnSpeedModifier()
|
||||
local wound = part:getDeepWoundSpeedModifier()
|
||||
local temp = 0.0
|
||||
|
||||
if part:getScratchTime() > 2.0 or part:getCutTime() > 5.0 or part:getBurnTime() > 0
|
||||
or part:getDeepWoundTime() > 0 or part:isSplint() or part:getFractureTime() > 0
|
||||
or part:getBiteTime() > 0 then
|
||||
temp = (part:getScratchTime()/scratch) + (part:getCutTime()/cut) + (part:getBurnTime()/burn) + (part:getDeepWoundTime()/wound)
|
||||
temp = temp + (part:getBiteTime()/20.0)
|
||||
if part:bandaged() then
|
||||
temp = temp/2.0
|
||||
end
|
||||
if part:getFractureTime() > 0 then
|
||||
local frac = 0.4
|
||||
if part:getFractureTime() > 20 then
|
||||
frac = 1.0
|
||||
elseif part:getFractureTime() > 10 then
|
||||
frac = 0.7
|
||||
end
|
||||
if part:getSplintFactor() > 0 then
|
||||
frac = frac - 0.2
|
||||
frac = frac - math.min(part:getSplintFactor()/10.0, 0.8)
|
||||
end
|
||||
temp = math.max(0, frac)
|
||||
end
|
||||
|
||||
if pain and part:getPain() > 20 then
|
||||
temp = temp + (part:getPain()/10.0)
|
||||
end
|
||||
end
|
||||
return temp
|
||||
end
|
||||
|
||||
BrutalAttack.getArmsInjurySpeedModifier = function(player, right)
|
||||
local out = 1.0
|
||||
local temp = 0.0
|
||||
local part
|
||||
if right then
|
||||
part = player:getBodyDamage():getBodyPart(BodyPartType.Hand_R)
|
||||
temp = BrutalAttack.calcInjurySpeed(part, true)
|
||||
if temp > 0 then
|
||||
out = out - temp
|
||||
end
|
||||
|
||||
part = player:getBodyDamage():getBodyPart(BodyPartType.ForeArm_R)
|
||||
temp = BrutalAttack.calcInjurySpeed(part, true)
|
||||
if temp > 0 then
|
||||
out = out - temp
|
||||
end
|
||||
|
||||
part = player:getBodyDamage():getBodyPart(BodyPartType.UpperArm_R)
|
||||
temp = BrutalAttack.calcInjurySpeed(part, true)
|
||||
if temp > 0 then
|
||||
out = out - temp
|
||||
end
|
||||
else
|
||||
part = player:getBodyDamage():getBodyPart(BodyPartType.Hand_L)
|
||||
temp = BrutalAttack.calcInjurySpeed(part, true)
|
||||
if temp > 0 then
|
||||
out = out - temp
|
||||
end
|
||||
|
||||
part = player:getBodyDamage():getBodyPart(BodyPartType.ForeArm_L)
|
||||
temp = BrutalAttack.calcInjurySpeed(part, true)
|
||||
if temp > 0 then
|
||||
out = out - temp
|
||||
end
|
||||
|
||||
part = player:getBodyDamage():getBodyPart(BodyPartType.UpperArm_L)
|
||||
temp = BrutalAttack.calcInjurySpeed(part, true)
|
||||
if temp > 0 then
|
||||
out = out - temp
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local onPlayerUpdateClothes = function(player)
|
||||
-- recalc attack speeds
|
||||
local speed = 1.0
|
||||
local items = player:getWornItems()
|
||||
for i=0, items:size()-1 do
|
||||
local item = items:get(i):getItem()
|
||||
if instanceof(item, "Clothing") then
|
||||
speed = speed + item:getCombatSpeedModifier() - 1.0
|
||||
end
|
||||
-- if instanceof(item, "InventoryContainer") then
|
||||
-- speed = speed + ((item:getActualWeight()/100.0) + 0.1) - 1.0
|
||||
-- end
|
||||
end
|
||||
player:getModData().BrutalHandwork = player:getModData().BrutalHandwork or {}
|
||||
player:getModData().BrutalHandwork.CombatSpeed = speed
|
||||
end
|
||||
|
||||
local onPlayerCreate = function(player)
|
||||
local character = getSpecificPlayer(player)
|
||||
-- i know this is preserved, but i want to reset it
|
||||
character:getModData().BrutalHandwork = {
|
||||
wasShove = false,
|
||||
leftAttack = false,
|
||||
|
||||
combo = 1,
|
||||
}
|
||||
end
|
||||
|
||||
local setup = function()
|
||||
Events.OnCreatePlayer.Add(onPlayerCreate)
|
||||
Events.OnClothingUpdated.Add(onPlayerUpdateClothes)
|
||||
|
||||
BrutalAttack.BareHands = InventoryItemFactory.CreateItem("Base.Fisticuffs")
|
||||
--BrutalAttack.BareHands = InventoryItemFactory.CreateItem("Base.BareHands")
|
||||
--BrutalAttack.isLastStand = getCore():getGameMode()=="LastStand"
|
||||
end
|
||||
|
||||
BrutalAttack.setupGameEvents = function()
|
||||
Events.OnGameBoot.Remove(setup)
|
||||
Events.OnGameBoot.Add(setup)
|
||||
end
|
||||
|
||||
return BrutalAttack
|
||||
41
BrutalHandwork/Contents/mods/BrutalHandwork/media/lua/client/TOC_Compat.lua
Executable file
41
BrutalHandwork/Contents/mods/BrutalHandwork/media/lua/client/TOC_Compat.lua
Executable file
@@ -0,0 +1,41 @@
|
||||
-- Compatibility for The Only Cure
|
||||
local TOC_Compat = {}
|
||||
|
||||
-- Raw access, must pass valid part
|
||||
--- @param player
|
||||
--- @param part string
|
||||
--- @return boolean
|
||||
TOC_Compat.hasArmPart = function(player, part)
|
||||
if not player or not part then return false end
|
||||
local data = (player:getModData().TOC and player:getModData().TOC.Limbs) or nil
|
||||
if not data then return false end
|
||||
return not data[part] or (data[part].is_cut and data[part].is_prosthesis_equipped) or not data[part].is_cut
|
||||
end
|
||||
|
||||
-- Check if hand is available
|
||||
--- @param player
|
||||
--- @param left boolean -- optional
|
||||
--- @return boolean
|
||||
TOC_Compat.hasHand = function(player, left)
|
||||
return TOC_Compat.hasArmPart(player, ((left and "Left_Hand") or "Right_Hand"))
|
||||
end
|
||||
|
||||
-- Check if both hands are available
|
||||
--- @param player
|
||||
--- @return boolean
|
||||
TOC_Compat.hasBothHands = function(player)
|
||||
return TOC_Compat.hasHand(player) and TOC_Compat.hasHand(player, true)
|
||||
end
|
||||
|
||||
-- This returns a number for the hands that you have
|
||||
----- 11 == both hands
|
||||
----- 10 == left hand
|
||||
----- 01 (1) == right hand
|
||||
----- 00 (0) == no hands
|
||||
--- @param player
|
||||
--- @return integer
|
||||
TOC_Compat.getHands = function(player)
|
||||
return ((TOC_Compat.hasHand(player) and 1) or 0) + ((TOC_Compat.hasHand(player, true) and 10) or 0)
|
||||
end
|
||||
|
||||
return TOC_Compat
|
||||
@@ -0,0 +1,134 @@
|
||||
require "TimedActions/ISBaseTimedAction"
|
||||
|
||||
BHMeleeAttack = ISBaseTimedAction:derive("BHMeleeAttack");
|
||||
|
||||
local BrutalAttack = require("BrutalAttack")
|
||||
BrutalHands = BrutalHands or {}
|
||||
|
||||
function BHMeleeAttack:isValid()
|
||||
return true
|
||||
end
|
||||
|
||||
function BHMeleeAttack:waitToStart()
|
||||
return false
|
||||
end
|
||||
|
||||
function BHMeleeAttack:update()
|
||||
-- we need to force the current facing direction until the animation starts
|
||||
if self.lockDir then
|
||||
self.character:setDirectionAngle(self.vec)
|
||||
end
|
||||
end
|
||||
|
||||
-- safeguard to make sure that the action is ended
|
||||
function BHMeleeAttack:beDone()
|
||||
self.character:setVariable("AttackAnim", false)
|
||||
self.character:setBlockMovement(false)
|
||||
self.character:setMeleeDelay(8)
|
||||
end
|
||||
|
||||
function BHMeleeAttack:start()
|
||||
local prone, stand = BrutalAttack.GetAvailableTargetCount(self.character, self.weapon)
|
||||
if stand == 0 and prone > 0 then
|
||||
self:forceStop()
|
||||
-- Fall through to doing the character stomp or main attack
|
||||
self.character:DoAttack(self.chargeDelta)
|
||||
return
|
||||
end
|
||||
|
||||
local atype = "bash"
|
||||
if self.unarmed then
|
||||
local hands = (BrutalHands.TOC and BrutalHands.TOC.getHands(self.character)) or 11
|
||||
local rand = 4
|
||||
local randoff = 1
|
||||
if hands == 00 then
|
||||
self:forceStop()
|
||||
-- Fall through to doing the character stomp or push
|
||||
return self.character:DoAttack(self.chargeDelta)
|
||||
elseif hands == 01 then -- right only
|
||||
rand = 2
|
||||
elseif hands == 10 then -- left only
|
||||
randoff = 3
|
||||
end
|
||||
local num = ZombRand(rand)+randoff
|
||||
if num==1 then
|
||||
atype = "rpunch1"
|
||||
elseif num==2 then
|
||||
atype = "rpunch2"
|
||||
elseif num==3 then
|
||||
atype = "lpunch2"
|
||||
else
|
||||
atype = "lpunch1"
|
||||
end
|
||||
--atype = (ZombRand(3) == 1 and "lpunch1") or "rpunch1"
|
||||
elseif self.weapon:getSubCategory() == "Stab" then
|
||||
self.maxHit = 1
|
||||
atype = "knife"
|
||||
end
|
||||
|
||||
self.character:setVariable("LCombatSpeed", self.speed)
|
||||
self.character:setVariable("AttackAnim", true)
|
||||
self:setActionAnim("LAttack")
|
||||
self:setAnimVariable("LAttackType", atype)
|
||||
end
|
||||
|
||||
function BHMeleeAttack:animEvent(event, parameter)
|
||||
if event == 'StartAttack' then
|
||||
if self.swingSound then
|
||||
self.character:getEmitter():playSound(self.swingSound)
|
||||
end
|
||||
self.lockDir = false
|
||||
elseif event == 'SetVariable' then
|
||||
local str = BrutalAttack.SplitValueString(parameter)
|
||||
for k,v in pairs(str) do
|
||||
self.character:setVariable(k,v)
|
||||
end
|
||||
elseif event == 'AttackCollisionCheck' then
|
||||
BrutalAttack.FindAndAttackTargets(self.character, self.weapon, true)
|
||||
if isClient() then
|
||||
sendClientCommand(self.character, "BrutalAttack", "Attack", {PID=self.character:getPlayerNum(), Offhand=true, extraRange=true})
|
||||
end
|
||||
elseif event == 'BlockMovement' and SandboxVars.AttackBlockMovements then
|
||||
self.character:setBlockMovement((parameter == "TRUE" and true) or false)
|
||||
elseif event == 'EndAttack' then
|
||||
self:forceComplete()
|
||||
end
|
||||
end
|
||||
|
||||
function BHMeleeAttack:stop()
|
||||
self:beDone()
|
||||
ISBaseTimedAction.stop(self)
|
||||
end
|
||||
|
||||
function BHMeleeAttack:perform()
|
||||
self:beDone()
|
||||
-- needed to remove from queue / start next.
|
||||
ISBaseTimedAction.perform(self)
|
||||
triggerEvent("OnPlayerAttackFinished", self.character, self.weapon)
|
||||
end
|
||||
|
||||
function BHMeleeAttack:new(character, weapon, chargeDelta)
|
||||
local o = ISBaseTimedAction.new(self, character)
|
||||
|
||||
o.weapon = weapon
|
||||
o.speed = BrutalAttack.CalcCombatSpeed(character, weapon, false)
|
||||
o.maxTime = -1
|
||||
o.stopOnAim = false
|
||||
o.stopOnWalk = false
|
||||
o.stopOnRun = false
|
||||
|
||||
o.useProgressBar = false
|
||||
|
||||
o.swingSound = weapon:getSwingSound()
|
||||
o.hitSound = weapon:getZombieHitSound()
|
||||
|
||||
o.vec = character:getDirectionAngle()
|
||||
-- Needed if we fall through
|
||||
o.chargeDelta = chargeDelta
|
||||
o.lockDir = true
|
||||
o.lHandAttack = true
|
||||
|
||||
o.unarmed = weapon and weapon:getCategories():contains("Unarmed")
|
||||
|
||||
return o
|
||||
end
|
||||
220
BrutalHandwork/Contents/mods/BrutalHandwork/media/lua/client/zBrutalHandwork.lua
Executable file
220
BrutalHandwork/Contents/mods/BrutalHandwork/media/lua/client/zBrutalHandwork.lua
Executable file
@@ -0,0 +1,220 @@
|
||||
------------------------------------------
|
||||
-- Brutal Handwork Init
|
||||
------------------------------------------
|
||||
|
||||
BrutalHands = BrutalHands or {}
|
||||
|
||||
------------------------------------------
|
||||
-- Brutal Handwork Configuration
|
||||
------------------------------------------
|
||||
|
||||
BrutalHands.config = {}
|
||||
|
||||
local BrutalAttack = require("BrutalAttack")
|
||||
BrutalAttack.setupGameEvents()
|
||||
|
||||
BrutalHands.TOC = nil
|
||||
if getActivatedMods():contains("Amputation2") then
|
||||
BrutalHands.TOC = require('TOC_Compat')
|
||||
end
|
||||
|
||||
------------------------------------------
|
||||
-- Brutal Handwork Utilities
|
||||
------------------------------------------
|
||||
|
||||
local function BrutalHandwork()
|
||||
print(getText("UI_Init_BrutalHandwork"))
|
||||
end
|
||||
|
||||
BrutalHandwork()
|
||||
|
||||
local mouseDown = false
|
||||
|
||||
local attackHook = function(character, chargeDelta, primary)
|
||||
if not instanceof(character, "IsoPlayer") or character:isAttackStarted() or not character:isAuthorizeMeleeAction() then return end
|
||||
|
||||
-- Here we check if the primary weapon is actually a weapon
|
||||
primary = (instanceof(primary, "HandWeapon") and primary) or nil
|
||||
|
||||
-- Get the secondary weapon, do the same check
|
||||
local secondary = character:getSecondaryHandItem()
|
||||
secondary = (instanceof(secondary, "HandWeapon") and secondary) or nil
|
||||
|
||||
-- check if we can actually use that arm, if applicable
|
||||
---- set our weapons to nil if we don't have that arm
|
||||
--local hasRArm = true
|
||||
if BrutalHands.TOC then
|
||||
primary = (BrutalHands.TOC.hasHand(character, false) and primary) or nil
|
||||
secondary = (BrutalHands.TOC.hasHand(character, true) and secondary) or nil
|
||||
--hasRArm = BrutalHands.TOC.hasHand(character, false)
|
||||
end
|
||||
|
||||
-- get our mod data
|
||||
local brutal = character:getModData().BrutalHandwork
|
||||
|
||||
-- get our ModKey
|
||||
local mk = isFHModBindDown(character)
|
||||
|
||||
-- if we are always ready to punch, or the modkey is down.
|
||||
if (SandboxVars.BrutalHandwork.AlwaysUnarmed or mk) then
|
||||
-- we have nothing
|
||||
if not primary and not secondary then
|
||||
-- make our secondary hand the item so it doesn't trip the main attack
|
||||
secondary = BrutalAttack.BareHands
|
||||
elseif primary and twoH and primary:getCategories():contains("Unarmed") then
|
||||
-- if we have an unarmed weapon equipped, then we use our custom attack; secondary will still be our weapon
|
||||
primary = nil
|
||||
-- This isn't really implemented yet
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if its 2 handed
|
||||
local twoH = primary and (primary == secondary)
|
||||
|
||||
-- If we made it here and there's still nothing equipped, then just push
|
||||
---- This seems to set our push to start next update loop, otherwise we get a weird epic attack that is a push but it does like 100+ damage
|
||||
if not primary and not secondary then
|
||||
character:setInitiateAttack(false)
|
||||
character:setDoShove(true)
|
||||
brutal.wasShove = true
|
||||
brutal.leftAttack = false
|
||||
return
|
||||
end
|
||||
|
||||
-- we could break our weapon, or just unequip it while the thing is going. bail if so
|
||||
if not secondary then
|
||||
brutal.leftAttack = false
|
||||
end
|
||||
|
||||
-- override our modkey with left attack setting
|
||||
mk = secondary and not twoH and (brutal.leftAttack or mk)
|
||||
|
||||
local did = false
|
||||
|
||||
-- if no modkey or shoving, and we have a primary
|
||||
if not mk and primary then
|
||||
-- fall through
|
||||
ISReloadWeaponAction.attackHook(character, chargeDelta, primary or 1)
|
||||
did = true
|
||||
end
|
||||
|
||||
if not did and secondary then
|
||||
ISTimedActionQueue.clear(character)
|
||||
|
||||
if secondary:isRanged() then
|
||||
character:setDoShove(true)
|
||||
return
|
||||
-- Coming soon!
|
||||
-- if ISReloadWeaponAction.canShoot(secondary) then
|
||||
-- character:playSound(secondary:getSwingSound());
|
||||
-- local radius = secondary:getSoundRadius();
|
||||
-- if isClient() then -- limit sound radius in MP
|
||||
-- radius = radius / 1.8;
|
||||
-- end
|
||||
-- character:addWorldSoundUnlessInvisible(radius, secondary:getSoundVolume(), false);
|
||||
-- character:startMuzzleFlash()
|
||||
-- character:DoAttack(0);
|
||||
-- else
|
||||
-- character:DoAttack(0);
|
||||
-- character:setRangedWeaponEmpty(true);
|
||||
-- end
|
||||
-- nerf so players in vehicles cannot use melee attacks
|
||||
elseif not character:getVehicle() then
|
||||
ISTimedActionQueue.add(BHMeleeAttack:new(character, secondary, chargeDelta or 0))
|
||||
end
|
||||
end
|
||||
|
||||
-- if we have a left and right weapon, and its not 2handed, and we have the option to automelee enabled
|
||||
if primary and secondary and not twoH and SandboxVars.BrutalHandwork.DualWieldMelee then
|
||||
brutal.leftAttack = not (brutal.wasShove or brutal.leftAttack)
|
||||
else
|
||||
brutal.leftAttack = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Removed the default attack hook
|
||||
Hook.Attack.Remove(ISReloadWeaponAction.attackHook)
|
||||
Hook.Attack.Add(attackHook)
|
||||
|
||||
-- We are going to override this function so that doing a left hand attack cannot be canceled :)
|
||||
local _isPlayerDoingActionThatCanBeCancelled = isPlayerDoingActionThatCanBeCancelled
|
||||
function isPlayerDoingActionThatCanBeCancelled(playerObj)
|
||||
if not playerObj then return false end
|
||||
local queue = ISTimedActionQueue.queues[playerObj]
|
||||
if queue and #queue.queue > 0 and queue.queue[1].lHandAttack then
|
||||
return false
|
||||
end
|
||||
return _isPlayerDoingActionThatCanBeCancelled(playerObj)
|
||||
end
|
||||
|
||||
local forceAttack = function(character)
|
||||
character:setDoShove(false)
|
||||
attackHook(character, character:getPrimaryHandItem(), 1.0)
|
||||
return true
|
||||
end
|
||||
|
||||
local checkDoAttack = function(character)
|
||||
if not character or not character:isAiming() or character:getMeleeDelay() > 0.0 then return false end
|
||||
local queue = ISTimedActionQueue.queues[character]
|
||||
if queue and #queue.queue > 0 and queue.queue[1].lHandAttack then
|
||||
return false
|
||||
end
|
||||
local hands = (BrutalHands.TOC and BrutalHands.TOC.getHands(character)) or 11
|
||||
local primary = character:getPrimaryHandItem()
|
||||
primary = (instanceof(primary, "HandWeapon") and primary) or nil
|
||||
local secondary = character:getSecondaryHandItem()
|
||||
secondary = (instanceof(secondary, "HandWeapon") and secondary) or nil
|
||||
-- just do nothing here
|
||||
if not primary and not secondary and not (SandboxVars.BrutalHandwork.EnableUnarmed and (SandboxVars.BrutalHandwork.AlwaysUnarmed or isFHModBindDown(character))) then return false end
|
||||
if hands == 1 then
|
||||
-- if we only have the right hand, then the attackHook will handle everything
|
||||
--if not instanceof(primary, "HandWeapon") then return forceAttack(character) end
|
||||
return false -- we'll still do the base attack, so just ignore
|
||||
elseif hands == 11 then
|
||||
-- if we have a primary weapon, then the attackHook will do the thing
|
||||
if primary then return false end
|
||||
-- otherwise, manually attack
|
||||
return forceAttack(character)
|
||||
elseif hands == 10 then
|
||||
-- just our left, do the attack
|
||||
return forceAttack(character)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- soooooooooo, i guess TOC makes it so you no longer do the attack hook
|
||||
---- That's fine, we'll just do it ourselves
|
||||
local onMouseClick = function(x,y)
|
||||
checkDoAttack(getSpecificPlayer(0))
|
||||
mouseDown = true
|
||||
end
|
||||
|
||||
-- This is a little hack so we can still hold the offhand attack
|
||||
local onMouseUp = function(x,y)
|
||||
mouseDown = false
|
||||
end
|
||||
|
||||
local playerUpdate = function(player)
|
||||
local num = player:getPlayerNum()
|
||||
if (num == 0 and mouseDown) or (JoypadState.players[num+1] and (getControllerAxisValue(player:getJoypadBind(), 5) > 0.90)) then
|
||||
checkDoAttack(player)
|
||||
end
|
||||
end
|
||||
|
||||
local OnWeaponHitCharacter = function(player, target, weapon, damage)
|
||||
print("OnWeaponHitCharacter: " .. tostring(damage))
|
||||
print("IsCritical: " .. tostring(player:isCriticalHit()))
|
||||
end
|
||||
|
||||
Events.OnGameStart.Add(function()
|
||||
Events.OnMouseDown.Add(onMouseClick)
|
||||
Events.OnMouseUp.Add(onMouseUp)
|
||||
Events.OnPlayerUpdate.Add(playerUpdate)
|
||||
if isDebugEnabled() then
|
||||
Events.OnWeaponHitCharacter.Add(OnWeaponHitCharacter)
|
||||
end
|
||||
-- if SandboxVars.BrutalHandwork.BaseAttackOverride then
|
||||
-- --Hook.WeaponHitCharacter.Add(WeaponHitCharacter)
|
||||
-- Hook.WeaponHitCharacter.Add(BrutalAttack.OnWeaponHitCharacter)
|
||||
-- end
|
||||
end)
|
||||
@@ -0,0 +1,15 @@
|
||||
Sandbox_EN = {
|
||||
Sandbox_BrutalHandwork = "Brutal Handwork",
|
||||
|
||||
Sandbox_BrutalHandwork_DualWieldMelee = "Automatically alternate left and right attacks when dual-wielding melee weapons",
|
||||
Sandbox_BrutalHandwork_DualWieldMelee_tooltip = "When a player is dual-wielding melee weapons, automatically alternate between left and right attacks. Disable to require the Modifier to be pressed for an offhand attack.",
|
||||
|
||||
Sandbox_BrutalHandwork_EnableUnarmed = "Enable Unarmed Attacks",
|
||||
Sandbox_BrutalHandwork_EnableUnarmed_tooltip = "Even when a player is unarmed, they will be able to attack. By default, must be aiming and holding the Modifier key to punch.",
|
||||
|
||||
Sandbox_BrutalHandwork_AlwaysUnarmed = "Always raise fists when unarmed",
|
||||
Sandbox_BrutalHandwork_AlwaysUnarmed_tooltip = "When a player is unarmed, always raise their fists when aiming for unarmed attacks. Disable to require the Modifier to be held when aiming.",
|
||||
|
||||
Sandbox_BrutalHandwork_BaseAttackOverride = "EXPERIMENTAL: Main Attack Damage Override",
|
||||
Sandbox_BrutalHandwork_BaseAttackOverride_tooltip = "Main Attacks use the damage calculation functions from BrutalHandwork instead of Vanilla. This forces consistency between the expected damage for both hand attacks. <LINE> WARNING: This option is currently experimental, but is likely to become the default and will be required for many additional options in the future. It is stable, but may cause inconsistencies compared to vanilla as it is still being developed. PLEASE READ the mod's description for current limitations!",
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
UI_EN = {
|
||||
UI_Init_BrtualHandwork = "Hello: Brutal Handwork!",
|
||||
UI_optionscreen_binding_BrtualHandwork = Brutal Handwork",
|
||||
}
|
||||
21
BrutalHandwork/Contents/mods/BrutalHandwork/media/sandbox-options.txt
Executable file
21
BrutalHandwork/Contents/mods/BrutalHandwork/media/sandbox-options.txt
Executable file
@@ -0,0 +1,21 @@
|
||||
VERSION = 1,
|
||||
option BrutalHandwork.DualWieldMelee
|
||||
{
|
||||
type = boolean, default = false,
|
||||
page = BrutalHandwork,
|
||||
translation = BrutalHandwork_DualWieldMelee,
|
||||
}
|
||||
|
||||
option BrutalHandwork.EnableUnarmed
|
||||
{
|
||||
type = boolean, default = true,
|
||||
page = BrutalHandwork,
|
||||
translation = BrutalHandwork_EnableUnarmed,
|
||||
}
|
||||
|
||||
option BrutalHandwork.AlwaysUnarmed
|
||||
{
|
||||
type = boolean, default = false,
|
||||
page = BrutalHandwork,
|
||||
translation = BrutalHandwork_AlwaysUnarmed,
|
||||
}
|
||||
33
BrutalHandwork/Contents/mods/BrutalHandwork/media/scripts/brutalweapons.txt
Executable file
33
BrutalHandwork/Contents/mods/BrutalHandwork/media/scripts/brutalweapons.txt
Executable file
@@ -0,0 +1,33 @@
|
||||
module Base {
|
||||
item Fisticuffs {
|
||||
DisplayCategory = Weapon,
|
||||
MaxRange = 0.8,
|
||||
WeaponSprite = null,
|
||||
MinAngle = 0.65,
|
||||
MinimumSwingTime = 2,
|
||||
Type = Weapon,
|
||||
SwingAnim = Shove,
|
||||
KnockBackOnNoDeath = TRUE,
|
||||
WeaponWeight = 0,
|
||||
DisplayName = Bare Hands,
|
||||
Categories = Unarmed,
|
||||
SwingAmountBeforeImpact = 0.1,
|
||||
SwingTime = 2,
|
||||
MinDamage = 0.1,
|
||||
SplatNumber = 1,
|
||||
EnduranceMod = 1.7,
|
||||
Weight = 1,
|
||||
PushBackMod = 0.5,
|
||||
MaxDamage = 0.25,
|
||||
SplatBloodOnNoDeath = FALSE,
|
||||
MaxHitCount = 1,
|
||||
Icon = Axe,
|
||||
DoorDamage = 2,
|
||||
TreeDamage = 1,
|
||||
RunAnim = Run_Weapon2,
|
||||
IdleAnim = Idle,
|
||||
DoorHitSound = BareHandsHit,
|
||||
HitSound = BareHandsHit,
|
||||
HitFloorSound = BareHandsHit,
|
||||
}
|
||||
}
|
||||
11
BrutalHandwork/Contents/mods/BrutalHandwork/mod.info
Executable file
11
BrutalHandwork/Contents/mods/BrutalHandwork/mod.info
Executable file
@@ -0,0 +1,11 @@
|
||||
name=Brutal Handwork
|
||||
id=BrutalHandwork
|
||||
require=FancyHandwork
|
||||
authors=dhert
|
||||
|
||||
description=An overhaul to combat to make your player more Brutal!
|
||||
|
||||
pzversion=41
|
||||
tags=Realistic;Framework
|
||||
|
||||
poster=poster.png
|
||||
BIN
BrutalHandwork/Contents/mods/BrutalHandwork/poster.png
Executable file
BIN
BrutalHandwork/Contents/mods/BrutalHandwork/poster.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 612 KiB |
BIN
BrutalHandwork/preview.png
Executable file
BIN
BrutalHandwork/preview.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
9
BrutalHandwork/workshop.txt
Executable file
9
BrutalHandwork/workshop.txt
Executable file
@@ -0,0 +1,9 @@
|
||||
version=1
|
||||
id=2934621024
|
||||
title=Brutal Handwork
|
||||
description=[h1]Supports B41+. Works in Multiplayer[/h1]
|
||||
description=[h3]A new save is not required[/h3]
|
||||
description=
|
||||
description=[img]https://i.imgur.com/p7Fv1Z6.gif[/img]
|
||||
tags=Build 41;Balance;Framework;Realistic
|
||||
visibility=private
|
||||
Reference in New Issue
Block a user