cod5-sdk/raw/maps/hol2_airstrike.gsc
2008-11-20 00:00:00 +00:00

794 lines
No EOL
22 KiB
Text

/* Sweet player controlled airstrike stuff
To use:
Call this line above _load:
thread maps\_dpad_asset::rocket_barrage_init();
Call this line in your onPlayerSpawn function in your level:
self thread maps\_dpad_asset::rocket_barrage_player_init();
You probably want to set up a level.radioguy for communication with the player.
Those string are the targetnames of script_structs in the map.
*/
#include maps\_utility;
#include common_scripts\utility;
#include maps\_vehicle;
#include maps\hol2;
#using_animtree ("generic_human");
// needs to be called above _load in your level
airstrike_init()
{
level._effect["target_smoke"] = loadfx ("env/smoke/fx_smoke_ground_marker_green_w");
level._effect["rocket_trail"] = loadfx("weapon/rocket/fx_lci_rocket_geotrail");
level._effect["grenade_smoke"] = loadfx("weapon/grenade/fx_smoke_grenade_generic");
level._effect["air_napalm"] = loadfx("maps/pel1/fx_napalm_midair_burst");
level.rocketbarrage_traceLength = 4000; // the furthest distance the player can fire
level.barrage_charge_time = 30; // time in seconds until player can use again
level.rocket_barrage_allowed = false; // is the barrage allowed to be used now?
level.friendly_check_radius = 700; // friendlies in this radius will diallow barrage use
}
// needs to be threaded on each player in your onSpawn function in your level
airstrike_player_init()
{
self.rocket_targeting_on = false; // is the player targeting at the moment?
self.is_firing_rocket_barrage = false; // the barrage being fired by the player?
self.rocket_barrages_remaining = 3; // number of barrages left
self.rockets_are_out_times = 0; // this is for the radio guys dialogue: keeping tally on how many barrages you have left
self.rocket_barrage_friendly_fire_count = 0; // this is for the radio guys dialogue: you aimed at an enemy
self.rocket_barrage_ai_was_hit = false; // this is for the radio guys dialogue: was enemy hit?
self.rocket_barrage_ok = false; // is the barrage fire valid?
self thread rocket_barrage_watcher();
self thread rocket_barrage_hud_elements_think();
}
// this basically stays on, looping. this keeps an eye on everything, allows, targeting
// etc.
rocket_barrage_watcher()
{
self endon ("death"); // remember to put these on player functions for co-op
self endon ("disconnect"); // remember to put these on player functions for co-op
// Saftey checks
if (!isdefined(self.is_firing_rocket_barrage))
{
return;
}
if (!isdefined(level.rocket_barrage_allowed))
{
return;
}
for(;;)
{
// if the player isn't firing and firing is allowed at the moment
if (!self.is_firing_rocket_barrage && level.rocket_barrage_allowed )
{
weap = self getcurrentweapon();
// if the weapons is the rocket barrage and targeting isnt on
if(self getcurrentweapon() == "rocket_barrage" && !self.rocket_targeting_on)
{
// begin targeting (smoke)
self thread rocket_barrage_targeting();
self.rocket_targeting_on = true;
wait 0.5;
}
// if the weapon is rocket barrage and you're already targeting, turn it off
else if(self getcurrentweapon() != "rocket_barrage" && self.rocket_targeting_on)
{
self.Rocket_Targeting_On = false;
self notify("end rocket barrage targeting");
delete_spotting_target();
wait 0.5;
}
}
// if player is firing and the barrage is allowed
else if (self.is_firing_rocket_barrage && level.rocket_barrage_allowed)
{
// if the player is trying to fire while the barrage is going, send a notify
if(self getcurrentweapon() == "rocket_barrage")
{
self notify ("activate pressed during barage");
wait 0.1;
}
}
wait (0.05);
}
}
// Targeting thread, sets up the drawing of smoke
rocket_barrage_targeting()
{
self endon ("end rocket barrage targeting");
self endon ("rocket barrage firing");
self endon ("death");
self endon ("disconnect");
self notify("start rocket barrage targeting");
// targetpoint is a script_model with tag_origin, using playfxon tag for the smoke.
// model moves around as player looks around
targetpoint = spawn("script_model", get_players()[0].origin);
targetpoint setmodel("tag_origin");
self.rocket_barrage_target = targetpoint;
wait (0.1);
//self disableweapons();
thread draw_smoke(targetpoint);
for (;;)
{
// Trace to where the player is looking
direction = self getPlayerAngles();
direction_vec = anglesToForward( direction );
eye = self getEye();
// offset 2 units on the Z to fix the bug where it would drop through the ground sometimes
trace = bullettrace( eye, eye + vector_multiply( direction_vec , level.rocketbarrage_traceLength ), 0, undefined );
trace2 = bullettrace( trace["position"]+(0,0,2), trace["position"] - (0,0,100000), 0, undefined );
// debug
//thread draw_line_for_time( eye, trace2["position"], 1, 0, 0, 0.05 );
targetpoint.origin = trace2["position"];
friends = getaiarray("allies");
players = get_players();
friends = array_merge(friends, players);
for (i = 0; i < friends.size; i++)
{
if (distance(targetpoint.origin, friends[i].origin) > level.friendly_check_radius)
{
self.rocket_barrage_ok = true;
}
else
{
self.rocket_barrage_ok = false; // disallow if friends and players are nearby
}
}
self thread rocket_barrage_fire_watch(targetpoint.origin);
wait (0.05);
}
}
// draws the smoke every 2 frames or so
draw_smoke(targetpoint)
{
self endon ("target smoke deleted");
self endon ("death");
self endon ("disconnect");
wait (0.1);
while (1)
{
playfxontag(level._effect["target_smoke"], targetpoint, "tag_origin");
wait 0.1;
}
}
// this handles a lot of the radio guy functionality, what he says, etc.
// also tracks how many barrages are left.
rocket_barrage_fire_watch(fire_point)
{
self endon ("death");
self endon ("disconnect");
// confirming the player's fire
if(self attackbuttonPressed( ) && !self.is_firing_rocket_barrage && self.rocket_barrage_ok)
{
self.is_firing_rocket_barrage = true;
self.rocket_targeting_on = false;
if (self.rocket_barrages_remaining == 3)
{
level thread rocket_barrage_radio_guy( "confirm_fire1" );
}
else if (self.rocket_barrages_remaining == 2)
{
level thread rocket_barrage_radio_guy( "confirm_fire2" );
}
else if (self.rocket_barrages_remaining == 1)
{
level thread rocket_barrage_radio_guy( "confirm_fire3" );
}
self.rocket_barrages_remaining--;
self thread rocket_barrage_fire(fire_point);
}
// letting the player know how many shots are left
else if(self attackbuttonPressed( ) && !self.is_firing_rocket_barrage && self.rocket_barrages_remaining <= 0)
{
if (self.rockets_are_out_times == 0)
{
level thread rocket_barrage_radio_guy( "0left1" );
self.rockets_are_out_times++;
}
else if (self.rockets_are_out_times == 1)
{
level thread rocket_barrage_radio_guy( "0left2" );
self.rockets_are_out_times++;
}
else if (self.rockets_are_out_times == 2)
{
level thread rocket_barrage_radio_guy( "0left3" );
self.rockets_are_out_times = 0;
}
}
// friendly fire! not firing!
else if (self attackbuttonPressed( ) && !self.is_firing_rocket_barrage && !self.rocket_barrage_ok)
{
if (self.rocket_barrage_friendly_fire_count == 0)
{
level thread rocket_barrage_radio_guy( "friendly_fire1" );
self.rocket_barrage_friendly_fire_count++;
}
else if (self.rocket_barrage_friendly_fire_count == 1)
{
level thread rocket_barrage_radio_guy( "friendly_fire2" );
self.rocket_barrage_friendly_fire_count = 0;
}
}
}
rocket_barrage_fire(firepoint)
{
self endon ("death");
self endon ("disconnect");
fire_point = spawn("script_origin", firepoint);
// check where the firepoint is
if (level.script == "hol2")
{
level notify ("airstrike_called");
// near woodstiger
woodstiger_area = getentarray("woodstiger_airstrike_area", "targetname");
for (i=0; i < woodstiger_area.size; i++)
{
if (fire_point istouching(woodstiger_area[i]))
{
if (flag("woodstiger_inplace"))
{
thread call_airstrike("woodstiger", fire_point);
}
else
{
thread call_strafing_run("woodstrafe", fire_point);
}
}
}
// near gulchtiger
gulchtiger_area = getentarray("gulchtiger_airstrike_area", "targetname");
for (i=0; i < gulchtiger_area.size; i++)
{
if (fire_point istouching(gulchtiger_area[i]))
{
if (flag("gulchtiger_inplace")&& !flag("gulchtiger_inloop"))
{
thread call_airstrike("gulchtiger", fire_point);
}
else
{
thread call_strafing_run("gulchstrafe", fire_point);
}
}
}
// in front of graveyard
f_gyard_area = getentarray("front_graveyard_strafing_area", "targetname");
for (i=0; i < f_gyard_area.size; i++)
{
if (fire_point istouching(f_gyard_area[i]) && !flag("gulchtiger_inloop"))
{
thread call_strafing_run("gravefront", fire_point);
}
else if (fire_point istouching(f_gyard_area[i]) && flag("gulchtiger_inloop"))
{
thread call_airstrike("woodstiger", fire_point);
}
}
hq_area = getentarray("hq_strafing_area", "targetname");
for (i=0; i < hq_area.size; i++)
{
if (fire_point istouching(hq_area[i]))
{
thread call_strafing_run("hq", fire_point);
}
}
churchside_area = getentarray("churchside_strafing_Area", "targetname");
for (i=0; i < churchside_area.size; i++)
{
if (fire_point istouching(churchside_area[i]))
{
thread call_strafing_run("churchside", fire_point);
}
}
flak_area = getentarray("flak_strafing_area", "targetname");
for (i=0; i < flak_area.size; i++)
{
if (fire_point istouching(flak_area[i]))
{
thread call_strafing_run("flak", fire_point);
}
}
}
self notify ("rocket barrage firing");
// remove smoke
delete_spotting_target();
// wait until recharge
wait (level.barrage_charge_time);
self.rocket_barrage_ai_was_hit = false;
// reset weaqpons ammo after recharge
self SetWeaponAmmoClip( "rocket_barrage", 1 );
self notify ("rocket barrage recharging");
self.rocket_barrage_fired_at_time = gettime();
self.is_firing_rocket_barrage = false;
}
// rocket barrage is actually firing now
// This stuff is from before I hol2ized it
// get rid of the spotting target, just delete it
delete_spotting_target()
{
self endon ("death");
self endon ("disconnect");
if (isdefined(self.rocket_barrage_target))
{
self.rocket_barrage_target delete();
}
self notify ("target smoke deleted");
}
// sets up the hud bar for the player, kinda buggy (flashes when you fire),
// might be handled in code later, but at least this works for now
rocket_barrage_hud_elements_think()
{
self endon ("death");
self endon ("disconnect");
x_placement = 100;
y_placement = 425;
barsize_x = 72;
barsize_y = 10;
bar_difference_x = 6;
bar_difference_y = 4;
// background bar
self.rocket_hud_elem_background = newclienthudelem(self);
self.rocket_hud_elem_background.x = x_placement;
self.rocket_hud_elem_background.y = y_placement;
self.rocket_hud_elem_background setshader( "black", barsize_x, barsize_y );
self.rocket_hud_elem_background.alignX = "left";
self.rocket_hud_elem_background.alignY = "bottom";
self.rocket_hud_elem_background.alpha =1;
self.rocket_hud_elem_background.foreground = true;
self.rocket_hud_elem_background.sort = 1;
// foreground bar
self.rocket_hud_elem_foreground = newclienthudelem(self);
self.rocket_hud_elem_foreground.x = x_placement + (bar_difference_x / 2);
self.rocket_hud_elem_foreground.y = y_placement - (bar_difference_y / 2);
self.rocket_hud_elem_foreground setshader( "white", (barsize_x - bar_difference_x) , (barsize_y - bar_difference_y) );
self.rocket_hud_elem_foreground.alignX = "left";
self.rocket_hud_elem_foreground.alignY = "bottom";
self.rocket_hud_elem_foreground.alpha = 1;
self.rocket_hud_elem_foreground.foreground = true;
self.rocket_hud_elem_foreground.sort = 2;
thread rocket_barrage_hud_elements_show();
while (1)
{
self waittill ("rocket barrage firing");
self.rocket_hud_elem_foreground ScaleOverTime( 0.05, 1, (barsize_y - bar_difference_y) );
self.rocket_hud_elem_foreground.color = (1,0,0);
wait (0.05);
self.rocket_hud_elem_foreground ScaleOverTime( level.barrage_charge_time - 0.05, (barsize_x - bar_difference_x), (barsize_y - bar_difference_y) );
wait (level.barrage_charge_time / 3);
self.rocket_hud_elem_foreground.color = (1,0.5,0);
wait (level.barrage_charge_time / 3);
self.rocket_hud_elem_foreground.color = (1,1,0);
wait (level.barrage_charge_time / 3);
self.rocket_hud_elem_foreground.color = (1,1,1);
}
}
// display / turn off the hud elems depending on notifies
rocket_barrage_hud_elements_show()
{
self endon ("death");
self endon ("disconnect");
while (1)
{
self.rocket_hud_elem_background.alpha = 0;
self.rocket_hud_elem_foreground.alpha = 0;
self waittill_any ("start rocket barrage targeting", "activate pressed during barage");
self.rocket_hud_elem_background.alpha = 1;
self.rocket_hud_elem_foreground.alpha = 1;
self waittill_any ("end rocket barrage targeting", "rocket barrage firing", "activate pressed during barage" );
}
}
// the actual sounds for the guy to play depending on the anim_sound, which is a string
rocket_barrage_radio_guy( anim_sound )
{
/*
if (isdefined(level.radioguy.isplayingsound) && level.radioguy.isplayingsound)
{
return;
}
switch( anim_sound )
{
case "init":
level.radioguy playsound ("Pel01_G2A_RADI_004A", "sounddone"); // called
level.radioguy.isplayingsound = true;
break;
}
// make sure his sounds dont overlap
level.radioguy waittill ("sounddone");
level.radioguy.isplayingsound = false;
*/
}
// check to see if AI are nearby the impacts
rocket_barrage_check_if_ai_hit(damageradius, hitpoint, which_player)
{
ai = getaiarray("axis");
for (i = 0; i < ai.size; i++)
{
if (isdefined (ai[i]))
{
if (distance(hitpoint, ai[i].origin) < damageradius)
{
if (isdefined(which_player))
{
which_player.rocket_barrage_ai_was_hit = true;
}
}
}
}
}
strafe_go(spawngroup, runpath, fire_point)
{
scripted_spawn_go(spawngroup);
wait 0.3;
spitfire = getent("spitfire_at_"+runpath, "targetname");
spitfire startpath();
firenode = getvehiclenode (runpath+"1_start_fire", "script_noteworthy");
endnode = getvehiclenode (runpath+"1_end_fire", "script_noteworthy");
spitfire thread custom_strafe(fire_point,firenode, endnode );
wait 1.5;
spitfire = getent("spitfire_at_"+runpath+"2", "targetname");
spitfire startpath();
firenode = getvehiclenode (runpath+"2_start_fire", "script_noteworthy");
endnode = getvehiclenode (runpath+"2_end_fire", "script_noteworthy");
spitfire thread custom_strafe(fire_point,firenode, endnode );
}
call_strafing_run(runpath, fire_point)
{
if (runpath == "gravefront")
{
level thread strafe_go(8,runpath,fire_point);
}
if (runpath == "hq")
{
level thread strafe_go(100,runpath, fire_point);
}
if (runpath == "churchside")
{
level thread strafe_go(101,runpath, fire_point);
}
if (runpath == "flak")
{
level thread strafe_go(102, runpath, fire_point);
}
if (runpath == "woodstrafe")
{
level thread strafe_go(120,runpath,fire_point);
}
if (runpath == "gulchstrafe")
{
level thread strafe_go(121, runpath, fire_point);
}
}
call_airstrike(runpath, fire_point)
{
if (runpath == "woodstiger")
{
level thread strafe_go(7, runpath, fire_point);
woods_tiger = getent("woods_tiger", "targetname");
gulch_tiger = getent("gulch_tiger", "targetname");
getvehiclenode ("woodstiger2_end_fire", "script_noteworthy") waittill ("trigger");
woods_tiger.health = 2;
wait 1;
if (isdefined(gulch_tiger) && gulch_tiger.health > 1 && flag("gulchtiger_inloop"))
{
gulch_tiger.health = 2;
radiusdamage(gulch_tiger.origin, 1000, 10000,8000);
flag_set("gulchtiger_dead");
}
if (isdefined(woods_tiger)&& woods_tiger.health > 1)
{
radiusdamage(woods_tiger.origin, 1000, 10000,8000);
// wait for a plane to hit this node, then just blow up all the enemies with timed intervals
}
flag_set("woodstiger_dead");
}
if (runpath == "gulchtiger")
{
level thread strafe_go(22, runpath, fire_point);
node = getvehiclenode("gulchtiger1_end_fire", "script_noteworthy");
node waittill ("trigger");
gulch_panzer = getent("gulch_panzer", "targetname");
if (isdefined(gulch_panzer))
gulch_panzer.health = 2;
flag_set("planes_came");
gulch_tiger = getent("gulch_tiger", "targetname");
if (isdefined(gulch_tiger))
gulch_tiger.health = 2;
wait 1;
if (isdefined(gulch_tiger) && gulch_tiger.health > 0)
{
radiusdamage(gulch_tiger.origin, 500, 2000,800);
}
if (isdefined(gulch_panzer) && gulch_panzer.health > 0)
{
radiusdamage(gulch_panzer.origin, 500, 2000,800);
}
flag_set("gulchtiger_dead");
}
}
callStrike_bombEffect( plane )
{
bomb = spawnbomb( plane.origin, plane.angles );
bomb moveGravity( vector_scale( anglestoforward( plane.angles ), 2000 ), 2 );
bomb thread maps\_planeweapons::bomb_wiggle();
trace_dist = 64;
while( 1 )
{
vec1 = bomb.origin;
direction = AnglesToForward( ( 90, 0, 0 ) );
vec2 = vec1 + vectorScale( direction, 10000 );
trace_result = BulletTrace( vec1, vec2, false, undefined );
dist = Distance( bomb.origin, trace_result["position"] );
// println( "Dist ", dist );
//if( !IsDefined( old_dist ) )
// Check the distance, in order to blow up... Failsafe, if the bomb happened to go through the ground
// the >= 10000 should pickup and blowup.
if( dist < trace_dist || dist >= 10000 )
{
break;
}
// if( IsDefined( self.origin ) )
// {
// print3d( ( self.origin +( 0, 0, 16 ) ), self.origin, ( 1, 1, 1 ), 1, 1 );
// print3d( ( self.origin +( 0, 0, 32 ) ), dist, ( 1, 1, 1 ), 1, 1 );
// print3d( ( self.origin +( 0, 0, 48 ) ), trace_result["surfacetype"], ( 1, 1, 1 ), 1, 1 );
// }
// line( vec1, trace_result["position"] );
wait( 0.05 );
}
bombOrigin = bomb.origin;
bombAngles = bomb.angles;
playfx( level._effect["snow_exp"], bomb.origin );
radiusDamage( bomb.origin, 512, 400, 30);
bomb delete();
}
spawnbomb( origin, angles )
{
bomb = spawn( "script_model", origin );
bomb.angles = angles;
bomb setModel( "aircraft_bomb" );
return bomb;
}
vector_scale(vec, scale)
{
vec = (vec[0] * scale, vec[1] * scale, vec[2] * scale);
return vec;
}
plane_shake_player()
{
self endon ("death");
breakit = 0;
while (breakit ==0)
{
players = get_players();
for (i=0; i < players.size; i++)
{
dist = distance(players[i].origin, self.origin);
if (dist < 3300)
{
wait 0.3;
earthquake(0.2, 4.5, players[i].origin, 1000);
breakit++;
break;
}
}
wait 0.2;
}
}
custom_strafe(o_spot, startfire_node, endfire_node)
{
self thread plane_shake_player();
self endon ("death");
spot = spawn("script_origin", o_spot.origin);
// ticks a var once the stopfire node is hit and stops firing
startfire_node waittill_trig_n_notify("empty_notify", self);
self.ticker = 0;
// ticks a var once the stopfire node is hit and stops firing
endfire_node thread trig_node_tick(self);
vec = self.origin - spot.origin;
groundvec = (self.origin[0], self.origin[1], spot.origin[2]) - spot.origin;
n_groundvec = vectornormalize(groundvec);
spot.origin = spot.origin + (n_groundvec*2000);
while(1)
{
spot.origin = spot.origin - (n_groundvec*250);
vec = self.origin - spot.origin;
dist = distance(spot.origin, self.origin);
groundvec = (self.origin[0], self.origin[1], spot.origin[2]) - spot.origin;
n_groundvec = vectornormalize(groundvec);
ground_ang = vectortoangles( n_groundvec );
groundr_ang = anglestoright(ground_ang);
groundr_vec = vectornormalize(groundr_ang);
rspot = spot.origin - (groundr_vec*75);
lspot = spot.origin + (groundr_vec*75);
lgun = self gettagorigin("tag_gunLeft");
rgun = self gettagorigin("tag_gunRight");
angle = vectortoangles( vec );;
self.angles = (angle);
wait 0.1;
magicbullet("m1a1_coaxial_mg", rgun, rspot);
bullettracer(rgun, rspot, true);
throughvec = vectornormalize(rgun - rspot);
trace = bulletTrace( rgun, rspot, false, undefined );
traceHit = trace["position"];
dist = distance(tracehit, spot.origin);
// this loop is because the bullets are hitting the skybox and/or portal brushes
if (dist > 2000)
{
counter = 0;
while (dist > 4000 || counter < 10)
{
rgun = rgun - (throughvec*1000);
magicbullet("m1a1_coaxial_mg", rgun, rspot);
bullettracer(rgun, rspot, true);
trace = bulletTrace( rgun, rspot, false, undefined );
traceHit = trace["position"];
dist = distance(tracehit, spot.origin);
counter ++;
wait 0.001;
}
}
playfx (level._effect["snow_exp"], traceHit);
traceHit = trace["position"];
dist = distance(tracehit, get_players()[0].origin);
if (dist > 150)
{
radiusdamage(tracehit, 150, 1000, 500);
}
magicbullet("m1a1_coaxial_mg", lgun, lspot);
bullettracer(lgun, lspot, true);
trace = bulletTrace( self.origin, lspot, false, undefined );
traceHit = trace["position"];
dist = distance(tracehit, get_players()[0].origin);
if (dist > 150)
{
radiusdamage(tracehit, 150, 1000, 500);
}
if (self.ticker > 0)
break;
}
spot delete();
}
trig_node_tick(plane)
{
while (1)
{
self waittill ("trigger", triggerer);
if (plane == triggerer)
break;
}
plane.ticker ++;
}