2023-04-13 17:30:38 +02:00

415 lines
16 KiB
Plaintext

#using scripts\shared\gameskill_shared;
#using scripts\shared\name_shared;
#using scripts\shared\util_shared;
#using scripts\shared\ai\systems\debug;
#using scripts\shared\ai\systems\shared;
#using scripts\shared\ai\archetype_utility;
#using scripts\shared\ai\systems\weaponList;
#using_animtree("generic");
//--------------------------------------------------------------------------------
// Weapon Initialization
//--------------------------------------------------------------------------------
function initWeapon( weapon )
{
self.weaponInfo[weapon.name] = SpawnStruct();
self.weaponInfo[weapon.name].position = "none";
self.weaponInfo[weapon.name].hasClip = true;
if ( IsDefined( weapon.ClipModel ) )
self.weaponInfo[weapon.name].useClip = true;
else
self.weaponInfo[weapon.name].useClip = false;
}
//--------------------------------------------------------------------------------
// Main
//--------------------------------------------------------------------------------
function main()
{
self.a = SpawnStruct();
self.a.weaponPos = [];
// Init weapons to "none"
// This is done here for now, but might be better to
// just have the converter set the empty weapon slots to "none" instead of ""
if ( self.weapon == level.weaponNone )
self AiUtility::setCurrentWeapon( level.weaponNone );
// primary weapon
self AiUtility::setPrimaryWeapon(self.weapon);
// secondary weapon
if ( self.secondaryweapon == level.weaponNone )
self AiUtility::setSecondaryWeapon( level.weaponNone );
self AiUtility::setSecondaryWeapon( self.secondaryweapon );
self AiUtility::setCurrentWeapon(self.primaryweapon);
self.initial_primaryweapon = self.primaryweapon;
self.initial_secondaryweapon = self.secondaryweapon;
self initWeapon( self.primaryweapon );
self initWeapon( self.secondaryweapon );
self initWeapon( self.sidearm );
self.weapon_positions = array( "left", "right", "chest", "back" );
for (i = 0; i < self.weapon_positions.size; i++)
{
self.a.weaponPos[self.weapon_positions[i]] = level.weaponNone;
}
self.lastWeapon = self.weapon;
self thread beginGrenadeTracking();
self thread globalGrenadeTracking();
firstInit();
// AI_TODO - Proper ammo tracking for rocketlauncher AI's
self.a.rockets = 3;
self.a.rocketVisible = true;
// Set initial states for poses
self.a.pose = "stand";
self.a.prevPose = self.a.pose;
self.a.movement = "stop";
self.a.special = "none";
self.a.gunHand = "none"; // Initialize so that PutGunInHand works properly.
shared::placeWeaponOn( self.primaryweapon, "right" );
if ( isdefined( self.secondaryweaponclass ) && self.secondaryweaponclass != "none" && self.secondaryweaponclass != "pistol" )
shared::placeWeaponOn( self.secondaryweapon, "back");
self.a.combatEndTime = GetTime();
self.a.nextGrenadeTryTime = 0;
// set up all the aiming stuff
self.a.isAiming = false;
self.rightAimLimit = 45;
self.leftAimLimit = -45;
self.upAimLimit = 45;
self.downAimLimit = -45;
// setup the speed variables
self.walk = false;
self.sprint = false;
self.a.postScriptFunc = undefined;
// use the GDT settings to start with
self.baseAccuracy = self.accuracy;
// set default accuracy mod
if( !isdefined(self.script_accuracy) )
self.script_accuracy = 1;
// scale baseAccuracy based on number of coop players
if( self.team == "axis" || self.team == "team3" )
self thread gameskill::axisAccuracyControl();
else if (self.team == "allies")
self thread gameskill::alliesAccuracyControl();
self.a.missTime = 0;
self.bulletsInClip = self.weapon.clipSize;
// state tracking
self.lastEnemySightTime = 0; // last time we saw our current enemy
self.combatTime = 0; // how long we've been in/out of combat
self.suppressed = false; // if we're currently suppressed
self.suppressedTime = 0; // how long we've been in/out of suppression
if ( self.team == "allies" )
self.suppressionThreshold = 0.75;
else
self.suppressionThreshold = 0.5;
// Random range makes the grenades less accurate and do less damage, but also makes it difficult to throw back.
if ( self.team == "allies" )
self.randomGrenadeRange = 0;
else
self.randomGrenadeRange = 128;
self.reacquire_state = 0;
}
function setNameAndRank()
{
self endon ( "death" );
self name::get();
}
function DoNothing()
{
}
function set_anim_playback_rate()
{
self.animplaybackrate = 0.9 + RandomFloat( 0.2 );
self.moveplaybackrate = 1;
}
function trackVelocity()
{
self endon ("death");
for (;;)
{
self.oldOrigin = self.origin;
wait (0.2);
}
}
/#
function checkApproachAngles( transTypes )
{
idealTransAngles[1] = 45;
idealTransAngles[2] = 0;
idealTransAngles[3] = -45;
idealTransAngles[4] = 90;
idealTransAngles[6] = -90;
idealTransAngles[7] = 135;
idealTransAngles[8] = 180;
idealTransAngles[9] = -135;
wait .05;
for ( i = 1; i <= 9; i++ )
{
for ( j = 0; j < transTypes.size; j++ )
{
trans = transTypes[j];
idealAdd = 0;
if ( trans == "left" || trans == "left_crouch" )
{
idealAdd = 90;
}
else if ( trans == "right" || trans == "right_crouch" )
{
idealAdd = -90;
}
if ( isdefined( anim.coverTransAngles[ trans ][i] ) )
{
correctAngle = AngleClamp180( idealTransAngles[i] + idealAdd );
actualAngle = AngleClamp180( anim.coverTransAngles[ trans ][i] );
if ( AbsAngleClamp180( actualAngle - correctAngle ) > 7 )
{
println( "^1Cover approach animation has bad yaw delta: anim.coverTrans[\"" + trans + "\"][" + i + "]; is ^2" + actualAngle + "^1, should be closer to ^2" + correctAngle + "^1." );
}
}
}
}
for ( i = 1; i <= 9; i++ )
{
for ( j = 0; j < transTypes.size; j++ )
{
trans = transTypes[j];
idealAdd = 0;
if ( trans == "left" || trans == "left_crouch" )
{
idealAdd = 90;
}
else if ( trans == "right" || trans == "right_crouch" )
{
idealAdd = -90;
}
if ( isdefined( anim.coverExitAngles[ trans ][i] ) )
{
correctAngle = AngleClamp180( -1 * (idealTransAngles[i] + idealAdd + 180) );
actualAngle = AngleClamp180( anim.coverExitAngles[ trans ][i] );
if ( AbsAngleClamp180( actualAngle - correctAngle ) > 7 )
{
println( "^1Cover exit animation has bad yaw delta: anim.coverTrans[\"" + trans + "\"][" + i + "]; is ^2" + actualAngle + "^1, should be closer to ^2" + correctAngle + "^1." );
}
}
}
}
}
#/
function getExitSplitTime( approachType, dir )
{
return anim.coverExitSplit[ approachType ][ dir ];
}
function getTransSplitTime( approachType, dir )
{
return anim.coverTransSplit[ approachType ][ dir ];
}
function firstInit()
{
// Initialization that should happen once per level
if ( IsDefined(anim.NotFirstTime) ) // Use this to trigger the first init
{
return;
}
anim.NotFirstTime = true;
anim.grenadeTimers["player_frag_grenade_sp"] = randomIntRange( 1000, 20000 );
anim.grenadeTimers["player_flash_grenade_sp"] = randomIntRange( 1000, 20000 );
anim.grenadeTimers["player_double_grenade"] = randomIntRange( 10000, 60000 );
anim.grenadeTimers["AI_frag_grenade_sp"] = randomIntRange( 0, 20000 );
anim.grenadeTimers["AI_flash_grenade_sp"] = randomIntRange( 0, 20000 );
anim.numGrenadesInProgressTowardsPlayer = 0;
anim.lastGrenadeLandedNearPlayerTime = -1000000;
anim.lastFragGrenadeToPlayerStart = -1000000;
thread setNextPlayerGrenadeTime();
if ( !isdefined( level.flag ) )
{
level.flag = [];
}
level.painAI = undefined;
anim.coverCrouchLeanPitch = -55;
}
function onPlayerConnect()
{
player = self;
firstInit();
player.invul = false;
}
function setNextPlayerGrenadeTime()
{
waittillframeend;
// might not be defined if load::main() wasn't called
if ( isdefined( anim.playerGrenadeRangeTime ) )
{
maxTime = int( anim.playerGrenadeRangeTime * 0.7 );
if ( maxTime < 1 )
{
maxTime = 1;
}
anim.grenadeTimers["player_frag_grenade_sp"] = randomIntRange( 0, maxTime );
anim.grenadeTimers["player_flash_grenade_sp"] = randomIntRange( 0, maxTime );
}
if ( isdefined( anim.playerDoubleGrenadeTime ) )
{
maxTime = int( anim.playerDoubleGrenadeTime );
minTime = int( maxTime / 2 );
if ( maxTime <= minTime )
{
maxTime = minTime + 1;
}
anim.grenadeTimers["player_double_grenade"] = randomIntRange( minTime, maxTime );
}
}
function AddToMissiles(grenade)
{
if(!isdefined(level.missileEntities))level.missileEntities=[];
if ( !isdefined( level.missileEntities ) ) level.missileEntities = []; else if ( !IsArray( level.missileEntities ) ) level.missileEntities = array( level.missileEntities ); level.missileEntities[level.missileEntities.size]=grenade;;
while ( IsDefined(grenade) )
{
{wait(.05);};
}
ArrayRemoveValue(level.missileEntities,grenade);
}
function globalGrenadeTracking()
{
if(!isdefined(level.missileEntities))level.missileEntities=[];
self endon ( "death" );
self thread globalGrenadeLauncherTracking();
self thread globalMissileTracking();
for ( ;; )
{
self waittill ( "grenade_fire", grenade, weapon );
grenade.owner=self;
grenade.weapon = weapon;
level thread AddToMissiles(grenade);
}
}
function globalGrenadeLauncherTracking()
{
self endon ( "death" );
for ( ;; )
{
self waittill ( "grenade_launcher_fire", grenade, weapon );
grenade.owner=self;
grenade.weapon = weapon;
level thread AddToMissiles(grenade);
}
}
function globalMissileTracking()
{
self endon ( "death" );
for ( ;; )
{
self waittill ( "missile_fire", grenade, weapon );
grenade.owner=self;
grenade.weapon = weapon;
level thread AddToMissiles(grenade);
}
}
function beginGrenadeTracking()
{
self endon ( "death" );
for ( ;; )
{
self waittill ( "grenade_fire", grenade, weapon );
grenade thread grenade_earthQuake();
}
}
function endOnDeath()
{
self waittill( "death" );
waittillframeend;
self notify ( "end_explode" );
}
function grenade_earthQuake() //self == grenade
{
self thread endOnDeath();
self endon( "end_explode" );
self waittill( "explode", position );
PlayRumbleOnPosition( "grenade_rumble", position );
earthquake( 0.3, 0.5, position, 400 );
}
//--------------------------------------------------------------------------------
// end script
//--------------------------------------------------------------------------------
function end_script()
{
}