Advertisement
Guest User

Untitled

a guest
Sep 19th, 2017
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 77.95 KB | None | 0 0
  1. #include maps\_utility;
  2. #include common_scripts\utility;
  3. #include maps\_zombiemode_utility;
  4. #include animscripts\zombie_Utility;
  5.  
  6. #using_animtree( "generic_human" );
  7.  
  8. init()
  9. {
  10. PrecacheRumble( "explosion_generic" );
  11.  
  12. director_precache_models();
  13.  
  14. init_director_zombie_anims();
  15.  
  16. level._effect["director_groundhit"] = loadfx("maps/zombie/fx_zombie_boss_grnd_hit");
  17. level._effect["director_spawn"] = loadfx("maps/zombie/fx_zombie_boss_spawn");
  18. level._effect["director_weapon_light"] = loadfx("maps/zombie/fx_zombie_boss_weapon_light");
  19. level._effect["director_weapon_light_big"] = loadfx("maps/zombie/fx_zombie_boss_weapon_light_big");
  20. level._effect["director_weapon_light_blink"] = loadfx("maps/zombie/fx_zombie_boss_weapon_light_blink");
  21. level._effect["director_weapon_docile"] = loadfx("maps/zombie/fx_zombie_boss_weapon_docile");
  22. level._effect["director_death_head"] = loadfx("maps/zombie/fx_zombie_boss_death_head");
  23. level._effect["director_death_torso"] = loadfx("maps/zombie/fx_zombie_boss_death_torso");
  24. level._effect["director_death_weapon"] = loadfx("maps/zombie/fx_zombie_boss_weapon_defeat");
  25. level._effect["director_impact_humangun"] = loadfx("weapon/human_gun/fx_hgun_impact_exp_lrg");
  26. level._effect["director_impact_humangun_upgraded"] = loadfx("weapon/human_gun/fx_hgun_impact_exp_lrg_ug");
  27.  
  28. // Function that will be used to calculate the value of different spawners when choosing which to use when spawning new boss
  29. // Functions that overload this, should return an int, with a higher value indicating a better spawner
  30. if( !isDefined( level.director_zombie_spawn_heuristic ) )
  31. {
  32. level.director_zombie_spawn_heuristic = maps\_zombiemode_ai_director::director_zombie_default_spawn_heuristic;
  33. }
  34.  
  35. // Function that will be used to calculate the value of different idle nodes for bosses in the "non-active" state
  36. // Functions that overload this, should return an int, with a higher value indicating a better node
  37. if( !isDefined( level.director_zombie_pathfind_heuristic ) )
  38. {
  39. level.director_zombie_pathfind_heuristic = maps\_zombiemode_ai_director::director_zombie_default_pathfind_heuristic;
  40. }
  41.  
  42. if ( !isDefined( level.director_zombie_enter_level ) )
  43. {
  44. level.director_zombie_enter_level = maps\_zombiemode_ai_director::director_zombie_default_enter_level;
  45. }
  46.  
  47. if ( !isDefined( level.director_reenter_level ) )
  48. {
  49. level.director_reenter_level = ::director_reenter_level;
  50. }
  51.  
  52. if ( !isDefined( level.director_exit_level ) )
  53. {
  54. level.director_exit_level = ::director_exit_level;
  55. }
  56.  
  57. if ( !isDefined( level.director_find_exit ) )
  58. {
  59. level.director_find_exit = ::director_find_exit;
  60. }
  61.  
  62. if ( !isDefined( level.director_devgui_health ) )
  63. {
  64. level.director_devgui_health = ::director_devgui_health;
  65. }
  66.  
  67. precacheshellshock( "electrocution" );
  68.  
  69. // Number of current active boss zombies
  70. level.num_director_zombies = 0;
  71.  
  72. level.director_zombie_spawners = GetEntArray( "boss_zombie_spawner", "targetname" );
  73. array_thread( level.director_zombie_spawners, ::add_spawn_function, maps\_zombiemode_ai_director::director_prespawn );
  74.  
  75. // Counters and timers used by the boss, can be overloaded on a level by level basis
  76. if( !isDefined( level.max_director_zombies ) )
  77. {
  78. level.max_director_zombies = 1;
  79. }
  80. if( !isDefined( level.director_zombie_health_mult ) )
  81. {
  82. level.director_zombie_health_mult = 7;
  83. }
  84. if( !isDefined( level.director_zombie_max_health ) )
  85. {
  86. level.director_zombie_max_health = 1000000;
  87. }
  88. if( !isDefined( level.director_zombie_scream_a_chance ) )
  89. {
  90. level.director_zombie_scream_a_chance = 100;
  91. }
  92. if( !isDefined( level.director_zombie_scream_a_radius ) )
  93. {
  94. level.director_zombie_scream_a_radius_sq = 1024*1024;
  95. }
  96. if( !isDefined( level.director_zombie_scream_b_chance ) )
  97. {
  98. level.director_zombie_scream_b_chance = 0;
  99. }
  100. if( !isDefined( level.director_zombie_scream_b_radius ) )
  101. {
  102. level.director_zombie_scream_b_radius_sq = 512*512;
  103. }
  104. if( !isDefined( level.director_zombie_groundhit_damage ) )
  105. {
  106. level.director_zombie_groundhit_damage = 90;
  107. }
  108. if( !isDefined( level.director_zombie_groundhit_radius ) )
  109. {
  110. level.director_zombie_groundhit_radius = 256;
  111. }
  112. if( !isDefined( level.director_zombie_proximity_wake ) )
  113. {
  114. level.director_zombie_proximity_wake = 1296;
  115. }
  116. if( !isDefined( level.director_ground_attack_delay ) )
  117. {
  118. level.director_ground_attack_delay = 5000;
  119. }
  120. if( !isDefined( level.director_max_ammo_chance_default ) )
  121. {
  122. level.director_max_ammo_chance_default = 10;
  123. }
  124. if( !isDefined( level.director_max_ammo_chance_inc ) )
  125. {
  126. level.director_max_ammo_chance_inc = 5;
  127. }
  128. if( !isDefined( level.director_max_damage_taken ) )
  129. {
  130. level.director_max_damage_taken = 250000;
  131. level.director_max_damage_taken_easy = 1000;
  132.  
  133. //if ( is_true( level.debug_director ) )
  134. //{
  135. // level.director_max_damage_taken = 1000;
  136. //}
  137. }
  138. if( !isDefined( level.director_max_speed_buff ) )
  139. {
  140. level.director_max_speed_buff = 2;
  141. }
  142.  
  143. level thread director_zombie_manager();
  144. //level thread director_zombie_update_proximity_wake();
  145. level.director_death = 0;
  146. level.director_health_reduce = 0.7;
  147.  
  148. // added for zombie speed buff
  149. level.scr_anim["zombie"]["sprint5"] = %ai_zombie_fast_sprint_01;
  150. level.scr_anim["zombie"]["sprint6"] = %ai_zombie_fast_sprint_02;
  151.  
  152. level.director_zombie_range = 480 * 480;
  153. level.director_enemy_range = 900 * 900;
  154. level.director_speed_buff_range = 300;
  155. level.director_speed_buff_range_sq = level.director_speed_buff_range * level.director_speed_buff_range;
  156. level.director_electric_buff_range = 256;
  157. level.director_electric_buff_range_sq = level.director_electric_buff_range * level.director_electric_buff_range;
  158. level.director_electrify_range_sq = 1024 * 1024;
  159. level.director_speed_buff = 0;
  160.  
  161. level thread setup_player_damage_watchers();
  162. level thread director_max_ammo_watcher();
  163. }
  164.  
  165. director_precache_models()
  166. {
  167. PrecacheModel( "t5_weapon_engineer_club" );
  168. PrecacheModel( "c_zom_george_romero_zombiefied_fb" );
  169. }
  170.  
  171. #using_animtree( "generic_human" );
  172. director_prespawn()
  173. {
  174. self.animname = "director_zombie";
  175.  
  176. self.custom_idle_setup = maps\_zombiemode_ai_director::director_zombie_idle_setup;
  177.  
  178. self.a.idleAnimOverrideArray = [];
  179. self.a.idleAnimOverrideArray["stand"] = [];
  180. self.a.idleAnimOverrideWeights["stand"] = [];
  181. self.a.idleAnimOverrideArray["stand"][0][0] = %ai_zombie_boss_idle_a_coast;
  182. self.a.idleAnimOverrideWeights["stand"][0][0] = 10;
  183. self.a.idleAnimOverrideArray["stand"][0][1] = %ai_zombie_boss_idle_b_coast;
  184. self.a.idleAnimOverrideWeights["stand"][0][1] = 10;
  185.  
  186. self.ignoreall = true;
  187. self.allowdeath = true; // allows death during animscripted calls
  188. self.is_zombie = true; // needed for melee.gsc in the animscripts
  189. self.has_legs = true; // Sumeet - This tells the zombie that he is allowed to stand anymore or not, gibbing can take
  190. // out both legs and then the only allowed stance should be prone.
  191. self allowedStances( "stand" );
  192.  
  193. self.gibbed = false;
  194. self.head_gibbed = false;
  195.  
  196. // might need this so co-op zombie players cant block zombie pathing
  197. //self PushPlayer( true );
  198.  
  199. self.disableArrivals = true;
  200. self.disableExits = true;
  201. self.grenadeawareness = 0;
  202. self.badplaceawareness = 0;
  203.  
  204. self.ignoreSuppression = true;
  205. self.suppressionThreshold = 1;
  206. self.noDodgeMove = true;
  207. self.dontShootWhileMoving = true;
  208. self.pathenemylookahead = 0;
  209.  
  210. self.badplaceawareness = 0;
  211. self.chatInitialized = false;
  212.  
  213. self.a.disablePain = true;
  214. self disable_react(); // SUMEET - zombies dont use react feature.
  215.  
  216. //self thread maps\_zombiemode_ai_director::director_zombie_think();
  217. //self thread maps\_zombiemode_ai_director::director_health_watch();
  218.  
  219. self.freezegun_damage = 0;
  220.  
  221. self.dropweapon = false;
  222. self thread maps\_zombiemode_spawner::zombie_damage_failsafe();
  223.  
  224. self thread maps\_zombiemode_spawner::delayed_zombie_eye_glow(); // delayed eye glow for ground crawlers (the eyes floated above the ground before the anim started)
  225. self.flame_damage_time = 0;
  226. self.meleeDamage = 50;
  227. self.no_powerups = true;
  228.  
  229. self.custom_damage_func = ::director_custom_damage;
  230. self.nuke_damage_func = ::director_nuke_damage;
  231. self.tesla_damage_func = ::director_tesla_damage;
  232. self.actor_full_damage_func = ::director_full_damage;
  233.  
  234. self.instakill_func = ::director_instakill;
  235. self.humangun_hit_response = ::director_humangun_hit_response;
  236. self.melee_anim_func = ::director_melee_anim;
  237. self.set_animarray_standing_override = ::director_set_animarray_standing;
  238. self.melee_miss_func = ::director_melee_miss;
  239. self.flinger_func = ::director_fling;
  240. self.non_attacker_func = ::director_non_attacker;
  241.  
  242. self.noChangeDuringMelee = true;
  243. self.ignore_enemy_count = true;
  244. self.ignore_water_damage = true;
  245. self.ignore_speed_buff = true;
  246.  
  247. self.ignore_devgui_death = true;
  248.  
  249. self.no_damage_points = true;
  250. self.electrified = true;
  251. self.ground_hit = false;
  252. self.nextGroundHit = 0;
  253.  
  254. self.can_move_with_bolt = true;
  255. self.ignore_all_poi = true;
  256.  
  257. self.check_melee_path = true;
  258. self.allowpain = false;
  259.  
  260. self setTeamForEntity( "axis" );
  261.  
  262. //self setPhysParams( 15, 0, 72 );
  263.  
  264. if ( isDefined( level.director_init_done ) )
  265. {
  266. self thread [[ level.director_init_done ]]();
  267. }
  268.  
  269. level.zombie_director = self;
  270.  
  271. self notify( "zombie_init_done" );
  272. }
  273.  
  274. director_health_watch()
  275. {
  276. self endon( "death" );
  277.  
  278. while ( 1 )
  279. {
  280. /#
  281. iprintln( "health = " + self.health );
  282. #/
  283.  
  284. wait( 1 );
  285. }
  286. }
  287.  
  288. director_zombie_idle_setup()
  289. {
  290. self.a.array["turn_left_45"] = %exposed_tracking_turn45L;
  291. self.a.array["turn_left_90"] = %exposed_tracking_turn90L;
  292. self.a.array["turn_left_135"] = %exposed_tracking_turn135L;
  293. self.a.array["turn_left_180"] = %exposed_tracking_turn180L;
  294. self.a.array["turn_right_45"] = %exposed_tracking_turn45R;
  295. self.a.array["turn_right_90"] = %exposed_tracking_turn90R;
  296. self.a.array["turn_right_135"] = %exposed_tracking_turn135R;
  297. self.a.array["turn_right_180"] = %exposed_tracking_turn180L;
  298. self.a.array["exposed_idle"] = array( %ai_zombie_boss_idle_a_coast, %ai_zombie_boss_idle_b_coast );
  299. self.a.array["straight_level"] = %ai_zombie_boss_idle_a_coast;
  300. self.a.array["stand_2_crouch"] = %ai_zombie_shot_leg_right_2_crawl;
  301. }
  302.  
  303. init_director_zombie_anims()
  304. {
  305. // deaths
  306. level.scr_anim["director_zombie"]["death1"] = %ai_zombie_boss_death_coast;
  307. level.scr_anim["director_zombie"]["death2"] = %ai_zombie_boss_death_a_coast;
  308. level.scr_anim["director_zombie"]["death3"] = %ai_zombie_boss_death_explode_coast;
  309. level.scr_anim["director_zombie"]["death4"] = %ai_zombie_boss_death_mg_coast;
  310.  
  311. // run cycles
  312.  
  313. level.scr_anim["director_zombie"]["walk1"] = %ai_zombie_boss_walk_slow_coast;
  314. level.scr_anim["director_zombie"]["walk2"] = %ai_zombie_boss_walk_a_coast;
  315.  
  316. level.scr_anim["director_zombie"]["run1"] = %ai_zombie_walk_fast_v1;
  317. level.scr_anim["director_zombie"]["run2"] = %ai_zombie_walk_fast_v2;
  318. level.scr_anim["director_zombie"]["run3"] = %ai_zombie_walk_fast_v3;
  319. level.scr_anim["director_zombie"]["run4"] = %ai_zombie_run_v2;
  320. level.scr_anim["director_zombie"]["run5"] = %ai_zombie_run_v4;
  321. level.scr_anim["director_zombie"]["run6"] = %ai_zombie_run_v3;
  322.  
  323. level.scr_anim["director_zombie"]["sprint1"] = %ai_zombie_boss_sprint_a_coast;
  324. level.scr_anim["director_zombie"]["sprint2"] = %ai_zombie_boss_sprint_a_coast;
  325. level.scr_anim["director_zombie"]["sprint3"] = %ai_zombie_boss_sprint_b_coast;
  326. level.scr_anim["director_zombie"]["sprint4"] = %ai_zombie_boss_sprint_b_coast;
  327.  
  328. // run cycles in prone
  329. level.scr_anim["director_zombie"]["crawl1"] = %ai_zombie_crawl;
  330. level.scr_anim["director_zombie"]["crawl2"] = %ai_zombie_crawl_v1;
  331. level.scr_anim["director_zombie"]["crawl3"] = %ai_zombie_crawl_v2;
  332. level.scr_anim["director_zombie"]["crawl4"] = %ai_zombie_crawl_v3;
  333. level.scr_anim["director_zombie"]["crawl5"] = %ai_zombie_crawl_v4;
  334. level.scr_anim["director_zombie"]["crawl6"] = %ai_zombie_crawl_v5;
  335. level.scr_anim["director_zombie"]["crawl_hand_1"] = %ai_zombie_walk_on_hands_a;
  336. level.scr_anim["director_zombie"]["crawl_hand_2"] = %ai_zombie_walk_on_hands_b;
  337.  
  338. level.scr_anim["director_zombie"]["crawl_sprint1"] = %ai_zombie_crawl_sprint;
  339. level.scr_anim["director_zombie"]["crawl_sprint2"] = %ai_zombie_crawl_sprint_1;
  340. level.scr_anim["director_zombie"]["crawl_sprint3"] = %ai_zombie_crawl_sprint_2;
  341.  
  342. // transitions
  343. level.scr_anim["director_zombie"]["walk2sprint"] = %ai_zombie_boss_walk_2_sprint_coast;
  344. level.scr_anim["director_zombie"]["sprint2walk"] = %ai_zombie_boss_sprint_2_walk_coast;
  345.  
  346.  
  347. if( !isDefined( level._zombie_melee ) )
  348. {
  349. level._zombie_melee = [];
  350. }
  351. if( !isDefined( level._zombie_walk_melee ) )
  352. {
  353. level._zombie_walk_melee = [];
  354. }
  355. if( !isDefined( level._zombie_run_melee ) )
  356. {
  357. level._zombie_run_melee = [];
  358. }
  359. level._zombie_melee["director_zombie"] = [];
  360. level._zombie_walk_melee["director_zombie"] = [];
  361. level._zombie_run_melee["director_zombie"] = [];
  362.  
  363. level._zombie_melee["director_zombie"][0] = %ai_zombie_boss_attack_multiswing_a_coast;
  364. level._zombie_melee["director_zombie"][1] = %ai_zombie_boss_attack_multiswing_b_coast;
  365. level._zombie_melee["director_zombie"][2] = %ai_zombie_boss_attack_swing_overhead_coast;
  366. level._zombie_melee["director_zombie"][3] = %ai_zombie_boss_attack_swing_swipe_coast;
  367.  
  368. if( isDefined( level.director_zombie_anim_override ) )
  369. {
  370. [[ level.director_zombie_anim_override ]]();
  371. }
  372.  
  373. //level._zombie_walk_melee["director_zombie"][0] = %ai_zombie_boss_walk_headhit;
  374.  
  375. level._zombie_run_melee["director_zombie"][0] = %ai_zombie_boss_attack_running_coast;
  376. level._zombie_run_melee["director_zombie"][1] = %ai_zombie_boss_attack_sprinting_coast;
  377. level._zombie_run_melee["director_zombie"][2] = %ai_zombie_boss_attack_running_coast;
  378.  
  379. // melee in crawl
  380. if( !isDefined( level._zombie_melee_crawl ) )
  381. {
  382. level._zombie_melee_crawl = [];
  383. }
  384. level._zombie_melee_crawl["director_zombie"] = [];
  385. level._zombie_melee_crawl["director_zombie"][0] = %ai_zombie_attack_crawl;
  386. level._zombie_melee_crawl["director_zombie"][1] = %ai_zombie_attack_crawl_lunge;
  387.  
  388. if( !isDefined( level._zombie_stumpy_melee ) )
  389. {
  390. level._zombie_stumpy_melee = [];
  391. }
  392. level._zombie_stumpy_melee["director_zombie"] = [];
  393. level._director_zombie_stumpy_melee["director_zombie"][0] = %ai_zombie_walk_on_hands_shot_a;
  394. level._director_zombie_stumpy_melee["director_zombie"][1] = %ai_zombie_walk_on_hands_shot_b;
  395.  
  396. // tesla deaths
  397. if( !isDefined( level._zombie_tesla_deaths ) )
  398. {
  399. level._zombie_tesla_deaths = [];
  400. }
  401. level._zombie_tesla_death["director_zombie"] = [];
  402. level._zombie_tesla_death["director_zombie"][0] = %ai_zombie_boss_tesla_death_a_coast;
  403. level._zombie_tesla_death["director_zombie"][1] = %ai_zombie_boss_tesla_death_a_coast;
  404. level._zombie_tesla_death["director_zombie"][2] = %ai_zombie_boss_tesla_death_a_coast;
  405. level._zombie_tesla_death["director_zombie"][3] = %ai_zombie_boss_tesla_death_a_coast;
  406. level._zombie_tesla_death["director_zombie"][4] = %ai_zombie_boss_tesla_death_a_coast;
  407.  
  408. if( !isDefined( level._zombie_tesla_crawl_death ) )
  409. {
  410. level._zombie_tesla_crawl_death = [];
  411. }
  412. level._zombie_tesla_crawl_death["director_zombie"] = [];
  413. level._zombie_tesla_crawl_death["director_zombie"][0] = %ai_zombie_tesla_crawl_death_a;
  414. level._zombie_tesla_crawl_death["director_zombie"][1] = %ai_zombie_tesla_crawl_death_b;
  415.  
  416. // deaths
  417. if( !isDefined( level._zombie_deaths ) )
  418. {
  419. level._zombie_deaths = [];
  420. }
  421. level._zombie_deaths["director_zombie"] = [];
  422. level._zombie_deaths["director_zombie"][0] = %ai_zombie_boss_death_coast;
  423. level._zombie_deaths["director_zombie"][1] = %ai_zombie_boss_death_a_coast;
  424. level._zombie_deaths["director_zombie"][2] = %ai_zombie_boss_death_explode_coast;
  425. level._zombie_deaths["director_zombie"][3] = %ai_zombie_boss_death_mg_coast;
  426.  
  427. /*
  428. ground crawl
  429. */
  430.  
  431. // set up the arrays
  432. if( !isDefined( level._zombie_rise_anims ) )
  433. {
  434. level._zombie_rise_anims = [];
  435. }
  436.  
  437. level._zombie_rise_anims["director_zombie"] = [];
  438.  
  439. level._zombie_rise_anims["director_zombie"][1]["walk"][0] = %ai_zombie_traverse_ground_v1_walk;
  440.  
  441. level._zombie_rise_anims["director_zombie"][1]["run"][0] = %ai_zombie_traverse_ground_v1_run;
  442.  
  443. level._zombie_rise_anims["director_zombie"][1]["sprint"][0] = %ai_zombie_traverse_ground_climbout_fast;
  444.  
  445. level._zombie_rise_anims["director_zombie"][2]["walk"][0] = %ai_zombie_traverse_ground_v2_walk_altA;
  446.  
  447. // ground crawl death
  448. if( !isDefined( level._zombie_rise_death_anims ) )
  449. {
  450. level._zombie_rise_death_anims = [];
  451. }
  452. level._zombie_rise_death_anims["director_zombie"] = [];
  453.  
  454. level._zombie_rise_death_anims["director_zombie"][1]["in"][0] = %ai_zombie_traverse_ground_v1_deathinside;
  455. level._zombie_rise_death_anims["director_zombie"][1]["in"][1] = %ai_zombie_traverse_ground_v1_deathinside_alt;
  456.  
  457. level._zombie_rise_death_anims["director_zombie"][1]["out"][0] = %ai_zombie_traverse_ground_v1_deathoutside;
  458. level._zombie_rise_death_anims["director_zombie"][1]["out"][1] = %ai_zombie_traverse_ground_v1_deathoutside_alt;
  459.  
  460. level._zombie_rise_death_anims["director_zombie"][2]["in"][0] = %ai_zombie_traverse_ground_v2_death_low;
  461. level._zombie_rise_death_anims["director_zombie"][2]["in"][1] = %ai_zombie_traverse_ground_v2_death_low_alt;
  462.  
  463. level._zombie_rise_death_anims["director_zombie"][2]["out"][0] = %ai_zombie_traverse_ground_v2_death_high;
  464. level._zombie_rise_death_anims["director_zombie"][2]["out"][1] = %ai_zombie_traverse_ground_v2_death_high_alt;
  465.  
  466. //taunts
  467. if( !isDefined( level._zombie_run_taunt ) )
  468. {
  469. level._zombie_run_taunt = [];
  470. }
  471. if( !isDefined( level._zombie_board_taunt ) )
  472. {
  473. level._zombie_board_taunt = [];
  474. }
  475.  
  476. level._zombie_run_taunt["director_zombie"] = [];
  477. level._zombie_board_taunt["director_zombie"] = [];
  478.  
  479. level._zombie_board_taunt["director_zombie"][0] = %ai_zombie_taunts_4;
  480. level._zombie_board_taunt["director_zombie"][1] = %ai_zombie_taunts_7;
  481. level._zombie_board_taunt["director_zombie"][2] = %ai_zombie_taunts_9;
  482. level._zombie_board_taunt["director_zombie"][3] = %ai_zombie_taunts_5b;
  483. level._zombie_board_taunt["director_zombie"][4] = %ai_zombie_taunts_5c;
  484. level._zombie_board_taunt["director_zombie"][5] = %ai_zombie_taunts_5d;
  485. level._zombie_board_taunt["director_zombie"][6] = %ai_zombie_taunts_5e;
  486. level._zombie_board_taunt["director_zombie"][7] = %ai_zombie_taunts_5f;
  487. }
  488.  
  489. director_zombie_spawn()
  490. {
  491. self.script_moveoverride = true;
  492.  
  493. if( !isDefined( level.num_director_zombies ) )
  494. {
  495. level.num_director_zombies = 0;
  496. }
  497. level.num_director_zombies++;
  498.  
  499. director_zombie = self maps\_zombiemode_net::network_safe_stalingrad_spawn( "boss_zombie_spawn", 1 );
  500. director_zombie Hide();
  501.  
  502. //Sound - Shawn J - adding boss spawn sound - note: sound is played in 2d so it doesn't matter what it's played off of.
  503. //iprintlnbold( "Boss_Spawning!" );
  504. //self playsound( "zmb_engineer_spawn" );
  505.  
  506. self.count = 666;
  507.  
  508. self.last_spawn_time = GetTime();
  509.  
  510. if( !spawn_failed( director_zombie ) )
  511. {
  512. director_zombie.script_noteworthy = self.script_noteworthy;
  513. director_zombie.targetname = self.targetname;
  514. director_zombie.target = self.target;
  515. director_zombie.deathFunction = maps\_zombiemode_ai_director::director_zombie_die;
  516. director_zombie.animname = "director_zombie";
  517.  
  518. director_zombie thread director_zombie_think();
  519. }
  520. else
  521. {
  522. level.num_director_zombies--;
  523. }
  524. }
  525.  
  526. director_zombie_manager()
  527. {
  528. // check for one start boss spawner before anything else
  529. start_boss = getent( "start_boss_spawner", "script_noteworthy" );
  530. if ( isDefined( start_boss ) )
  531. {
  532. while ( true )
  533. {
  534. if ( level.num_director_zombies < level.max_director_zombies )
  535. {
  536. start_boss director_zombie_spawn();
  537. break;
  538. }
  539. wait( 0.5 );
  540. }
  541. }
  542.  
  543. while( true )
  544. {
  545. AssertEx( isDefined( level.num_director_zombies ) && isDefined( level.max_director_zombies ), "Either max_director_zombies or num_director_zombies not defined, this should never be the case!" );
  546. while( level.num_director_zombies < level.max_director_zombies )
  547. {
  548. spawner = director_zombie_pick_best_spawner();
  549. if( isDefined( spawner ) )
  550. {
  551. spawner director_zombie_spawn();
  552. }
  553. wait( 10 );
  554. }
  555. wait( 10 );
  556. }
  557. }
  558.  
  559. director_zombie_pick_best_spawner()
  560. {
  561. best_spawner = undefined;
  562. best_score = -1;
  563. for( i = 0; i < level.director_zombie_spawners.size; i++ )
  564. {
  565. score = [[ level.director_zombie_spawn_heuristic ]]( level.director_zombie_spawners[i] );
  566. if( score > best_score )
  567. {
  568. best_spawner = level.director_zombie_spawners[i];
  569. best_score = score;
  570. }
  571. }
  572. return best_spawner;
  573. }
  574.  
  575. show_damage()
  576. {
  577. while ( 1 )
  578. {
  579. iprintln( "damage = " + self.dmg_taken );
  580. wait( 1 );
  581. }
  582. }
  583.  
  584. director_display_damage()
  585. {
  586. self endon( "death" );
  587.  
  588. while ( 1 )
  589. {
  590. display = GetDvarInt( #"scr_director_display_damage" );
  591. if ( display )
  592. {
  593. print3d( self.origin + ( 0, 0, 72 ), "Damage " + self.dmg_taken, ( 1, 1, 1 ), 1, 1, 10 );
  594. }
  595. wait( .5 );
  596. }
  597. }
  598.  
  599. director_devgui_health()
  600. {
  601. if ( isDefined( level.zombie_director ) )
  602. {
  603. level.zombie_director director_reset_health( true );
  604. }
  605. }
  606.  
  607. director_reset_health( easy )
  608. {
  609. players = getplayers();
  610. num_players = players.size;
  611.  
  612. self.max_damage_taken = level.director_max_damage_taken * num_players;
  613. if ( is_true( easy ) )
  614. {
  615. self.max_damage_taken = level.director_max_damage_taken_easy * num_players;
  616. }
  617.  
  618. self.damage_one = self.max_damage_taken * .33;
  619. self.damage_two = self.max_damage_taken * .66;
  620.  
  621. director_print( "reset damage " + self.max_damage_taken );
  622. }
  623.  
  624. director_flip_light_flag()
  625. {
  626. if ( !is_true( self.director_light_set ) )
  627. {
  628. self.director_light_set = true;
  629. self setclientflag( level._ZOMBIE_ACTOR_FLAG_DIRECTOR_LIGHT );
  630. }
  631. else
  632. {
  633. self.director_light_set = undefined;
  634. self clearclientflag( level._ZOMBIE_ACTOR_FLAG_DIRECTOR_LIGHT );
  635. }
  636. }
  637.  
  638. director_reset_light_flag()
  639. {
  640. self endon( "death" );
  641.  
  642. if ( self.health_state == "pristine" )
  643. {
  644. self director_flip_light_flag();
  645. wait( 0.25 );
  646. self director_flip_light_flag();
  647. wait( 0.25 );
  648. self director_flip_light_flag();
  649. wait( 0.25 );
  650. self director_flip_light_flag();
  651. }
  652. else if ( self.health_state == "full" )
  653. {
  654. self director_flip_light_flag();
  655. wait( 0.25 );
  656. self director_flip_light_flag();
  657. wait( 0.25 );
  658. self director_flip_light_flag();
  659. }
  660. else if ( self.health_state == "damage_one" )
  661. {
  662. self director_flip_light_flag();
  663. wait( 0.25 );
  664. self director_flip_light_flag();
  665. }
  666. else if ( self.health_state == "damage_two" )
  667. {
  668. self director_flip_light_flag();
  669. }
  670. }
  671.  
  672. director_watch_damage()
  673. {
  674. self endon( "death" );
  675. self endon( "humangun_leave" );
  676.  
  677. self.dmg_taken = 0;
  678.  
  679. /#
  680. self thread director_display_damage();
  681. #/
  682.  
  683. //self thread show_damage();
  684. self director_reset_health( false );
  685.  
  686. self.health_state = "pristine";
  687.  
  688. while ( 1 )
  689. {
  690. self waittill( "damage", amount, attacker, direction, point, method );
  691.  
  692. if ( !is_true( self.start_zombies ) )
  693. {
  694. self.start_zombies = true;
  695. self notify( "director_spawn_zombies" );
  696. }
  697.  
  698. if ( is_true( self.leaving_level ) )
  699. {
  700. return;
  701. }
  702.  
  703. self.dmg_taken += amount;
  704.  
  705. if ( self.health_state == "pristine" )
  706. {
  707. self.health_state = "full";
  708. self director_flip_light_flag();
  709. }
  710. else if ( self.health_state == "full" && self.dmg_taken >= self.damage_one )
  711. {
  712. self.health_state = "damage_one";
  713. self director_flip_light_flag();
  714.  
  715. if( IsDefined( level._audio_director_vox_play ) )
  716. {
  717. rand = RandomIntRange( 0, 5 );
  718. self thread [[ level._audio_director_vox_play ]]( "vox_romero_weaken_" + rand, .25 );
  719. }
  720.  
  721. if( IsDefined( attacker ) && IsPlayer( attacker ) )
  722. {
  723. attacker thread maps\_zombiemode_audio::create_and_play_dialog( "director", "weaken" );
  724. }
  725. }
  726. else if ( self.health_state == "damage_one" && self.dmg_taken >= self.damage_two )
  727. {
  728. self.health_state = "damage_two";
  729. self.light StopLoopSound(2);
  730. self director_flip_light_flag();
  731.  
  732. if( IsDefined( level._audio_director_vox_play ) )
  733. {
  734. rand = RandomIntRange( 0, 5 );
  735. self thread [[ level._audio_director_vox_play ]]( "vox_romero_weaken_" + rand, .25 );
  736. }
  737.  
  738. if( IsDefined( attacker ) && IsPlayer( attacker ) )
  739. {
  740. attacker thread maps\_zombiemode_audio::create_and_play_dialog( "director", "weaken" );
  741. }
  742. }
  743.  
  744. if ( self.dmg_taken >= self.max_damage_taken )
  745. {
  746. self director_flip_light_flag();
  747. break;
  748. }
  749.  
  750. if ( is_true( self.in_water ) )
  751. {
  752. wait_network_frame();
  753. if ( !is_true( self.leaving_level ) && !is_true( self.entering_level ) && !is_true( self.sprint2walk ) )
  754. {
  755. self thread director_scream_in_water();
  756. }
  757. }
  758. }
  759.  
  760. self setclientflag( level._ZOMBIE_ACTOR_FLAG_DIRECTOR_DEATH );
  761.  
  762. if ( is_true( self.is_sliding ) )
  763. {
  764. self.skip_stumble = true;
  765. self waittill( "zombie_end_traverse" );
  766. }
  767.  
  768. self notify( "director_exit" );
  769.  
  770. self.defeated = true;
  771.  
  772. self notify( "disable_activation" );
  773. self notify( "disable_buff" );
  774.  
  775. self notify( "stop_find_flesh" );
  776. self notify( "zombie_acquire_enemy" );
  777.  
  778. self.ignoreall = true;
  779.  
  780. if ( is_true( self.is_traversing ) )
  781. {
  782. self.skip_stumble = true;
  783. self waittill( "zombie_end_traverse" );
  784. }
  785.  
  786. level notify( "director_submerging_audio" );
  787.  
  788. if( IsDefined( level._audio_director_vox_play ) )
  789. {
  790. self thread [[ level._audio_director_vox_play ]]( "vox_director_die", .25, true );
  791. }
  792.  
  793. if ( is_true( self.skip_stumble ) )
  794. {
  795. self.skip_stumble = undefined;
  796. }
  797. else
  798. {
  799. self animcustom( ::director_custom_stumble );
  800. self waittill_notify_or_timeout( "stumble_done", 7.2 );
  801. }
  802.  
  803. if ( isdefined( level.director_should_drop_special_powerup ) && [[level.director_should_drop_special_powerup]]() )
  804. {
  805. level thread maps\_zombiemode_powerups::specific_powerup_drop( "tesla", self.origin );
  806. }
  807. else
  808. {
  809. level thread maps\_zombiemode_powerups::specific_powerup_drop( "minigun", self.origin );
  810. }
  811.  
  812. forward = VectorNormalize( AnglesToForward( self.angles ) );
  813. end_pos = self.origin - vector_scale( forward, 32 );
  814.  
  815. level thread maps\_zombiemode_powerups::specific_powerup_drop( "free_perk", end_pos );
  816.  
  817. level notify( "quiet_on_the_set_achieved" );
  818.  
  819. exit = self thread [[ level.director_find_exit ]]();
  820. self thread director_leave_map( exit, self.in_water );
  821. }
  822.  
  823. //-----------------------------------------------------------------------------------------------
  824. // stumble anim and fx
  825. //-----------------------------------------------------------------------------------------------
  826. director_custom_stumble()
  827. {
  828. director_print( "custom stumble" );
  829.  
  830. stumble_anim = %ai_zombie_boss_stumble_coast;
  831.  
  832. self thread director_stumble_watcher( "stumble_anim" );
  833.  
  834. self SetFlaggedAnimKnobAllRestart( "stumble_anim", stumble_anim, %body, 1, .1, 1 );
  835. animscripts\traverse\zombie_shared::wait_anim_length( stumble_anim, .02 );
  836.  
  837. self notify( "stumble_done" );
  838. }
  839.  
  840. director_stumble_watcher( animname )
  841. {
  842. self endon( "death" );
  843.  
  844. self waittillmatch( animname, "weapon_fx" );
  845.  
  846. playfxontag( level._effect["director_death_weapon"], self, "tag_light" );
  847. }
  848.  
  849. //-----------------------------------------------------------------------------------------------
  850. // reaction when shot in water
  851. //-----------------------------------------------------------------------------------------------
  852. director_scream_in_water()
  853. {
  854. self endon( "death" );
  855.  
  856. if ( !isDefined( self.water_scream ) )
  857. {
  858. self.water_scream = true;
  859.  
  860. if ( is_true( self.is_melee ) )
  861. {
  862. while ( 1 )
  863. {
  864. if ( !is_true( self.is_melee ) )
  865. {
  866. break;
  867. }
  868. wait_network_frame();
  869. }
  870. }
  871.  
  872. if( IsDefined( level._audio_director_vox_play ) )
  873. {
  874. self thread [[ level._audio_director_vox_play ]]( "vox_director_pain_yell", .25, true );
  875. }
  876.  
  877. //scream_anim = %ai_zombie_boss_enrage_start_scream_coast;
  878. scream_anim = %ai_zombie_boss_nuke_react_coast;
  879.  
  880. self thread director_scream_delay();
  881. //self thread scream_a_watcher( "scream_anim" );
  882.  
  883. self thread director_zombie_sprint_watcher( "scream_anim" );
  884. self director_animscripted( scream_anim, "scream_anim" );
  885.  
  886. wait( 3 );
  887.  
  888. self.water_scream = undefined;
  889. }
  890. }
  891.  
  892. director_scream_delay()
  893. {
  894. wait( 2.6 );
  895. clientnotify( "ZDA" );
  896. self thread director_blur();
  897. }
  898.  
  899. director_blur()
  900. {
  901. self endon( "death" );
  902.  
  903. players = getplayers();
  904.  
  905. for ( i = 0; i < players.size; i++ )
  906. {
  907. player = players[i];
  908. player ShellShock( "electrocution", 1.7, true );
  909. }
  910. }
  911.  
  912. //-----------------------------------------------------------------------------------------------
  913. // main ai for the director
  914. //-----------------------------------------------------------------------------------------------
  915. director_zombie_think()
  916. {
  917. self endon( "death" );
  918.  
  919. //self.goalradius = 128;
  920. //self.pathEnemyFightDist = 64;
  921. //self.meleeAttackDist = 64;
  922. self.pathEnemyFightDist = 96;
  923. self.meleeAttackDist = 96;
  924.  
  925. self.maxhealth = level.director_zombie_max_health;
  926. self.health = level.director_zombie_max_health;
  927.  
  928. //try to prevent always turning towards the enemy
  929. self.maxsightdistsqrd = 96 * 96;
  930.  
  931. self.is_activated = false;
  932. self.entering_level = true;
  933. self.zombie_move_speed = "walk";
  934.  
  935. self director_zombie_choose_buff();
  936.  
  937. self [[ level.director_zombie_enter_level ]]();
  938.  
  939. level notify( "audio_begin_director_vox" );
  940.  
  941. self thread director_watch_damage();
  942. self thread zombie_melee_watcher();
  943. self thread director_zombie_update_goal_radius();
  944. self thread director_kill_prone();
  945.  
  946. self.ignoreall = false;
  947.  
  948. if ( isDefined( level.director_zombie_custom_think ) )
  949. {
  950. self thread [[ level.director_zombie_custom_think ]]();
  951. }
  952.  
  953. //self thread director_zombie_check_for_activation();
  954. self thread director_zombie_check_for_buff();
  955. //self thread director_zombie_check_player_proximity();
  956. self thread director_zombie_choose_run();
  957. self thread director_zombie_health_manager();
  958.  
  959. self SetClientFlag( level._ZOMBIE_ACTOR_FLAG_DIRECTORS_STEPS ); // director's footsteps, handled by csc
  960.  
  961. self.entering_level = undefined;
  962.  
  963. self BloodImpact( "hero" );
  964.  
  965. self thread director_zombie_update();
  966. }
  967.  
  968. //-----------------------------------------------------------------------------------------------
  969. // director main update loop
  970. //-----------------------------------------------------------------------------------------------
  971. director_zombie_update()
  972. {
  973. self endon( "death" );
  974. self endon( "director_exit" );
  975.  
  976. while( true )
  977. {
  978. if ( is_true( self.custom_think ) )
  979. {
  980. wait_network_frame();
  981. continue;
  982. }
  983. else if ( is_true( self.defeated ) )
  984. {
  985. wait( 5 );
  986. continue;
  987. }
  988. else if ( is_true( self.performing_activation ) )
  989. {
  990. wait_network_frame();
  991. continue;
  992. }
  993. else if ( is_true( self.ground_hit ) )
  994. {
  995. wait_network_frame();
  996. continue;
  997. }
  998. else if ( !is_true( self.following_player ) )
  999. {
  1000. self thread maps\_zombiemode_spawner::find_flesh();
  1001. self.following_player = true;
  1002. }
  1003. wait( 1 );
  1004. }
  1005. }
  1006.  
  1007. //-----------------------------------------------------------------------------------------------
  1008. // prop light the director holds
  1009. //-----------------------------------------------------------------------------------------------
  1010. director_add_weapon()
  1011. {
  1012. self Attach( "t5_weapon_engineer_club", "tag_weapon_right" );
  1013.  
  1014. self.light = Spawn( "script_model", self GetTagOrigin( "tag_light" ) );
  1015. self.light PlayLoopSound("zmb_director_light_docile_loop", 2 );
  1016. self.light.angles = self GetTagAngles( "tag_light" );
  1017. self.light SetModel( "tag_origin" );
  1018. self.light LinkTo( self, "tag_light" );
  1019.  
  1020. wait_network_frame();
  1021. wait_network_frame();
  1022. self director_flip_light_flag();
  1023. }
  1024.  
  1025. //-----------------------------------------------------------------------------------------------
  1026. // decide which buff to use
  1027. //-----------------------------------------------------------------------------------------------
  1028. director_zombie_choose_buff()
  1029. {
  1030. if ( is_true( self.ground_hit ) || GetTime() < self.nextGroundHit || !self.is_activated )
  1031. {
  1032. self.buff = "speed";
  1033. }
  1034. else
  1035. {
  1036. rand = RandomInt( 100 );
  1037. if ( rand < 50 )
  1038. {
  1039. self.buff = "electric";
  1040. }
  1041. else
  1042. {
  1043. self.buff = "speed";
  1044. }
  1045. }
  1046.  
  1047. //director_print( "next buff is " + self.buff );
  1048. }
  1049.  
  1050. director_zombie_default_pathfind_heuristic( node )
  1051. {
  1052. // Skip any nodes that don't have a zone or whose zones are not yet active
  1053. if( !isDefined( node.targetname ) || !isDefined( level.zones[node.targetname] ) )
  1054. {
  1055. return -1;
  1056. }
  1057.  
  1058. players = get_players();
  1059. score = 0;
  1060.  
  1061. for( i = 0; i < players.size; i++ )
  1062. {
  1063. dist = distanceSquared( node.origin, players[i].origin );
  1064. if( dist > 10000*10000 )
  1065. {
  1066. dist = 10000*10000;
  1067. }
  1068. if( dist <= 1 )
  1069. {
  1070. score += 10000*10000;
  1071. continue;
  1072. }
  1073. score += int( 10000*10000/dist );
  1074. }
  1075.  
  1076. return score;
  1077. }
  1078.  
  1079. // Weight the spawner based on the position where a director_zombie died
  1080. director_zombie_default_spawn_heuristic( spawner )
  1081. {
  1082. if( isDefined( spawner.last_spawn_time ) && (GetTime() - spawner.last_spawn_time < 30000) )
  1083. {
  1084. return -1;
  1085. }
  1086.  
  1087. if( !isDefined( spawner.script_noteworthy ) )
  1088. {
  1089. return -1;
  1090. }
  1091.  
  1092. if( !isDefined( level.zones ) || !isDefined( level.zones[ spawner.script_noteworthy ] ) || !level.zones[ spawner.script_noteworthy ].is_enabled )
  1093. {
  1094. return -1;
  1095. }
  1096.  
  1097. score = 0;
  1098.  
  1099. // if we don't have a position, give score relative to player positions, farther is better
  1100. players = get_players();
  1101.  
  1102. for( i = 0; i < players.size; i++ )
  1103. {
  1104. score = int( distanceSquared( spawner.origin, players[i].origin ) );
  1105. }
  1106.  
  1107. return score;
  1108. }
  1109.  
  1110. //-----------------------------------------------------------------------------------------------
  1111. // picks run anim if director is aggro'd or not
  1112. //-----------------------------------------------------------------------------------------------
  1113. director_zombie_choose_run()
  1114. {
  1115. self endon( "death" );
  1116.  
  1117. while( true )
  1118. {
  1119. if ( isDefined( self.choose_run ) )
  1120. {
  1121. if ( self thread [[ self.choose_run ]]() )
  1122. {
  1123. wait_network_frame();
  1124. continue;
  1125. }
  1126. }
  1127.  
  1128. if ( is_true( self.walk2sprint ) )
  1129. {
  1130. transition_anim = level.scr_anim["director_zombie"]["walk2sprint"];
  1131.  
  1132. self set_run_anim( "walk2sprint" );
  1133. self.run_combatanim = transition_anim;
  1134. self.crouchRunAnim = transition_anim;
  1135. self.crouchrun_combatanim = transition_anim;
  1136. self.needs_run_update = true;
  1137.  
  1138. time = getAnimLength( transition_anim );
  1139. wait( time );
  1140. self.walk2sprint = undefined;
  1141. }
  1142.  
  1143. if ( is_true( self.sprint2walk ) )
  1144. {
  1145. self animcustom( ::director_sprint2walk );
  1146. self waittill_notify_or_timeout( "transition_done", 1.74 );
  1147. //self waittill( "transition_done" );
  1148. self.sprint2walk = undefined;
  1149. }
  1150.  
  1151. if( self.is_activated )
  1152. {
  1153. self.zombie_move_speed = "sprint";
  1154. rand = randomIntRange( 1, 4 );
  1155.  
  1156. self set_run_anim( "sprint"+rand );
  1157. self.run_combatanim = level.scr_anim["director_zombie"]["sprint"+rand];
  1158. self.crouchRunAnim = level.scr_anim["director_zombie"]["sprint"+rand];
  1159. self.crouchrun_combatanim = level.scr_anim["director_zombie"]["sprint"+rand];
  1160. self.needs_run_update = true;
  1161.  
  1162. self director_wait_for_run_change();
  1163. }
  1164. else
  1165. {
  1166. walk_version = "walk1";
  1167. //if ( level.round_number > 15 )
  1168. //{
  1169. // walk_version = "walk2";
  1170. //}
  1171.  
  1172. self.zombie_move_speed = "walk";
  1173. self set_run_anim( walk_version );
  1174. self.run_combatanim = level.scr_anim["director_zombie"][walk_version];
  1175. self.crouchRunAnim = level.scr_anim["director_zombie"][walk_version];
  1176. self.crouchrun_combatanim = level.scr_anim["director_zombie"][walk_version];
  1177. self.needs_run_update = true;
  1178. }
  1179.  
  1180. wait_network_frame();
  1181. }
  1182. }
  1183.  
  1184. director_wait_for_run_change()
  1185. {
  1186. self endon( "death" );
  1187. self endon( "director_calmed" );
  1188. self endon( "director_exit" );
  1189. self endon( "director_run_change" );
  1190.  
  1191. randf = randomFloatRange( 2, 3 );
  1192. wait( randf );
  1193. }
  1194.  
  1195. //-----------------------------------------------------------------------------------------------
  1196. // prevent director from dying
  1197. //-----------------------------------------------------------------------------------------------
  1198. director_zombie_health_manager()
  1199. {
  1200. self endon( "death" );
  1201.  
  1202. while ( 1 )
  1203. {
  1204. self waittill( "damage" );
  1205. self.maxhealth = level.director_zombie_max_health;
  1206. self.health = level.director_zombie_max_health;
  1207.  
  1208. director_print( "health = " + self.health );
  1209. }
  1210. }
  1211.  
  1212. //-----------------------------------------------------------------------------------------------
  1213. // update goal radius and attack distance for increased melee range
  1214. //-----------------------------------------------------------------------------------------------
  1215. director_zombie_update_goal_radius()
  1216. {
  1217. self endon( "death" );
  1218. self endon( "director_exit" );
  1219.  
  1220. while ( 1 )
  1221. {
  1222. if ( is_true( self.leaving_level ) )
  1223. {
  1224. self.pathEnemyFightDist = 48;
  1225. self.meleeAttackDist = 48;
  1226. self.goalradius = 32;
  1227. return;
  1228. }
  1229.  
  1230. if ( isDefined( self.enemy ) )
  1231. {
  1232. heightDiff = abs( self.enemy.origin[2] - self.origin[2] );
  1233. in_zone = self maps\_zombiemode_zone_manager::entity_in_zone( "residence_roof_zone" );
  1234. canMelee = animscripts\zombie_melee::CanMeleeDesperate();
  1235.  
  1236. if ( heightDiff < 24 && !is_true( self.is_activated ) && !in_zone && canMelee )
  1237. {
  1238. self.pathEnemyFightDist = 96;
  1239. self.meleeAttackDist = 96;
  1240. self.goalradius = 90;
  1241. }
  1242. else
  1243. {
  1244. self.pathEnemyFightDist = 48;
  1245. self.meleeAttackDist = 48;
  1246. self.goalradius = 32;
  1247. }
  1248. }
  1249.  
  1250. wait( .5 );
  1251. }
  1252. }
  1253.  
  1254. //-----------------------------------------------------------------------------------------------
  1255. // kill player if director walks on top of them
  1256. //-----------------------------------------------------------------------------------------------
  1257. director_kill_prone()
  1258. {
  1259. self endon( "death" );
  1260.  
  1261. _KILL_DIST = 144;
  1262. _HEIGHT_DIST = 48;
  1263.  
  1264. while ( 1 )
  1265. {
  1266. if ( isdefined( self.enemy ) )
  1267. {
  1268. if ( is_true( self.is_activated ) )
  1269. {
  1270. d = Distance2DSquared( self.enemy.origin, self.origin );
  1271. h = self.enemy.origin[2] - self.origin[2];
  1272.  
  1273. if ( d < _KILL_DIST && h < _HEIGHT_DIST )
  1274. {
  1275. self.enemy DoDamage( self.enemy.health * 10, self.enemy.origin, self );
  1276. }
  1277.  
  1278. //director_print( "d = " + d + " h = " + h );
  1279. }
  1280. }
  1281. wait( 0.5 );
  1282. }
  1283. }
  1284.  
  1285. director_zombie_check_player_proximity()
  1286. {
  1287. self endon( "death" );
  1288.  
  1289. while ( 1 )
  1290. {
  1291. if ( isdefined( self.performing_activation ) && self.performing_activation )
  1292. {
  1293. break;
  1294. }
  1295.  
  1296. players = getplayers();
  1297. for ( i = 0; i < players.size; i++ )
  1298. {
  1299. dist = DistanceSquared( self.origin, players[i].origin );
  1300. //iprintln( "dist = " + dist );
  1301. if ( dist < level.director_zombie_proximity_wake )
  1302. {
  1303. self notify( "hit_player" );
  1304. break;
  1305. }
  1306. }
  1307.  
  1308. wait_network_frame();
  1309. }
  1310. }
  1311.  
  1312. director_zombie_update_proximity_wake()
  1313. {
  1314. while ( !isdefined( level.round_number ) )
  1315. {
  1316. wait( 1 );
  1317. }
  1318.  
  1319. while ( 1 )
  1320. {
  1321. if ( level.round_number >= 20 )
  1322. {
  1323. level.director_zombie_proximity_wake = 120;
  1324. break;
  1325. }
  1326. else if ( level.round_number >= 15 )
  1327. {
  1328. level.director_zombie_proximity_wake = 102;
  1329. }
  1330. else if ( level.round_number >= 10 )
  1331. {
  1332. level.director_zombie_proximity_wake = 84;
  1333. }
  1334.  
  1335. wait( 1 );
  1336. }
  1337. }
  1338.  
  1339. //-----------------------------------------------------------------------------------------------
  1340. // give points for activating
  1341. //-----------------------------------------------------------------------------------------------
  1342. director_activation_damage()
  1343. {
  1344. self endon( "death" );
  1345. self endon( "disable_activation" );
  1346. self endon( "hit_player" );
  1347.  
  1348. //self waittill( "damage", amount, attacker, direction, point, method );
  1349. self waittill( "activation_damage", attacker, weapon );
  1350.  
  1351. if ( isDefined( attacker ) && IsPlayer( attacker ) )
  1352. {
  1353. attacker maps\_zombiemode_score::player_add_points( "damage" );
  1354. attacker thread maps\_zombiemode_audio::create_and_play_dialog( "director", "anger" );
  1355. }
  1356.  
  1357. self notify( "director_aggro" );
  1358. }
  1359.  
  1360. director_activation_hit_player()
  1361. {
  1362. self endon( "death" );
  1363. self endon( "disable_activation" );
  1364. self endon( "damage" );
  1365.  
  1366. self waittill( "hit_player" );
  1367. self notify( "director_aggro" );
  1368. }
  1369.  
  1370. //-----------------------------------------------------------------------------------------------
  1371. // waits for damage to activate
  1372. //-----------------------------------------------------------------------------------------------
  1373. director_zombie_check_for_activation()
  1374. {
  1375. self endon( "death" );
  1376. self endon( "disable_activation" );
  1377.  
  1378. self.is_activated = false;
  1379.  
  1380. self thread director_activation_damage();
  1381. self thread director_activation_hit_player();
  1382. self waittill( "director_aggro" );
  1383. self notify( "director_spawn_zombies" );
  1384.  
  1385. self.is_activated = true;
  1386.  
  1387. if ( is_true( self.is_traversing ) )
  1388. {
  1389. self waittill( "zombie_end_traverse" );
  1390. }
  1391.  
  1392. self notify( "stop_find_flesh" );
  1393. self.following_player = false;
  1394. self.performing_activation = true;
  1395. self.ground_hit = true;
  1396.  
  1397. self thread scream_a_watcher( "aggro_anim" );
  1398. self thread groundhit_watcher( "aggro_anim" );
  1399. self thread director_zombie_sprint_watcher( "aggro_anim" );
  1400. self thread director_zombified_watcher( "aggro_anim" );
  1401. //self thread scream_b_watcher( "aggro_anim" );
  1402.  
  1403. //Sound - Shawn J - adding eng hit exert
  1404. if( IsDefined( level._audio_director_vox_play ) )
  1405. {
  1406. self thread [[ level._audio_director_vox_play ]]( "vox_director_angered", .25, true );
  1407. }
  1408. //self PlaySound( "vox_director_angered" );
  1409. self playsound("zmb_director_light_start");
  1410.  
  1411. aggro_anim = %ai_zombie_boss_enrage_start_coast;
  1412. if ( RandomInt( 100 ) < 50 )
  1413. {
  1414. aggro_anim = %ai_zombie_boss_enrage_start_a_coast;
  1415. }
  1416.  
  1417. if( IsDefined( level._audio_director_vox_play ) )
  1418. {
  1419. self thread [[ level._audio_director_vox_play ]]( "vox_director_slam", .25, true );
  1420. }
  1421. //self PlaySound( "vox_director_slam" );
  1422. self director_animscripted( aggro_anim, "aggro_anim", true );
  1423.  
  1424. self.performing_activation = false;
  1425. self.ground_hit = false;
  1426.  
  1427. self.delay_time = undefined;
  1428.  
  1429. self notify( "director_activated" );
  1430.  
  1431. if ( !is_true( self.is_traversing ) )
  1432. {
  1433. self director_transition( "sprint" );
  1434. }
  1435.  
  1436. // once activated can use the ground hit attack
  1437. self thread director_zombie_ground_hit_think();
  1438. }
  1439.  
  1440. //-----------------------------------------------------------------------------------------------
  1441. // model swap during the scream
  1442. //-----------------------------------------------------------------------------------------------
  1443. director_zombified_watcher( animname )
  1444. {
  1445. self endon( "death" );
  1446.  
  1447. self waittillmatch( animname, "scream_a" );
  1448.  
  1449. if ( !is_true( self.director_zombified ) )
  1450. {
  1451. self setmodel( "c_zom_george_romero_zombiefied_fb" );
  1452. self.director_zombified = true;
  1453. }
  1454. }
  1455.  
  1456. //-----------------------------------------------------------------------------------------------
  1457. // needs to be far enough from the enemy and close enough to zombies to activate
  1458. //-----------------------------------------------------------------------------------------------
  1459. director_zombie_check_for_buff()
  1460. {
  1461. self endon( "death" );
  1462. self endon( "disable_buff" );
  1463.  
  1464. wait( 5 );
  1465.  
  1466. while ( 1 )
  1467. {
  1468. if ( is_true( self.performing_activation ) )
  1469. {
  1470. wait( 3 );
  1471. continue;
  1472. }
  1473.  
  1474. if ( is_true( self.is_transition ) )
  1475. {
  1476. wait( 1 );
  1477. continue;
  1478. }
  1479.  
  1480. if ( self.buff == "speed" )
  1481. {
  1482. if ( level.round_number < 6 )
  1483. {
  1484. self director_zombie_choose_buff();
  1485. wait( 3 );
  1486. continue;
  1487. }
  1488.  
  1489. num = director_zombie_get_num_speed_buff();
  1490. if ( num >= level.director_max_speed_buff )
  1491. {
  1492. self director_zombie_choose_buff();
  1493. wait( 3 );
  1494. continue;
  1495. }
  1496. }
  1497.  
  1498. //if ( self director_zombie_enemy_is_far() )
  1499. {
  1500. zombies_in_range = director_get_zombies_to_buff();
  1501. if ( zombies_in_range.size )
  1502. {
  1503. self thread director_zombie_apply_buff( zombies_in_range );
  1504. self.buff_cooldown = GetTime() + ( zombies_in_range.size * 5000 );
  1505. self director_buff_cooldown();
  1506. }
  1507. }
  1508.  
  1509. wait( 1 );
  1510. }
  1511. }
  1512.  
  1513. director_buff_cooldown()
  1514. {
  1515. self endon( "death" );
  1516.  
  1517. while ( 1 )
  1518. {
  1519. t = GetTime();
  1520. if ( t >= self.buff_cooldown )
  1521. {
  1522. break;
  1523. }
  1524. wait( 0.1 );
  1525. }
  1526. }
  1527.  
  1528. director_get_zombies_to_buff()
  1529. {
  1530. zombies_in_range = [];
  1531.  
  1532. zombies = GetAiSpeciesArray( "axis", "all" );
  1533. for ( i = 0; i < zombies.size; i++ )
  1534. {
  1535. if ( !self director_zombie_can_buff( zombies[i] ) )
  1536. {
  1537. continue;
  1538. }
  1539.  
  1540. zombies_in_range = add_to_array( zombies_in_range, zombies[i] );
  1541. }
  1542.  
  1543. return zombies_in_range;
  1544. }
  1545.  
  1546. //-----------------------------------------------------------------------------------------------
  1547. // enemy is far enough from the director
  1548. //-----------------------------------------------------------------------------------------------
  1549. director_zombie_enemy_is_far()
  1550. {
  1551. self endon( "death" );
  1552.  
  1553. far_enough = false;
  1554.  
  1555. if ( isDefined( self.favoriteenemy ) )
  1556. {
  1557. height = Abs( self.origin[2] - self.favoriteenemy.origin[2] );
  1558. if ( height > 72 )
  1559. {
  1560. far_enough = true;
  1561. }
  1562. dist_enemy = DistanceSquared( self.origin, self.favoriteenemy.origin );
  1563. if ( dist_enemy > level.director_enemy_range )
  1564. {
  1565. far_enough = true;
  1566. }
  1567. }
  1568.  
  1569. return far_enough;
  1570. }
  1571.  
  1572. //-----------------------------------------------------------------------------------------------
  1573. // check if zombie can use this type of buff
  1574. //-----------------------------------------------------------------------------------------------
  1575. director_zombie_can_buff( zombie )
  1576. {
  1577. self endon( "death" );
  1578.  
  1579. if ( is_true( zombie.ignoreme ) )
  1580. {
  1581. return false;
  1582. }
  1583.  
  1584. range = level.director_speed_buff_range_sq;
  1585.  
  1586. if ( self.buff == "electric" )
  1587. {
  1588. range = level.director_electric_buff_range_sq;
  1589.  
  1590. if ( is_true( zombie.electrified ) )
  1591. {
  1592. return false;
  1593. }
  1594. }
  1595. else if ( self.buff == "speed" )
  1596. {
  1597. if ( is_true( zombie.ignore_speed_buff ) )
  1598. {
  1599. return false;
  1600. }
  1601.  
  1602. if ( is_true( zombie.speed_buff ) )
  1603. {
  1604. return false;
  1605. }
  1606.  
  1607. if ( is_true( zombie.in_water ) )
  1608. {
  1609. return false;
  1610. }
  1611. }
  1612.  
  1613. height = Abs( self.origin[2] - zombie.origin[2] );
  1614. if ( height > 72 ) // basically on the same plane
  1615. {
  1616. return false;
  1617. }
  1618.  
  1619. dist = DistanceSquared( self.origin, zombie.origin );
  1620. if ( dist > range )
  1621. {
  1622. return false;
  1623. }
  1624.  
  1625. // needs to be in front of the director
  1626. forward = VectorNormalize( AnglesToForward( self.angles ) );
  1627. zombie_dir = VectorNormalize( zombie.origin - self.origin );
  1628. dot = VectorDot( forward, zombie_dir );
  1629. if ( dot < 0.5 )
  1630. {
  1631. return false;
  1632. }
  1633.  
  1634. return true;
  1635. }
  1636.  
  1637. //-----------------------------------------------------------------------------------------------
  1638. // use director buff on zombies
  1639. //-----------------------------------------------------------------------------------------------
  1640. director_zombie_apply_buff( zombies )
  1641. {
  1642. self endon( "death" );
  1643.  
  1644. if ( self.buff == "electric" )
  1645. {
  1646. self director_zombie_electric_buff( zombies );
  1647. }
  1648. else if ( self.buff == "speed" )
  1649. {
  1650. enrage_anim = %ai_zombie_boss_enrage_start_scream_coast;
  1651. self director_zombie_speed_buff( zombies, enrage_anim );
  1652. }
  1653.  
  1654. self director_zombie_choose_buff();
  1655. }
  1656.  
  1657. //-----------------------------------------------------------------------------------------------
  1658. // play scream anim and then speed up surrounding zombies
  1659. //-----------------------------------------------------------------------------------------------
  1660. director_zombie_speed_buff( zombies, enrage_anim )
  1661. {
  1662. self endon( "death" );
  1663.  
  1664. director_print( "apply speed buff " + zombies.size );
  1665.  
  1666. if( IsDefined( level._audio_director_vox_play ) )
  1667. {
  1668. self thread [[ level._audio_director_vox_play ]]( "vox_director_speed_buff", .25, true );
  1669. }
  1670. //self playsound( "vox_director_laugh" );
  1671.  
  1672. if ( IsDefined( enrage_anim ) )
  1673. {
  1674. self director_animscripted( enrage_anim, "enrage_anim" );
  1675. }
  1676.  
  1677. level.director_speed_buff = director_zombie_get_num_speed_buff();
  1678. speed_count = level.director_max_speed_buff - level.director_speed_buff;
  1679.  
  1680. director_print( "speed buff current = " + level.director_speed_buff + " adding " + speed_count );
  1681.  
  1682. if ( speed_count > zombies.size )
  1683. {
  1684. speed_count = zombies.size;
  1685. }
  1686.  
  1687. for ( i = 0; i < speed_count; i++ )
  1688. {
  1689. if ( isDefined( zombies[i] ) )
  1690. {
  1691. zombies[i] thread zombie_speed_buff();
  1692. }
  1693. }
  1694.  
  1695. players = getplayers();
  1696. for(i=0;i<players.size;i++)
  1697. {
  1698. if( DistanceSquared( self.origin, players[i].origin ) <= 600 * 600 )
  1699. {
  1700. players[i] thread maps\_zombiemode_audio::create_and_play_dialog( "general", "react_sprinters" );
  1701. break;
  1702. }
  1703. }
  1704. }
  1705.  
  1706. director_zombie_get_num_speed_buff()
  1707. {
  1708. num = 0;
  1709. zombies = GetAiSpeciesArray( "axis", "all" );
  1710. for ( i = 0; i < zombies.size; i++ )
  1711. {
  1712. if ( is_true( zombies[i].speed_buff ) )
  1713. {
  1714. num++;
  1715. }
  1716. }
  1717.  
  1718. return num;
  1719. }
  1720.  
  1721. //-----------------------------------------------------------------------------------------------
  1722. // use faster sprint to catch up to players
  1723. //-----------------------------------------------------------------------------------------------
  1724. zombie_speed_buff()
  1725. {
  1726. self endon( "death" );
  1727.  
  1728. self.speed_buff = true;
  1729.  
  1730. fast_sprint = "sprint5";
  1731. if ( RandomInt( 100 ) < 50 )
  1732. {
  1733. fast_sprint = "sprint6";
  1734. }
  1735.  
  1736. self.zombie_move_speed = "sprint";
  1737. self set_run_anim( fast_sprint );
  1738. self.run_combatanim = level.scr_anim[ self.animname ][ fast_sprint ];
  1739. self.needs_run_update = true;
  1740.  
  1741. /*
  1742. while ( 1 )
  1743. {
  1744. if ( isDefined( self.favoriteenemy ) )
  1745. {
  1746. height = Abs( self.origin[2] - self.favoriteenemy.origin[2] );
  1747. dist_sq = DistanceSquared( self.origin, self.favoriteenemy.origin );
  1748. if ( dist_sq < level.director_zombie_range && height <= 120 )
  1749. {
  1750. break;
  1751. }
  1752. }
  1753. wait( 0.3 );
  1754. }
  1755.  
  1756. self thread zombie_speed_debuff();
  1757. */
  1758. }
  1759.  
  1760. //-----------------------------------------------------------------------------------------------
  1761. // back to previous speed
  1762. //-----------------------------------------------------------------------------------------------
  1763. zombie_speed_debuff()
  1764. {
  1765. self endon( "death" );
  1766.  
  1767. self.speed_buff = false;
  1768.  
  1769. switch( self.zombie_move_speed )
  1770. {
  1771. case "walk":
  1772. var = randomintrange( 1, 9 );
  1773. self set_run_anim( "walk" + var );
  1774. self.run_combatanim = level.scr_anim[ self.animname ][ "walk" + var ];
  1775. break;
  1776.  
  1777. case "run":
  1778. var = randomintrange( 1, 7 );
  1779. self set_run_anim( "run" + var );
  1780. self.run_combatanim = level.scr_anim[ self.animname ][ "run" + var ];
  1781. break;
  1782.  
  1783. case "sprint":
  1784. var = randomintrange( 1, 5 );
  1785. self set_run_anim( "sprint" + var );
  1786. self.run_combatanim = level.scr_anim[ self.animname ][ "sprint" + var ];
  1787. break;
  1788. }
  1789.  
  1790. self.needs_run_update = true;
  1791. }
  1792.  
  1793. //-----------------------------------------------------------------------------------------------
  1794. // play ground hit fx
  1795. //-----------------------------------------------------------------------------------------------
  1796. groundhit_fx_watcher( animname )
  1797. {
  1798. self endon( "death" );
  1799.  
  1800. self waittillmatch( animname, "wrench_hit" );
  1801.  
  1802. playfxontag( level._effect["director_groundhit"], self, "tag_origin" );
  1803. }
  1804.  
  1805. //-----------------------------------------------------------------------------------------------
  1806. // play ground hit anim and then electrify zombies
  1807. //-----------------------------------------------------------------------------------------------
  1808. director_zombie_electric_buff( zombies )
  1809. {
  1810. self endon( "death" );
  1811.  
  1812. director_print( "apply electric buff " + zombies.size );
  1813.  
  1814. if( IsDefined( level._audio_director_vox_play ) )
  1815. {
  1816. self thread [[ level._audio_director_vox_play ]]( "vox_director_slam", .25, true );
  1817. }
  1818. //self playsound( "vox_director_slam" );
  1819.  
  1820. if ( is_true( self.is_activated ) )
  1821. {
  1822. self animcustom( ::director_zombie_ground_hit );
  1823. self waittill( "ground_hit_done" );
  1824. return;
  1825. }
  1826.  
  1827. hit_anim = %ai_zombie_boss_enrage_start_slamground_coast;
  1828. self thread groundhit_fx_watcher( "hit_anim" );
  1829.  
  1830. self director_animscripted( hit_anim, "hit_anim" );
  1831.  
  1832. if( IsDefined( level._audio_director_vox_play ) )
  1833. {
  1834. self thread [[ level._audio_director_vox_play ]]( "vox_director_electric_buff", .25, true );
  1835. }
  1836. //self PlaySound( "vox_director_laugh" );
  1837.  
  1838. for ( i = 0; i < zombies.size; i++ )
  1839. {
  1840. if ( isDefined( zombies[i] ) )
  1841. {
  1842. zombies[i] thread zombie_set_electric_buff();
  1843. }
  1844. }
  1845.  
  1846. players = getplayers();
  1847. for(i=0;i<players.size;i++)
  1848. {
  1849. if( DistanceSquared( self.origin, players[i].origin ) <= 600 * 600 )
  1850. {
  1851. players[i] thread maps\_zombiemode_audio::create_and_play_dialog( "general", "react_sparkers" );
  1852. break;
  1853. }
  1854. }
  1855. }
  1856.  
  1857. //-----------------------------------------------------------------------------------------------
  1858. // play transition anim
  1859. //-----------------------------------------------------------------------------------------------
  1860. director_sprint2walk()
  1861. {
  1862. self endon( "death" );
  1863.  
  1864. transition_anim = level.scr_anim["director_zombie"]["sprint2walk"];
  1865.  
  1866. self thread director_sprint2walk_watcher( "transition_anim" );
  1867.  
  1868. time = getAnimLength( transition_anim );
  1869. self SetFlaggedAnimKnobAllRestart( "transition_anim", transition_anim, %body, 1, .1, 1 );
  1870. wait( time );
  1871.  
  1872. self notify( "transition_done" );
  1873. }
  1874.  
  1875. director_sprint2walk_watcher( animname )
  1876. {
  1877. self endon( "death" );
  1878.  
  1879. self waittillmatch( animname, "swap_fx" );
  1880.  
  1881. Playfx( level._effect["director_water_burst_sm"], self.origin );
  1882. self setmodel( "c_zom_george_romero_light_fb" );
  1883. self.director_zombified = undefined;
  1884. }
  1885.  
  1886. //-----------------------------------------------------------------------------------------------
  1887. // play ground hti anim
  1888. //-----------------------------------------------------------------------------------------------
  1889. director_zombie_ground_hit()
  1890. {
  1891. self endon( "death" );
  1892.  
  1893. if ( self.ground_hit )
  1894. {
  1895. return;
  1896. }
  1897.  
  1898. self.ground_hit = true;
  1899.  
  1900. self thread groundhit_watcher( "groundhit_anim" );
  1901.  
  1902. groundhit_anim = %ai_zombie_boss_run_hitground_coast;
  1903. self SetFlaggedAnimKnobAllRestart( "groundhit_anim", groundhit_anim, %body, 1, .1, 1 );
  1904. animscripts\traverse\zombie_shared::wait_anim_length( groundhit_anim, .02 );
  1905.  
  1906. self.ground_hit = false;
  1907.  
  1908. self.nextGroundHit = GetTime() + level.director_ground_attack_delay;
  1909. self notify( "ground_hit_done" );
  1910. }
  1911.  
  1912. director_zombie_update_next_groundhit()
  1913. {
  1914. self.nextGroundHit = GetTime() + level.director_ground_attack_delay;
  1915. }
  1916.  
  1917. director_zombie_ground_hit_think()
  1918. {
  1919. self endon( "death" );
  1920. self endon( "director_calmed" );
  1921. self endon( "director_exit" );
  1922.  
  1923. self.ground_hit = false;
  1924. self.nextGroundHit = GetTime() + level.director_ground_attack_delay;
  1925.  
  1926. while( 1 )
  1927. {
  1928. if ( is_true( self.is_traversing ) )
  1929. {
  1930. self waittill( "zombie_end_traverse" );
  1931. continue;
  1932. }
  1933.  
  1934. if ( is_true( self.is_fling ) )
  1935. {
  1936. wait( 2 );
  1937. continue;
  1938. }
  1939.  
  1940. if ( !self.ground_hit && GetTime() >= self.nextGroundHit )
  1941. {
  1942. players = GetPlayers();
  1943. closeEnough = false;
  1944. origin = self GetEye();
  1945.  
  1946. for ( i = 0; i < players.size; i++ )
  1947. {
  1948. if ( players[i] maps\_laststand::player_is_in_laststand() )
  1949. {
  1950. continue;
  1951. }
  1952.  
  1953. if ( is_true( players[i].divetoprone ) )
  1954. {
  1955. continue;
  1956. }
  1957.  
  1958. stance = players[i] GetStance();
  1959. if ( stance == "prone" )
  1960. {
  1961. continue;
  1962. }
  1963.  
  1964. test_origin = players[i] GetEye();
  1965. d = DistanceSquared( origin, test_origin );
  1966.  
  1967. if ( d > level.director_zombie_groundhit_radius * level.director_zombie_groundhit_radius )
  1968. {
  1969. continue;
  1970. }
  1971.  
  1972. if ( !BulletTracePassed( origin, test_origin, false, undefined ) )
  1973. {
  1974. continue;
  1975. }
  1976.  
  1977. closeEnough = true;
  1978. break;
  1979. }
  1980.  
  1981. if ( closeEnough )
  1982. {
  1983.  
  1984. if( IsDefined( level._audio_director_vox_play ) )
  1985. {
  1986. self thread [[ level._audio_director_vox_play ]]( "vox_director_slam", .25, true );
  1987. }
  1988. //self PlaySound( "vox_director_slam" );
  1989. self animcustom( ::director_zombie_ground_hit );
  1990. }
  1991. }
  1992.  
  1993. wait_network_frame();
  1994. }
  1995. }
  1996.  
  1997. scream_a_watcher( animname )
  1998. {
  1999. self endon( "death" );
  2000.  
  2001. //rand = RandomInt( 100 );
  2002. //if( rand > level.director_zombie_scream_a_chance )
  2003. //{
  2004. // return;
  2005. //}
  2006.  
  2007. self waittillmatch( animname, "scream_a" );
  2008.  
  2009. /*
  2010. players = get_players();
  2011. affected_players = [];
  2012. for( i = 0; i < players.size; i++ )
  2013. {
  2014. if( distanceSquared( players[i].origin, self.origin ) < level.director_zombie_scream_a_radius_sq )
  2015. {
  2016. affected_players = array_add( affected_players, players[i] );
  2017. }
  2018. }
  2019. for( i = 0; i < affected_players.size; i++ )
  2020. {
  2021. affected_players[i] ShellShock( "electrocution", 1.5, true );
  2022. }
  2023. */
  2024.  
  2025. clientnotify( "ZDA" );
  2026.  
  2027. self thread director_blur();
  2028. }
  2029.  
  2030. director_zombie_sprint_watcher( animname )
  2031. {
  2032. self endon( "death" );
  2033.  
  2034. self waittillmatch( animname, "scream_a" );
  2035.  
  2036. origin = self GetEye();
  2037. zombies = get_array_of_closest( origin, GetAiSpeciesArray( "axis", "all" ), undefined, undefined, level.director_speed_buff_range );
  2038.  
  2039. if ( IsDefined( zombies ) )
  2040. {
  2041. zombies_in_range = [];
  2042.  
  2043. for ( i = 0; i < zombies.size; i++ )
  2044. {
  2045. if ( !IsDefined( zombies[i] ) )
  2046. {
  2047. continue;
  2048. }
  2049.  
  2050. if ( is_true( zombies[i].ignore_speed_buff ) )
  2051. {
  2052. continue;
  2053. }
  2054.  
  2055. if ( is_true( zombies[i].speed_buff ) )
  2056. {
  2057. continue;
  2058. }
  2059.  
  2060. if ( is_true( zombies[i].in_water ) )
  2061. {
  2062. continue;
  2063. }
  2064.  
  2065. height = Abs( self.origin[2] - zombies[i].origin[2] );
  2066. if ( height > 72 ) // basically on the same plane
  2067. {
  2068. continue;
  2069. }
  2070.  
  2071. if ( zombies[i] == self )
  2072. {
  2073. continue;
  2074. }
  2075.  
  2076. // needs to be in front of the director
  2077. forward = VectorNormalize( AnglesToForward( self.angles ) );
  2078. zombie_dir = VectorNormalize( zombies[i].origin - self.origin );
  2079. dot = VectorDot( forward, zombie_dir );
  2080. if ( dot < 0.5 )
  2081. {
  2082. continue;
  2083. }
  2084.  
  2085. zombies_in_range = add_to_array( zombies_in_range, zombies[i] );
  2086. }
  2087.  
  2088. if ( zombies_in_range.size > 0 )
  2089. {
  2090. self director_zombie_speed_buff( zombies_in_range );
  2091. }
  2092. }
  2093. }
  2094.  
  2095. groundhit_watcher( animname )
  2096. {
  2097. self endon( "death" );
  2098.  
  2099. self waittillmatch( animname, "wrench_hit" );
  2100.  
  2101. // PlayFx( level._effect["director_groundhit"], self.origin );
  2102. playfxontag(level._effect["director_groundhit"],self,"tag_origin");
  2103. //self RadiusDamage( self.origin, level.director_zombie_groundhit_radius, level.director_zombie_groundhit_damage, level.director_zombie_groundhit_damage, self );
  2104.  
  2105. origin = self GetEye();
  2106. zombies = get_array_of_closest( origin, GetAiSpeciesArray( "axis", "all" ), undefined, undefined, level.director_electric_buff_range );
  2107.  
  2108. electrified = 0;
  2109.  
  2110. if ( IsDefined( zombies ) )
  2111. {
  2112. for ( i = 0; i < zombies.size; i++ )
  2113. {
  2114. if ( !IsDefined( zombies[i] ) )
  2115. {
  2116. continue;
  2117. }
  2118.  
  2119. if ( is_true( zombies[i].electrified ) )
  2120. {
  2121. continue;
  2122. }
  2123.  
  2124. test_origin = zombies[i] GetEye();
  2125.  
  2126. if ( !BulletTracePassed( origin, test_origin, false, undefined ) )
  2127. {
  2128. continue;
  2129. }
  2130.  
  2131. if ( zombies[i] == self )
  2132. {
  2133. continue;
  2134. }
  2135.  
  2136. zombies[i] zombie_set_electric_buff();
  2137.  
  2138. electrified++;
  2139. }
  2140. }
  2141.  
  2142. director_print( "apply electric buff " + electrified );
  2143.  
  2144. players = get_players();
  2145. affected_players = [];
  2146. for( i = 0; i < players.size; i++ )
  2147. {
  2148. test_origin = players[i] GetEye();
  2149. d = DistanceSquared( origin, test_origin );
  2150. if( d > level.director_electrify_range_sq )
  2151. {
  2152. continue;
  2153. }
  2154. heightDiff = abs( origin[2] - test_origin[2] );
  2155. if ( heightDiff > 96 )
  2156. {
  2157. continue;
  2158. }
  2159. if ( !BulletTracePassed( origin, test_origin, false, undefined ) )
  2160. {
  2161. continue;
  2162. }
  2163.  
  2164. affected_players = array_add( affected_players, players[i] );
  2165. }
  2166. for( i = 0; i < affected_players.size; i++ )
  2167. {
  2168. //affected_players[i] DoDamage( level.director_zombie_groundhit_damage, self.origin, self );
  2169. //affected_players[i] ShellShock( "electrocution", 1.5, true );
  2170. if ( affected_players[i] IsOnGround() )
  2171. {
  2172. affected_players[i] player_electrify();
  2173. }
  2174. }
  2175. }
  2176.  
  2177. scream_b_watcher( animname )
  2178. {
  2179. self endon( "death" );
  2180.  
  2181. rand = RandomInt( 100 );
  2182. if( rand > level.director_zombie_scream_b_chance )
  2183. {
  2184. return;
  2185. }
  2186.  
  2187. self waittillmatch( animname, "scream_b" );
  2188.  
  2189. players = get_players();
  2190. affected_players = [];
  2191. for( i = 0; i < players.size; i++ )
  2192. {
  2193. if( distanceSquared( players[i].origin, self.origin ) < level.director_zombie_scream_b_radius_sq )
  2194. {
  2195. affected_players = array_add( affected_players, players[i] );
  2196. }
  2197. }
  2198. for( i = 0; i < affected_players.size; i++ )
  2199. {
  2200. affected_players[i] ShellShock( "electrocution", 1.5, true );
  2201. }
  2202. }
  2203.  
  2204. director_zombie_die()
  2205. {
  2206. // keep the director alive for the game over screen
  2207. return true;
  2208. }
  2209.  
  2210. director_custom_damage( player )
  2211. {
  2212. self endon( "death" );
  2213.  
  2214. if ( isDefined( self.ground_hit ) && self.ground_hit )
  2215. {
  2216. return level.director_zombie_groundhit_damage;
  2217. }
  2218.  
  2219. return self.meleeDamage;
  2220. }
  2221.  
  2222. director_nuke_damage()
  2223. {
  2224. self endon( "death" );
  2225.  
  2226. if ( is_true( self.is_traversing ) )
  2227. {
  2228. return;
  2229. }
  2230.  
  2231. if ( is_true( self.leaving_level ) )
  2232. {
  2233. return;
  2234. }
  2235.  
  2236. if ( !isDefined( self.nuke_react ) )
  2237. {
  2238. self.nuke_react = true;
  2239.  
  2240. nuke_anim = %ai_zombie_boss_nuke_react_coast;
  2241.  
  2242. self director_animscripted( nuke_anim, "nuke_anim" );
  2243.  
  2244. self.nuke_react = undefined;
  2245. }
  2246. }
  2247.  
  2248. director_tesla_damage( origin, player )
  2249. {
  2250. self.zombie_tesla_hit = false;
  2251.  
  2252. if ( is_true( self.leaving_level ) )
  2253. {
  2254. return;
  2255. }
  2256.  
  2257. if ( !is_true( self.is_activated ) )
  2258. {
  2259. self notify( "activation_damage", player, "tesla_gun_zm" );
  2260. }
  2261. }
  2262.  
  2263. //-----------------------------------------------------------------------------------------------
  2264. // packed assault rifles are buffed against the director
  2265. //-----------------------------------------------------------------------------------------------
  2266. director_full_damage( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, modelIndex, psOffsetTime )
  2267. {
  2268. self endon( "death" );
  2269.  
  2270. self notify( "activation_damage", attacker, weapon );
  2271.  
  2272. if ( sHitLoc == "head" || sHitLoc == "helmet" || sHitLoc == "neck" )
  2273. {
  2274. return damage;
  2275. }
  2276.  
  2277. switch ( weapon )
  2278. {
  2279. case "aug_acog_mk_upgraded_zm":
  2280. case "commando_upgraded_zm":
  2281. damage *= 4.75; // 3.25
  2282. break;
  2283.  
  2284. case "galil_upgraded_zm":
  2285. case "fnfal_upgraded_zm":
  2286. damage *= 3.5; // 2.5
  2287. break;
  2288.  
  2289. case "famas_upgraded_zm":
  2290. damage *= 9.25;
  2291. break;
  2292.  
  2293. case "zombie_nesting_doll_single":
  2294. damage /= 20;
  2295. break;
  2296. }
  2297.  
  2298. return damage;
  2299. }
  2300.  
  2301. director_zombie_default_enter_level()
  2302. {
  2303. Playfx( level._effect["director_spawn"], self.origin );
  2304. playsoundatposition( "zmb_bolt", self.origin );
  2305. PlayRumbleOnPosition("explosion_generic", self.origin);
  2306. }
  2307.  
  2308. setup_player_damage_watchers()
  2309. {
  2310. flag_wait( "all_players_connected" );
  2311.  
  2312. players = getplayers();
  2313. for ( i = 0; i < players.size; i++ )
  2314. {
  2315. players[i].player_damage_override = ::player_damage_watcher;
  2316. }
  2317. }
  2318.  
  2319. //-----------------------------------------------------------------------------------------------
  2320. // player is hit by an electrified zombie
  2321. //-----------------------------------------------------------------------------------------------
  2322. player_damage_watcher( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, modelIndex, psOffsetTime )
  2323. {
  2324. if ( IsPlayer( eAttacker ) )
  2325. {
  2326. return;
  2327. }
  2328.  
  2329. if ( is_true( eAttacker.electrified ) )
  2330. {
  2331. self player_electrify();
  2332. }
  2333. }
  2334.  
  2335.  
  2336. player_electrify()
  2337. {
  2338. self endon( "death" );
  2339. self endon( "disconnect" );
  2340.  
  2341. SHOCK_TIME = 0.25;
  2342.  
  2343. if ( !IsDefined( self.electrified ) )
  2344. {
  2345. self.electrified = true;
  2346. self setelectrified( SHOCK_TIME );
  2347. self ShellShock( "electrocution", 0.5, true );
  2348. self PlaySound("zmb_director_damage_zort");
  2349. self setclientflag( level._CF_PLAYER_ELECTRIFIED );
  2350. wait( SHOCK_TIME );
  2351. self clearclientflag( level._CF_PLAYER_ELECTRIFIED );
  2352. self.electrified = undefined;
  2353. }
  2354. }
  2355.  
  2356. //-----------------------------------------------------------------------------------------------
  2357. // set fx for client
  2358. //-----------------------------------------------------------------------------------------------
  2359. zombie_set_electric_buff()
  2360. {
  2361. self.electrified = true;
  2362. self setclientflag( level._ZOMBIE_ACTOR_FLAG_ELECTRIFIED );
  2363.  
  2364. self playloopsound("zmb_electric_zombie_loop");
  2365.  
  2366. self thread zombie_melee_watcher(true);
  2367.  
  2368. self.actor_killed_override = ::zombie_clear_electric_buff;
  2369. }
  2370.  
  2371. //-----------------------------------------------------------------------------------------------
  2372. // if a player melees an electrified zombie, play lightning fx
  2373. //-----------------------------------------------------------------------------------------------
  2374. zombie_melee_watcher(is_zombie)
  2375. {
  2376. self endon( "death" );
  2377.  
  2378. if(is_true(is_zombie))
  2379. {
  2380. self endon("stop_melee_watch");
  2381. }
  2382.  
  2383. while ( 1 )
  2384. {
  2385. self waittill( "damage", amount, attacker, direction, point, method );
  2386.  
  2387. if ( IsPlayer( attacker ) )
  2388. {
  2389. if ( method == "MOD_MELEE" )
  2390. {
  2391. attacker player_electrify();
  2392. attacker thread maps\_zombiemode_audio::create_and_play_dialog( "general", "damage_shocked" );
  2393. }
  2394. }
  2395. }
  2396. }
  2397.  
  2398. //-----------------------------------------------------------------------------------------------
  2399. // clear fx for client and check for drop
  2400. //-----------------------------------------------------------------------------------------------
  2401. zombie_clear_electric_buff( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime )
  2402. {
  2403. self clearclientflag( level._ZOMBIE_ACTOR_FLAG_ELECTRIFIED );
  2404.  
  2405. self StopLoopSound(3);
  2406.  
  2407. if ( IsDefined( sMeansOfDeath ) && IsDefined( attacker ) && IsPlayer( attacker ))
  2408. {
  2409. if ( sMeansOfDeath == "MOD_MELEE" )
  2410. {
  2411. attacker player_electrify();
  2412. }
  2413. }
  2414.  
  2415. if ( IsDefined( sMeansOfDeath ) )
  2416. {
  2417. if ( is_true( level.director_max_ammo_available ) && !is_true( self.ignoreme ) )
  2418. {
  2419. self zombie_drop_max_ammo();
  2420. }
  2421. }
  2422.  
  2423. self.electrified = undefined;
  2424. }
  2425.  
  2426. //-----------------------------------------------------------------------------------------------
  2427. // try to drop a max ammo
  2428. //-----------------------------------------------------------------------------------------------
  2429. zombie_drop_max_ammo()
  2430. {
  2431. chance = RandomInt( 100 );
  2432.  
  2433. director_print( "chance " + chance + " < " + level.director_max_ammo_chance );
  2434.  
  2435. if ( chance < level.director_max_ammo_chance )
  2436. {
  2437. level.director_max_ammo_available = false;
  2438. level.director_max_ammo_chance = level.director_max_ammo_chance_default;
  2439. level thread maps\_zombiemode_powerups::specific_powerup_drop( "full_ammo", self.origin );
  2440. level notify( "director_max_ammo_drop" );
  2441. }
  2442. else
  2443. {
  2444. level.director_max_ammo_chance += level.director_max_ammo_chance_inc;
  2445. }
  2446. }
  2447.  
  2448. //-----------------------------------------------------------------------------------------------
  2449. // figure out what rounds electrified zombies can potentially drop max ammo
  2450. //-----------------------------------------------------------------------------------------------
  2451. director_max_ammo_watcher()
  2452. {
  2453. level.director_max_ammo_available = false;
  2454. level.director_max_ammo_chance = level.director_max_ammo_chance_default;
  2455.  
  2456. flag_wait( "power_on" );
  2457.  
  2458. level.director_max_ammo_round = level.round_number + randomintrange( 1, 4 );
  2459.  
  2460. director_print( "next max ammo round " + level.director_max_ammo_round );
  2461.  
  2462. while ( 1 )
  2463. {
  2464. level waittill( "between_round_over" );
  2465.  
  2466. if ( level.round_number >= level.director_max_ammo_round )
  2467. {
  2468. level.director_max_ammo_available = true;
  2469. level waittill( "director_max_ammo_drop" );
  2470. level.director_max_ammo_round = level.round_number + randomintrange( 4, 6 );
  2471.  
  2472. director_print( "next max ammo round " + level.director_max_ammo_round );
  2473. }
  2474. }
  2475. }
  2476.  
  2477. //-----------------------------------------------------------------------------------------------
  2478. // unaffected by instakill
  2479. //-----------------------------------------------------------------------------------------------
  2480. director_instakill()
  2481. {
  2482. }
  2483.  
  2484. //-----------------------------------------------------------------------------------------------
  2485. // humangun calms director for a short time unpacked
  2486. // calms director permanently when packed
  2487. // sends the director away if packed and shot in water
  2488. //-----------------------------------------------------------------------------------------------
  2489. director_humangun_hit_response( upgraded )
  2490. {
  2491. // ignore when entering/exiting the level
  2492. if ( is_true( self.defeated ) || is_true( self.leaving_level ) || is_true( self.entering_level ) )
  2493. {
  2494. return;
  2495. }
  2496.  
  2497. if ( upgraded )
  2498. {
  2499. if ( !is_true( self.impact_humangun_upgraded ) )
  2500. {
  2501. self.impact_humangun_upgraded = true;
  2502. self setclientflag( level._ZOMBIE_ACTOR_FLAG_HUMANGUN_UPGRADED_HIT_RESPONSE );
  2503. }
  2504. else
  2505. {
  2506. self.impact_humangun_upgraded = undefined;
  2507. self clearclientflag( level._ZOMBIE_ACTOR_FLAG_HUMANGUN_UPGRADED_HIT_RESPONSE );
  2508. }
  2509.  
  2510. if ( isDefined( self.water_trigger ) && isDefined( self.water_trigger.target ) )
  2511. {
  2512. self notify( "disable_activation" );
  2513. self notify( "disable_buff" );
  2514.  
  2515. self notify( "stop_find_flesh" );
  2516. self notify( "zombie_acquire_enemy" );
  2517.  
  2518. self notify( "humangun_leave" );
  2519.  
  2520. self.ignoreall = true;
  2521.  
  2522. self setclientflag( level._ZOMBIE_ACTOR_FLAG_DIRECTOR_DEATH );
  2523.  
  2524. exit = getstruct( self.water_trigger.target, "targetname" );
  2525. self thread director_leave_map( exit, true );
  2526. }
  2527. else
  2528. {
  2529. self director_humangun_react();
  2530. self director_calmed( undefined, true );
  2531. }
  2532. }
  2533. else
  2534. {
  2535. if ( !is_true( self.impact_humangun ) )
  2536. {
  2537. self.impact_humangun = true;
  2538. self setclientflag( level._ZOMBIE_ACTOR_FLAG_HUMANGUN_HIT_RESPONSE );
  2539. }
  2540. else
  2541. {
  2542. self.impact_humangun = undefined;
  2543. self clearclientflag( level._ZOMBIE_ACTOR_FLAG_HUMANGUN_HIT_RESPONSE );
  2544. }
  2545.  
  2546. if ( is_true( self.in_water ) )
  2547. {
  2548. return;
  2549. }
  2550.  
  2551. self director_humangun_react();
  2552. self director_calmed( 10, true );
  2553. }
  2554. }
  2555.  
  2556. //-----------------------------------------------------------------------------------------------
  2557. // immediate switch to walking when shot by humangun
  2558. //-----------------------------------------------------------------------------------------------
  2559. director_humangun_react()
  2560. {
  2561. if ( is_true( self.is_activated ) )
  2562. {
  2563. self notify( "disable_activation" );
  2564. self.finish_anim = undefined;
  2565. }
  2566.  
  2567. self animcustom( ::director_custom_idle );
  2568. self thread director_delay_melee( 0.6 );
  2569. }
  2570.  
  2571. director_delay_melee( time )
  2572. {
  2573. self endon( "death" );
  2574.  
  2575. self.cant_melee = true;
  2576. wait( time );
  2577. self.cant_melee = false;
  2578. }
  2579.  
  2580. director_custom_idle()
  2581. {
  2582. self endon( "death" );
  2583.  
  2584. idle_anim = %ai_zombie_boss_idle_b_coast;
  2585. self SetFlaggedAnimKnobAllRestart( "idle_anim", idle_anim, %body, 1, .1, 1 );
  2586. wait( 0.5 );
  2587. //animscripts\traverse\zombie_shared::wait_anim_length( idle_anim, .02 );
  2588. }
  2589.  
  2590. //-----------------------------------------------------------------------------------------------
  2591. // leave the map for x seconds / rounds
  2592. //-----------------------------------------------------------------------------------------------
  2593. director_leave_map( exit, calm )
  2594. {
  2595. self endon( "death" );
  2596.  
  2597. self.leaving_level = true;
  2598. self [[ level.director_exit_level ]]( exit, calm );
  2599. self.leaving_level = undefined;
  2600.  
  2601. if ( !is_true( self.defeated ) )
  2602. {
  2603. self thread director_reset_light_flag();
  2604. }
  2605.  
  2606. self thread director_reenter_map();
  2607.  
  2608. }
  2609.  
  2610. //-----------------------------------------------------------------------------------------------
  2611. // wait a bit and come back
  2612. //-----------------------------------------------------------------------------------------------
  2613. director_reenter_map()
  2614. {
  2615. r = RandomInt( 100 );
  2616. devgui_timeaway = 0;
  2617.  
  2618. /#
  2619. devgui_timeaway = GetDvarInt( #"scr_director_time_away" );
  2620. #/
  2621.  
  2622. if ( devgui_timeaway > 0 )
  2623. {
  2624. director_print( "devgui leave for " + devgui_timeaway );
  2625. wait( devgui_timeaway );
  2626. }
  2627. else if ( is_true( self.defeated ) || r > 50 )
  2628. {
  2629. director_print( "leaving for the round" );
  2630. level waittill( "between_round_over" );
  2631. wait( 1 );
  2632. level waittill( "between_round_over" );
  2633. }
  2634. else
  2635. {
  2636. s = RandomIntRange( 60, 300 );
  2637. director_print( "leaving for " + s + " seconds" );
  2638. wait( s );
  2639. }
  2640.  
  2641. self.entering_level = true;
  2642. self [[ level.director_reenter_level ]]();
  2643.  
  2644. self.performing_activation = false;
  2645. self.ground_hit = false;
  2646. self.following_player = false;
  2647. self.defeated = undefined;
  2648.  
  2649. level notify( "audio_begin_director_vox" );
  2650.  
  2651. self thread director_zombie_check_for_buff();
  2652. self thread director_watch_damage();
  2653. self thread director_zombie_update_goal_radius();
  2654. self thread director_zombie_update();
  2655.  
  2656. self.entering_level = undefined;
  2657. }
  2658.  
  2659. director_reenter_level()
  2660. {
  2661. }
  2662.  
  2663. director_exit_level()
  2664. {
  2665. }
  2666.  
  2667. director_find_exit()
  2668. {
  2669. }
  2670.  
  2671. //-----------------------------------------------------------------------------------------------
  2672. // play a transition anim
  2673. //-----------------------------------------------------------------------------------------------
  2674. director_transition( type )
  2675. {
  2676. self endon( "death" );
  2677.  
  2678. if ( !is_true( self.is_traversing ) )
  2679. {
  2680. if ( type == "walk" )
  2681. {
  2682. self.sprint2walk = true;
  2683. director_print( "sprint2walk" );
  2684. }
  2685. else if ( type == "sprint" )
  2686. {
  2687. self.walk2sprint = true;
  2688. director_print( "walk2sprint" );
  2689. }
  2690.  
  2691. self notify( "director_run_change" );
  2692. }
  2693. }
  2694.  
  2695. //-----------------------------------------------------------------------------------------------
  2696. // puts director back into docile state
  2697. //-----------------------------------------------------------------------------------------------
  2698. director_calmed( delay, humangun )
  2699. {
  2700. if ( is_true( self.is_activated ) )
  2701. {
  2702. director_print( "director_calmed" );
  2703.  
  2704. self.is_activated = false;
  2705. self notify( "director_calmed" );
  2706.  
  2707.  
  2708. if ( !is_true( self.in_water ) )
  2709. {
  2710. self thread director_zombie_check_for_activation();
  2711. }
  2712.  
  2713. if ( !is_true( humangun ) && !is_true( self.is_traversing ) && !is_true( self.ignore_transition ) )
  2714. {
  2715. self director_transition( "walk" );
  2716. }
  2717. else
  2718. {
  2719. self setmodel( "c_zom_george_romero_light_fb" );
  2720. self.director_zombified = undefined;
  2721. }
  2722. }
  2723.  
  2724. if ( isDefined( delay ) )
  2725. {
  2726. if ( isDefined( self.delay_time ) )
  2727. {
  2728. self.delay_time += delay * 1000;
  2729. }
  2730. else
  2731. {
  2732. self.delay_time = GetTime() + delay * 1000;
  2733. self thread director_delayed_activation();
  2734. }
  2735. }
  2736. }
  2737.  
  2738. director_delayed_activation()
  2739. {
  2740. self endon( "death" );
  2741. self endon( "disable_activation" );
  2742.  
  2743. while ( 1 )
  2744. {
  2745. if ( !isDefined( self.delay_time ) )
  2746. {
  2747. return;
  2748. }
  2749.  
  2750. if ( GetTime() >= self.delay_time )
  2751. {
  2752. if ( !self.is_activated )
  2753. {
  2754. self notify( "hit_player" );
  2755. }
  2756. self.delay_time = undefined;
  2757. return;
  2758. }
  2759.  
  2760. wait_network_frame();
  2761. }
  2762. }
  2763.  
  2764. //-----------------------------------------------------------------------------------------------
  2765. // play trail fx during a melee attack
  2766. //-----------------------------------------------------------------------------------------------
  2767. director_melee_anim( attack_anim )
  2768. {
  2769. self endon( "death" );
  2770.  
  2771. if ( !isDefined( self.is_melee ) )
  2772. {
  2773. self.is_melee = true;
  2774. time = getAnimLength( attack_anim );
  2775. wait( time );
  2776. self.is_melee = undefined;
  2777. }
  2778. }
  2779.  
  2780. //-----------------------------------------------------------------------------------------------
  2781. // override standing anims
  2782. //-----------------------------------------------------------------------------------------------
  2783. director_set_animarray_standing()
  2784. {
  2785. self.a.array["exposed_idle"] = array( %ai_zombie_boss_idle_a_coast, %ai_zombie_boss_idle_b_coast );
  2786. self.a.array["straight_level"] = %ai_zombie_boss_idle_a_coast;
  2787. self.a.array["stand_2_crouch"] = %ai_zombie_boss_idle_a_coast;
  2788. }
  2789.  
  2790. //-----------------------------------------------------------------------------------------------
  2791. // force director to melee hit if close enough
  2792. //-----------------------------------------------------------------------------------------------
  2793. director_melee_miss()
  2794. {
  2795. self endon( "death" );
  2796.  
  2797. if ( isDefined( self.enemy ) )
  2798. {
  2799. d = Distance( self.origin, self.enemy.origin );
  2800. //director_print( "director missed " + d );
  2801. heightDiff = abs( self.enemy.origin[2] - self.origin[2] ); // be sure we're on the same floor
  2802. if ( d <= self.meleeAttackDist && heightDiff < 96 )
  2803. {
  2804. if ( is_true( self.enemy.is_frozen ) )
  2805. {
  2806. if ( isDefined( self.enemy.ice_trigger ) )
  2807. {
  2808. self.enemy.ice_trigger notify( "damage" );
  2809. }
  2810. }
  2811. else
  2812. {
  2813. self.enemy DoDamage( self.meleeDamage, self.origin, self, 0, "MOD_MELEE" );
  2814. }
  2815. }
  2816. }
  2817. }
  2818.  
  2819. //-----------------------------------------------------------------------------------------------
  2820. // flail in air during a fling
  2821. //-----------------------------------------------------------------------------------------------
  2822. director_fling( pos )
  2823. {
  2824. self endon( "death" );
  2825.  
  2826. self.is_fling = true;
  2827. self animcustom( ::director_custom_fling );
  2828. self.is_fling = undefined;
  2829. }
  2830.  
  2831. director_custom_fling()
  2832. {
  2833. self endon( "death" );
  2834.  
  2835. fling_anim = %ai_zombie_boss_flinger_flail_coast;
  2836. self SetFlaggedAnimKnobAllRestart( "fling_anim", fling_anim, %body, 1, .1, 1 );
  2837. animscripts\traverse\zombie_shared::wait_anim_length( fling_anim, .02 );
  2838. }
  2839.  
  2840. //-----------------------------------------------------------------------------------------------
  2841. // attacker was not the player
  2842. //-----------------------------------------------------------------------------------------------
  2843. director_non_attacker( damage, weapon )
  2844. {
  2845. if ( is_true( self.leaving_level ) )
  2846. {
  2847. return damage;
  2848. }
  2849.  
  2850. if ( !is_true( self.is_activated ) )
  2851. {
  2852. self notify( "activation_damage", undefined, weapon );
  2853. }
  2854.  
  2855. return damage;
  2856. }
  2857.  
  2858. //-----------------------------------------------------------------------------------------------
  2859. // plays a one off anim
  2860. //-----------------------------------------------------------------------------------------------
  2861. director_animscripted( director_anim, director_notify, finish_anim )
  2862. {
  2863. if ( !is_true( self.finish_anim ) )
  2864. {
  2865. if ( is_true( finish_anim ) )
  2866. {
  2867. self.finish_anim = true;
  2868. }
  2869.  
  2870. self.is_animscripted = true;
  2871.  
  2872. time = getAnimLength( director_anim );
  2873. self animscripted( director_notify, self.origin, self.angles, director_anim, "normal", %body, 1, 0.1 );
  2874. wait( time );
  2875.  
  2876. self.is_animscripted = undefined;
  2877. self.finish_anim = undefined;
  2878. }
  2879. else
  2880. {
  2881. director_print( "animscripted never played" );
  2882. }
  2883. }
  2884.  
  2885. director_print( str )
  2886. {
  2887. /#
  2888. if ( is_true( level.debug_director ) )
  2889. {
  2890. iprintln( str + "\n" );
  2891. }
  2892. #/
  2893. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement