From 8858b712e7fe71a1dcc38e1d8a2b2f97cfa30754 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Mon, 4 Mar 2024 23:36:57 -0800 Subject: [PATCH] Fix clientfield alt system. Improve _random mixed variant. --- .../clientscripts/mp/zombies/_zm_ai_mechz.csc | 36 +++++- zm_ai_pack/maps/mp/zombies/_zm_ai_brutus.gsc | 3 +- zm_ai_pack/maps/mp/zombies/_zm_ai_leaper.gsc | 2 +- zm_ai_pack/maps/mp/zombies/_zm_ai_mechz.gsc | 4 +- .../maps/mp/zombies/_zm_ai_screecher.gsc | 1 + zm_ai_pack/scripts/zm/clientfield_alt_sys.csc | 48 ++++---- zm_ai_pack/scripts/zm/clientfield_alt_sys.gsc | 108 +++++++++++++++++- .../scripts/zm/zm_ai_pack/_round_manager.gsc | 2 + .../zm/zm_ai_pack/mixed_variants/_random.gsc | 69 ++++++++--- zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.csc | 1 - zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.gsc | 63 +++++++++- zm_coolweps/TODO.txt | 6 +- 12 files changed, 287 insertions(+), 56 deletions(-) diff --git a/zm_ai_pack/clientscripts/mp/zombies/_zm_ai_mechz.csc b/zm_ai_pack/clientscripts/mp/zombies/_zm_ai_mechz.csc index c7cdc13..03aa1fd 100644 --- a/zm_ai_pack/clientscripts/mp/zombies/_zm_ai_mechz.csc +++ b/zm_ai_pack/clientscripts/mp/zombies/_zm_ai_mechz.csc @@ -203,6 +203,10 @@ cleanup_fx_alt( index ) } } + if ( getDvarInt( "clientfield_alt_mechz_debug" ) ) + { + print( "cleanup_fx_alt( " + unique_script_id + " )" ); + } self notify( unique_script_id ); } @@ -223,14 +227,27 @@ cleanup_fx( localclientnum, index, bnewent, binitialsnap, fieldname, bwasdemojum self notify( unique_script_id ); } -mechz_handle_fx_alt( new_val, old_val ) +mechz_handle_fx_alt( new_val ) { + if ( !isdefined( self.mechz_handle_fx_alt_old_val ) ) + { + self.mechz_handle_fx_alt_old_val = 0; + } newval = int( new_val ); - oldval = old_val != "" ? int( old_val ) : 0; + oldval = self.mechz_handle_fx_alt_old_val; + if ( getDvarInt( "clientfield_alt_mechz_debug" ) ) + { + print( "mechz_handle_fx_alt( " + oldval + ", " + newval + " )" ); + } for ( i = 0; i < level.mechz_clientside_fx.size; i++ ) { - set_in_new = ( newval & 1 << i ) != 0; - set_in_old = ( oldval & 1 << i ) != 0; + set_in_new = ( newval & ( 1 << i ) ) != 0; + set_in_old = ( oldval & ( 1 << i ) ) != 0; + + if ( getDvarInt( "clientfield_alt_mechz_debug" ) ) + { + print( "mechz_handle_fx_alt( checked bits: " + set_in_new + ", " + set_in_old + " )" ); + } if ( set_in_new && !set_in_old ) { @@ -249,6 +266,8 @@ mechz_handle_fx_alt( new_val, old_val ) if ( isdefined( self.smoke_fx ) ) deletefx( 0, self.smoke_fx ); } + + self.mechz_handle_fx_alt_old_val = newval; } mechz_handle_fx( localclientnum, oldval, newval, bnewent, binitialsnap, fieldname, bwasdemojump ) @@ -322,9 +341,13 @@ mechz_screen_shake_loop( localclientnum ) } } -mechz_claw_callback_alt( new_val, old_val ) +mechz_claw_callback_alt( new_val ) { - oldval = old_val != "" ? int( old_val ) : 0; + if ( !isdefined( self.mechz_claw_callback_alt_old_val ) ) + { + self.mechz_claw_callback_alt_old_val = 0; + } + oldval = self.mechz_claw_callback_alt_old_val; newval = int( new_val ); if ( oldval == 1 && newval == 0 ) { @@ -333,6 +356,7 @@ mechz_claw_callback_alt( new_val, old_val ) } else if ( newval == 1 ) self thread mechz_screen_shake_loop( 0 ); + self.mechz_claw_callback_alt_old_val = newval; } mechz_claw_callback( localclientnum, oldval, newval, bnewent, binitialsnap, fieldname, bwasdemojump ) diff --git a/zm_ai_pack/maps/mp/zombies/_zm_ai_brutus.gsc b/zm_ai_pack/maps/mp/zombies/_zm_ai_brutus.gsc index 6f84cc8..1e64df8 100644 --- a/zm_ai_pack/maps/mp/zombies/_zm_ai_brutus.gsc +++ b/zm_ai_pack/maps/mp/zombies/_zm_ai_brutus.gsc @@ -71,7 +71,8 @@ main() precachestring( &"ZOMBIE_LOCKED_COST_6000" ); flag_init( "brutus_setup_complete" ); setdvar( "zombie_double_wide_checks", 1 ); - + scripts\zm\clientfield_alt_sys::register_clientfield_alt( "actor", "helmet_off" ); + scripts\zm\clientfield_alt_sys::register_clientfield_alt( "actor", "brutus_lock_down" ); if ( !isdefined( level.vsmgr_prio_zm_brutus_teargas ) ) level.vsmgr_prio_overlay_zm_ai_screecher_blur = 50; diff --git a/zm_ai_pack/maps/mp/zombies/_zm_ai_leaper.gsc b/zm_ai_pack/maps/mp/zombies/_zm_ai_leaper.gsc index ba0b528..2309b6b 100644 --- a/zm_ai_pack/maps/mp/zombies/_zm_ai_leaper.gsc +++ b/zm_ai_pack/maps/mp/zombies/_zm_ai_leaper.gsc @@ -37,7 +37,7 @@ precache_fx() init() { leaper_spawner_init(); - leaper_calc_anim_offsets(); + level thread leaper_calc_anim_offsets(); if ( !isdefined( level.leapers_per_player ) ) level.leapers_per_player = 2; diff --git a/zm_ai_pack/maps/mp/zombies/_zm_ai_mechz.gsc b/zm_ai_pack/maps/mp/zombies/_zm_ai_mechz.gsc index 272fffb..38fdf5e 100644 --- a/zm_ai_pack/maps/mp/zombies/_zm_ai_mechz.gsc +++ b/zm_ai_pack/maps/mp/zombies/_zm_ai_mechz.gsc @@ -49,8 +49,8 @@ precache() register_clientfields() { - //registerclientfield( "actor", "mechz_fx", 14000, 12, "int" ); - //registerclientfield( "toplayer", "mechz_grab", 14000, 1, "int" ); + scripts\zm\clientfield_alt_sys::register_clientfield_alt( "actor", "mechz_fx" ); + scripts\zm\clientfield_alt_sys::register_clientfield_alt( "toplayer", "mechz_grab" ); if ( getDvar( "mapname" ) != "zm_buried" || getDvar( "g_gametype" ) != "zclassic" ) { registerclientfield( "actor", "anim_rate", 14000, 2, "float" ); diff --git a/zm_ai_pack/maps/mp/zombies/_zm_ai_screecher.gsc b/zm_ai_pack/maps/mp/zombies/_zm_ai_screecher.gsc index bf5c7e2..763c5e1 100644 --- a/zm_ai_pack/maps/mp/zombies/_zm_ai_screecher.gsc +++ b/zm_ai_pack/maps/mp/zombies/_zm_ai_screecher.gsc @@ -54,6 +54,7 @@ init() /# level thread screecher_debug(); #/ + registerclientfield( "actor", "render_third_person", 1, 1, "int" ); level.near_miss = 0; } diff --git a/zm_ai_pack/scripts/zm/clientfield_alt_sys.csc b/zm_ai_pack/scripts/zm/clientfield_alt_sys.csc index b5f2dcf..c45b130 100644 --- a/zm_ai_pack/scripts/zm/clientfield_alt_sys.csc +++ b/zm_ai_pack/scripts/zm/clientfield_alt_sys.csc @@ -1,60 +1,58 @@ -execute_clientfield_alt_callback_internal( data, last_data, field_type, field_name ) +execute_clientfield_alt_callback_internal( data, field_type, field_name ) { - entnum = data.entnum; - ent = undefined; - field_data = level.clientfield_alts[ field_type ][ field_name ]; - ent = getEntByNum( 0, entnum ); + foreach ( item in data ) + { + entnum = item.entnum; + field_data = level.clientfield_alts[ field_type ][ field_name ]; + ent = getEntByNum( 0, entnum ); - assert( isDefined( ent ) ); + assert( isDefined( ent ) ); - ent thread [[ field_data.callback ]]( data.value, last_data.value ); + ent thread [[ field_data.callback ]]( item.value ); + } } get_data_from_payload( payload ) { - struct = spawnStruct(); - if ( payload != "" ) + data = []; + keys = strtok( payload, "|" ); + foreach ( key in keys ) { - tokens = strTok( payload, " " ); - + struct = spawnStruct(); + tokens = strTok( key, " " ); + struct.entnum = int( tokens[ 0 ] ); struct.value = tokens[ 1 ]; - } - else - { - struct.entnum = -1; - struct.value = ""; + data[ data.size ] = struct; } - return struct; + return data; } -execute_clientfield_alt_callback( payload, last_payload, field_type, field_name ) +execute_clientfield_alt_callback( payload, field_type, field_name ) { data = get_data_from_payload( payload ); - last_data = get_data_from_payload( last_payload ); - execute_clientfield_alt_callback_internal( data, last_data, field_type, field_name ); + execute_clientfield_alt_callback_internal( data, field_type, field_name ); } handle_clientfield_alt_callbacks( dvar_name, field_type, field_name ) { level endon( "disconnect" ); - old_dvar_value = getDvar( dvar_name ); for (;;) { dvar_value = getDvar( dvar_name ); - if ( dvar_value != old_dvar_value ) + if ( dvar_value != "" ) { if ( getDvarInt( "clientfield_alt_debug" ) ) { print( "handle_clientfield_alt_callbacks( " + dvar_name + ", " + field_type + ", " + field_name + " )" ); - print( "handle_clientfield_alt_callbacks() dvar_value: \"" + dvar_value + "\" old_dvar_value: \"" + old_dvar_value + "\"" ); + print( "handle_clientfield_alt_callbacks() dvar_value: \"" + dvar_value + "\"" ); } - level execute_clientfield_alt_callback( dvar_value, old_dvar_value, field_type, field_name ); - old_dvar_value = dvar_value; + level execute_clientfield_alt_callback( dvar_value, field_type, field_name ); + setdvar( dvar_name, "" ); } wait 0.01; diff --git a/zm_ai_pack/scripts/zm/clientfield_alt_sys.gsc b/zm_ai_pack/scripts/zm/clientfield_alt_sys.gsc index 76be85e..cb058e0 100644 --- a/zm_ai_pack/scripts/zm/clientfield_alt_sys.gsc +++ b/zm_ai_pack/scripts/zm/clientfield_alt_sys.gsc @@ -1,15 +1,115 @@ +main() +{ + level thread on_player_connecting(); +} + +init() +{ + keys = getarraykeys( level.clientfield_alts ); + for ( i = 0; i < keys.size; i++ ) + { + if ( keys[ i ] == "toplayer" ) + { + continue; + } + fields = level.clientfield_alts[ keys[ i ] ]; + for ( j = 0; j < fields.size; j++ ) + { + initialize_clientfield_alt_storage_for_level( fields[ j ] ); + level thread send_clientdvar_messages_allplayers( fields[ j ] ); + } + } +} + +on_player_connecting() +{ + for (;;) + { + level waittill( "connecting", player ); + fields = level.clientfield_alts[ "toplayer" ]; + for ( i = 0; i < fields.size; i++ ) + { + player initialize_clientfield_alt_storage_for_player( fields[ i ] ); + player send_clientdvar_messages_toplayer( fields[ i ] ); + } + } +} + set_clientfield_alt_toplayer( field_name, ent, value ) { entnum = ent getEntityNumber(); - self setClientDvar( field_name, entnum + " " + value ); + self.clientfield_alt_storage[ field_name ] += entnum + " " + value + "|"; +} + +send_clientdvar_messages_toplayer( field_name ) +{ + self endon( "disconnect" ); + for (;;) + { + wait 0.05; + + if ( self.clientfield_alt_storage[ field_name ] == "" ) + { + continue; + } + self setclientdvar( field_name, self.clientfield_alt_storage[ field_name ] ); + self.clientfield_alt_storage[ field_name ] = ""; + } } set_clientfield_alt_allplayers( field_name, ent, value ) { - foreach ( player in level.players ) + entnum = ent getEntityNumber(); + level.clientfield_alt_storage[ field_name ] += entnum + " " + value + "|"; +} + +send_clientdvar_messages_allplayers( field_name ) +{ + for (;;) { - entnum = ent getEntityNumber(); - player setClientDvar( field_name, entnum + " " + value ); + wait 0.05; + + if ( level.clientfield_alt_storage[ field_name ] == "" ) + { + continue; + } + for ( i = 0; i < level.players.size; i++ ) + { + level.players[ i ] setclientdvar( field_name, level.clientfield_alt_storage[ field_name ] ); + } + level.clientfield_alt_storage[ field_name ] = ""; } +} + +initialize_clientfield_alt_storage_for_player( field_name ) +{ + if ( !isdefined( self.clientfield_alt_storage ) ) + { + self.clientfield_alt_storage = []; + } + self.clientfield_alt_storage[ field_name ] = ""; +} + +initialize_clientfield_alt_storage_for_level( field_name ) +{ + if ( !isdefined( level.clientfield_alt_storage ) ) + { + level.clientfield_alt_storage = []; + } + level.clientfield_alt_storage[ field_name ] = ""; +} + +register_clientfield_alt( field_type, field_name ) +{ + if ( !isDefined( level.clientfield_alts ) ) + { + level.clientfield_alts = []; + } + if ( !isDefined( level.clientfield_alts[ field_type ] ) ) + { + level.clientfield_alts[ field_type ] = []; + } + + level.clientfield_alts[ field_type ][ level.clientfield_alts[ field_type ].size ] = field_name; } \ No newline at end of file diff --git a/zm_ai_pack/scripts/zm/zm_ai_pack/_round_manager.gsc b/zm_ai_pack/scripts/zm/zm_ai_pack/_round_manager.gsc index f350246..2d56688 100644 --- a/zm_ai_pack/scripts/zm/zm_ai_pack/_round_manager.gsc +++ b/zm_ai_pack/scripts/zm/zm_ai_pack/_round_manager.gsc @@ -584,6 +584,7 @@ determine_mixed_round_preset() if ( current_iterations >= max_iterations ) { + assertmsg( "Round Manager ERROR: Reached max iterations for picking mixed preset type" ); return level.round_manager_mixed_round_presets[ possible_presets[ 0 ] ]; } } @@ -640,6 +641,7 @@ pick_mixed_round_preset_variant( variants ) if ( current_iterations >= max_iterations ) { + assertmsg( "Round Manager ERROR: Reached max iterations for picking mixed variant type" ); variants[ possible_variants[ 0 ] ].last_time = gettime(); return variants[ possible_variants[ 0 ] ]; } diff --git a/zm_ai_pack/scripts/zm/zm_ai_pack/mixed_variants/_random.gsc b/zm_ai_pack/scripts/zm/zm_ai_pack/mixed_variants/_random.gsc index b3fb5de..3a5ac45 100644 --- a/zm_ai_pack/scripts/zm/zm_ai_pack/mixed_variants/_random.gsc +++ b/zm_ai_pack/scripts/zm/zm_ai_pack/mixed_variants/_random.gsc @@ -6,34 +6,53 @@ main() { - set_dvar_if_unset( "rm_mixed_preset_default_random_variant_allowed_aitypes", "normal zombie_dog mechz" ); + set_dvar_if_unset( "rm_mixed_preset_default_random_variant_allowed_aitypes", "normal zombie_dog mechz brutus" ); set_dvar_if_unset( "rm_mixed_preset_default_random_variant_wave_spawn_limit", 24 ); set_dvar_if_unset( "rm_mixed_preset_default_random_variant_wave_spawn_cooldown", 1 ); - set_dvar_if_unset( "rm_mixed_preset_default_random_variant_mechz_spawn_chance_1000", 10 ); - set_dvar_if_unset( "rm_mixed_preset_default_random_variant_zombie_dog_spawn_chance_1000", 200 ); + set_dvar_if_unset( "rm_mixed_preset_default_random_variant_mechz_spawn_chance_10000_base", 100 ); + set_dvar_if_unset( "rm_mixed_preset_default_random_variant_zombie_dog_spawn_chance_10000_base", 1200 ); + set_dvar_if_unset( "rm_mixed_preset_default_random_variant_brutus_spawn_chance_10000_base", 150 ); + + set_dvar_if_unset( "rm_mixed_preset_default_random_variant_mechz_spawn_chance_10000_increase_per_round", 2 ); + set_dvar_if_unset( "rm_mixed_preset_default_random_variant_zombie_dog_spawn_chance_10000_increase_per_round", 6 ); + set_dvar_if_unset( "rm_mixed_preset_default_random_variant_brutus_spawn_chance_10000_increase_per_round", 2 ); } spawning_random() { - mechz_spawn_chance = getdvarint( "rm_mixed_preset_default_random_variant_mechz_spawn_chance_1000" ); - zombie_dog_chance = getdvarint( "rm_mixed_preset_default_random_variant_zombie_dog_spawn_chance_1000" ); + mechz_spawn_chance = getdvarint( "rm_mixed_preset_default_random_variant_mechz_spawn_chance_10000_base" ); + zombie_dog_chance = getdvarint( "rm_mixed_preset_default_random_variant_zombie_dog_spawn_chance_10000_base" ); count = 0; for (;;) { wait_for_free_ai_slot( ::get_all_ai_count ); + + aitypes_string = getdvar( "rm_mixed_preset_default_random_variant_allowed_aitypes" ); + if ( aitypes_string == "" ) + { + wait 1; + continue; + } + aitypes = strtok( aitypes_string, " " ); + aitypes = array_randomize( aitypes ); ai = undefined; - random_number = randomint( 1000 ); - if ( random_number < mechz_spawn_chance ) + has_normal = false; + for ( i = 0; i < aitypes.size; i++ ) { - ai = [[ level.round_manager_aitype_spawning_funcs[ "mechz" ] ]](); + if ( aitypes[ i ] == "normal" ) + { + has_normal = true; + continue; + } + ai = attempt_random_spawn( aitypes[ i ] ); + if ( isdefined( ai ) ) + { + break; + } } - else if ( random_number < zombie_dog_chance ) - { - ai = [[ level.round_manager_aitype_spawning_funcs[ "zombie_dog" ] ]](); - } - else + if ( !isdefined( ai ) ) { ai = [[ level.round_manager_aitype_spawning_funcs[ "normal" ] ]](); } @@ -71,4 +90,28 @@ spawning_cooldown() spawning_round_start() { +} + +attempt_random_spawn( type ) +{ + chance_base = getdvarint( "rm_mixed_preset_default_random_variant_" + type + "_spawn_chance_10000_base" ); + + chance_per_round = getdvarint( "rm_mixed_preset_default_random_variant_" + type + "_spawn_chance_10000_increase_per_round" ); + + chance_scaled = chance_base + ( chance_per_round * ( level.round_number - getdvarint( "rm_mixed_round_min_start_round" ) ) ); + + if ( chance_scaled <= 0 ) + { + return undefined; + } + + random_number = randomint( 10000 ); + + ai = undefined; + if ( chance_scaled < random_number ) + { + ai = [[ level.round_manager_aitype_spawning_funcs[ type ] ]](); + } + + return ai; } \ No newline at end of file diff --git a/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.csc b/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.csc index 10584bc..bdce326 100644 --- a/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.csc +++ b/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.csc @@ -40,7 +40,6 @@ main() init() { - } add_visionset_callback( func ) diff --git a/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.gsc b/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.gsc index 03b7f62..8cb48ac 100644 --- a/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.gsc +++ b/zm_ai_pack/scripts/zm/zm_ai_pack_mod_main.gsc @@ -25,6 +25,9 @@ main() pluto_sys::replacefunc( maps\mp\animscripts\zm_dog_combat::domeleeafterwait, ::domeleeafterwait_override ); pluto_sys::replacefunc( maps\mp\animscripts\zm_dog_combat::handlemeleebiteattacknotetracks, ::handlemeleebiteattacknotetracks_override ); + //pluto_sys::replacefunc( maps\mp\animscripts\zm_run::setanimstatefromspeed, ::setanimstatefromspeed_override ); + //pluto_sys::replacefunc( maps\mp\animscripts\zm_melee::set_zombie_melee_anim_state, ::set_zombie_melee_anim_state_override ); + level.script = toLower( getDvar( "mapname" ) ); level.gametype = toLower( getDvar( "g_gametype" ) ); @@ -79,7 +82,7 @@ init() if ( isDefined( level.ai_data[ keys[ i ] ].init ) && isDefined( level.ai_data[ keys[ i ] ].should_execute ) && level.ai_data[ keys[ i ] ].should_execute ) { - level [[ level.ai_data[ keys[ i ] ].init ]](); + level thread [[ level.ai_data[ keys[ i ] ].init ]](); } } @@ -113,6 +116,64 @@ watch_for_damage_from_players() } } +setanimstatefromspeed_override() +{ + animstate = self maps\mp\animscripts\zm_utility::append_missing_legs_suffix( "zm_move_" + self.zombie_move_speed ); + + if ( isdefined( self.a.gib_ref ) && self.a.gib_ref == "no_legs" ) + animstate = "zm_move_stumpy"; + + if ( isdefined( self.has_legs ) && self.has_legs && isdefined( self.original_move_substate_before_melee ) && isdefined( self.original_move_state_before_melee ) + && self.original_move_state_before_melee == animstate ) + { + substate = self.original_move_substate_before_melee; + self setanimstatefromasd( animstate, substate ); + self.original_move_state_before_melee = undefined; + self.original_move_substate_before_melee = undefined; + } + else if ( isdefined( self.preserve_asd_substates ) && self.preserve_asd_substates && ( animstate == self getanimstatefromasd() ) ) + { + substate = self getanimsubstatefromasd(); + self setanimstatefromasd( animstate, substate ); + } + else + { + self setanimstatefromasd( animstate ); + } + if ( isdefined( self.setanimstatefromspeed ) ) + self [[ self.setanimstatefromspeed ]]( animstate, substate ); +} + +set_zombie_melee_anim_state_override( zombie ) +{ + if ( isdefined( level.melee_anim_state ) ) + melee_anim_state = self [[ level.melee_anim_state ]](); + + if ( !isdefined( melee_anim_state ) ) + { + if ( !zombie.has_legs && zombie.a.gib_ref == "no_legs" ) + melee_anim_state = "zm_stumpy_melee"; + else + { + switch ( zombie.zombie_move_speed ) + { + case "walk": + melee_anim_state = maps\mp\animscripts\zm_utility::append_missing_legs_suffix( "zm_walk_melee" ); + break; + case "run": + case "sprint": + default: + melee_anim_state = maps\mp\animscripts\zm_utility::append_missing_legs_suffix( "zm_run_melee" ); + break; + } + } + } + + zombie.original_move_state_before_melee = self getanimstatefromasd(); + zombie.original_move_substate_before_melee = self getanimsubstatefromasd(); + zombie setanimstatefromasd( melee_anim_state ); +} + add_spawn_functions_to_spawners() { flag_wait( "initial_blackscreen_passed" ); diff --git a/zm_coolweps/TODO.txt b/zm_coolweps/TODO.txt index c114685..7fe1017 100644 --- a/zm_coolweps/TODO.txt +++ b/zm_coolweps/TODO.txt @@ -6,8 +6,10 @@ implement waw-reimagined changes crossbow and paped variant spas shotgun from SP every wonder weapon on every map -faster sprint anims for zombies (supersprint and chase_bus) +faster sprint anims for zombies (supersprint and chase_bus) some from the old coolweps mod all the good ai types from BO2 and possibly BO1/BO3 elemental variants of certain special enemies at higher rounds(electric panzer, flaming dogs, acid warden, aura) aats -chicky-chicky comes in random variants 1. random projectiles in 360 radius, airstrike where bullet lands, turret shooter, friendly ai shooter \ No newline at end of file +chicky-chicky comes in random variants 1. random projectiles in 360 radius, airstrike where bullet lands, turret shooter, friendly ai shooter + +fix zombie move anims changing when meleeing an enemy \ No newline at end of file