1 #using scripts\codescripts\struct;
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\challenges_shared;
5 #using scripts\shared\clientfield_shared;
6 #using scripts\shared\entityheadicons_shared;
7 #using scripts\shared\gameobjects_shared;
8 #using scripts\shared\hostmigration_shared;
9 #using scripts\shared\hud_util_shared;
10 #using scripts\shared\killstreaks_shared;
11 #using scripts\shared\popups_shared;
12 #using scripts\shared\scoreevents_shared;
13 #using scripts\shared\sound_shared;
14 #using scripts\shared\util_shared;
15 #using scripts\shared\weapons\_hacker_tool;
16 #using scripts\shared\weapons\_smokegrenade;
17 #using scripts\shared\weapons\_tacticalinsertion;
18 #using scripts\shared\weapons\_weapons;
19 #using scripts\shared\weapons\_heatseekingmissile;
20 #using scripts\shared\weapons\_weaponobjects;
21 #using scripts\shared\vehicleriders_shared;
22 #using scripts\shared\flag_shared;
23 #using scripts\shared\flagsys_shared;
25 #using scripts\mp\_challenges;
26 #using scripts\mp\_util;
27 #using scripts\mp\gametypes\_battlechatter;
28 #using scripts\mp\gametypes\_hostmigration;
29 #using scripts\mp\killstreaks\_ai_tank;
30 #using scripts\mp\killstreaks\_airsupport;
31 #using scripts\mp\killstreaks\_emp;
32 #using scripts\mp\killstreaks\_helicopter;
33 #using scripts\mp\killstreaks\_killstreak_bundles;
34 #using scripts\mp\killstreaks\_killstreak_detect;
35 #using scripts\mp\killstreaks\_killstreak_hacking;
36 #using scripts\mp\killstreaks\_killstreak_weapons;
37 #using scripts\mp\killstreaks\_killstreakrules;
38 #using scripts\mp\killstreaks\_killstreaks;
39 #using scripts\mp\killstreaks\_supplydrop;
40 #using scripts\mp\killstreaks\_combat_robot;
42 #insert scripts\mp\_hacker_tool.gsh;
43 #insert scripts\shared\shared.gsh;
44 #insert scripts\shared\version.gsh;
45 #insert scripts\mp\killstreaks\_killstreaks.gsh;
47 #define SUPPLY_DROP_NAME "supply_drop"
48 #define SUPPLY_DROP_AI_TANK_NAME "supply_drop_ai_tank"
49 #define SUPPLY_DROP_COMBAT_ROBOT_NAME "supply_drop_combat_robot"
51 #define SUPPY_DROP_ON_TARGET_DISTANCE 3.7
52 #define SUPPY_DROP_NAV_MESH_VALID_LOCATION_BOUNDARY 12
53 #define SUPPY_DROP_NAV_MESH_VALID_LOCATION_TOLERANCE 4
55 #define SUPPLY_DROP_CRATE_STATE_NONE 0
56 #define SUPPLY_DROP_CRATE_STATE_CAPTURE 1
57 #define SUPPLY_DROP_CRATE_STATE_HACK 2
58 #define SUPPLY_DROP_CRATE_STATE_DISARM 3
61 #precache( "material", "compass_supply_drop_black" );
62 #precache( "material", "compass_supply_drop_green" );
63 #precache( "material", "compass_supply_drop_red" );
64 #precache( "material", "compass_supply_drop_white" );
65 #precache( "material", "waypoint_recon_artillery_strike" );
66 #precache( "material", "t7_hud_ks_wpn_turret_drop" );
67 #precache( "material", "t7_hud_ks_rolling_thunder_drop" );
68 #precache( "material", "t7_hud_ks_drone_amws_drop" );
72 #precache( "material","headicon_dead");
73 #precache( "string", "KILLSTREAK_CAPTURING_CRATE" );
74 #precache( "string", "KILLSTREAK_HACKING_CRATE" );
75 #precache( "string", "KILLSTREAK_SUPPLY_DROP_DISARM_HINT" );
76 #precache( "triggerstring", "KILLSTREAK_SUPPLY_DROP_DISARM_HINT" );
77 #precache( "string", "KILLSTREAK_SUPPLY_DROP_DISARMING_CRATE" );
78 #precache( "string", "KILLSTREAK_SUPPLY_DROP_HACKED" );
80 #precache( "triggerstring", "KILLSTREAK_AI_TANK_CRATE" );
81 #precache( "triggerstring", "KILLSTREAK_MINIGUN_CRATE" );
82 #precache( "triggerstring", "PLATFORM_MINIGUN_GAMBLER" );
83 #precache( "triggerstring", "KILLSTREAK_M32_CRATE" );
84 #precache( "triggerstring", "PLATFORM_M32_GAMBLER" );
85 #precache( "triggerstring", "KILLSTREAK_AMMO_CRATE" );
86 #precache( "triggerstring", "PLATFORM_AMMO_CRATE_GAMBLER" );
87 #precache( "triggerstring", "KILLSTREAK_RADAR_CRATE" );
88 #precache( "triggerstring", "PLATFORM_RADAR_GAMBLER" );
89 #precache( "triggerstring", "KILLSTREAK_RCBOMB_CRATE" );
90 #precache( "triggerstring", "PLATFORM_RCBOMB_GAMBLER" );
91 #precache( "triggerstring", "KILLSTREAK_MISSILE_DRONE_CRATE" );
92 #precache( "triggerstring", "PLATFORM_MISSILE_DRONE_GAMBLER" );
93 #precache( "triggerstring", "KILLSTREAK_COUNTERU2_CRATE" );
94 #precache( "triggerstring", "PLATFORM_COUNTERU2_GAMBLER" );
95 #precache( "triggerstring", "KILLSTREAK_REMOTE_MISSILE_CRATE" );
96 #precache( "triggerstring", "PLATFORM_REMOTE_MISSILE_GAMBLER" );
97 #precache( "triggerstring", "KILLSTREAK_PLANE_MORTAR_CRATE");
98 #precache( "triggerstring", "PLATFORM_PLANE_MORTAR_GAMBLER" );
99 #precache( "triggerstring", "KILLSTREAK_AUTO_TURRET_CRATE" );
100 #precache( "triggerstring", "PLATFORM_AUTO_TURRET_GAMBLER" );
101 #precache( "triggerstring", "KILLSTREAK_MICROWAVE_TURRET_CRATE" );
102 #precache( "triggerstring", "PLATFORM_MICROWAVE_TURRET_GAMBLER" );
103 #precache( "triggerstring", "KILLSTREAK_MINIGUN_CRATE" );
104 #precache( "triggerstring", "PLATFORM_MINIGUN_GAMBLER" );
105 #precache( "triggerstring", "KILLSTREAK_M32_CRATE" );
106 #precache( "triggerstring", "PLATFORM_M32_GAMBLER" );
107 #precache( "triggerstring", "KILLSTREAK_HELICOPTER_GUARD_CRATE" );
108 #precache( "triggerstring", "PLATFORM_HELICOPTER_GUARD_GAMBLER" );
109 #precache( "triggerstring", "KILLSTREAK_SATELLITE_CRATE" );
110 #precache( "triggerstring", "PLATFORM_SATELLITE_GAMBLER" );
111 #precache( "triggerstring", "KILLSTREAK_QRDRONE_CRATE" );
112 #precache( "triggerstring", "PLATFORM_QRDRONE_GAMBLER" );
113 #precache( "triggerstring", "KILLSTREAK_AI_TANK_CRATE" );
114 #precache( "triggerstring", "PLATFORM_AI_TANK_GAMBLER" );
115 #precache( "triggerstring", "KILLSTREAK_HELICOPTER_CRATE" );
116 #precache( "triggerstring", "PLATFORM_HELICOPTER_GAMBLER" );
117 #precache( "triggerstring", "KILLSTREAK_EMP_CRATE" );
118 #precache( "triggerstring", "PLATFORM_EMP_GAMBLER" );
119 #precache( "triggerstring", "KILLSTREAK_RAPS_CRATE" );
120 #precache( "triggerstring", "PLATFORM_RAPS_GAMBLER" );
121 #precache( "triggerstring", "KILLSTREAK_DART_CRATE" );
122 #precache( "triggerstring", "PLATFORM_DART_GAMBLER" );
123 #precache( "triggerstring", "KILLSTREAK_SENTINEL_CRATE" );
124 #precache( "triggerstring", "PLATFORM_SENTINEL_GAMBLER" );
125 #precache( "triggerstring", "KILLSTREAK_COMBAT_ROBOT_CRATE" );
126 #precache( "triggerstring", "PLATFORM_COMBAT_ROBOT_GAMBLER" );
127 #precache( "triggerstring", "KILLSTREAK_REMOTE_MORTAR_CRATE" );
128 #precache( "triggerstring", "PLATFORM_REMOTE_MORTAR_GAMBLER" );
129 #precache( "triggerstring", "KILLSTREAK_HELICOPTER_GUNNER_CRATE" );
130 #precache( "triggerstring", "PLATFORM_HELICOPTER_GUNNER_GAMBLER" );
131 #precache( "triggerstring", "KILLSTREAK_DOGS_CRATE" );
132 #precache( "triggerstring", "PLATFORM_DOGS_GAMBLER" );
133 #precache( "triggerstring", "KILLSTREAK_MISSILE_SWARM_CRATE" );
134 #precache( "triggerstring", "PLATFORM_MISSILE_SWARM_GAMBLER" );
135 #precache( "triggerstring", "KILLSTREAK_EARNED_SUPPLY_DROP" );
136 #precache( "triggerstring", "KILLSTREAK_DRONE_STRIKE_CRATE" );
137 #precache( "triggerstring", "PLATFORM_DRONE_STRIKE_GAMBLER" );
138 #precache( "triggerstring", "PLATFORM_AI_TANK_CRATE_GAMBLER" );
140 #precache( "string", "KILLSTREAK_AIRSPACE_FULL" );
141 #precache( "string", "KILLSTREAK_SUPPLY_DROP_INBOUND" );
142 #precache( "string", "FriendlyBlue" );
143 #precache( "string", "EnemyOrange" );
144 #precache( "eventstring", "mpl_killstreak_supply" );
145 #precache( "fx", "killstreaks/fx_supply_drop_smoke" );
146 #precache( "fx", "explosions/fx_exp_grenade_default" );
148 #using_animtree ( "mp_vehicles" );
150 #namespace supplydrop;
154 level.crateModelFriendly =
"wpn_t7_care_package_world";
155 level.crateModelEnemy =
"wpn_t7_care_package_world";
156 level.crateModelTank =
"wpn_t7_drop_box";
157 level.crateModelBoobyTrapped =
"wpn_t7_care_package_world";
158 level.vtolDropHelicopterVehicleInfo =
"vtol_supplydrop_mp";
160 level.crateOwnerUseTime = 500;
161 level.crateNonOwnerUseTime = GetGametypeSetting(
"crateCaptureTime") * 1000;
162 level.crate_headicon_offset = (0, 0, 15);
163 level.supplyDropDisarmCrate = &
"KILLSTREAK_SUPPLY_DROP_DISARM_HINT";
164 level.disarmingCrate = &
"KILLSTREAK_SUPPLY_DROP_DISARMING_CRATE";
166 level.supplydropCarePackageIdleAnim = %o_drone_supply_care_idle;
167 level.supplydropCarePackageDropAnim = %o_drone_supply_care_drop;
168 level.supplydropAiTankIdleAnim = %o_drone_supply_agr_idle;
169 level.supplydropAiTankDropAnim = %o_drone_supply_agr_drop;
182 level._supply_drop_smoke_fx =
"killstreaks/fx_supply_drop_smoke";
183 level._supply_drop_explosion_fx =
"explosions/fx_exp_grenade_default";
187 killstreaks::register_dialog(
SUPPLY_DROP_NAME,
"mpl_killstreak_supply",
"supplyDropDialogBundle",
"supplyDropPilotDialogBundle",
"friendlySupplyDrop",
"enemySupplyDrop",
"enemySupplyDropMultiple",
"friendlySupplyDropHacked",
"enemySupplyDropHacked",
"requestSupplyDrop",
"threatSupplyDrop" );
195 level.crateTypes = [];
196 level.categoryTypeWeight = [];
264 level.crateCategoryWeights = [];
265 level.crateCategoryTypeWeights = [];
267 foreach( categoryKey, category
in level.crateTypes )
279 level.crateCategoryWeights[category] = 0;
281 crateTypeKeys = getarraykeys( level.crateTypes[category] );
285 for ( crateType = 0; crateType < crateTypeKeys.size; crateType++ )
287 typeKey = crateTypeKeys[crateType];
288 level.crateTypes[category][typeKey].previousWeight = level.crateCategoryWeights[category];
289 level.crateCategoryWeights[category] += level.crateTypes[category][typeKey].weight;
290 level.crateTypes[category][typeKey].weight = level.crateCategoryWeights[category];
296 level.crateCategoryTypeWeights[category] = 0;
297 crateTypeKeys = getarraykeys( level.categoryTypeWeight[category] );
301 for ( crateType = 0; crateType < crateTypeKeys.size; crateType++ )
303 typeKey = crateTypeKeys[crateType];
304 level.crateCategoryTypeWeights[category] += level.categoryTypeWeight[category][typeKey].weight;
305 level.categoryTypeWeight[category][typeKey].weight = level.crateCategoryTypeWeights[category];
313 if ( !isdefined(level.categoryTypeWeight[category]) )
315 level.categoryTypeWeight[category] = [];
318 level.categoryTypeWeight[category][type] = SpawnStruct();
320 level.categoryTypeWeight[category][type].weight = weight;
324 startIndex = undefined;
325 finalIndex = undefined;
327 crateNameKeys = getarraykeys( level.crateTypes[category] );
331 for ( crateName = 0; crateName < crateNameKeys.size; crateName++ )
333 nameKey = crateNameKeys[crateName];
335 if ( level.crateTypes[category][nameKey].type == type )
338 totalWeight = totalWeight + level.crateTypes[category][nameKey].weight;
340 if ( !isdefined( startIndex ) )
342 startIndex = crateName;
345 if ( isdefined( finalIndex ) && (( finalIndex + 1 ) != crateName ) )
347 /#
util::error(
"Crate type declaration must be contiguous");#/
353 finalIndex = crateName;
357 level.categoryTypeWeight[category][type].totalCrateWeight = totalWeight;
358 level.categoryTypeWeight[category][type].crateCount = count;
359 level.categoryTypeWeight[category][type].startIndex = startIndex;
360 level.categoryTypeWeight[category][type].finalIndex = finalIndex;
373 itemName = level.killstreaks[
name].menuName;
375 if( IsItemRestricted( itemName ) )
378 if ( !isdefined(level.crateTypes[category]) )
380 level.crateTypes[category] = [];
383 crateType = SpawnStruct();
384 crateType.type = type;
385 crateType.name =
name;
386 crateType.weight = weight;
387 crateType.hint = hint;
388 crateType.hint_gambler = hint_gambler;
389 crateType.giveFunction = giveFunction;
391 if( isdefined(crateWeapon) )
393 crateType.objective = GetCrateHeadObjective( crateWeapon );
395 if ( isdefined( landFunctionOverride ) )
397 crateType.landFunctionOverride = landFunctionOverride;
400 level.crateTypes[category][
name] = crateType;
402 game[
"strings"][
name +
"_hint"] = hint;
407 if( !isdefined(level.crateTypes) || !isdefined(level.crateTypes[category]) )
410 Assert( isdefined(level.crateTypes) );
411 Assert( isdefined(level.crateTypes[category]) );
412 Assert( isdefined(level.crateCategoryWeights[category]) );
416 randomWeightEnd = RandomIntRange( 1, level.crateCategoryWeights[category] + 1 );
417 find_another =
false;
419 crateNameKeys = getarraykeys( level.crateTypes[category] );
421 if ( isdefined( level.categoryTypeWeight[category] ) )
423 randomWeightEnd = RandomInt(level.crateCategoryTypeWeights[category] ) + 1;
424 crateTypeKeys = getarraykeys( level.categoryTypeWeight[category] );
426 for ( crateType = 0; crateType < crateTypeKeys.size; crateType++ )
428 typeKey = crateTypeKeys[crateType];
430 if ( level.categoryTypeWeight[category][typeKey].weight < randomWeightEnd )
433 crateTypeStart = level.categoryTypeWeight[category][typeKey].startIndex;
434 randomWeightEnd = RandomInt( level.categoryTypeWeight[category][typeKey].totalCrateWeight) + 1;
435 randomWeightEnd += level.crateTypes[category][crateNameKeys[crateTypeStart]].previousWeight;
440 for ( crateType = crateTypeStart; crateType < crateNameKeys.size; crateType++ )
442 typeKey = crateNameKeys[crateType];
444 if ( level.crateTypes[category][typeKey].weight < randomWeightEnd )
448 if( isdefined( gambler_crate_name ) && level.crateTypes[category][typeKey].name == gambler_crate_name )
456 if( crateType < crateNameKeys.size - 1 )
460 else if( crateType > 0 )
464 typeKey = crateNameKeys[crateType];
471 if( isdefined(level.dev_gui_supply_drop) && level.dev_gui_supply_drop !=
"random" && level.dev_gui_supply_drop !=
"" )
473 typeKey = level.dev_gui_supply_drop;
477 return level.crateTypes[category][typeKey];
482 if ( !IsAlive(
self ) || !isdefined( crate.crateType ) )
485 Assert( isdefined(crate.crateType.giveFunction),
"no give function defined for " + crate.crateType.name );
487 return [[crate.crateType.giveFunction]](
"inventory_" + crate.crateType.name );
492 self endon(
"give_crate_killstreak_done" );
493 if ( isdefined( extraEndon ) )
495 self endon( extraEndon );
497 self waittill( event );
498 self notify(
"give_crate_killstreak_done", removeCrate );
508 switch ( weapon.name )
539 weapon = GetWeapon(weapon_name);
540 if ( weapon == level.weaponNone )
543 currentWeapon =
self GetCurrentWeapon();
545 if ( currentWeapon == weapon ||
self HasWeapon( weapon ) )
547 self GiveMaxAmmo( weapon );
553 if ( currentWeapon.isSupplyDropWeapon || isdefined( level.grenade_array[currentWeapon] )|| isdefined( level.inventory_array[currentWeapon] ) )
555 self TakeWeapon(
self.lastdroppableweapon );
556 self GiveWeapon( weapon );
557 self switchToWeapon( weapon );
561 self AddWeaponStat( weapon,
"used", 1 );
565 self GiveWeapon( weapon );
566 self switchToWeapon( weapon );
568 self waittill(
"weapon_change", newWeapon );
579 self endon(
"disconnect");
580 self endon(
"spawned_player");
582 supplyDropWeapon = level.weaponNone;
583 currentWeapon =
self GetCurrentWeapon();
584 prevWeapon = currentWeapon;
585 if ( currentWeapon.isSupplyDropWeapon )
587 supplyDropWeapon = currentWeapon;
590 if( supplyDropWeapon.isGrenadeWeapon )
591 trigger_event =
"grenade_fire";
593 trigger_event =
"weapon_fired";
595 self thread
supplyDropWatcher( package_contents_id, trigger_event, supplyDropWeapon, context );
597 self.supplyGrenadeDeathDrop =
false;
601 player AllowMelee(
false );
603 player AllowMelee(
true );
605 if ( !isdefined( notifyString ) || ( notifyString != trigger_event ) )
612 if( isdefined( player.markerPosition ) )
618 self notify (
"trigger_weapon_shutdown" );
621 if ( supplyDropWeapon == level.weaponNone )
627 if ( isdefined(
self ) )
632 self TakeWeapon( supplyDropWeapon );
636 if (
self HasWeapon( supplyDropWeapon ) ||
self GetAmmoCount( supplyDropWeapon ) )
660 level.droplocations[killstreak_id] = location;
665 level.droplocations[killstreak_id] = undefined;
671 foreach( dropLocation
in level.dropLocations )
673 if( Distance2DSquared( dropLocation, location ) < 60 * 60 )
677 if ( context.perform_physics_trace ===
true )
680 if( isdefined( context.tracemask ) )
681 mask = context.tracemask;
683 radius = context.radius;
685 trace = physicstrace( location + ( 0,0, 5000 ), location + ( 0, 0, 10 ), ( -radius, -radius, 0 ), ( radius, radius, 2 * radius ), undefined, mask );
689 if(
trace[
"fraction"] < 1 )
701 closestPoint = GetClosestPointOnNavMesh( location, max( context.max_dist_from_location, 24 ), context.dist_from_boundary );
703 isValidPoint = isdefined( closestPoint );
706 if ( isValidPoint && context.check_same_floor ===
true && Abs( location[2] - closestPoint[2] ) > 96 )
707 isValidPoint =
false;
709 if ( isValidPoint && Distance2DSquared( location, closestPoint ) >
SQR( context.max_dist_from_location ) )
710 isValidPoint =
false;
714 if ( GetDVarInt(
"scr_supply_drop_valid_location_debug", 0 ) )
719 otherClosestPoint = GetClosestPointOnNavMesh( location, GetDVarFloat(
"scr_supply_drop_valid_location_radius_debug", 96 ), context.dist_from_boundary );
720 if ( isdefined( otherClosestPoint ) )
722 sphere( otherClosestPoint, context.max_dist_from_location, ( 1, 0, 0 ), 0.8,
false, 20, 1 );
728 sphere( closestPoint, context.max_dist_from_location, ( 0, 1, 0 ), 0.8,
false, 20, 1 );
729 util::drawcylinder( closestPoint, context.radius, 8000, 1.0/60.0, undefined, ( 0, 0.9, 0 ), 0.7 );
744 context = SpawnStruct();
745 context.radius = level.killstreakCoreBundle.ksAirdropSupplydropRadius;
748 context.perform_physics_trace =
true;
750 context.objective = &
"airdrop_supplydrop";
751 context.validLocationSound = level.killstreakCoreBundle.ksValidCarepackageLocationSound;
753 context.dropTag =
"tag_attach";
754 context.dropTagOffset = ( -32, 0, 23 );
755 context.killstreakType = killstreak;
759 player notify(
"supply_drop_marker_done" );
772 weapon = GetWeapon(
"minigun" );
773 currentWeapon =
self GetCurrentWeapon();
777 if ( currentWeapon.isSupplyDropWeapon || isdefined( level.grenade_array[currentWeapon] ) || isdefined( level.inventory_array[currentWeapon] ) )
779 self TakeWeapon(
self.lastdroppableweapon );
780 self GiveWeapon( weapon );
781 self SwitchToWeapon( weapon );
784 self setBlockWeaponPickup( weapon,
true );
791 self TakeWeapon( currentWeapon );
792 self GiveWeapon( weapon );
793 self SwitchToWeapon( weapon );
796 self setBlockWeaponPickup( weapon,
true );
805 weapon = GetWeapon(
"m202_flash" );
806 currentWeapon =
self GetCurrentWeapon();
810 if ( currentWeapon.isSupplyDropWeapon || isdefined( level.grenade_array[currentWeapon] ) || isdefined( level.inventory_array[currentWeapon] ) )
812 self TakeWeapon(
self.lastdroppableweapon );
813 self GiveWeapon( weapon );
814 self SwitchToWeapon( weapon );
817 self setBlockWeaponPickup( weapon,
true );
824 self TakeWeapon( currentWeapon );
825 self GiveWeapon( weapon );
826 self SwitchToWeapon( weapon );
829 self setBlockWeaponPickup( weapon,
true );
837 self iPrintLnBold( level.killstreaks[ killstreak].notAvailableText );
842 weapon = GetWeapon(
"m220_tow" );
843 currentWeapon =
self GetCurrentWeapon();
847 if ( currentWeapon.isSupplyDropWeapon || isdefined( level.grenade_array[currentWeapon] ) || isdefined( level.inventory_array[currentWeapon] ) )
849 self TakeWeapon(
self.lastdroppableweapon );
850 self GiveWeapon( weapon );
851 self SwitchToWeapon( weapon );
854 self setBlockWeaponPickup( weapon,
true );
861 self TakeWeapon( currentWeapon );
862 self GiveWeapon( weapon );
863 self SwitchToWeapon( weapon );
866 self setBlockWeaponPickup( weapon,
true );
874 self iPrintLnBold( level.killstreaks[killstreak].notAvailableText );
879 weapon = GetWeapon(
"mp40_blinged" );
880 currentWeapon =
self GetCurrentWeapon();
884 if ( currentWeapon.isSupplyDropWeapon || isdefined( level.grenade_array[currentWeapon] ) || isdefined( level.inventory_array[currentWeapon] ) )
886 self TakeWeapon(
self.lastdroppableweapon );
887 self GiveWeapon( weapon );
888 self SwitchToWeapon( weapon );
891 self setBlockWeaponPickup( weapon,
true );
898 self TakeWeapon( currentWeapon );
899 self GiveWeapon( weapon );
900 self SwitchToWeapon( weapon );
903 self setBlockWeaponPickup( weapon,
true );
910 self endon(
"disconnect" );
911 self endon(
"supplyDropWatcher" );
912 self endon(
"trigger_weapon_shutdown" );
913 self endon(
"spawned_player" );
914 self endon(
"weapon_change" );
919 self notify(
"cleanup_marker" );
924 if( isdefined( context ) && isdefined( context.marker ) )
926 context.marker
delete();
927 context.marker = undefined;
928 if( isdefined( context.markerFXHandle ) )
930 context.markerFXHandle
delete();
931 context.markerFXHandle = undefined;
934 if ( isdefined( player ) )
946 player endon(
"supplyDropWatcher" );
947 player endon(
"spawned_player" );
948 player endon(
"disconnect" );
949 player endon(
"weapon_change" );
950 player endon(
"death" );
952 markerModel =
spawn(
"script_model", ( 0, 0, 0 ) );
953 context.marker = markerModel;
962 minRange = level.killstreakCoreBundle.ksMinAirdropTargetRange;
963 maxRange = level.killstreakCoreBundle.ksMaxAirdropTargetRange;
965 forwardVector = VectorScale( AnglesToForward( player GetPlayerAngles() ), maxRange );
969 if( isdefined( context.tracemask ) )
970 mask = context.tracemask;
973 results = physicstrace( player GetEye(), player GetEye() + forwardVector, ( -radius, -radius, 0 ), ( radius, radius, 2 * radius ), player, mask );
976 markerModel.origin = results[
"position"];
978 tooClose = DistanceSquared( markerModel.origin, player.origin ) < minRange * minRange;
980 if( ( results[
"normal"][2] > 0.7 ) && !tooClose && isdefined( context.isLocationGood ) && [[context.isLocationGood]]( markerModel.origin, context ) )
982 player.markerPosition = markerModel.origin;
987 player.markerPosition = undefined;
998 self notify(
"supplyDropWatcher" );
1000 self endon(
"supplyDropWatcher" );
1001 self endon(
"spawned_player" );
1002 self endon(
"disconnect" );
1003 self endon(
"weapon_change" );
1008 if ( killstreak_id == -1 )
1011 context.killstreak_id = killstreak_id;
1015 if( !supplyDropWeapon.isGrenadeWeapon )
1026 self waittill( trigger_event, weapon_instance, weapon );
1028 isSupplyDropWeapon =
true;
1029 if( trigger_event ==
"grenade_fire" )
1030 isSupplyDropWeapon = weapon.isSupplyDropWeapon;
1032 if ( isdefined(
self ) && isSupplyDropWeapon )
1034 if( isdefined( context ) )
1036 if( !isdefined( player.markerPosition ) || !supplydrop::islocationgood( player.markerPosition, context ) )
1038 if( isdefined( level.killstreakCoreBundle.ksInvalidLocationSound ) )
1039 player playsoundtoplayer( level.killstreakCoreBundle.ksInvalidLocationSound, player );
1041 if( isdefined( level.killstreakCoreBundle.ksInvalidLocationString ) )
1042 player iPrintLnBold( Istring( level.killstreakCoreBundle.ksInvalidLocationString ) );
1047 if( isdefined( context.validLocationSound ) )
1048 player playsoundtoplayer( context.validLocationSound, player );
1050 self thread
heliDeliverCrate( player.markerPosition, weapon_instance,
self, team, killstreak_id, package_contents_id, context );
1054 self thread
doSupplyDrop( weapon_instance, weapon,
self, killstreak_id, package_contents_id );
1063 self notify(
"cleanup_marker" );
1075 self endon(
"supplyDropWatcher" );
1076 self endon(
"spawned_player" );
1077 self endon(
"disconnect" );
1078 self endon(
"weapon_change" );
1079 self endon(
"death" );
1080 self endon(
"trigger_weapon_shutdown" );
1082 self waittill(
"emp_jammed" );
1089 self endon(
"death" );
1090 self endon(
"stationary");
1092 GRENADE_LIFETIME = 10;
1095 wait( GRENADE_LIFETIME );
1097 if( !isdefined(
self ) )
1100 self notify(
"grenade_timeout" );
1104 if ( weapon.name ==
"ai_tank_drop" )
1107 self notify(
"cleanup_marker" );
1109 else if ( weapon.name ==
"inventory_ai_tank_drop" )
1112 self notify(
"cleanup_marker" );
1114 else if ( weapon.name ==
"combat_robot_drop" )
1117 self notify(
"cleanup_marker" );
1119 else if ( weapon.name ==
"inventory_combat_robot_drop" )
1122 self notify(
"cleanup_marker" );
1130 self endon(
"supplyDropWatcher" );
1131 self endon(
"spawned_player" );
1132 self endon(
"disconnect" );
1133 self endon(
"trigger_weapon_shutdown" );
1134 self endon(
"death" );
1136 self waittill(
"weapon_change" );
1138 self notify(
"cleanup_marker" );
1143 self endon(
"disconnect" );
1144 self endon(
"weapon_change" );
1146 self waittill (
"grenade_pullback", weapon );
1152 self waittill (
"death" );
1155 self.supplyGrenadeDeathDrop =
true;
1157 if( weapon.isSupplyDropWeapon )
1162 if ( !
IS_TRUE(
self.usingKillstreakFromInventory ) )
1174 self notify(
"watchForGrenadePutDown" );
1175 self endon(
"watchForGrenadePutDown" );
1176 self endon(
"death" );
1177 self endon(
"disconnect" );
1181 self notify (
"trigger_weapon_shutdown" );
1188 self endon(
"supply_drop_marker_done" );
1190 self endon(
"disconnect" );
1191 self endon(
"spawned_player" );
1193 currentWeapon =
self GetCurrentWeapon();
1195 while ( currentWeapon.isSupplyDropWeapon )
1197 self waittill(
"weapon_change", currentWeapon );
1204 self notify(
"supply_drop_marker_done" );
1211 switch (
self.crateType.type )
1215 if( isDefined(
self.crateType.objective) )
1217 return self.crateType.objective;
1219 else if (
self.crateType.name ==
"inventory_ai_tank_drop" )
1221 icon =
"t7_hud_ks_drone_amws";
1226 icon = level.killStreakIcons[killstreak];
1233 switch(
self.crateType.name )
1236 icon =
"hud_ks_minigun";
1239 icon =
"hud_ks_m32";
1242 icon =
"hud_ks_m202";
1245 icon =
"hud_ks_tv_guided_missile";
1251 icon =
"waypoint_recon_artillery_strike";
1259 icon =
"hud_ammo_refill";
1268 return icon +
"_drop";
1274 self SetCursorHint(
"HINT_NOICON");
1276 if( !isdefined(
self.crateType ) )
1279 self setHintString(
self.crateType.hint );
1280 if ( isdefined(
self.crateType.hint_gambler ) )
1282 self setHintStringForPerk(
"specialty_showenemyequipment",
self.crateType.hint_gambler );
1286 objective_add( crateObjID,
"invisible",
self.origin );
1288 objective_icon( crateObjID,
"compass_supply_drop_white" );
1289 objective_setcolor( crateObjID, &
"FriendlyBlue" );
1290 objective_state( crateObjID,
"active" );
1291 self.friendlyObjID = crateObjID;
1292 self.enemyObjID = [];
1296 if (isdefined( hacker ))
1302 if ( level.teambased )
1304 objective_team( crateObjID,
self.team );
1306 foreach( team
in level.teams )
1308 if (
self.team == team )
1312 objective_add( crateObjID,
"invisible",
self.origin );
1313 if( isdefined(
self.hacker ) )
1316 objective_icon( crateObjID,
"compass_supply_drop_black" );
1321 objective_icon( crateObjID,
"compass_supply_drop_white" );
1322 objective_setcolor( crateObjID, &
"EnemyOrange" );
1324 objective_team( crateObjID, team );
1325 objective_state( crateObjID,
"active" );
1326 self.enemyObjID[
self.enemyObjID.size] = crateObjID;
1331 if ( !
self.visibleToAll )
1333 Objective_SetInvisibleToAll( crateObjID );
1336 objective_add( enemyCrateObjID,
"invisible",
self.origin );
1337 objective_icon( enemyCrateObjID,
"compass_supply_drop_white" );
1338 objective_setcolor( enemyCrateObjID, &
"EnemyOrange" );
1339 objective_state( enemyCrateObjID,
"active" );
1341 if ( isplayer(
self.owner ) )
1343 Objective_SetInvisibleToPlayer( enemyCrateObjID,
self.owner );
1346 self.enemyObjID[
self.enemyObjID.size] = enemyCrateObjID;
1349 if ( isplayer(
self.owner ) )
1351 Objective_SetVisibleToPlayer( crateObjID,
self.owner );
1354 if( isdefined(
self.hacker ) )
1356 Objective_SetInvisibleToPlayer( crateObjID,
self.hacker );
1359 objective_add( crateObjID,
"invisible",
self.origin );
1361 objective_icon( crateObjID,
"compass_supply_drop_black" );
1362 objective_state( crateObjID,
"active" );
1363 Objective_SetInvisibleToAll( crateObjID );
1364 Objective_SetVisibleToPlayer( crateObjID,
self.hacker );
1365 self.hackerObjID = crateObjID;
1369 if( !
self.visibleToAll && isdefined( icon ) )
1372 if(
self.entityHeadObjectives.size > 0 )
1374 objectiveID =
self.entityHeadObjectives[
self.entityHeadObjectives.size - 1];
1375 if( isdefined( objectiveID ) )
1377 Objective_SetInvisibleToAll( objectiveID );
1378 Objective_SetVisibleToPlayer( objectiveID,
self.owner );
1383 if ( isdefined(
self.owner ) && IsPlayer(
self.owner) &&
self.owner
util::is_bot() )
1385 self.owner notify(
"bot_crate_landed",
self );
1388 if ( isdefined(
self.owner ) )
1390 self.owner notify(
"crate_landed",
self );
1398 ksBundle = level.killstreakBundle[ killstreak ];
1399 if ( isdefined( ksBundle ) && isdefined( ksBundle.ksRicochetPostLandDuration ) && ksBundle.ksRicochetPostLandDuration > 0 )
1401 endtime = GetTime() + ( ksBundle.ksRicochetPostLandDuration * 1000 );
1408 self makeunusable();
1410 if ( isdefined(
self.friendlyObjID) )
1412 Objective_Delete(
self.friendlyObjID );
1414 self.friendlyObjID = undefined;
1417 if ( isdefined(
self.enemyObjID) )
1419 foreach( objId
in self.enemyObjID )
1421 Objective_Delete( objId );
1424 self.enemyObjID = [];
1427 if ( isdefined(
self.hackerObjID) )
1429 Objective_Delete(
self.hackerObjID );
1431 self.hackerObjID = undefined;
1438 self notify(
"ownerTeamChangeWatcher_singleton" );
1439 self endon (
"ownerTeamChangeWatcher_singleton");
1441 self endon(
"death");
1443 if ( !level.teamBased || !isdefined(
self.owner ) )
1446 self.owner waittill(
"joined_team");
1448 self.owner = undefined;
1453 PhysicsExplosionSphere( origin, radius, radius, 0 );
1458 level notify(
"drop_objects_to_ground", origin, stickyObjectRadius );
1469 crate waittill(
"death");
1477 crate_ents = GetEntArray(
"care_package",
"script_noteworthy" );
1478 radius_sq = radius * radius;
1479 for ( i = 0 ; i < crate_ents.size ; i++ )
1481 if ( DistanceSquared( origin, crate_ents[i].origin ) < radius_sq )
1490 self endon(
"death");
1492 if ( isdefined(
self.droppingToGround ) )
1495 self.droppingToGround =
true;
1505 self.droppingToGround = undefined;
1515 function crateSpawn( killstreak, killstreakId, owner, team, drop_origin, drop_angle )
1517 crate =
spawn(
"script_model", drop_origin, 1 );
1520 crate.angles = drop_angle;
1521 crate.visibleToAll =
false;
1522 crate.script_noteworthy =
"care_package";
1525 if ( killstreak ==
"ai_tank_drop" || killstreak ==
"inventory_ai_tank_drop" )
1527 crate setModel( level.crateModelTank );
1528 crate setEnemyModel( level.crateModelTank );
1532 crate setModel( level.crateModelFriendly );
1533 crate setEnemyModel( level.crateModelEnemy );
1537 crate DisconnectPaths();
1539 switch( killstreak )
1542 crate.crateType = level.crateTypes[ killstreak ][
"autoturret" ];
1544 case "tow_turret_drop":
1545 crate.crateType = level.crateTypes[ killstreak ][
"auto_tow" ];
1547 case "m220_tow_drop":
1548 crate.crateType = level.crateTypes[ killstreak ][
"m220_tow" ];
1550 case "ai_tank_drop":
1551 case "inventory_ai_tank_drop":
1552 crate.crateType = level.crateTypes[ killstreak ][
"ai_tank_drop" ];
1554 case "minigun_drop":
1555 case "inventory_minigun_drop":
1556 crate.crateType = level.crateTypes[ killstreak ][
"minigun" ];
1559 case "inventory_m32_drop":
1560 crate.crateType = level.crateTypes[ killstreak ][
"m32" ];
1572 if( !isdefined(
self ) )
1582 if ( isdefined(
self.friendlyObjID) )
1584 Objective_Delete(
self.friendlyObjID );
1586 self.friendlyObjID = undefined;
1589 if ( isdefined(
self.enemyObjID) )
1591 foreach( objId
in self.enemyObjID )
1593 Objective_Delete( objId );
1596 self.enemyObjID = undefined;
1599 if ( isdefined(
self.hackerObjID) )
1601 Objective_Delete(
self.hackerObjID );
1603 self.hackerObjID = undefined;
1611 if ( isdefined (
self.killcament ) )
1621 self endon(
"death");
1622 self endon(
"stationary");
1628 self.angles =
self.angles;
1629 self.origin =
self.origin;
1631 self notify(
"stationary" );
1636 self endon(
"death");
1637 self endon(
"stationary");
1657 forcePoint =
self.origin;
1659 DEFAULT( params.ksLandingVelocity, 100 );
1660 initialVelocity = ( 0, 0, -params.ksLandingVelocity / 40 );
1662 self PhysicsLaunch( forcePoint, initialVelocity );
1670 self waittill(
"stationary");
1677 const height_diff = 10;
1678 trace = GroundTrace(
self.origin + (0,0,height_diff),
self.origin + ( 0, 0, -10000 ),
false, e_ignore,
false );
1681 recordLine(
self.origin + (0,0,height_diff),
trace[
"position" ],
ORANGE,
"Animscript",
self );
1684 return Distance(
self.origin,
trace[
"position" ] );
1700 DEFAULT( params.ksThrustersOffHeight, 100 );
1701 DEFAULT( params.ksTotalDropTime, 4 );
1702 DEFAULT( params.ksAccelTimePercentage, 0.65 );
1704 accelTime = params.ksTotalDropTime * params.ksAccelTimePercentage;
1705 decelTime = params.ksTotalDropTime - accelTime;
1707 target = ( v_target_location[0], v_target_location[1], v_target_location[2] + params.ksThrustersOffHeight );
1710 crate moveto( target, params.ksTotalDropTime, accelTime, decelTime ) ;
1712 crate thread
WatchForCrateKill( v_target_location[2] +
VAL( params.ksStartCrateKillHeightFromGround, 200 ) );
1714 wait( accelTime - 0.05 );
1721 crate waittill(
"movedone" );
1735 self endon(
"entityshutdown" );
1736 self endon(
"stationary" );
1737 self endon(
"death" );
1741 while( abs(
self.velocity[2] ) > 5 )
1746 self PlaySound(
"phy_impact_supply" );
1751 self endon(
"entityshutdown" );
1752 self endon(
"stationary" );
1754 self.velocity = ( 0,0,0 );
1755 self.old_origin =
self.origin;
1757 while( isdefined(
self ) )
1759 self.velocity = (
self.origin -
self.old_origin );
1760 self.old_origin =
self.origin;
1769 forcePoint =
self.origin;
1771 initialVelocity = ( 0, 0, 0 );
1773 self PhysicsLaunch(forcePoint,initialVelocity);
1778 self waittill(
"stationary");
1783 self notify(
"supplyDropWatcher" );
1785 self endon(
"supplyDropWatcher" );
1786 self endon(
"spawned_player" );
1787 self endon(
"disconnect" );
1788 self endon(
"death" );
1789 self endon (
"grenade_timeout" );
1793 self.angles = ( 0,
self.angles[1], 90 );
1794 fuse_time = weapon.fuseTime / 1000;
1800 PlayFXOnTag( level._supply_drop_smoke_fx,
self,
"tag_fx" );
1801 proj_explosion_sound = weapon.projExplosionSound;
1810 function doSupplyDrop( weapon_instance, weapon, owner, killstreak_id, package_contents_id, context )
1812 weapon endon (
"explode" );
1813 weapon endon (
"grenade_timeout" );
1814 self endon(
"disconnect" );
1816 weapon_instance thread
watchExplode( weapon, owner, killstreak_id, package_contents_id );
1818 weapon_instance notify(
"stoppedMoving" );
1820 self thread
heliDeliverCrate( weapon_instance.origin, weapon, owner, team, killstreak_id, package_contents_id, context );
1825 self endon(
"stoppedMoving" );
1827 self waittill(
"explode", position );
1829 owner thread
heliDeliverCrate( position, weapon, owner, team, killstreak_id, package_contents_id );
1836 crate thread deleteOnOwnerLeave();
1847 crate endon(
"death" );
1854 self endon(
"death" );
1859 function dropCrate( origin, angle, killstreak, owner, team, killcamEnt, killstreak_id, package_contents_id, crate_, context )
1861 angle = ( angle[0] * 0.5, angle[1] * 0.5, angle[2] * 0.5 );
1863 if ( isdefined( crate_ ) )
1865 origin = crate_.origin;
1866 angle = crate_.angles;
1869 crate =
crateSpawn( killstreak, killstreak_id, owner, team, origin, angle );
1870 killCamEnt unlink();
1871 killCamEnt linkto( crate );
1872 crate.killcamEnt = killcamEnt;
1873 crate.killstreak_id = killstreak_id;
1874 crate.package_contents_id = package_contents_id;
1878 crate endon(
"death");
1882 trace = GroundTrace( crate.origin + ( 0, 0, -100 ), crate.origin + ( 0, 0, -10000 ),
false, crate,
false );
1883 v_target_location =
trace[
"position"];
1886 if ( GetDvarInt(
"scr_supply_drop_valid_location_debug", 0 ) )
1888 util::drawcylinder( v_target_location, context.radius, 8000, 99999999,
"stop_heli_drop_valid_location_dropped_cylinder", ( 0, 0, 0.9 ), 0.8 );
1898 if ( isdefined( crate.crateType ) && isdefined( crate.crateType.landFunctionOverride ) )
1900 [[crate.crateType.landFunctionOverride]]( crate, killstreak, owner, team, context );
1909 if( isdefined( crate.crateType ) && isdefined( crate.crateType.hint_gambler ))
1922 self endon(
"delete" );
1923 crate endon(
"death" );
1924 crate endon(
"entityshutdown" );
1925 crate endon(
"stationary" );
1927 waitBeforeRotationCheck = GetDvarFloat(
"scr_supplydrop_killcam_rot_wait", 0.5 );
1928 wait( waitBeforeRotationCheck );
1930 minCos = GetDvarFloat(
"scr_supplydrop_killcam_max_rot", 0.999 );
1934 currentDirection = VectorNormalize( AnglesToForward( crate.angles ) );
1936 while( cosine > minCos )
1938 oldDirection = currentDirection;
1940 currentDirection = VectorNormalize( AnglesToForward( crate.angles ) );
1941 cosine = vectordot( oldDirection, currentDirection );
1951 crate waittill(
"captured", player, remote_hack );
1955 if ( isdefined( deleteCrate ) && !deleteCrate )
1960 playerHasEngineerPerk = player HasPerk(
"specialty_showenemyequipment" );
1963 if( ( playerHasEngineerPerk || remote_hack==
true ) &&
1965 ((level.teambased && team != player.team) || !level.teambased) )
1968 spawn_explosive_crate( crate.origin, crate.angles, category, owner, team, player, playerHasEngineerPerk );
1969 crate MakeUnusable();
1984 crate =
crateSpawn( killstreak, undefined, owner, team, origin, angle );
1985 crate SetOwner( owner );
1986 crate SetTeam( team );
1988 if ( level.teambased )
1990 crate setEnemyModel( level.crateModelBoobyTrapped );
1991 crate MakeUsable( team );
1995 crate setEnemyModel( level.crateModelEnemy );
1998 crate.hacker = hacker;
1999 crate.visibleToAll =
false;
2001 crate setHintStringForPerk(
"specialty_showenemyequipment", level.supplyDropDisarmCrate );
2006 crate.playerHasEngineerPerk = playerHasEngineerPerk;
2011 killCamEnt =
spawn(
"script_model",
self.origin + (0,0,60) );
2012 self.killcament = killcament;
2013 self waittill(
"captured", player, remote_hack );
2016 if ( !player HasPerk(
"specialty_showenemyequipment" ) && !remote_hack )
2021 if( !isdefined(
self.hacker ) )
2025 self RadiusDamage(
self.origin, 256, 300, 75,
self.hacker,
"MOD_EXPLOSIVE", GetWeapon(
"supplydrop" ) );
2026 PlayFX( level._supply_drop_explosion_fx,
self.origin );
2027 PlaySoundAtPosition(
"wpn_grenade_explode",
self.origin );
2031 PlaySoundAtPosition (
"mpl_turret_alert",
self.origin );
2042 self endon(
"death" );
2045 PlaySoundAtPosition( alias,
self.origin );
2048 interval = (interval / 1.2);
2060 crate endon(
"death" );
2061 crate endon(
"stationary" );
2063 while ( crate.origin[2] > start_kill_watch_z_threshold )
2068 stationaryThreshold = 2;
2070 maxFramesTillStationary = 20;
2071 numFramesStationary = 0;
2076 if( isdefined(
self.velocity ) )
2077 vel = abs(
self.velocity[2] );
2079 if( vel > killThreshold )
2085 if( vel < stationaryThreshold )
2086 numFramesStationary++;
2088 numFramesStationary = 0;
2090 if( numFramesStationary >= maxFramesTillStationary )
2099 self endon(
"death" );
2102 stationaryThreshold = 2;
2104 maxFramesTillStationary = 20;
2105 numFramesStationary = 0;
2109 if ( isdefined(
self.velocity ) )
2110 vel = abs(
self.velocity[2] );
2112 if ( vel > killThreshold )
2118 if ( vel < stationaryThreshold )
2119 numFramesStationary++;
2121 numFramesStationary = 0;
2123 if ( numFramesStationary >= maxFramesTillStationary )
2132 self endon(
"death" );
2133 self endon(
"stationary" );
2137 players = GetPlayers();
2140 for ( i = 0; i < players.size; i++ )
2142 if ( players[i].sessionstate !=
"playing" )
2145 if ( players[i].team ==
"spectator" )
2151 if ( !IsAlive( players[i] ) )
2154 flattenedSelfOrigin = (
self.origin[0],
self.origin[1], 0 );
2155 flattenedPlayerOrigin = (players[i].origin[0], players[i].origin[1], 0 );
2157 if ( DistanceSquared( flattenedSelfOrigin, flattenedPlayerOrigin ) > 64 * 64 )
2167 start =
self.origin;
2170 start =
self GetPointInBounds( 1.0, 0.0, 0.0 );
2173 start =
self GetPointInBounds( -1.0, 0.0, 0.0 );
2176 start =
self GetPointInBounds( 0.0, -1.0, 0.0 );
2179 start =
self GetPointInBounds( 0.0, 1.0, 0.0 );
2182 start =
self GetPointInBounds( 1.0, 1.0, 0.0 );
2185 start =
self GetPointInBounds( -1.0, 1.0, 0.0 );
2188 start =
self GetPointInBounds( 1.0, -1.0, 0.0 );
2191 start =
self GetPointInBounds( -1.0, -1.0, 0.0 );
2205 end = start + ( 0, 0, -8000 );
2207 trace = BulletTrace( start,
end,
true,
self,
true,
true );
2209 if ( isdefined(
trace[
"entity" ] ) && IsPlayer(
trace[
"entity" ] ) && IsAlive(
trace[
"entity" ] ) )
2211 player =
trace[
"entity" ];
2213 if ( player.sessionstate !=
"playing" )
2216 if ( player.team ==
"spectator" )
2219 if ( DistanceSquared( start,
trace[
"position" ] ) < 12 * 12 ||
self IsTouching( player ) )
2221 player DoDamage( player.health + 1, player.origin,
self.owner,
self,
"none",
"MOD_HIT_BY_OBJECT", 0, GetWeapon(
"supplydrop" ) );
2222 player playsound (
"mpl_supply_crush" );
2223 player playsound (
"phy_impact_supply" );
2230 if ( !isdefined(
self ) )
2234 extraBoundary = ( 10, 10, 10 );
2235 players = GetPlayers();
2238 crate_bottom_point =
self.origin;
2242 foreach( player
in level.players )
2244 if( isdefined( player ) && IsAlive( player ) )
2246 stance = player GetStance();
2247 stance_z_offset = ( ( stance ==
"stand" ) ? 40 : ( ( stance ==
"crouch" ) ? 18 : 6 ) );
2248 player_test_point = player.origin + ( 0, 0, stance_z_offset );
2252 if ( ( player_test_point[2] < crate_bottom_point[2] ) &&
self IsTouching( player, extraBoundary ) )
2254 attacker = ( isdefined(
self.owner ) ?
self.owner : self );
2256 player DoDamage( player.health + 1, player.origin, attacker,
self,
"none",
"MOD_HIT_BY_OBJECT", 0, GetWeapon(
"supplydrop" ) );
2257 player playsound (
"mpl_supply_crush");
2258 player playsound (
"phy_impact_supply");
2265 vehicles = GetEntArray(
"script_vehicle",
"classname" );
2266 foreach( vehicle
in vehicles )
2268 if( IsVehicle( vehicle ) )
2270 if( isdefined( vehicle.archetype ) && ( vehicle.archetype ==
"wasp" ) )
2272 if( crate IsTouching( vehicle, ( 2, 2, 2 ) ) )
2274 vehicle notify(
"sentinel_shutdown" );
2283 if ( !isdefined(
self ) )
2286 extraBoundary = ( 10, 10, 10 );
2287 actors = GetActorArray();
2288 for( i = 0; i < actors.size; i++ )
2290 if( isdefined( actors[i] ) && isdefined( actors[i].isAiClone ) && IsAlive( actors[i] ) && ( actors[i].origin[2] <
self.origin[2] ) &&
self IsTouching( actors[i], extraBoundary ) )
2292 attacker = ( isdefined(
self.owner ) ?
self.owner : self );
2294 actors[i] DoDamage( actors[i].health + 1, actors[i].origin, attacker,
self,
"none",
"MOD_HIT_BY_OBJECT", 0, GetWeapon(
"supplydrop" ) );
2295 actors[i] playsound (
"mpl_supply_crush");
2296 actors[i] playsound (
"phy_impact_supply");
2303 extraBoundary = ( 10, 10, 10 );
2304 if( isdefined( player ) && isdefined( player.weaponObjectWatcherArray ) )
2306 for( watcher = 0; watcher < player.weaponObjectWatcherArray.size; watcher++ )
2308 objectWatcher = player.weaponObjectWatcherArray[watcher];
2309 objectArray = objectWatcher.objectArray;
2311 if( isdefined( objectArray ) )
2313 for( weaponObject = 0; weaponObject < objectArray.size; weaponObject++ )
2315 if( isdefined(objectArray[weaponObject]) &&
self IsTouching( objectArray[weaponObject], extraBoundary ) )
2317 if( isdefined(objectWatcher.onDetonateCallback) )
2335 extraBoundary = ( 15, 15, 15 );
2336 if( isdefined( player ) && isdefined( player.tacticalInsertion ) &&
self IsTouching( player.tacticalInsertion, extraBoundary ) )
2344 useEnt =
spawn(
"script_origin",
self.origin );
2345 useEnt.curProgress = 0;
2346 useEnt.inUse =
false;
2349 useEnt.owner =
self;
2358 self endon (
"death" );
2359 owner waittill (
"death" );
2367 while( isdefined(
self) )
2369 self waittill(
"trigger", player );
2371 if ( !isdefined(
self ) )
2374 if ( !isAlive( player ) )
2377 if ( !player isOnGround() )
2380 if ( isdefined(
self.owner ) &&
self.owner == player )
2387 if( isdefined(
self.hacker ) )
2389 useEnt.hacker =
self.hacker;
2392 self.useEnt = useEnt;
2396 if ( isdefined( useEnt ) )
2401 if (
result && isdefined(
self ) )
2404 self notify(
"captured", player,
false );
2411 self endon(
"joined_team");
2413 while( isdefined(
self) )
2415 self waittill(
"trigger", player );
2417 if ( !isdefined(
self ) )
2420 if ( !isAlive( player ) )
2426 if ( !isdefined(
self.owner ) )
2429 if (
self.owner != player )
2434 if (
result && isdefined(
self ) && isdefined( player ) )
2436 self notify(
"captured", player,
false );
2443 player notify (
"use_hold" );
2448 self.curProgress = 0;
2451 self.useTime = useTime;
2457 if ( isdefined( player ) )
2459 player notify(
"done_using" );
2462 if ( isdefined( player ) )
2465 if ( IsAlive(player) )
2473 if ( isdefined(
self ) )
2487 if ( !isdefined(
self ) )
2490 if (
self.curProgress >=
self.useTime )
2493 if ( !IsAlive( player ) )
2496 if ( player.throwingGrenade )
2499 if ( !(player useButtonPressed()) )
2502 if ( player meleeButtonPressed() )
2505 if ( player IsInVehicle() )
2508 if ( player IsWeaponViewOnlyLinked() )
2511 if ( player IsRemoteControlling() )
2519 level endon (
"game_ended" );
2520 self endon(
"disabled");
2521 self.owner endon(
"crate_use_interrupt" );
2529 self.curProgress += (50 *
self.useRate);
2532 if (
self.curProgress >=
self.useTime )
2538 return isAlive( player );
2550 self endon(
"death" );
2555 self waittill(
"trigger_use_doubletap", player );
2558 if ( !player HasPerk(
"specialty_showenemyequipment" ))
2562 if( isdefined(
self.useEnt ) &&
self.useEnt.inUse )
2565 if( IsDefined(
self.owner ) &&
self.owner != player )
2569 player playlocalsound (
"uin_gamble_perk");
2573 self setHintStringForPerk(
"specialty_showenemyequipment",
self.crateType.hint );
2575 self notify(
"crate_use_interrupt" );
2576 level notify(
"use_interrupt",
self );
2584 self setHintString(
self.crateType.hint );
2593 self endon(
"disconnect");
2597 if(
self HasPerk(
"specialty_showenemyequipment" ) &&
2598 object.owner !=
self &&
2599 !isdefined(
object.hacker ) &&
2600 ( ( level.teambased &&
object.owner.team !=
self.team ) || !level.teambased ) )
2603 self PlayLocalSound (
"evt_hacker_hacking" );
2605 else if(
self HasPerk(
"specialty_showenemyequipment" ) &&
2606 isdefined(
object.hacker ) &&
2607 (
object.owner ==
self ||
2608 ( level.teambased &&
object.owner.team ==
self.team ) ) )
2611 self PlayLocalSound (
"evt_hacker_hacking" );
2616 self.is_capturing_own_supply_drop = (
object.owner === self ) && ( !isdefined(
object.originalOwner ) ||
object.originalOwner == self );
2620 while ( isAlive(
self ) && isdefined(
object) &&
object.inUse && !level.gameEnded )
2622 if ( lastRate !=
object.useRate )
2624 if(
object.curProgress >
object.useTime)
2625 object.curProgress =
object.useTime;
2627 if ( !
object.useRate )
2634 barFrac =
object.curProgress /
object.useTime;
2635 rateOfChange =
object.useRate /
object.useTime;
2636 captureCrateTotalTime = 0;
2637 if ( rateOfChange > 0 )
2639 captureCrateTotalTime = ( ( 1 - barFrac ) / rateOfChange );
2646 lastRate =
object.useRate;
2650 self.is_capturing_own_supply_drop =
false;
2655 function spawn_helicopter( owner, team, origin, angles, model, targetname, killstreak_id, context )
2657 chopper = spawnHelicopter( owner, origin, angles, model, targetname );
2658 if ( !isdefined( chopper ) )
2660 if ( isplayer( owner ) )
2663 self notify(
"cleanup_marker" );
2675 chopper.maxhealth = level.heli_maxhealth;
2677 chopper.rocketDamageOneShot = chopper.maxhealth + 1;
2678 chopper.damageTaken = 0;
2681 if ( context.killstreakref ===
"inventory_ai_tank_drop" || context.killstreakref ===
"ai_tank_drop" )
2685 else if ( context.killstreakref ===
"inventory_combat_robot" || context.killstreakref ===
"combat_robot" )
2692 chopper.spawnTime = GetTime();
2695 supplydropSpeed = GetDvarInt(
"scr_supplydropSpeedStarting", 250 );
2696 supplydropAccel = GetDvarInt(
"scr_supplydropAccelStarting", 100 );
2697 chopper SetSpeed( supplydropSpeed, supplydropAccel );
2699 maxPitch = GetDvarInt(
"scr_supplydropMaxPitch", 25);
2700 maxRoll = GetDvarInt(
"scr_supplydropMaxRoll", 45 );
2701 chopper SetMaxPitchRoll( 0, maxRoll );
2703 chopper SetDrawInfrared(
true );
2705 Target_Set(chopper, ( 0, 0, -25 ));
2707 if ( isplayer( owner ) )
2723 return (0, RandomInt(360), 0);
2728 drop_direction = (0, drop_direction[1] + degrees, 0 );
2730 if( drop_direction[1] >= 360 )
2731 drop_direction = (0, drop_direction[1] - 360, 0 );
2733 return drop_direction;
2738 dist = -1 * GetDvarInt(
"scr_supplydropIncomingDistance", 15000 );
2739 pathRandomness = 100;
2740 direction = drop_direction + (0, RandomIntRange( -2, 3 ), 0);
2742 start_origin = drop_origin + ( AnglesToForward( direction ) * dist );
2743 start_origin += ( (randomfloat(2) - 1)*pathRandomness, (randomfloat(2) - 1)*pathRandomness, 0 );
2745 if ( GetDvarInt(
"scr_noflyzones_debug", 0 ) )
2747 if ( level.noFlyZones.size )
2749 index = RandomIntRange( 0, level.noFlyZones.size );
2750 delta = drop_origin - level.noFlyZones[index].origin;
2751 delta = ( delta[0] + RandomInt(10), delta[1] + RandomInt(10), 0 );
2752 delta = VectorNormalize( delta );
2753 start_origin = drop_origin + ( delta * dist );
2757 return start_origin;
2762 pathRandomness = 150;
2763 dist = -1 * GetDvarInt(
"scr_supplydropOutgoingDistance", 15000);
2766 if ( RandomIntRange(0,2) == 0 )
2767 turn = RandomIntRange( 60,121);
2769 turn = -1 * RandomIntRange( 60,121);
2771 direction = drop_direction + (0, turn, 0);
2773 end_origin = drop_origin + ( AnglesToForward( direction ) * dist );
2774 end_origin += ( (randomfloat(2) - 1)*pathRandomness , (randomfloat(2) - 1)*pathRandomness , 0 );
2781 angles = VectorToAngles( (direction[0], direction[1], 0) );
2783 offset_world = RotatePoint( offset, angles );
2785 return (point + offset_world);
2790 goalPath = SpawnStruct();
2799 direction = ( goal - goalPath.start );
2808 goalPath.path[0] = goal + goal_world_offset;
2816 goalPath = SpawnStruct();
2820 while ( tries < total_tries )
2828 if ( IsDefined( goalPath.path ) && startNoFlyZones.size == 0 )
2830 if ( goalPath.path.size > 1 )
2832 direction = ( goalPath.path[goalPath.path.size - 1] - goalPath.path[goalPath.path.size - 2] );
2836 direction = ( goalPath.path[goalPath.path.size - 1] - goalPath.start );
2838 goalPath.path[goalPath.path.size - 1] =
addOffsetOntoPoint(goalPath.path[goalPath.path.size - 1], direction, goal_offset);
2840 sphere( goalPath.path[goalPath.path.size - 1], 10, (0,0,1), 1,
true, 10, 1000 );
2855 direction = ( goal - goalPath.start );
2864 goalPath = SpawnStruct();
2866 goalPath.start = start;
2871 goalPath.path[0] = goal;
2881 goalPath = SpawnStruct();
2883 while ( tries < total_tries )
2889 if ( isdefined( goalPath.path ) )
2898 leave_nodes = getentarray(
"heli_leave",
"targetname" );
2899 foreach ( node
in leave_nodes )
2903 if ( isdefined( goalPath.path ) )
2911 goalPath.path[0] =
getHeliEnd( origin, drop_direction );
2918 if ( weapon == level.weaponNone )
2921 switch ( weapon.name )
2926 case "tow_turret_drop":
2929 case "supplydrop_marker":
2930 case "inventory_supplydrop_marker":
2934 self AddWeaponStat( GetWeapon(
"supplydrop" ),
"used", 1 );
2936 case "ai_tank_drop":
2937 case "inventory_ai_tank_drop":
2940 self AddWeaponStat( GetWeapon(
"ai_tank_drop" ),
"used", 1 );
2942 case "inventory_minigun_drop":
2943 case "minigun_drop":
2947 case "inventory_m32_drop":
2950 case "combat_robot_drop":
2960 player
util::waittill_any(
"death",
"disconnect",
"joined_team",
"joined_spectators",
"cleanup_marker" );
2968 return ( isdefined( context.dropTag ) ? chopper GetTagOrigin( context.dropTag ) + RotatePoint(
VAL( context.dropTagOffset, (0,0,0) ), chopper.angles ) : chopper.origin );
2971 function heliDeliverCrate( origin, weapon, owner, team, killstreak_id, package_contents_id, context )
2976 self notify(
"cleanup_marker" );
2981 if ( GetDvarInt(
"scr_supply_drop_valid_location_debug", 0 ) )
2983 level notify(
"stop_heli_drop_valid_location_marked_cylinder" );
2984 level notify(
"stop_heli_drop_valid_location_arrived_at_goal_cylinder" );
2985 level notify(
"stop_heli_drop_valid_location_dropped_cylinder" );
2986 util::drawcylinder( origin, context.radius, 8000, 99999999,
"stop_heli_drop_valid_location_marked_cylinder", ( 0.4, 0, 0.4 ), 0.8 );
2990 if ( !isdefined( context.marker ) )
2993 context.markerFXHandle = SpawnFx( level.killstreakCoreBundle.fxMarkedLocation, context.marker.origin + ( 0, 0, 5 ), ( 0, 0, 1 ), ( 1, 0, 0 ) );
2994 context.markerFXHandle.team = owner.team;
2995 TriggerFX( context.markerFXHandle );
2997 killstreakBundle = ( isdefined( context.killstreakType ) ? level.killstreakbundle[ context.killstreakType ] : undefined );
2998 ricochetDistance = ( isdefined( killstreakBundle ) ? killstreakBundle.ksRicochetDistance : undefined );
3001 context.marker.team = owner.team;
3007 if( isdefined( weapon ) )
3010 rear_hatch_offset_local = GetDvarInt(
"scr_supplydropOffset", 0);
3012 drop_origin = origin;
3014 drop_height += level.zOffsetCounter * 350;
3015 level.zOffsetCounter++;
3016 if( level.zOffsetCounter >= 5 )
3017 level.zOffsetCounter = 0;
3019 heli_drop_goal = ( drop_origin[0], drop_origin[1], drop_height );
3022 sphere( heli_drop_goal, 10, (0,1,0), 1,
true, 10, 1000 );
3025 goalPath = undefined;
3027 if ( IsDefined( context.dropOffset ) )
3035 goal_path_setup_needs_finishing =
true;
3038 drop_direction = VectorToAngles( (heli_drop_goal[0], heli_drop_goal[1], 0) - (goalPath.start[0], goalPath.start[1], 0));
3040 if( isdefined( context.vehiclename ) )
3041 helicopterVehicleInfo = context.vehiclename;
3043 helicopterVehicleInfo = level.vtolDropHelicopterVehicleInfo;
3049 helicopterVehicleInfo,
3051 killstreak_id, context );
3053 if ( goal_path_setup_needs_finishing ===
true )
3057 goal_path_setup_needs_finishing =
false;
3061 waitForOnlyOneDropLocation =
false;
3063 while( level.dropLocations.size > 1 && waitForOnlyOneDropLocation)
3066 ArrayRemoveValue( level.dropLocations, undefined );
3068 wait_for_drop =
false;
3069 foreach(
id, dropLocation
in level.dropLocations )
3071 if(
id < killstreak_id )
3073 wait_for_drop =
true;
3083 chopper.killstreakWeaponName = weapon.name;
3085 if( isdefined( context ) && isdefined( context.hasFlares ) )
3087 chopper.numFlares = 3;
3088 chopper.flareOffset = ( 0, 0 ,0 );
3093 chopper.numFlares = 0;
3096 killCamEnt =
spawn(
"script_model", chopper.origin + (0,0,800) );
3097 killCamEnt.angles = (100, chopper.angles[1], chopper.angles[2]);
3098 killCamEnt.startTime = gettime();
3099 killCamEnt linkTo( chopper );
3102 if ( isplayer( owner ) )
3104 Target_SetTurretAquire(
self,
false );
3108 if ( !isdefined( chopper ) )
3111 if( isdefined( context ) && isdefined( context.prolog ) )
3113 chopper [[context.prolog]]( context );
3117 chopper thread
heliDropCrate( level.killstreakWeapons[weapon], owner, rear_hatch_offset_local, killCamEnt, killstreak_id, package_contents_id, context );
3121 chopper endon(
"death");
3127 chopper waittill(
"drop_goal" );
3129 if( isdefined( context ) && isdefined( context.epilog ) )
3131 chopper [[context.epilog]]( context );
3135 PrintLn(
"Chopper Incoming Time: " + ( GetTime() - chopper.spawnTime ) );
3141 if ( GetDvarInt(
"scr_supply_drop_valid_location_debug", 0 ) )
3143 if ( isdefined( context.dropOffset ) )
3145 chopper_drop_point = chopper.origin - RotatePoint( context.dropOffset, chopper.angles );
3152 trace = GroundTrace( chopper_drop_point + ( 0, 0, -100 ), chopper_drop_point + ( 0, 0, -10000 ),
false, undefined,
false );
3153 debug_drop_location =
trace[
"position"];
3155 util::drawcylinder( debug_drop_location, context.radius, 8000, 99999999,
"stop_heli_drop_valid_location_arrived_at_goal_cylinder", ( 1.0, 0.6, 0.0 ), 0.9 );
3157 IPrintLn(
"Goal notified at 2D distance: " + Distance2D( chopper_drop_point, heli_drop_goal ) );
3162 last_distance_from_goal_squared =
SQR( 9999999.0 );
3163 continue_waiting =
true;
3164 remaining_tries = 30;
3165 while ( continue_waiting && remaining_tries > 0 )
3167 if ( isdefined( context.dropOffset ) )
3169 chopper_drop_point = chopper.origin - RotatePoint( context.dropOffset, chopper.angles );
3176 current_distance_from_goal_squared = Distance2DSquared( chopper_drop_point, heli_drop_goal );
3177 continue_waiting = ( ( current_distance_from_goal_squared < last_distance_from_goal_squared ) && ( current_distance_from_goal_squared >
SQR(
SUPPY_DROP_ON_TARGET_DISTANCE ) ) );
3178 last_distance_from_goal_squared = current_distance_from_goal_squared;
3181 if ( GetDvarInt(
"scr_supply_drop_valid_location_debug", 0 ) )
3183 sphere( chopper_drop_point, 8, ( 1, 0, 0 ), 0.9,
false, 20, 1 );
3187 if ( continue_waiting )
3190 if ( GetDvarInt(
"scr_supply_drop_valid_location_debug", 0 ) )
3192 IPrintLn(
"--- 2D distance: " + Distance2D( chopper_drop_point, heli_drop_goal ) );
3203 if ( GetDvarInt(
"scr_supply_drop_valid_location_debug", 0 ) )
3205 IPrintLn(
"Crate Dropped at 2D distance: " + Distance2D( chopper_drop_point, heli_drop_goal ) );
3209 chopper notify(
"drop_crate", chopper.origin, chopper.angles, chopper.owner);
3210 chopper.dropTime = GetTime();
3211 chopper playsound (
"veh_supply_drop");
3215 if ( isdefined( level.killstreakWeapons[weapon] ) )
3220 supplydropSpeed = GetDvarInt(
"scr_supplydropSpeedLeaving", 250 );
3221 supplydropAccel = GetDvarInt(
"scr_supplydropAccelLeaving", 60 );
3222 chopper setspeed( supplydropSpeed, supplydropAccel );
3228 PrintLn(
"Chopper Outgoing Time: " + ( GetTime() - chopper.dropTime ) );
3230 chopper notify(
"leaving" );
3237 self endon(
"leaving" );
3238 self endon(
"helicopter_gone" );
3239 self endon(
"death" );
3241 SAM_TURRET_AQUIRE_DIST = 1500;
3245 if( Distance( destination,
self.origin ) < SAM_TURRET_AQUIRE_DIST )
3248 if(
self.origin[0] > level.spawnMins[0] &&
self.origin[0] < level.spawnMaxs[0] &&
3249 self.origin[1] > level.spawnMins[1] &&
self.origin[1] < level.spawnMaxs[1] )
3255 Target_SetTurretAquire(
self,
true );
3260 self endon(
"drop_goal");
3261 self endon(
"death");
3265 supplydropSpeed = GetDvarInt(
"scr_supplydropSpeed", 400);
3266 supplydropAccel = GetDvarInt(
"scr_supplydropAccel", 60);
3267 self SetYawSpeed( 100, 60, 60 );
3268 self SetSpeed( supplydropSpeed, supplydropAccel );
3271 maxPitch = GetDvarInt(
"scr_supplydropMaxPitch", 25);
3272 maxRoll = GetDvarInt(
"scr_supplydropMaxRoll", 35 );
3273 self SetMaxPitchRoll( maxPitch, maxRoll );
3276 function heliDropCrate( killstreak, originalOwner, offset, killCamEnt, killstreak_id, package_contents_id, context )
3279 originalOwner endon (
"disconnect" );
3281 crate =
crateSpawn( killstreak, killstreak_id, originalOwner,
self.team,
self.origin,
self.angles );
3283 if ( killstreak ==
"inventory_supply_drop" || killstreak ==
"supply_drop" )
3285 crate LinkTo( helicopter,
VAL( context.dropTag,
"tag_origin" ),
VAL( context.dropTagOffset, (0,0,0) ) );
3288 else if ( killstreak ==
"inventory_ai_tank_drop" || killstreak ==
"ai_tank_drop" || killstreak ==
"ai_tank_marker" )
3290 crate LinkTo( helicopter,
VAL( context.dropTag,
"tag_origin" ),
VAL( context.dropTagOffset, (0,0,0) ) );
3296 helicopter waittill(
"drop_crate", origin, angles, chopperOwner );
3298 if ( isdefined( chopperOwner ) )
3300 owner = chopperOwner;
3302 if ( owner != originalOwner )
3310 owner = originalOwner;
3313 if ( isdefined(
self ) )
3317 if ( killstreak ==
"inventory_supply_drop" || killstreak ==
"supply_drop" )
3321 else if ( killstreak ==
"inventory_ai_tank_drop" || killstreak ==
"ai_tank_drop" )
3329 if ( isdefined( enemy ) && Distance2DSquared( origin, enemy.origin ) < enemyRadius * enemyRadius )
3335 if( team == owner.team )
3338 rear_hatch_offset_height = GetDvarInt(
"scr_supplydropOffsetHeight", 200);
3339 rear_hatch_offset_world = RotatePoint( ( offset, 0, 0), angles );
3340 drop_origin = origin - (0,0,rear_hatch_offset_height) - rear_hatch_offset_world;
3341 thread
dropCrate(drop_origin, angles, killstreak, owner, team, killCamEnt, killstreak_id, package_contents_id, crate, context );
3347 self endon(
"leaving" );
3348 self endon(
"helicopter_gone" );
3349 self endon(
"death" );
3353 if(
self.damageTaken >
self.maxhealth )
3359 if (! isdefined(
self) )
3363 self SetSpeed( 25, 5 );
3364 self thread
lbSpin( RandomIntRange(180, 220) );
3366 wait( RandomFloatRange( .5, 1.5 ) );
3368 self notify(
"drop_crate",
self.origin,
self.angles,
self.owner );
3376 forward = (
self.origin + ( 0, 0, 1 ) ) -
self.origin;
3377 playfx ( level.chopper_fx[
"explode"][
"death"],
self.origin, forward );
3380 self playSound( level.heli_sound[
"crash"] );
3381 self notify (
"explode" );
3383 if ( isdefined(
self.delete_after_destruction_wait_time ) )
3397 self endon(
"explode" );
3400 playfxontag( level.chopper_fx[
"explode"][
"large"],
self,
"tail_rotor_jnt" );
3401 playfxontag( level.chopper_fx[
"fire"][
"trail"][
"large"],
self,
"tail_rotor_jnt" );
3403 self setyawspeed( speed, speed, speed );
3404 while ( isdefined(
self ) )
3406 self settargetyaw(
self.angles[1]+(speed*0.9) );
3413 self waittill(
"death");
3415 self notify(
"cleanup_marker" );
3423 SetDvar(
"scr_supply_drop_gui",
"");
3430 devgui_string = GetDvarString(
"scr_supply_drop_gui");
3432 level.dev_gui_supply_drop = devgui_string;