428 lines
9.9 KiB
Text
428 lines
9.9 KiB
Text
|
/***********************************************************************
|
||
|
|
||
|
tool_pliers.script
|
||
|
|
||
|
***********************************************************************/
|
||
|
|
||
|
// blend times
|
||
|
#define PLIERS_IDLE_TO_LOWER 4
|
||
|
#define PLIERS_IDLE_TO_PUNCH 0
|
||
|
#define PLIERS_RAISE_TO_IDLE 4
|
||
|
#define PLIERS_PUNCH_TO_IDLE 1
|
||
|
|
||
|
#define GUI_STATE_IDLE 0
|
||
|
#define GUI_STATE_ARMING 1
|
||
|
#define GUI_STATE_CONNECTED 2
|
||
|
|
||
|
object tool_pliers : weapon_base {
|
||
|
|
||
|
void preinit();
|
||
|
void init();
|
||
|
void destroy();
|
||
|
void Lower();
|
||
|
void Idle();
|
||
|
|
||
|
void Attack();
|
||
|
boolean CheckAttack( float mask );
|
||
|
void StartFireEffect();
|
||
|
void StopFireEffect();
|
||
|
boolean fireEffectOn;
|
||
|
|
||
|
boolean AttackValid();
|
||
|
|
||
|
void ToolTipThread_Raise();
|
||
|
|
||
|
void Repair();
|
||
|
void Arm();
|
||
|
void Disarm();
|
||
|
void Construct();
|
||
|
void Hack();
|
||
|
void Possess();
|
||
|
|
||
|
void UpdateGUI();
|
||
|
|
||
|
handle GetTextHandleForState( float state );
|
||
|
|
||
|
float fireRate;
|
||
|
float repairCount;
|
||
|
float count;
|
||
|
|
||
|
float meleeDistance;
|
||
|
|
||
|
entity cachedEntity;
|
||
|
float cachedAction;
|
||
|
|
||
|
boolean disarmCharge;
|
||
|
boolean armCharge;
|
||
|
boolean armNormal;
|
||
|
boolean canRepair;
|
||
|
boolean canConstruct;
|
||
|
boolean canHack;
|
||
|
boolean canDisguise;
|
||
|
|
||
|
boolean playingFireSound;
|
||
|
|
||
|
float nextActionFailMessageTime;
|
||
|
|
||
|
float guiHandle;
|
||
|
handle guiTextHandle;
|
||
|
}
|
||
|
|
||
|
void tool_pliers::preinit() {
|
||
|
meleeDistance = getFloatKey( "melee_distance" );
|
||
|
|
||
|
armNormal = getIntKey( "can_arm_normal" );
|
||
|
armCharge = getIntKey( "can_arm_charge" );
|
||
|
disarmCharge = getIntKey( "can_disarm_charge" );
|
||
|
canRepair = getIntKey( "can_repair" );
|
||
|
canConstruct = getIntKey( "can_construct" );
|
||
|
canHack = getIntKey( "can_hack" );
|
||
|
canDisguise = getIntKey( "can_disguise" );
|
||
|
|
||
|
fireRate = getFloatKeyWithDefault( "fire_rate", 0.1f );
|
||
|
repairCount = getFloatKeyWithDefault( "repair_count", 5.f );
|
||
|
|
||
|
if ( sys.doClientSideStuff() ) {
|
||
|
guiHandle = getGUI( "0" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void tool_pliers::init() {
|
||
|
if ( myPlayer.isLocalPlayer() ) {
|
||
|
thread ToolTipThread_Raise();
|
||
|
}
|
||
|
|
||
|
weaponState( "Raise", 0 );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::destroy() {
|
||
|
if ( myPlayer != $null_entity ) {
|
||
|
myPlayer.AI_HOLD_WEAPON = false;
|
||
|
}
|
||
|
stopAllEffects();
|
||
|
DestroySound();
|
||
|
|
||
|
if ( playingFireSound ) {
|
||
|
playingFireSound = false;
|
||
|
startSound( "snd_stop", SND_WEAPON_FIRE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Lower() {
|
||
|
StopFireEffect();
|
||
|
|
||
|
if ( playingFireSound ) {
|
||
|
playingFireSound = false;
|
||
|
startSound( "snd_stop", SND_WEAPON_FIRE );
|
||
|
}
|
||
|
|
||
|
startSound( "snd_lower", SND_WEAPON_IDLE );
|
||
|
|
||
|
Base_Lower();
|
||
|
}
|
||
|
|
||
|
boolean tool_pliers::AttackValid() {
|
||
|
boolean performAction = CheckAttack( MASK_VEHICLESOLID | CONTENTS_PLAYERCLIP );
|
||
|
|
||
|
if ( !performAction ) {
|
||
|
performAction = CheckAttack( CONTENTS_TRIGGER );
|
||
|
}
|
||
|
|
||
|
if ( !performAction ) {
|
||
|
performAction = CheckAttack( CONTENTS_RENDERMODEL );
|
||
|
}
|
||
|
|
||
|
return performAction;
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Idle() {
|
||
|
weaponReady();
|
||
|
playCycle( ANIMCHANNEL_ALL, "idle" );
|
||
|
StopFireEffect();
|
||
|
|
||
|
UpdateCharge();
|
||
|
|
||
|
while ( true ) {
|
||
|
UpdateGUI();
|
||
|
|
||
|
if ( WEAPON_LOWERWEAPON ) {
|
||
|
SetProgressBarVisible( false );
|
||
|
weaponState( "Lower", PLIERS_IDLE_TO_LOWER );
|
||
|
}
|
||
|
|
||
|
if ( WEAPON_ATTACK ) {
|
||
|
if ( AttackValid() ) {
|
||
|
if ( !playingFireSound ) {
|
||
|
playingFireSound = true;
|
||
|
startSound( "snd_start", SND_WEAPON_FIRE );
|
||
|
}
|
||
|
|
||
|
nextActionFailMessageTime = sys.getTime() + 2.f;
|
||
|
|
||
|
weaponState( "Attack", PLIERS_IDLE_TO_PUNCH );
|
||
|
} else {
|
||
|
if ( !myPlayer.isToolTipPlaying() ) {
|
||
|
if ( sys.getTime() > nextActionFailMessageTime ) {
|
||
|
nextActionFailMessageTime = sys.getTime() + 5.f;
|
||
|
if ( cachedAction == AC_NONE ) {
|
||
|
myPlayer.sendToolTip( GetToolTip( getKey( "tt_action_failed" ) ) );
|
||
|
} else if ( cachedAction == AC_ENEMY_REPAIR ) {
|
||
|
myPlayer.sendToolTip( GetToolTip( getKey( "tt_enemy_repair" ) ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( playingFireSound ) {
|
||
|
playingFireSound = false;
|
||
|
startSound( "snd_stop", SND_WEAPON_FIRE );
|
||
|
}
|
||
|
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void tool_pliers::StartFireEffect() {
|
||
|
if ( !fireEffectOn ) {
|
||
|
playEffect( "fx_fire", idleEffectJoint, 1 );
|
||
|
fireEffectOn = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void tool_pliers::StopFireEffect() {
|
||
|
if ( fireEffectOn ) {
|
||
|
stopEffect( "fx_fire" );
|
||
|
fireEffectOn = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Attack() {
|
||
|
myPlayer.AI_HOLD_WEAPON = true;
|
||
|
|
||
|
float currentCachedAction = cachedAction;
|
||
|
|
||
|
if ( getFloatKey( "has_startfire_anim" ) > 0 ) {
|
||
|
playAnim( ANIMCHANNEL_ALL, "fire_start" );
|
||
|
waitUntil( animDone( ANIMCHANNEL_ALL, 0 ) );
|
||
|
}
|
||
|
|
||
|
StartFireEffect();
|
||
|
|
||
|
while ( true ) {
|
||
|
UpdateGUI();
|
||
|
|
||
|
if ( cachedAction == AC_REPAIR ) {
|
||
|
Repair();
|
||
|
} else if ( cachedAction == AC_ARM || cachedAction == AC_ARM_CHARGE ) {
|
||
|
Arm();
|
||
|
} else if ( cachedAction == AC_DISARM || cachedAction == AC_DISARM_CHARGE ) {
|
||
|
Disarm();
|
||
|
} else if ( cachedAction == AC_CONSTRUCT ) {
|
||
|
Construct();
|
||
|
} else if ( cachedAction == AC_HACK ) {
|
||
|
Hack();
|
||
|
} else if ( cachedAction == AC_POSSESS ) {
|
||
|
Possess();
|
||
|
}
|
||
|
|
||
|
float finishTime = sys.getTime() + fireRate;
|
||
|
|
||
|
while ( sys.getTime() < finishTime ) {
|
||
|
if ( animDone( ANIMCHANNEL_ALL, PLIERS_PUNCH_TO_IDLE ) ) {
|
||
|
playAnim( ANIMCHANNEL_ALL, "fire" );
|
||
|
}
|
||
|
|
||
|
sys.waitFrame();
|
||
|
}
|
||
|
|
||
|
// re-enable running for any player that had it disabled AFTER the animation (otherwise it's pointless)
|
||
|
myPlayer.disableRun( 0.f );
|
||
|
|
||
|
if ( !WEAPON_ATTACK ) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( WEAPON_LOWERWEAPON ) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( !AttackValid() ) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( getFloatKey( "has_endfire_anim" ) > 0 ) {
|
||
|
playAnim( ANIMCHANNEL_ALL, "fire_end" );
|
||
|
waitUntil( animDone( ANIMCHANNEL_ALL, 0 ) );
|
||
|
}
|
||
|
|
||
|
myPlayer.AI_HOLD_WEAPON = false;
|
||
|
|
||
|
nextActionFailMessageTime = sys.getTime() + 2.f;
|
||
|
|
||
|
weaponState( "Idle", PLIERS_PUNCH_TO_IDLE );
|
||
|
}
|
||
|
|
||
|
boolean tool_pliers::CheckAttack( float mask ) {
|
||
|
cachedEntity = myPlayer.getCrosshairEntity();
|
||
|
cachedAction = AC_NONE;
|
||
|
|
||
|
if ( myPlayer.getCrosshairDistance( true ) > meleeDistance ) {
|
||
|
cachedEntity = $null_entity;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ( cachedEntity == $null_entity ) {
|
||
|
// there is no crosshair entity to take priority
|
||
|
// try doing a melee trace
|
||
|
melee( mask, meleeDistance, false, false );
|
||
|
cachedEntity = getMeleeEntity();
|
||
|
|
||
|
if ( cachedEntity == $null_entity ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( armCharge ) {
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_ARM_CHARGE ) ) {
|
||
|
cachedAction = AC_ARM_CHARGE;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( disarmCharge ) {
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_DISARM_CHARGE ) ) {
|
||
|
cachedAction = AC_DISARM_CHARGE;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( canRepair ) {
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_REPAIR ) ) {
|
||
|
cachedAction = AC_REPAIR;
|
||
|
return true;
|
||
|
} else if ( cachedEntity.vCheckActionCode( myPlayer, AC_ENEMY_REPAIR ) ) {
|
||
|
cachedAction = AC_ENEMY_REPAIR;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( armNormal ) {
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_ARM ) ) {
|
||
|
cachedAction = AC_ARM;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_DISARM ) ) {
|
||
|
cachedAction = AC_DISARM;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( canConstruct ) {
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_CONSTRUCT ) ) {
|
||
|
cachedAction = AC_CONSTRUCT;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( canHack ) {
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_HACK ) ) {
|
||
|
cachedAction = AC_HACK;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( canDisguise ) {
|
||
|
if ( cachedEntity.vCheckActionCode( myPlayer, AC_POSSESS ) ) {
|
||
|
cachedAction = AC_POSSESS;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Construct() {
|
||
|
myPlayer.disableRun( 1.f );
|
||
|
cachedEntity.vConstruct( myPlayer );
|
||
|
myPlayer.ShowProgressBar( cachedEntity, AC_CONSTRUCT );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Hack() {
|
||
|
myPlayer.disableRun( 1.f );
|
||
|
cachedEntity.vHack( myPlayer );
|
||
|
myPlayer.ShowProgressBar( cachedEntity, AC_HACK );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Possess() {
|
||
|
myPlayer.disableRun( 1.f );
|
||
|
cachedEntity.vPossess( myPlayer );
|
||
|
myPlayer.ShowProgressBar( cachedEntity, AC_POSSESS );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Repair() {
|
||
|
myPlayer.disableRun( 1.f );
|
||
|
|
||
|
float scale = 1.f;
|
||
|
team_base team = myPlayer.getGameTeam();
|
||
|
if ( team.HasRepairBonus( myPlayer ) ) {
|
||
|
scale = 1.20f;
|
||
|
}
|
||
|
|
||
|
cachedEntity.vRepair( repairCount * scale, myPlayer );
|
||
|
myPlayer.ShowProgressBar( cachedEntity, AC_REPAIR );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Disarm() {
|
||
|
cachedEntity.vArm( myPlayer );
|
||
|
myPlayer.ShowProgressBar( cachedEntity, AC_DISARM );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::Arm() {
|
||
|
cachedEntity.vArm( myPlayer );
|
||
|
myPlayer.ShowProgressBar( cachedEntity, AC_ARM );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::ToolTipThread_Raise() {
|
||
|
sys.wait( myPlayer.CalcTooltipWait() );
|
||
|
while ( myPlayer.isSinglePlayerToolTipPlaying() ) {
|
||
|
sys.wait( 1.0f );
|
||
|
}
|
||
|
myPlayer.cancelToolTips();
|
||
|
|
||
|
WAIT_FOR_TOOLTIP;
|
||
|
myPlayer.sendToolTip( GetToolTip( getKey( "tt_intro_1" ) ) );
|
||
|
|
||
|
WAIT_FOR_TOOLTIP;
|
||
|
myPlayer.sendToolTip( GetToolTip( getKey( "tt_intro_2" ) ) );
|
||
|
}
|
||
|
|
||
|
void tool_pliers::UpdateGUI() {
|
||
|
if ( myPlayer != sys.getLocalViewPlayer() || guiHandle == GUI_INVALID ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float guiState = GUI_STATE_IDLE;
|
||
|
if ( myPlayer.AI_HOLD_WEAPON ) {
|
||
|
guiState = GUI_STATE_ARMING;
|
||
|
} else if ( CheckAttack( MASK_VEHICLESOLID | CONTENTS_PLAYERCLIP ) ) {
|
||
|
if ( cachedAction == AC_ARM || cachedAction == AC_ARM_CHARGE ) {
|
||
|
guiState = GUI_STATE_CONNECTED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
guiTextHandle = GetTextHandleForState( guiState );
|
||
|
sys.setGUIHandle( GUI_GLOBALS_HANDLE, "armTool.statusTextHandle", guiTextHandle );
|
||
|
sys.setGUIFloat( GUI_GLOBALS_HANDLE, "armTool.isSearching", guiState == GUI_STATE_IDLE );
|
||
|
}
|
||
|
|
||
|
handle tool_pliers::GetTextHandleForState( float state ) {
|
||
|
if ( state == GUI_STATE_ARMING ) { return sys.localizeString( "game/arm/arming" );
|
||
|
} else if ( state == GUI_STATE_CONNECTED ) { return sys.localizeString( "game/arm/connected" );
|
||
|
} else if ( state == GUI_STATE_IDLE ) { return sys.localizeString( "game/arm/search" );
|
||
|
} else { sys.assert( 0 );
|
||
|
}
|
||
|
return 0;
|
||
|
}
|