burc_2004

_zm_ai_avogadro.gsc

Oct 21st, 2015
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 41.79 KB | None | 0 0
  1. #include maps/mp/zombies/_zm_weap_riotshield;
  2. #include maps/mp/zombies/_zm_stats;
  3. #include maps/mp/zombies/_zm_laststand;
  4. #include maps/mp/zombies/_zm_zonemgr;
  5. #include maps/mp/animscripts/zm_shared;
  6. #include maps/mp/zm_transit_bus;
  7. #include maps/mp/zombies/_zm_ai_basic;
  8. #include maps/mp/zombies/_zm_spawner;
  9. #include maps/mp/zombies/_zm;
  10. #include maps/mp/_visionset_mgr;
  11. #include maps/mp/zombies/_zm_ai_avogadro;
  12. #include maps/mp/animscripts/zm_utility;
  13. #include maps/mp/zombies/_zm_utility;
  14. #include maps/mp/_utility;
  15. #include common_scripts/utility;
  16.  
  17. precache()
  18. {
  19.     precacheshellshock( "electrocution" );
  20. /#
  21.     precachemodel( "fx_axis_createfx" );
  22. #/
  23.     precache_fx();
  24. }
  25.  
  26. precache_fx()
  27. {
  28.     level._effect[ "avogadro_bolt" ] = loadfx( "maps/zombie/fx_zombie_tesla_bolt_secondary" );
  29.     level._effect[ "avogadro_ascend" ] = loadfx( "maps/zombie/fx_zmb_avog_ascend" );
  30.     level._effect[ "avogadro_ascend_aerial" ] = loadfx( "maps/zombie/fx_zmb_avog_ascend_aerial" );
  31.     level._effect[ "avogadro_descend" ] = loadfx( "maps/zombie/fx_zmb_avog_descend" );
  32.     level._effect[ "avogadro_phase_trail" ] = loadfx( "maps/zombie/fx_zmb_avog_phase_trail" );
  33.     level._effect[ "avogadro_phasing" ] = loadfx( "maps/zombie/fx_zmb_avog_phasing" );
  34.     level._effect[ "avogadro_health_full" ] = loadfx( "maps/zombie/fx_zmb_avog_health_full" );
  35.     level._effect[ "avogadro_health_half" ] = loadfx( "maps/zombie/fx_zmb_avog_health_half" );
  36.     level._effect[ "avogadro_health_low" ] = loadfx( "maps/zombie/fx_zmb_avog_health_low" );
  37. }
  38.  
  39. init()
  40. {
  41.     init_phase_anims();
  42.     init_regions();
  43.     level.avogadro_spawners = getentarray( "avogadro_zombie_spawner", "script_noteworthy" );
  44.     array_thread( level.avogadro_spawners, ::add_spawn_function, ::avogadro_prespawn );
  45.     level.zombie_ai_limit_avogadro = 1;
  46.     if ( !isDefined( level.vsmgr_prio_overlay_zm_ai_avogadro_electrified ) )
  47.     {
  48.         level.vsmgr_prio_overlay_zm_ai_avogadro_electrified = 75;
  49.     }
  50.     maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_ai_avogadro_electrified", 1, level.vsmgr_prio_overlay_zm_ai_avogadro_electrified, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 );
  51.     maps/mp/zombies/_zm::register_player_damage_callback( ::avogadro_player_damage_callback );
  52.     level thread avogadro_spawning_logic();
  53. }
  54.  
  55. init_phase_anims()
  56. {
  57.     level.avogadro_phase = [];
  58.     level.avogadro_phase[ 0 ] = spawnstruct();
  59.     level.avogadro_phase[ 0 ].animstate = "zm_teleport_forward";
  60.     level.avogadro_phase[ 1 ] = spawnstruct();
  61.     level.avogadro_phase[ 1 ].animstate = "zm_teleport_left";
  62.     level.avogadro_phase[ 2 ] = spawnstruct();
  63.     level.avogadro_phase[ 2 ].animstate = "zm_teleport_right";
  64.     level.avogadro_phase[ 3 ] = spawnstruct();
  65.     level.avogadro_phase[ 3 ].animstate = "zm_teleport_back";
  66. }
  67.  
  68. init_regions()
  69. {
  70.     level.transit_region = [];
  71.     level.transit_region[ "bus" ] = spawnstruct();
  72.     level.transit_region[ "diner" ] = spawnstruct();
  73.     level.transit_region[ "farm" ] = spawnstruct();
  74.     level.transit_region[ "cornfield" ] = spawnstruct();
  75.     level.transit_region[ "power" ] = spawnstruct();
  76.     level.transit_region[ "town" ] = spawnstruct();
  77.     level.transit_region[ "bus" ].zones = [];
  78.     level.transit_region[ "bus" ].zones[ 0 ] = "zone_pri";
  79.     level.transit_region[ "bus" ].zones[ 1 ] = "zone_station_ext";
  80.     level.transit_region[ "bus" ].exploder = 200;
  81.     level.transit_region[ "bus" ].sndorigin = ( -6909, 4531, 396 );
  82.     level.transit_region[ "diner" ].zones = [];
  83.     level.transit_region[ "diner" ].zones[ 0 ] = "zone_roadside_west";
  84.     level.transit_region[ "diner" ].zones[ 1 ] = "zone_din";
  85.     level.transit_region[ "diner" ].zones[ 2 ] = "zone_roadside_east";
  86.     level.transit_region[ "diner" ].zones[ 3 ] = "zone_gas";
  87.     level.transit_region[ "diner" ].zones[ 4 ] = "zone_gar";
  88.     level.transit_region[ "diner" ].exploder = 220;
  89.     level.transit_region[ "diner" ].sndorigin = ( -5239, -6842, 457 );
  90.     level.transit_region[ "farm" ].zones = [];
  91.     level.transit_region[ "farm" ].zones[ 0 ] = "zone_far";
  92.     level.transit_region[ "farm" ].zones[ 1 ] = "zone_far_ext";
  93.     level.transit_region[ "farm" ].zones[ 2 ] = "zone_brn";
  94.     level.transit_region[ "farm" ].zones[ 3 ] = "zone_farm_house";
  95.     level.transit_region[ "farm" ].exploder = 230;
  96.     level.transit_region[ "farm" ].sndorigin = ( 7954, -5799, 582 );
  97.     level.transit_region[ "cornfield" ].zones = [];
  98.     level.transit_region[ "cornfield" ].zones[ 0 ] = "zone_amb_cornfield";
  99.     level.transit_region[ "cornfield" ].zones[ 1 ] = "zone_cornfield_prototype";
  100.     level.transit_region[ "cornfield" ].exploder = 240;
  101.     level.transit_region[ "cornfield" ].sndorigin = ( 10278, -662, 324 );
  102.     level.transit_region[ "power" ].zones = [];
  103.     level.transit_region[ "power" ].zones[ 0 ] = "zone_prr";
  104.     level.transit_region[ "power" ].zones[ 1 ] = "zone_pow";
  105.     level.transit_region[ "power" ].zones[ 2 ] = "zone_pcr";
  106.     level.transit_region[ "power" ].zones[ 3 ] = "zone_pow_warehouse";
  107.     level.transit_region[ "power" ].exploder = 250;
  108.     level.transit_region[ "power" ].sndorigin = ( 10391, 7604, -70 );
  109.     level.transit_region[ "town" ].zones = [];
  110.     level.transit_region[ "town" ].zones[ 0 ] = "zone_tow";
  111.     level.transit_region[ "town" ].zones[ 1 ] = "zone_bar";
  112.     level.transit_region[ "town" ].zones[ 2 ] = "zone_ban";
  113.     level.transit_region[ "town" ].zones[ 3 ] = "zone_ban_vault";
  114.     level.transit_region[ "town" ].zones[ 4 ] = "zone_town_north";
  115.     level.transit_region[ "town" ].zones[ 5 ] = "zone_town_west";
  116.     level.transit_region[ "town" ].zones[ 6 ] = "zone_town_south";
  117.     level.transit_region[ "town" ].zones[ 7 ] = "zone_town_barber";
  118.     level.transit_region[ "town" ].zones[ 8 ] = "zone_town_church";
  119.     level.transit_region[ "town" ].zones[ 9 ] = "zone_town_east";
  120.     level.transit_region[ "town" ].exploder = 260;
  121.     level.transit_region[ "town" ].sndorigin = ( 1460, -416, 318 );
  122. }
  123.  
  124. avogadro_prespawn()
  125. {
  126.     self endon( "death" );
  127.     level endon( "intermission" );
  128.     level.avogadro = self;
  129.     self.has_legs = 1;
  130.     self.no_gib = 1;
  131.     self.is_avogadro = 1;
  132.     self.ignore_enemy_count = 1;
  133.     recalc_zombie_array();
  134.     self.ignore_nuke = 1;
  135.     self.ignore_lava_damage = 1;
  136.     self.ignore_devgui_death = 1;
  137.     self.ignore_electric_trap = 1;
  138.     self.ignore_game_over_death = 1;
  139.     self.ignore_enemyoverride = 1;
  140.     self.ignore_solo_last_stand = 1;
  141.     self.ignore_riotshield = 1;
  142.     self.allowpain = 0;
  143.     self.core_model = getent( "core_model", "targetname" );
  144.     if ( isDefined( self.core_model ) )
  145.     {
  146.         if ( !isDefined( self.core_model.angles ) )
  147.         {
  148.             self.core_model.angles = ( 0, 0, 1 );
  149.         }
  150.         self forceteleport( self.core_model.origin, self.core_model.angles );
  151.     }
  152.     self set_zombie_run_cycle( "walk" );
  153.     self animmode( "normal" );
  154.     self orientmode( "face enemy" );
  155.     self maps/mp/zombies/_zm_spawner::zombie_setup_attack_properties();
  156.     self maps/mp/zombies/_zm_spawner::zombie_complete_emerging_into_playable_area();
  157.     self setfreecameralockonallowed( 0 );
  158.     self.zmb_vocals_attack = "zmb_vocals_zombie_attack";
  159.     self.meleedamage = 5;
  160.     self.actor_damage_func = ::avogadro_damage_func;
  161.     self.non_attacker_func = ::avogadro_non_attacker;
  162.     self.anchor = spawn( "script_origin", self.origin );
  163.     self.anchor.angles = self.angles;
  164.     self.phase_time = 0;
  165.     self.audio_loop_ent = spawn( "script_origin", self.origin );
  166.     self.audio_loop_ent linkto( self, "tag_origin" );
  167.     self.hit_by_melee = 0;
  168.     self.damage_absorbed = 0;
  169.     self.ignoreall = 1;
  170.     self.zombie_init_done = 1;
  171.     self notify( "zombie_init_done" );
  172.     self.stun_zombie = ::stun_avogadro;
  173.     self.jetgun_fling_func = ::fling_avogadro;
  174.     self.jetgun_drag_func = ::drag_avogadro;
  175.     self.depot_lava_pit = ::busplowkillzombie;
  176.     self.busplowkillzombie = ::busplowkillzombie;
  177.     self.region_timer = getTime() + 500;
  178.     self.shield = 1;
  179. }
  180.  
  181. avogadro_spawning_logic()
  182. {
  183.     level endon( "intermission" );
  184.     if ( level.intermission )
  185.     {
  186.         return;
  187.     }
  188. /#
  189.     if ( getDvarInt( "zombie_cheat" ) == 2 || getDvarInt( "zombie_cheat" ) >= 4 )
  190.     {
  191.         return;
  192. #/
  193.     }
  194.     spawner = getent( "avogadro_zombie_spawner", "script_noteworthy" );
  195.     if ( !isDefined( spawner ) )
  196.     {
  197. /#
  198.         assertmsg( "No avogadro spawner in the map." );
  199. #/
  200.         return;
  201.     }
  202.     ai = spawn_zombie( spawner, "avogadro" );
  203.     if ( !isDefined( ai ) )
  204.     {
  205. /#
  206.         assertmsg( "Avogadro: failed spawn" );
  207. #/
  208.         return;
  209.     }
  210.     ai waittill( "zombie_init_done" );
  211.     core_mover = getent( "core_mover", "targetname" );
  212.     ai linkto( core_mover, "tag_origin" );
  213.     ai.state = "chamber";
  214.     ai setanimstatefromasd( "zm_chamber_idle" );
  215.     ai thread avogadro_think();
  216.     ai thread avogadro_bus_watcher();
  217. }
  218.  
  219. avogadro_think()
  220. {
  221.     while ( 1 )
  222.     {
  223.         while ( isDefined( self.in_pain ) && self.in_pain )
  224.         {
  225.             wait 0,1;
  226.         }
  227.         switch( self.state )
  228.         {
  229.             case "chamber":
  230.                 wait_idle();
  231.                 break;
  232.             case "wait_for_player":
  233.                 player_look();
  234.                 break;
  235.             case "idle":
  236.                 chase_player();
  237.                 break;
  238.             case "chasing":
  239.                 chase_update();
  240.                 break;
  241.             case "chasing_bus":
  242.                 chase_bus_update();
  243.                 break;
  244.             case "cloud":
  245.                 cloud_update();
  246.                 break;
  247.             case "stay_attached":
  248.                 attach_update();
  249.                 break;
  250.         }
  251.         wait 0,1;
  252.     }
  253. }
  254.  
  255. avogadro_bus_watcher()
  256. {
  257.     plow_trigger = getent( "trigger_plow", "targetname" );
  258.     while ( 1 )
  259.     {
  260.         while ( self.state == "chasing_bus" || self.state == "attacking_bus" )
  261.         {
  262.             wait 0,1;
  263.         }
  264.         if ( isDefined( level.the_bus ) && isDefined( level.the_bus.ismoving ) && level.the_bus.ismoving && level.the_bus getspeedmph() > 5 )
  265.         {
  266.             if ( self istouching( plow_trigger ) )
  267.             {
  268.                 phase_node = getnode( "back_door_node", "targetname" );
  269.                 self avogadro_teleport( phase_node.origin, phase_node.angles, 1 );
  270.             }
  271.         }
  272.         wait 0,1;
  273.     }
  274. }
  275.  
  276. busplowkillzombie()
  277. {
  278.     if ( isDefined( self.is_teleport ) && self.is_teleport )
  279.     {
  280.         return;
  281.     }
  282.     phase_node = getnode( "back_door_node", "targetname" );
  283.     self avogadro_teleport( phase_node.origin, phase_node.angles, 1 );
  284. }
  285.  
  286. phase_from_bus()
  287. {
  288.     self ghost();
  289.     self notsolid();
  290.     wait 3;
  291.     self show();
  292.     self solid();
  293.     self notify( "phase_from_bus_done" );
  294. }
  295.  
  296. wait_idle()
  297. {
  298. /#
  299.     if ( getDvarInt( #"CFA4158E" ) )
  300.     {
  301.         self.state = "wait_for_player";
  302.         self unlink();
  303. #/
  304.     }
  305.     if ( flag( "power_on" ) )
  306.     {
  307.         self.state = "wait_for_player";
  308.         self unlink();
  309.     }
  310. }
  311.  
  312. player_look()
  313. {
  314.     players = get_players();
  315.     _a427 = players;
  316.     _k427 = getFirstArrayKey( _a427 );
  317.     while ( isDefined( _k427 ) )
  318.     {
  319.         player = _a427[ _k427 ];
  320.         vec_enemy = self.origin - player.origin;
  321.         vec_facing = anglesToForward( player.angles );
  322.         norm_facing = vectornormalize( vec_facing );
  323.         norm_enemy = vectornormalize( vec_enemy );
  324.         dot = vectordot( norm_facing, norm_enemy );
  325.         if ( dot > 0,707 )
  326.         {
  327. /#
  328.             avogadro_print( "player spotted" );
  329. #/
  330.             self avogadro_exit( "chamber" );
  331.         }
  332.         _k427 = getNextArrayKey( _a427, _k427 );
  333.     }
  334. /#
  335.     if ( getDvarInt( #"CFA4158E" ) )
  336.     {
  337.         avogadro_print( "player_look ignored" );
  338.         self avogadro_exit( "chamber" );
  339. #/
  340.     }
  341. }
  342.  
  343. chase_player()
  344. {
  345.     self.state = "chasing";
  346.     self set_zombie_run_cycle( "run" );
  347.     self thread maps/mp/zombies/_zm_ai_basic::find_flesh();
  348. }
  349.  
  350. chase_update()
  351. {
  352.     if ( self check_bus_attack() )
  353.     {
  354.         self chase_bus();
  355.     }
  356.     else if ( self check_phase() )
  357.     {
  358.         self do_phase();
  359.     }
  360.     else
  361.     {
  362.         if ( self check_range_attack() )
  363.         {
  364.             self range_attack();
  365.         }
  366.     }
  367.     if ( self region_empty() )
  368.     {
  369.         self avogadro_exit( "exit_idle" );
  370.     }
  371. }
  372.  
  373. check_bus_attack()
  374. {
  375.     if ( isDefined( self.favoriteenemy ) && isDefined( self.favoriteenemy.isonbus ) && self.favoriteenemy.isonbus )
  376.     {
  377.         return 1;
  378.     }
  379.     return 0;
  380. }
  381.  
  382. chase_bus()
  383. {
  384.     self notify( "stop_find_flesh" );
  385.     self notify( "zombie_acquire_enemy" );
  386.     self.chase_bus_entry = undefined;
  387.     dist_curr = 0;
  388.     _a515 = level.the_bus.openings;
  389.     _k515 = getFirstArrayKey( _a515 );
  390.     while ( isDefined( _k515 ) )
  391.     {
  392.         opening = _a515[ _k515 ];
  393.         if ( !isDefined( self.chase_bus_entry ) )
  394.         {
  395.             self.chase_bus_entry = opening;
  396.             dist_curr = distance2dsquared( self.origin, level.the_bus gettagorigin( self.chase_bus_entry.tagname ) );
  397.         }
  398.         else
  399.         {
  400.             dist_next = distance2dsquared( self.origin, level.the_bus gettagorigin( opening.tagname ) );
  401.             if ( dist_next < dist_curr )
  402.             {
  403.                 dist_curr = dist_next;
  404.                 self.chase_bus_entry = opening;
  405.             }
  406.         }
  407.         _k515 = getNextArrayKey( _a515, _k515 );
  408.     }
  409.     self set_zombie_run_cycle( "sprint" );
  410.     self.state = "chasing_bus";
  411. }
  412.  
  413. chase_bus_update()
  414. {
  415.     bus = level.the_bus;
  416.     if ( isDefined( bus ) && bus.numplayerson == 0 )
  417.     {
  418.         self chase_player();
  419.         return;
  420.     }
  421.     tag_pos = level.the_bus gettagorigin( self.chase_bus_entry.tagname );
  422.     self setgoalpos( tag_pos );
  423.     if ( bus getspeedmph() > 5 )
  424.     {
  425.         self.phase_state = level.avogadro_phase[ 0 ].animstate;
  426.         self.phase_substate = 0;
  427.         self setfreecameralockonallowed( 0 );
  428.         self.ignoreall = 1;
  429.         self thread phase_failsafe();
  430.         self animcustom( ::play_phase_anim );
  431. /#
  432.         avogadro_print( "long phase after bus" );
  433. #/
  434.         self waittill( "phase_anim_done" );
  435.         self.ignoreall = 0;
  436.         self setfreecameralockonallowed( 1 );
  437.     }
  438.     dist_sq = distancesquared( self.origin, tag_pos );
  439.     if ( dist_sq < 14400 )
  440.     {
  441.         self bus_attack();
  442.     }
  443. }
  444.  
  445. bus_attack()
  446. {
  447.     self endon( "stunned" );
  448.     self endon( "stop_bus_attack" );
  449.     bus_attack_struct = [];
  450.     bus_attack_struct[ 0 ] = spawnstruct();
  451.     bus_attack_struct[ 0 ].window_tag = "window_left_rear_jnt";
  452.     bus_attack_struct[ 0 ].substate = "bus_attack_back";
  453.     bus_attack_struct[ 1 ] = spawnstruct();
  454.     bus_attack_struct[ 1 ].window_tag = "window_right_front_jnt";
  455.     bus_attack_struct[ 1 ].substate = "bus_attack_front";
  456.     bus_attack_struct[ 2 ] = spawnstruct();
  457.     bus_attack_struct[ 2 ].window_tag = "window_left_2_jnt";
  458.     bus_attack_struct[ 2 ].substate = "bus_attack_left";
  459.     bus_attack_struct[ 3 ] = spawnstruct();
  460.     bus_attack_struct[ 3 ].window_tag = "window_right_3_jnt";
  461.     bus_attack_struct[ 3 ].substate = "bus_attack_right";
  462.     random_attack_struct = array_randomize( bus_attack_struct );
  463.     self.state = "attacking_bus";
  464.     self.bus_attack_time = 0;
  465.     self.bus_disabled = 0;
  466.     self.ignoreall = 1;
  467.     i = 0;
  468.     while ( i < 4 )
  469.     {
  470.         while ( isDefined( self.in_pain ) && self.in_pain )
  471.         {
  472.             wait 0,1;
  473.         }
  474.         attack_struct = random_attack_struct[ i ];
  475. /#
  476.         window = getDvarInt( #"5628DC9F" );
  477.         if ( window >= 0 )
  478.         {
  479.             attack_struct = bus_attack_struct[ window ];
  480. #/
  481.         }
  482.         self bus_disable( attack_struct );
  483.         if ( self.bus_disabled )
  484.         {
  485.             break;
  486.         }
  487.         else
  488.         {
  489.             i++;
  490.         }
  491.     }
  492.     if ( !self.bus_disabled )
  493.     {
  494.         self.shield = 1;
  495.         self unlink();
  496.         self avogadro_exit( "bus" );
  497.     }
  498.     else
  499.     {
  500.         level.the_bus thread maps/mp/zm_transit_bus::bus_disabled_by_emp( 30 );
  501.         self attach_to_bus();
  502.     }
  503. }
  504.  
  505. attach_to_bus()
  506. {
  507.     self endon( "death" );
  508.     self endon( "stop_health" );
  509.     if ( level.the_bus.numaliveplayersridingbus > 0 )
  510.     {
  511. /#
  512.         avogadro_print( "stay_attached " + self.bus_attack_struct.substate );
  513. #/
  514.         origin = level.the_bus gettagorigin( self.bus_attack_struct.window_tag );
  515.         angles = level.the_bus gettagangles( self.bus_attack_struct.window_tag );
  516.         self show();
  517.         self.shield = 0;
  518.         self animscripted( origin, angles, "zm_bus_attack", self.bus_attack_struct.substate );
  519.         self.bus_shock_time = 0;
  520.         self.state = "stay_attached";
  521.         return;
  522.     }
  523.     self detach_from_bus();
  524. }
  525.  
  526. attach_update()
  527. {
  528.     if ( level.the_bus.numaliveplayersridingbus > 0 )
  529.     {
  530.         wait 0,1;
  531.         self.bus_shock_time += 0,1;
  532.         while ( self.bus_shock_time >= 2 )
  533.         {
  534.             self.bus_shock_time = 0;
  535.             players = get_players();
  536.             _a702 = players;
  537.             _k702 = getFirstArrayKey( _a702 );
  538.             while ( isDefined( _k702 ) )
  539.             {
  540.                 player = _a702[ _k702 ];
  541.                 if ( isDefined( player.isonbus ) && player.isonbus )
  542.                 {
  543.                     maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", player, 1, 1 );
  544.                     player shellshock( "electrocution", 1 );
  545.                     player notify( "avogadro_damage_taken" );
  546.                 }
  547.                 _k702 = getNextArrayKey( _a702, _k702 );
  548.             }
  549.         }
  550.         return;
  551.     }
  552.     self detach_from_bus();
  553. }
  554.  
  555. detach_from_bus()
  556. {
  557.     self unlink();
  558. /#
  559.     avogadro_print( "unlinking from bus window" );
  560. #/
  561.     bus_forward = vectornormalize( anglesToForward( level.the_bus.angles ) );
  562.     unlink_pos = level.the_bus.origin + vectorScale( bus_forward, -144 );
  563.     unlink_pos = groundpos_ignore_water_new( unlink_pos + vectorScale( ( 0, 0, 1 ), 60 ) );
  564.     self.shield = 1;
  565.     self avogadro_teleport( unlink_pos, self.angles, 1 );
  566.     self.state = "idle";
  567.     self.ignoreall = 0;
  568. }
  569.  
  570. bus_disable_show( time )
  571. {
  572.     self endon( "death" );
  573.     wait time;
  574.     self.shield = 0;
  575.     self show();
  576. }
  577.  
  578. bus_disable( bus_attack_struct )
  579. {
  580.     self endon( "melee_pain" );
  581.     self.bus_attack_struct = bus_attack_struct;
  582.     origin = level.the_bus gettagorigin( bus_attack_struct.window_tag );
  583.     angles = level.the_bus gettagangles( bus_attack_struct.window_tag );
  584.     self avogadro_teleport( origin, angles, 0,5, bus_attack_struct.window_tag );
  585.     self linkto( level.the_bus, bus_attack_struct.window_tag );
  586.     bus_disable_show( 0,1 );
  587.     origin = level.the_bus gettagorigin( bus_attack_struct.window_tag );
  588.     angles = level.the_bus gettagangles( bus_attack_struct.window_tag );
  589.     self animscripted( origin, angles, "zm_bus_attack", bus_attack_struct.substate );
  590. /#
  591.     avogadro_print( "bus_disable " + bus_attack_struct.substate );
  592. #/
  593.     success = 0;
  594.     self.mod_melee = 0;
  595.     self.bus_shock_time = 0;
  596.     level thread maps/mp/zm_transit_bus::do_player_bus_zombie_vox( "avogadro_onbus", 45 );
  597.     while ( 1 )
  598.     {
  599.         wait 0,1;
  600.         self.bus_attack_time += 0,1;
  601.         if ( self.bus_attack_time >= 20 )
  602.         {
  603.             self.bus_disabled = 1;
  604.             level thread maps/mp/zm_transit_bus::do_player_bus_zombie_vox( "avogadro_stopbus", 45 );
  605.             return;
  606.         }
  607.         else
  608.         {
  609.             self.bus_shock_time += 0,1;
  610.             while ( self.bus_shock_time >= 2 )
  611.             {
  612.                 self.bus_shock_time = 0;
  613.                 players = get_players();
  614.                 _a796 = players;
  615.                 _k796 = getFirstArrayKey( _a796 );
  616.                 while ( isDefined( _k796 ) )
  617.                 {
  618.                     player = _a796[ _k796 ];
  619.                     if ( isDefined( player.isonbus ) && player.isonbus )
  620.                     {
  621.                         maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", player, 1, 1 );
  622.                         player shellshock( "electrocution", 1 );
  623.                         player notify( "avogadro_damage_taken" );
  624.                         player thread do_player_general_vox( "general", "avogadro_attack", 30, 45 );
  625.                     }
  626.                     _k796 = getNextArrayKey( _a796, _k796 );
  627.                 }
  628.             }
  629.             if ( level.the_bus.numaliveplayersridingbus == 0 )
  630.             {
  631.                 self detach_from_bus();
  632.                 self notify( "stop_bus_attack" );
  633.             }
  634.         }
  635.     }
  636. }
  637.  
  638. avogadro_exit( from )
  639. {
  640.     self.state = "exiting";
  641.     self notify( "stop_find_flesh" );
  642.     self notify( "zombie_acquire_enemy" );
  643.     self setfreecameralockonallowed( 0 );
  644.     self.audio_loop_ent stoploopsound( 0,5 );
  645.     self notify( "stop_health" );
  646.     if ( isDefined( self.health_fx ) )
  647.     {
  648.         self.health_fx unlink();
  649.         self.health_fx delete();
  650.     }
  651.     if ( isDefined( from ) )
  652.     {
  653.         if ( from == "bus" )
  654.         {
  655.             self playsound( "zmb_avogadro_death_short" );
  656.             playfx( level._effect[ "avogadro_ascend_aerial" ], self.origin );
  657.             self animscripted( self.origin, self.angles, "zm_bus_win" );
  658.             maps/mp/animscripts/zm_shared::donotetracks( "bus_win_anim" );
  659.         }
  660.         else if ( from == "chamber" )
  661.         {
  662.             self playsound( "zmb_avogadro_death_short" );
  663.             playfx( level._effect[ "avogadro_ascend" ], self.origin );
  664.             self animscripted( self.origin, self.angles, "zm_chamber_out" );
  665.             wait 0,4;
  666.             self ghost();
  667.             stop_exploder( 500 );
  668.         }
  669.         else
  670.         {
  671.             self playsound( "zmb_avogadro_death" );
  672.             playfx( level._effect[ "avogadro_ascend" ], self.origin );
  673.             self animscripted( self.origin, self.angles, "zm_exit" );
  674.             maps/mp/animscripts/zm_shared::donotetracks( "exit_anim" );
  675.         }
  676.     }
  677.     else
  678.     {
  679.         self playsound( "zmb_avogadro_death" );
  680.         playfx( level._effect[ "avogadro_ascend" ], self.origin );
  681.         self animscripted( self.origin, self.angles, "zm_exit" );
  682.         maps/mp/animscripts/zm_shared::donotetracks( "exit_anim" );
  683.     }
  684.     if ( !isDefined( from ) || from != "chamber" )
  685.     {
  686.         level thread do_avogadro_flee_vo( self );
  687.     }
  688.     self ghost();
  689.     self.hit_by_melee = 0;
  690.     self.anchor.origin = self.origin;
  691.     self.anchor.angles = self.angles;
  692.     self linkto( self.anchor );
  693.     if ( isDefined( from ) && from == "exit_idle" )
  694.     {
  695.         self.return_round = level.round_number + 1;
  696.     }
  697.     else
  698.     {
  699.         self.return_round = level.round_number + randomintrange( 2, 5 );
  700.     }
  701.     level.next_avogadro_round = self.return_round;
  702.     self.state = "cloud";
  703.     self thread cloud_update_fx();
  704. }
  705.  
  706. cloud_update_fx()
  707. {
  708.     self endon( "cloud_fx_end" );
  709.     level endon( "end_game" );
  710.     region = [];
  711.     region[ 0 ] = "bus";
  712.     region[ 1 ] = "diner";
  713.     region[ 2 ] = "farm";
  714.     region[ 3 ] = "cornfield";
  715.     region[ 4 ] = "power";
  716.     region[ 5 ] = "town";
  717.     self.current_region = undefined;
  718.     if ( !isDefined( self.sndent ) )
  719.     {
  720.         self.sndent = spawn( "script_origin", ( 0, 0, 1 ) );
  721.         self.sndent playloopsound( "zmb_avogadro_thunder_overhead" );
  722.     }
  723.     cloud_time = getTime();
  724.     vo_counter = 0;
  725.     while ( 1 )
  726.     {
  727.         if ( getTime() >= cloud_time )
  728.         {
  729.             if ( isDefined( self.current_region ) )
  730.             {
  731.                 exploder_num = level.transit_region[ self.current_region ].exploder;
  732.                 stop_exploder( exploder_num );
  733.             }
  734.             rand_region = array_randomize( region );
  735.             region_str = rand_region[ 0 ];
  736.             if ( !isDefined( self.current_region ) )
  737.             {
  738.                 region_str = region[ 4 ];
  739.             }
  740. /#
  741.             idx = getDvarInt( #"FD251E42" );
  742.             if ( idx >= 0 )
  743.             {
  744.                 region_str = region[ idx ];
  745.             }
  746.             avogadro_print( "clouds in region " + region_str );
  747. #/
  748.             self.current_region = region_str;
  749.             exploder_num = level.transit_region[ region_str ].exploder;
  750.             exploder( exploder_num );
  751.             self.sndent moveto( level.transit_region[ region_str ].sndorigin, 3 );
  752.             cloud_time = getTime() + 30000;
  753.         }
  754.         if ( vo_counter > 50 )
  755.         {
  756.             player = self get_player_in_region();
  757.             if ( isDefined( player ) )
  758.             {
  759.                 if ( isDefined( self._in_cloud ) && self._in_cloud )
  760.                 {
  761.                     player thread do_player_general_vox( "general", "avogadro_above", 90, 10 );
  762.                 }
  763.                 else
  764.                 {
  765.                     player thread do_player_general_vox( "general", "avogadro_arrive", 60, 40 );
  766.                 }
  767.             }
  768.             else
  769.             {
  770.                 level thread avogadro_storm_vox();
  771.             }
  772.             vo_counter = 0;
  773.         }
  774.         wait 0,1;
  775.         vo_counter++;
  776.     }
  777. }
  778.  
  779. cloud_update()
  780. {
  781.     self endon( "melee_pain" );
  782.     return_from_cloud = 0;
  783.     self._in_cloud = 1;
  784.     if ( level.round_number >= self.return_round )
  785.     {
  786. /#
  787.         avogadro_print( "return from round" );
  788. #/
  789.         return_from_cloud = 1;
  790.         self._in_cloud = 0;
  791.     }
  792.     while ( isDefined( return_from_cloud ) && return_from_cloud )
  793.     {
  794. /#
  795.         avogadro_print( "time to come back in " + self.current_region );
  796. #/
  797.         self notify( "cloud_fx_end" );
  798.         new_origin = cloud_find_spawn();
  799.         if ( isDefined( self.sndent ) )
  800.         {
  801.             self.sndent delete();
  802.             self.sndent = undefined;
  803.         }
  804.         if ( !isDefined( new_origin ) )
  805.         {
  806.             new_origin = maps/mp/zombies/_zm::check_for_valid_spawn_near_team();
  807.         }
  808.         while ( isDefined( new_origin ) )
  809.         {
  810.             self thread avogadro_update_health();
  811.             playsoundatposition( "zmb_avogadro_spawn_3d", new_origin );
  812.             self.audio_loop_ent playloopsound( "zmb_avogadro_loop", 0,5 );
  813.             self unlink();
  814.             ground_pos = groundpos_ignore_water_new( new_origin + vectorScale( ( 0, 0, 1 ), 60 ) );
  815.             playfx( level._effect[ "avogadro_descend" ], ground_pos );
  816.             self animscripted( ground_pos, self.anchor.angles, "zm_arrival" );
  817.             maps/mp/animscripts/zm_shared::donotetracks( "arrival_anim" );
  818.             self setfreecameralockonallowed( 1 );
  819.             time_to_leave = getTime() + 30000;
  820.             while ( 1 )
  821.             {
  822.                 if ( getTime() > time_to_leave )
  823.                 {
  824. /#
  825.                     avogadro_print( "enemy never showed - leaving" );
  826. #/
  827.                     self avogadro_exit( "exit_idle" );
  828.                     return;
  829.                 }
  830.                 if ( self enemy_in_region() )
  831.                 {
  832.                     self.ignoreall = 0;
  833.                     self.state = "idle";
  834.                     return;
  835.                 }
  836.                 wait 0,1;
  837.             }
  838.         }
  839.     }
  840. }
  841.  
  842. enemy_in_region()
  843. {
  844.     zones = level.transit_region[ self.current_region ].zones;
  845.     _a1071 = zones;
  846.     _k1071 = getFirstArrayKey( _a1071 );
  847.     while ( isDefined( _k1071 ) )
  848.     {
  849.         zone = _a1071[ _k1071 ];
  850.         if ( level.zones[ zone ].is_occupied )
  851.         {
  852.             self.ignoreall = 0;
  853.             self.state = "idle";
  854.             return 1;
  855.         }
  856.         _k1071 = getNextArrayKey( _a1071, _k1071 );
  857.     }
  858.     return 0;
  859. }
  860.  
  861. get_player_in_region()
  862. {
  863.     players = get_players();
  864.     players = array_randomize( players );
  865.     zones = level.transit_region[ self.current_region ].zones;
  866.     _a1091 = zones;
  867.     _k1091 = getFirstArrayKey( _a1091 );
  868.     while ( isDefined( _k1091 ) )
  869.     {
  870.         zone = _a1091[ _k1091 ];
  871.         while ( level.zones[ zone ].is_occupied )
  872.         {
  873.             _a1095 = players;
  874.             _k1095 = getFirstArrayKey( _a1095 );
  875.             while ( isDefined( _k1095 ) )
  876.             {
  877.                 player = _a1095[ _k1095 ];
  878.                 if ( player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( zone ) )
  879.                 {
  880.                     return player;
  881.                 }
  882.                 _k1095 = getNextArrayKey( _a1095, _k1095 );
  883.             }
  884.         }
  885.         _k1091 = getNextArrayKey( _a1091, _k1091 );
  886.     }
  887.     return undefined;
  888. }
  889.  
  890. cloud_find_spawn()
  891. {
  892.     zones = level.transit_region[ self.current_region ].zones;
  893.     use_points = [];
  894.     _a1116 = zones;
  895.     _k1116 = getFirstArrayKey( _a1116 );
  896.     while ( isDefined( _k1116 ) )
  897.     {
  898.         zone = _a1116[ _k1116 ];
  899.         if ( zone == "zone_pri" )
  900.         {
  901.             if ( !level.zones[ zone ].is_occupied )
  902.             {
  903.                 if ( !flag( "OnPriDoorYar2" ) )
  904.                 {
  905. /#
  906.                     avogadro_print( "zone_pri not occupied and door is closed" );
  907. #/
  908.                 }
  909.             }
  910.         }
  911.         else
  912.         {
  913.             while ( level.zones[ zone ].is_enabled && level.zones[ zone ].is_spawning_allowed )
  914.             {
  915.                 locations = level.zones[ zone ].avogadro_locations;
  916.                 _a1135 = locations;
  917.                 _k1135 = getFirstArrayKey( _a1135 );
  918.                 while ( isDefined( _k1135 ) )
  919.                 {
  920.                     loc = _a1135[ _k1135 ];
  921.                     use_points[ use_points.size ] = loc;
  922.                     _k1135 = getNextArrayKey( _a1135, _k1135 );
  923.                 }
  924.             }
  925.         }
  926.         _k1116 = getNextArrayKey( _a1116, _k1116 );
  927.     }
  928.     if ( use_points.size > 0 )
  929.     {
  930.         use_points = array_randomize( use_points );
  931.         return use_points[ 0 ].origin;
  932.     }
  933.     return undefined;
  934. }
  935.  
  936. avogadro_reveal( show_time )
  937. {
  938.     self endon( "death" );
  939.     self show();
  940.     wait show_time;
  941.     self ghost();
  942. }
  943.  
  944. avogadro_teleport( dest_pos, dest_angles, lerp_time, tag_override )
  945. {
  946.     self.is_teleport = 1;
  947.     self.phase_fx = spawn( "script_model", self.origin );
  948.     self.phase_fx setmodel( "tag_origin" );
  949.     self.phase_fx linkto( self );
  950.     wait 0,1;
  951.     playfxontag( level._effect[ "avogadro_phase_trail" ], self.phase_fx, "tag_origin" );
  952.     playfx( level._effect[ "avogadro_phasing" ], self.origin );
  953.     self avogadro_reveal( 0,1 );
  954.     self playsound( "zmb_avogadro_warp_out" );
  955.     self.anchor.origin = self.origin;
  956.     self.anchor.angles = self.angles;
  957.     self linkto( self.anchor );
  958.     self.anchor moveto( dest_pos, lerp_time );
  959.     self.anchor waittill( "movedone" );
  960.     self.anchor.origin = dest_pos;
  961.     self.anchor.angles = dest_angles;
  962.     self unlink();
  963.     wait 0,1;
  964.     if ( isDefined( tag_override ) )
  965.     {
  966.         dest_pos = level.the_bus gettagorigin( tag_override );
  967.         dest_angles = level.the_bus gettagangles( tag_override );
  968.     }
  969.     self forceteleport( dest_pos, dest_angles );
  970.     playfx( level._effect[ "avogadro_phasing" ], self.origin );
  971.     if ( isDefined( self.phase_fx ) )
  972.     {
  973.         self.phase_fx delete();
  974.     }
  975.     self avogadro_reveal( 0,1 );
  976.     self playsound( "zmb_avogadro_warp_in" );
  977.     self.is_teleport = 0;
  978. }
  979.  
  980. check_range_attack()
  981. {
  982. /#
  983.     if ( getDvarInt( #"A40002E9" ) )
  984.     {
  985.         return 0;
  986. #/
  987.     }
  988.     enemy = self.favoriteenemy;
  989.     if ( isDefined( enemy ) )
  990.     {
  991.         vec_enemy = enemy.origin - self.origin;
  992.         dist_sq = lengthsquared( vec_enemy );
  993.         if ( dist_sq > 14400 && dist_sq < 360000 )
  994.         {
  995.             vec_facing = anglesToForward( self.angles );
  996.             norm_facing = vectornormalize( vec_facing );
  997.             norm_enemy = vectornormalize( vec_enemy );
  998.             dot = vectordot( norm_facing, norm_enemy );
  999.             if ( dot > 0,99 )
  1000.             {
  1001.                 enemy_eye_pos = enemy geteye();
  1002.                 eye_pos = self geteye();
  1003.                 passed = bullettracepassed( eye_pos, enemy_eye_pos, 0, undefined );
  1004.                 if ( passed )
  1005.                 {
  1006.                     return 1;
  1007.                 }
  1008.             }
  1009.         }
  1010.     }
  1011.     return 0;
  1012. }
  1013.  
  1014. range_attack()
  1015. {
  1016.     self endon( "melee_pain" );
  1017.     enemy = self.favoriteenemy;
  1018.     if ( isDefined( enemy ) )
  1019.     {
  1020.         self thread shoot_bolt_wait( "ranged_attack", enemy );
  1021.         self show();
  1022.         self animscripted( self.origin, self.angles, "zm_ranged_attack_in" );
  1023.         maps/mp/animscripts/zm_shared::donotetracks( "ranged_attack" );
  1024.         self animscripted( self.origin, self.angles, "zm_ranged_attack_loop" );
  1025.         maps/mp/animscripts/zm_shared::donotetracks( "ranged_attack" );
  1026.         self animscripted( self.origin, self.angles, "zm_ranged_attack_out" );
  1027.         maps/mp/animscripts/zm_shared::donotetracks( "ranged_attack" );
  1028.         self.shield = 1;
  1029.         self thread avogadro_update_health();
  1030.         self ghost();
  1031.     }
  1032. }
  1033.  
  1034. shoot_bolt_wait( animname, enemy )
  1035. {
  1036.     self endon( "melee_pain" );
  1037.     self waittillmatch( animname );
  1038.     return "fire";
  1039.     self.shield = 0;
  1040.     self notify( "stop_health" );
  1041.     if ( isDefined( self.health_fx ) )
  1042.     {
  1043.         self.health_fx unlink();
  1044.         self.health_fx delete();
  1045.     }
  1046.     self thread shoot_bolt( enemy );
  1047. }
  1048.  
  1049. shoot_bolt( enemy )
  1050. {
  1051.     source_pos = self gettagorigin( "tag_weapon_right" );
  1052.     target_pos = enemy geteye();
  1053.     bolt = spawn( "script_model", source_pos );
  1054.     bolt setmodel( "tag_origin" );
  1055.     wait 0,1;
  1056.     self playsound( "zmb_avogadro_attack" );
  1057.     fx = playfxontag( level._effect[ "avogadro_bolt" ], bolt, "tag_origin" );
  1058.     bolt moveto( target_pos, 0,2 );
  1059.     bolt waittill( "movedone" );
  1060.     bolt.owner = self;
  1061.     bolt check_bolt_impact( enemy );
  1062.     bolt delete();
  1063. }
  1064.  
  1065. check_bolt_impact( enemy )
  1066. {
  1067.     if ( is_player_valid( enemy ) )
  1068.     {
  1069.         enemy_eye_pos = enemy geteye();
  1070.         dist_sq = distancesquared( self.origin, enemy_eye_pos );
  1071.         if ( dist_sq < 4096 )
  1072.         {
  1073.             passed = bullettracepassed( self.origin, enemy_eye_pos, 0, undefined );
  1074.             if ( passed )
  1075.             {
  1076.                 maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", enemy, 1, 1 );
  1077.                 enemy shellshock( "electrocution", 1 );
  1078.                 enemy playsoundtoplayer( "zmb_avogadro_electrified", enemy );
  1079.                 enemy dodamage( 60, enemy.origin );
  1080.                 enemy notify( "avogadro_damage_taken" );
  1081.             }
  1082.         }
  1083.     }
  1084. }
  1085.  
  1086. region_empty()
  1087. {
  1088.     if ( getTime() >= self.region_timer )
  1089.     {
  1090.         player = self get_player_in_region();
  1091.         if ( isDefined( player ) )
  1092.         {
  1093.             self.region_timer = getTime() + 500;
  1094.             return 0;
  1095.         }
  1096. /#
  1097.         debug_dist_sq = 0;
  1098. #/
  1099.         players = getplayers();
  1100.         _a1371 = players;
  1101.         _k1371 = getFirstArrayKey( _a1371 );
  1102.         while ( isDefined( _k1371 ) )
  1103.         {
  1104.             player = _a1371[ _k1371 ];
  1105.             if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() )
  1106.             {
  1107.             }
  1108.             else
  1109.             {
  1110.                 dist_sq = distancesquared( self.origin, player.origin );
  1111. /#
  1112.                 debug_dist_sq = distance( self.origin, player.origin );
  1113. #/
  1114.                 if ( dist_sq < 9000000 )
  1115.                 {
  1116.                     self.region_timer = getTime() + 500;
  1117.                     return 0;
  1118.                 }
  1119.             }
  1120.             _k1371 = getNextArrayKey( _a1371, _k1371 );
  1121.         }
  1122.         self.region_timer = getTime() + 500;
  1123. /#
  1124.         avogadro_print( "no one left to kill " + debug_dist_sq );
  1125. #/
  1126.         return 1;
  1127.     }
  1128.     return 0;
  1129. }
  1130.  
  1131. get_random_phase_state()
  1132. {
  1133.     index = randomint( 4 );
  1134.     state = level.avogadro_phase[ index ].animstate;
  1135.     return state;
  1136. }
  1137.  
  1138. check_phase()
  1139. {
  1140. /#
  1141.     if ( getDvarInt( #"CFB33742" ) )
  1142.     {
  1143.         return 0;
  1144. #/
  1145.     }
  1146.     if ( getTime() > self.phase_time )
  1147.     {
  1148.         if ( isDefined( self.is_traversing ) && self.is_traversing )
  1149.         {
  1150.             self.phase_time = getTime() + 2000;
  1151.             return 0;
  1152.         }
  1153.         self.phase_state = get_random_phase_state();
  1154.         self.phase_substate = randomint( 3 );
  1155.         anim_id = self getanimfromasd( self.phase_state, self.phase_substate );
  1156.         if ( self maymovefrompointtopoint( self.origin, getanimendpos( anim_id ) ) )
  1157.         {
  1158.             return 1;
  1159.         }
  1160.     }
  1161.     return 0;
  1162. }
  1163.  
  1164. do_phase()
  1165. {
  1166.     self endon( "death" );
  1167.     self.state = "phasing";
  1168.     self notify( "stop_find_flesh" );
  1169.     self notify( "zombie_acquire_enemy" );
  1170.     self setfreecameralockonallowed( 0 );
  1171.     self.ignoreall = 1;
  1172.     self thread phase_failsafe();
  1173.     self animcustom( ::play_phase_anim );
  1174.     self waittill( "phase_anim_done" );
  1175.     self.ignoreall = 0;
  1176.     self setfreecameralockonallowed( 1 );
  1177.     self.state = "idle";
  1178. }
  1179.  
  1180. play_phase_anim()
  1181. {
  1182.     self endon( "death" );
  1183.     self endon( "phase_anim_done" );
  1184.     self.phase_fx = spawn( "script_model", self.origin );
  1185.     self.phase_fx setmodel( "tag_origin" );
  1186.     self.phase_fx linkto( self );
  1187.     wait 0,05;
  1188.     playfxontag( level._effect[ "avogadro_phase_trail" ], self.phase_fx, "tag_origin" );
  1189.     playfx( level._effect[ "avogadro_phasing" ], self.origin );
  1190.     self avogadro_reveal( 0,1 );
  1191.     self playsound( "zmb_avogadro_warp_out" );
  1192.     self orientmode( "face enemy" );
  1193.     self setanimstatefromasd( self.phase_state, self.phase_substate );
  1194.     maps/mp/animscripts/zm_shared::donotetracks( "teleport_anim" );
  1195.     self.phase_fx delete();
  1196.     playfx( level._effect[ "avogadro_phasing" ], self.origin );
  1197.     self avogadro_reveal( 0,1 );
  1198.     self orientmode( "face default" );
  1199.     self playsound( "zmb_avogadro_warp_in" );
  1200.     self.phase_time = getTime() + 2000;
  1201.     self notify( "phase_anim_done" );
  1202. }
  1203.  
  1204. phase_failsafe()
  1205. {
  1206.     self endon( "phase_anim_done" );
  1207.     wait 1;
  1208.     if ( self.state == "phasing" || self.state == "chasing_bus" )
  1209.     {
  1210. /#
  1211.         avogadro_print( "phasing too long, failsafe kicking in" );
  1212. #/
  1213.         if ( isDefined( self.phase_fx ) )
  1214.         {
  1215.             self.phase_fx delete();
  1216.         }
  1217.         playfx( level._effect[ "avogadro_phasing" ], self.origin );
  1218.         self avogadro_reveal( 0,1 );
  1219.         self orientmode( "face default" );
  1220.         self playsound( "zmb_avogadro_warp_in" );
  1221.         self.phase_time = getTime() + 2000;
  1222.         self notify( "phase_anim_done" );
  1223.     }
  1224. }
  1225.  
  1226. avogadro_player_damage_callback( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime )
  1227. {
  1228.     if ( isDefined( einflictor ) && isDefined( einflictor.is_avogadro ) && einflictor.is_avogadro )
  1229.     {
  1230.         if ( smeansofdeath == "MOD_MELEE" )
  1231.         {
  1232.             maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", self, 0,25, 1 );
  1233.             self shellshock( "electrocution", 0,25 );
  1234.             self notify( "avogadro_damage_taken" );
  1235.             self thread do_player_general_vox( "general", "avogadro_attack", 15, 45 );
  1236.         }
  1237.     }
  1238.     return -1;
  1239. }
  1240.  
  1241. avogadro_pain_watcher()
  1242. {
  1243.     self notify( "stop_pain_watcher" );
  1244.     self endon( "stop_pain_watcher" );
  1245.     wait 4;
  1246.     if ( isDefined( self.in_pain ) && self.in_pain )
  1247.     {
  1248.         self.in_pain = 0;
  1249. /#
  1250.         avogadro_print( "in_pain for too long" );
  1251. #/
  1252.     }
  1253. }
  1254.  
  1255. avogadro_pain( einflictor )
  1256. {
  1257.     self endon( "melee_pain" );
  1258.     self.in_pain = 1;
  1259.     self playsound( "zmb_avogadro_pain" );
  1260.     self thread avogadro_pain_watcher();
  1261.     substate = 0;
  1262.     origin = self.origin;
  1263.     angles = self.angles;
  1264.     animstate = "zm_pain";
  1265.     if ( self.state == "attacking_bus" || self.state == "stay_attached" )
  1266.     {
  1267.         tag = self.bus_attack_struct.window_tag;
  1268.         if ( tag == "window_left_rear_jnt" )
  1269.         {
  1270.             animstate = "zm_bus_back_pain";
  1271.         }
  1272.         else
  1273.         {
  1274.             animstate = "zm_bus_pain";
  1275.         }
  1276.         origin = level.the_bus gettagorigin( tag );
  1277.         angles = level.the_bus gettagangles( tag );
  1278.     }
  1279.     if ( self.hit_by_melee < 4 )
  1280.     {
  1281.         self thread avogadro_update_health();
  1282.         self animscripted( origin, angles, animstate, substate );
  1283.         maps/mp/animscripts/zm_shared::donotetracks( "pain_anim" );
  1284.         self ghost();
  1285.         self.phase_time = getTime() - 1;
  1286.         if ( self.state == "stay_attached" )
  1287.         {
  1288.             self attach_to_bus();
  1289.         }
  1290.     }
  1291.     else self notify( "stop_bus_attack" );
  1292.     level notify( "avogadro_defeated" );
  1293.     if ( isDefined( einflictor ) && isplayer( einflictor ) )
  1294.     {
  1295.         einflictor maps/mp/zombies/_zm_stats::increment_client_stat( "avogadro_defeated", 0 );
  1296.         einflictor maps/mp/zombies/_zm_stats::increment_player_stat( "avogadro_defeated" );
  1297.     }
  1298.     if ( flag( "power_on" ) && flag( "switches_on" ) && self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr" ) )
  1299.     {
  1300. /#
  1301.         avogadro_print( "come back on power" );
  1302. #/
  1303.         self show();
  1304.         self.in_pain = 0;
  1305. /#
  1306.         avogadro_print( "pain cleared from zone_prr" );
  1307. #/
  1308.         self notify( "stop_pain_watcher" );
  1309.         self avogadro_teleport( self.core_model.origin, self.core_model.angles, 1 );
  1310.         core_mover = getent( "core_mover", "targetname" );
  1311.         self linkto( core_mover, "tag_origin" );
  1312.         while ( flag( "power_on" ) )
  1313.         {
  1314.             wait 0,1;
  1315.         }
  1316.         self show();
  1317.         self.state = "chamber";
  1318.         self setanimstatefromasd( "zm_chamber_idle" );
  1319.     }
  1320.     else
  1321.     {
  1322. /#
  1323.         if ( !flag( "power_on" ) )
  1324.         {
  1325.             avogadro_print( "no power" );
  1326.         }
  1327.         if ( !flag( "switches_on" ) )
  1328.         {
  1329.             avogadro_print( "no switches" );
  1330.         }
  1331.         if ( !self maps/mp/zombies/_zm_zonemgr::entity_in_zone( "zone_prr" ) )
  1332.         {
  1333.             avogadro_print( "no zone" );
  1334. #/
  1335.         }
  1336.         self show();
  1337.         self avogadro_exit();
  1338.     }
  1339.     self.in_pain = 0;
  1340. /#
  1341.     avogadro_print( "pain cleared normal" );
  1342. #/
  1343.     self notify( "stop_pain_watcher" );
  1344. }
  1345.  
  1346. avogadro_update_health()
  1347. {
  1348.     self endon( "death" );
  1349.     self notify( "stop_health" );
  1350.     self endon( "stop_health" );
  1351.     while ( 1 )
  1352.     {
  1353.         self avogadro_update_health_fx();
  1354.         wait 0,4;
  1355.     }
  1356. }
  1357.  
  1358. avogadro_update_health_fx()
  1359. {
  1360.     self endon( "death" );
  1361.     if ( !isDefined( self.health_fx ) )
  1362.     {
  1363.         tag_origin = self gettagorigin( "J_SpineUpper" );
  1364.         tag_angles = self gettagangles( "J_SpineUpper" );
  1365.         self.health_fx = spawn( "script_model", tag_origin );
  1366.         self.health_fx.angles = tag_angles;
  1367.         self.health_fx setmodel( "tag_origin" );
  1368.         self.health_fx linkto( self );
  1369.         wait 0,1;
  1370.     }
  1371.     if ( self.hit_by_melee == 0 )
  1372.     {
  1373.         playfxontag( level._effect[ "avogadro_health_full" ], self.health_fx, "tag_origin" );
  1374.     }
  1375.     else if ( self.hit_by_melee <= 2 )
  1376.     {
  1377.         playfxontag( level._effect[ "avogadro_health_half" ], self.health_fx, "tag_origin" );
  1378.     }
  1379.     else
  1380.     {
  1381.         playfxontag( level._effect[ "avogadro_health_low" ], self.health_fx, "tag_origin" );
  1382.     }
  1383. }
  1384.  
  1385. avogadro_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex )
  1386. {
  1387.     if ( self.state == "exiting" || self.state == "phasing" )
  1388.     {
  1389.         return 0;
  1390.     }
  1391.     if ( smeansofdeath == "MOD_MELEE" )
  1392.     {
  1393.         if ( isplayer( einflictor ) )
  1394.         {
  1395.             if ( isDefined( einflictor.avogadro_melee_time ) )
  1396.             {
  1397.             }
  1398.             if ( self.shield )
  1399.             {
  1400.                 einflictor.avogadro_melee_time = getTime();
  1401.                 maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_ai_avogadro_electrified", einflictor, 0,25, 1 );
  1402.                 einflictor shellshock( "electrocution", 0,25 );
  1403.                 einflictor notify( "avogadro_damage_taken" );
  1404.             }
  1405.             if ( sweapon == "riotshield_zm" )
  1406.             {
  1407.                 shield_damage = level.zombie_vars[ "riotshield_fling_damage_shield" ];
  1408.                 einflictor maps/mp/zombies/_zm_weap_riotshield::player_damage_shield( shield_damage, 0 );
  1409.             }
  1410.         }
  1411.         if ( !self.shield )
  1412.         {
  1413.             self.shield = 1;
  1414.             self notify( "melee_pain" );
  1415.             if ( sweapon == "tazer_knuckles_zm" )
  1416.             {
  1417.                 self.hit_by_melee += 2;
  1418.             }
  1419.             else
  1420.             {
  1421.                 self.hit_by_melee++;
  1422.             }
  1423.             self thread avogadro_pain( einflictor );
  1424. /#
  1425.             avogadro_print( "hit_by_melee: " + self.hit_by_melee );
  1426. #/
  1427.             if ( isplayer( einflictor ) )
  1428.             {
  1429.                 einflictor thread do_player_general_vox( "general", "avogadro_wound", 30, 35 );
  1430.                 level notify( "avogadro_stabbed" );
  1431.             }
  1432.         }
  1433.         else
  1434.         {
  1435. /#
  1436.             avogadro_print( "shield up, no damage" );
  1437. #/
  1438.         }
  1439.     }
  1440.     else
  1441.     {
  1442.         self update_damage_absorbed( idamage );
  1443.     }
  1444.     return 0;
  1445. }
  1446.  
  1447. update_damage_absorbed( damage )
  1448. {
  1449.     if ( self.hit_by_melee > 0 )
  1450.     {
  1451.         self.damage_absorbed += damage;
  1452.         if ( self.damage_absorbed >= 1000 )
  1453.         {
  1454.             self.damage_absorbed = 0;
  1455.             self.hit_by_melee--;
  1456.  
  1457. /#
  1458.             avogadro_print( "regen - hit_by_melee: " + self.hit_by_melee );
  1459. #/
  1460.         }
  1461.     }
  1462. }
  1463.  
  1464. avogadro_non_attacker( damage, weapon )
  1465. {
  1466.     if ( weapon == "zombie_bullet_crouch_zm" )
  1467.     {
  1468.         self update_damage_absorbed( damage );
  1469.     }
  1470.     return 0;
  1471. }
  1472.  
  1473. stun_avogadro()
  1474. {
  1475.     ignore_emp_states = [];
  1476.     ignore_emp_states[ 0 ] = "phasing";
  1477.     ignore_emp_states[ 1 ] = "chamber";
  1478.     ignore_emp_states[ 2 ] = "wait_for_player";
  1479.     ignore_emp_states[ 3 ] = "exiting";
  1480.     ignore_emp_states[ 4 ] = "cloud";
  1481.     _a1854 = ignore_emp_states;
  1482.     _k1854 = getFirstArrayKey( _a1854 );
  1483.     while ( isDefined( _k1854 ) )
  1484.     {
  1485.         state = _a1854[ _k1854 ];
  1486.         if ( self.state == state )
  1487.         {
  1488.             return;
  1489.         }
  1490.         _k1854 = getNextArrayKey( _a1854, _k1854 );
  1491.     }
  1492.     if ( self.hit_by_melee < 4 )
  1493.     {
  1494. /#
  1495.         avogadro_print( "stunned during " + self.state );
  1496. #/
  1497.         level notify( "stun_avogadro" );
  1498.         self notify( "stunned" );
  1499.         self notify( "melee_pain" );
  1500.         self.hit_by_melee += 4;
  1501.         self thread avogadro_pain();
  1502.     }
  1503. }
  1504.  
  1505. fling_avogadro( player )
  1506. {
  1507. }
  1508.  
  1509. drag_avogadro( vdir )
  1510. {
  1511. }
  1512.  
  1513. avogadro_debug_axis()
  1514. {
  1515. /#
  1516.     self endon( "death" );
  1517.     while ( 1 )
  1518.     {
  1519.         if ( !isDefined( self.debug_axis ) )
  1520.         {
  1521.             self.debug_axis = spawn( "script_model", self.origin );
  1522.             self.debug_axis setmodel( "fx_axis_createfx" );
  1523.         }
  1524.         else
  1525.         {
  1526.             self.debug_axis.origin = self.origin;
  1527.             self.debug_axis.angles = self.angles;
  1528.         }
  1529.         wait 0,1;
  1530. #/
  1531.     }
  1532. }
  1533.  
  1534. avogadro_print( str )
  1535. {
  1536. /#
  1537.     if ( getDvarInt( #"92514885" ) )
  1538.     {
  1539.         iprintln( "avogadro: " + str );
  1540.         if ( isDefined( self.debug_msg ) )
  1541.         {
  1542.             self.debug_msg[ self.debug_msg.size ] = str;
  1543.             if ( self.debug_msg.size > 64 )
  1544.             {
  1545.                 self.debug_msg = [];
  1546.             }
  1547.             return;
  1548.         }
  1549.         else
  1550.         {
  1551.             self.debug_msg = [];
  1552.             self.debug_msg[ self.debug_msg.size ] = str;
  1553. #/
  1554.         }
  1555.     }
  1556. }
  1557.  
  1558. do_avogadro_flee_vo( avogadro )
  1559. {
  1560.     players = get_players();
  1561.     _a1944 = players;
  1562.     _k1944 = getFirstArrayKey( _a1944 );
  1563.     while ( isDefined( _k1944 ) )
  1564.     {
  1565.         player = _a1944[ _k1944 ];
  1566.         if ( distancesquared( player.origin, avogadro.origin ) < 250000 )
  1567.         {
  1568.             player thread do_player_general_vox( "general", "avogadro_flee", 30, 45 );
  1569.             return;
  1570.         }
  1571.         _k1944 = getNextArrayKey( _a1944, _k1944 );
  1572.     }
  1573. }
  1574.  
  1575. avogadro_storm_vox()
  1576. {
  1577.     if ( isDefined( level.checking_avogadro_storm_vox ) && level.checking_avogadro_storm_vox )
  1578.     {
  1579.         return;
  1580.     }
  1581.     level.checking_avogadro_storm_vox = 1;
  1582.     players = get_players();
  1583.     players = array_randomize( players );
  1584.     _a1963 = players;
  1585.     _k1963 = getFirstArrayKey( _a1963 );
  1586.     while ( isDefined( _k1963 ) )
  1587.     {
  1588.         player = _a1963[ _k1963 ];
  1589.         if ( !player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_tbu" ) && !player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_amb_tunnel" ) && !player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_prr" ) || player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_pcr" ) && player maps/mp/zombies/_zm_zonemgr::is_player_in_zone( "zone_pow_warehouse" ) )
  1590.         {
  1591.         }
  1592.         else
  1593.         {
  1594.             player thread do_player_general_vox( "general", "avogadro_storm", 120, 2 );
  1595.         }
  1596.         _k1963 = getNextArrayKey( _a1963, _k1963 );
  1597.     }
  1598.     wait 5;
  1599.     level.checking_avogadro_storm_vox = 0;
  1600. }
Advertisement
Add Comment
Please, Sign In to add comment