// T6 GSC SOURCE
// Decompiled by https://github.com/xensik/gsc-tool
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\zombies\_zm_utility;
#include maps\mp\zombies\_zm_net;
#include maps\mp\zombies\_zm_spawner;
#include maps\mp\animscripts\shared;
#include maps\mp\zombies\_zm_audio;
#include maps\mp\zombies\_zm_zonemgr;
#include maps\mp\zombies\_zm_score;
#include maps\mp\zombies\_zm_powerups;

init()
{
    flag_init( "soul_catchers_charged" );
    level.soul_catchers = [];
    level.soul_catchers_vol = [];
    level.no_gib_in_wolf_area = ::check_for_zombie_in_wolf_area;
    level.soul_catcher_clip["rune_2"] = getent( "wolf_clip_docks", "targetname" );
    level.soul_catcher_clip["rune_3"] = getent( "wolf_clip_infirmary", "targetname" );

    foreach ( e_clip in level.soul_catcher_clip )
        e_clip setinvisibletoall();

    level thread create_anim_references_on_server();
    registerclientfield( "actor", "make_client_clone", 9000, 4, "int" );
    onplayerconnect_callback( ::toggle_redeemer_trigger );
    onplayerconnect_callback( ::hellhole_projectile_watch );
    onplayerconnect_callback( ::hellhole_tomahawk_watch );
    level.a_wolf_structs = getstructarray( "wolf_position", "targetname" );

    for ( i = 0; i < level.a_wolf_structs.size; i++ )
    {
        registerclientfield( "world", level.a_wolf_structs[i].script_parameters, 9000, 3, "int" );
        level.soul_catchers[i] = level.a_wolf_structs[i];
        level.soul_catchers_vol[i] = getent( level.a_wolf_structs[i].target, "targetname" );
    }

    for ( i = 0; i < level.soul_catchers.size; i++ )
    {
        level.soul_catchers[i].souls_received = 0;
        level.soul_catchers[i].is_eating = 0;
        level.soul_catchers[i] thread soul_catcher_check();

        if ( is_classic() )
            level.soul_catchers[i] thread soul_catcher_state_manager();
        else
            level.soul_catchers[i] thread grief_soul_catcher_state_manager();

        level.soul_catchers[i] thread wolf_head_removal( "tomahawk_door_sign_" + ( i + 1 ) );
        level.soul_catchers_vol[i] = getent( level.soul_catchers[i].target, "targetname" );
    }

    level.soul_catchers_charged = 0;
    level thread soul_catchers_charged();
    array_thread( level.zombie_spawners, ::add_spawn_function, ::zombie_spawn_func );
}

#using_animtree("fxanim_props");

create_anim_references_on_server()
{
    root = %root;
    wolfhead_intro_anim = %o_zombie_dreamcatcher_intro;
    wolfhead_outtro_anim = %o_zombie_dreamcatcher_outtro;
    woflhead_idle_anims = [];
    wolfhead_idle_anim[0] = %o_zombie_dreamcatcher_idle;
    wolfhead_idle_anim[1] = %o_zombie_dreamcatcher_idle_twitch_scan;
    wolfhead_idle_anim[2] = %o_zombie_dreamcatcher_idle_twitch_shake;
    wolfhead_idle_anim[3] = %o_zombie_dreamcatcher_idle_twitch_yawn;
    wolfhead_body_death = %ai_zombie_dreamcatch_impact;
    wolfhead_body_float = %ai_zombie_dreamcatch_rise;
    wolfhead_body_shrink = %ai_zombie_dreamcatch_shrink_a;
    wolfhead_pre_eat_anims = [];
    wolfhead_pre_eat_anims["right"] = %o_zombie_dreamcatcher_wallconsume_pre_eat_r;
    wolfhead_pre_eat_anims["left"] = %o_zombie_dreamcatcher_wallconsume_pre_eat_l;
    wolfhead_pre_eat_anims["front"] = %o_zombie_dreamcatcher_wallconsume_pre_eat_f;
    wolfhead_eat_anims["right"] = %o_zombie_dreamcatcher_wallconsume_align_r;
    wolfhead_eat_anims["left"] = %o_zombie_dreamcatcher_wallconsume_align_l;
    wolfhead_eat_anims["front"] = %o_zombie_dreamcatcher_wallconsume_align_f;
    wolfhead_body_anims["right"] = %ai_zombie_dreamcatcher_wallconsume_align_r;
    wolfhead_body_anims["left"] = %ai_zombie_dreamcatcher_wallconsume_align_l;
    wolfhead_body_anims["front"] = %ai_zombie_dreamcatcher_wallconsume_align_f;
}

soul_catcher_state_manager()
{
    wait 1.0;

    if ( self.script_noteworthy == "rune_3" )
    {
        trigger = getent( "wolf_hurt_trigger", "targetname" );
        trigger hide();
    }
    else if ( self.script_noteworthy == "rune_2" )
    {
        trigger = getent( "wolf_hurt_trigger_docks", "targetname" );
        trigger hide();
    }

    level setclientfield( self.script_parameters, 0 );

    self waittill( "first_zombie_killed_in_zone" );

    if ( self.script_noteworthy == "rune_3" )
    {
        trigger = getent( "wolf_hurt_trigger", "targetname" );
        trigger show();
    }
    else if ( self.script_noteworthy == "rune_2" )
    {
        trigger = getent( "wolf_hurt_trigger_docks", "targetname" );
        trigger show();
    }

    if ( isdefined( level.soul_catcher_clip[self.script_noteworthy] ) )
        level.soul_catcher_clip[self.script_noteworthy] setvisibletoall();

    level setclientfield( self.script_parameters, 1 );
    anim_length = getanimlength( %o_zombie_dreamcatcher_intro );
    wait( anim_length );

    while ( !self.is_charged )
    {
        level setclientfield( self.script_parameters, 2 );
        self waittill_either( "fully_charged", "finished_eating" );
    }

    level setclientfield( self.script_parameters, 6 );
    anim_length = getanimlength( %o_zombie_dreamcatcher_outtro );
    wait( anim_length );

    if ( isdefined( level.soul_catcher_clip[self.script_noteworthy] ) )
        level.soul_catcher_clip[self.script_noteworthy] delete();

    if ( self.script_noteworthy == "rune_3" )
    {
        trigger = getent( "wolf_hurt_trigger", "targetname" );
        trigger delete();
    }
    else if ( self.script_noteworthy == "rune_2" )
    {
        trigger = getent( "wolf_hurt_trigger_docks", "targetname" );
        trigger delete();
    }

    level setclientfield( self.script_parameters, 7 );
}

grief_soul_catcher_state_manager()
{
    wait 1;

    while ( true )
    {
        level setclientfield( self.script_parameters, 0 );

        self waittill( "first_zombie_killed_in_zone" );

        if ( isdefined( level.soul_catcher_clip[self.script_noteworthy] ) )
            level.soul_catcher_clip[self.script_noteworthy] setvisibletoall();

        level setclientfield( self.script_parameters, 1 );
        anim_length = getanimlength( %o_zombie_dreamcatcher_intro );
        wait( anim_length );

        while ( !self.is_charged )
        {
            level setclientfield( self.script_parameters, 2 );
            self waittill_either( "fully_charged", "finished_eating" );
        }

        level setclientfield( self.script_parameters, 6 );
        anim_length = getanimlength( %o_zombie_dreamcatcher_outtro );
        wait( anim_length );

        if ( isdefined( level.soul_catcher_clip[self.script_noteworthy] ) )
            level.soul_catcher_clip[self.script_noteworthy] delete();

        self.souls_received = 0;
        level thread wolf_spit_out_powerup();
        wait 20;
        self thread soul_catcher_check();
    }
}

wolf_spit_out_powerup()
{
    if ( !( isdefined( level.enable_magic ) && level.enable_magic ) )
        return;

    power_origin_struct = getstruct( "wolf_puke_powerup_origin", "targetname" );

    if ( randomint( 100 ) < 20 )
    {
        for ( i = 0; i < level.zombie_powerup_array.size; i++ )
        {
            if ( level.zombie_powerup_array[i] == "meat_stink" )
            {
                level.zombie_powerup_index = i;
                found = 1;
                break;
            }
        }
    }
    else
    {
        while ( true )
        {
            level.zombie_powerup_index = randomint( level.zombie_powerup_array.size );

            if ( level.zombie_powerup_array[level.zombie_powerup_index] == "nuke" )
            {
                wait 0.05;
                continue;
            }

            break;
        }
    }

    spawn_infinite_powerup_drop( power_origin_struct.origin, level.zombie_powerup_array[level.zombie_powerup_index] );
    power_ups = get_array_of_closest( power_origin_struct.origin, level.active_powerups, undefined, undefined, 100 );

    if ( isdefined( power_ups[0] ) )
        power_ups[0] movez( 120, 4 );
}

zombie_spawn_func()
{
    self.actor_killed_override = ::zombie_killed_override;
}

zombie_killed_override( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime )
{
    if ( !is_true( self.has_legs ) )
        return;

    if ( isplayer( attacker ) )
    {
        for ( i = 0; i < level.soul_catchers.size; i++ )
        {
            if ( self istouching( level.soul_catchers_vol[i] ) )
            {
                if ( !level.soul_catchers[i].is_charged )
                {
                    self.deathfunction = ::zombie_soul_catcher_death;
                    self.my_soul_catcher = level.soul_catchers[i];
                }
            }
        }
    }
}

check_for_zombie_in_wolf_area()
{
    for ( i = 0; i < level.soul_catchers.size; i++ )
    {
        if ( self istouching( level.soul_catchers_vol[i] ) )
        {
            if ( !level.soul_catchers[i].is_charged && !level.soul_catchers[i].is_eating )
                return true;
        }
    }

    return false;
}

zombie_soul_catcher_death()
{
    self thread maps\mp\zombies\_zm_spawner::zombie_death_animscript();

    if ( isdefined( self._race_team ) )
        team = self._race_team;

    level maps\mp\zombies\_zm_spawner::zombie_death_points( self.origin, self.damagemod, self.damagelocation, self.attacker, self, team );

    if ( self.my_soul_catcher.is_eating )
        return false;

    if ( self.my_soul_catcher.souls_received >= 6 )
        return false;

    self.my_soul_catcher.is_eating = 1;

    if ( self.my_soul_catcher.souls_received == 0 )
    {
        self.my_soul_catcher notify( "first_zombie_killed_in_zone" );
        self thread notify_wolf_intro_anim_complete();
    }

    client_notify_value = self get_correct_model_array();
    self setclientfield( "make_client_clone", client_notify_value );
    self setanimstatefromasd( "zm_portal_death" );
    self maps\mp\animscripts\shared::donotetracks( "portal_death" );

    if ( self.my_soul_catcher.souls_received == 0 )
        self waittill( "wolf_intro_anim_complete" );

    n_eating_anim = self which_eating_anim();
    self ghost();
    level setclientfield( self.my_soul_catcher.script_parameters, n_eating_anim );

    if ( n_eating_anim == 3 )
        total_wait_time = 3.0 + getanimlength( %ai_zombie_dreamcatcher_wallconsume_align_f );
    else if ( n_eating_anim == 4 )
        total_wait_time = 3.0 + getanimlength( %ai_zombie_dreamcatcher_wallconsume_align_r );
    else
        total_wait_time = 3.0 + getanimlength( %ai_zombie_dreamcatcher_wallconsume_align_l );

    wait( total_wait_time - 0.5 );
    self.my_soul_catcher.souls_received++;
    wait 0.5;
    self.my_soul_catcher notify( "finished_eating" );
    self.my_soul_catcher.is_eating = 0;
    self delete();
    return true;
}

get_correct_model_array()
{
    mod = 0;

    if ( self.model == "c_zom_guard_body" && isdefined( self.hatmodel ) && self.hatmodel == "c_zom_guard_hat" )
        mod = 4;

    if ( self.headmodel == "c_zom_zombie_barbwire_head" )
        return 1 + mod;

    if ( self.headmodel == "c_zom_zombie_hellcatraz_head" )
        return 2 + mod;

    if ( self.headmodel == "c_zom_zombie_mask_head" )
        return 3 + mod;

    if ( self.headmodel == "c_zom_zombie_slackjaw_head" )
        return 4 + mod;

    return 5;
}

notify_wolf_intro_anim_complete()
{
    anim_length = getanimlength( %o_zombie_dreamcatcher_intro );
    wait( anim_length );
    self notify( "wolf_intro_anim_complete" );
}

which_eating_anim()
{
    soul_catcher = self.my_soul_catcher;
    forward_dot = vectordot( anglestoforward( soul_catcher.angles ), vectornormalize( self.origin - soul_catcher.origin ) );

    if ( forward_dot > 0.85 )
        return 3;
    else
    {
        right_dot = vectordot( anglestoright( soul_catcher.angles ), self.origin - soul_catcher.origin );

        if ( right_dot > 0 )
            return 4;
        else
            return 5;
    }
}

soul_catcher_check()
{
    self.is_charged = 0;

    while ( true )
    {
        if ( self.souls_received >= 6 )
        {
            level.soul_catchers_charged++;
            level thread maps\mp\zombies\_zm_audio::sndmusicstingerevent( "tomahawk_" + level.soul_catchers_charged );
            self.is_charged = 1;
            self notify( "fully_charged" );
            break;
        }

        wait 0.05;
    }

    if ( level.soul_catchers_charged == 1 )
        self thread first_wolf_complete_vo();
    else if ( level.soul_catchers_charged >= level.soul_catchers.size )
        self thread final_wolf_complete_vo();
}

wolf_head_removal( wolf_head_model_string )
{
    wolf_head_model = getent( wolf_head_model_string, "targetname" );
    wolf_head_model setmodel( "p6_zm_al_dream_catcher_off" );

    self waittill( "fully_charged" );

    wolf_head_model setmodel( "p6_zm_al_dream_catcher" );
}

soul_catchers_charged()
{
    while ( true )
    {
        if ( level.soul_catchers_charged >= level.soul_catchers.size )
        {
            flag_set( "soul_catchers_charged" );
            level notify( "soul_catchers_charged" );
            break;
        }

        wait 1;
    }
}

first_wolf_encounter_vo()
{
    if ( !is_classic() )
        return;

    wait 2.0;
    a_players = getplayers();
    a_closest = get_array_of_closest( self.origin, a_players );

    for ( i = 0; i < a_closest.size; i++ )
    {
        if ( !( isdefined( a_closest[i].dontspeak ) && a_closest[i].dontspeak ) )
        {
            a_closest[i] thread do_player_general_vox( "general", "wolf_encounter" );
            level.wolf_encounter_vo_played = 1;
            break;
        }
    }
}

first_wolf_complete_vo()
{
    if ( !is_classic() )
        return;

    wait 3.5;
    a_players = getplayers();
    a_closest = get_array_of_closest( self.origin, a_players );

    for ( i = 0; i < a_closest.size; i++ )
    {
        if ( !( isdefined( a_closest[i].dontspeak ) && a_closest[i].dontspeak ) )
        {
            a_closest[i] thread do_player_general_vox( "general", "wolf_complete" );
            break;
        }
    }
}

final_wolf_complete_vo()
{
    if ( !is_classic() )
        return;

    wait 3.5;
    a_players = getplayers();
    a_closest = get_array_of_closest( self.origin, a_players );

    for ( i = 0; i < a_closest.size; i++ )
    {
        if ( !( isdefined( a_closest[i].dontspeak ) && a_closest[i].dontspeak ) )
        {
            a_closest[i] thread do_player_general_vox( "general", "wolf_final" );
            break;
        }
    }
}

tomahawk_upgrade_quest()
{
    if ( isdefined( level.gamedifficulty ) && level.gamedifficulty == 0 )
        return;

    self endon( "disconnect" );

    for ( self.tomahawk_upgrade_kills = 0; self.tomahawk_upgrade_kills < 15; self.tomahawk_upgrade_kills++ )
        self waittill( "got_a_tomahawk_kill" );

    wait 1.0;
    level thread maps\mp\zombies\_zm_audio::sndmusicstingerevent( "quest_generic" );
    e_org = spawn( "script_origin", self.origin + vectorscale( ( 0, 0, 1 ), 64.0 ) );
    e_org playsoundwithnotify( "zmb_easteregg_scream", "easteregg_scream_complete" );

    e_org waittill( "easteregg_scream_complete" );

    e_org delete();

    while ( level.round_number < 10 )
        wait 0.5;

    self ent_flag_init( "gg_round_done" );

    while ( !self ent_flag( "gg_round_done" ) )
    {
        level waittill( "between_round_over" );

        self.killed_with_only_tomahawk = 1;
        self.killed_something_thq = 0;

        if ( !self maps\mp\zombies\_zm_zonemgr::is_player_in_zone( "zone_golden_gate_bridge" ) )
            continue;

        level waittill( "end_of_round" );

        if ( !self.killed_with_only_tomahawk || !self.killed_something_thq )
            continue;

        if ( !self maps\mp\zombies\_zm_zonemgr::is_player_in_zone( "zone_golden_gate_bridge" ) )
            continue;

        self ent_flag_set( "gg_round_done" );
    }

    level thread maps\mp\zombies\_zm_audio::sndmusicstingerevent( "quest_generic" );
    e_org = spawn( "script_origin", self.origin + vectorscale( ( 0, 0, 1 ), 64.0 ) );
    e_org playsoundwithnotify( "zmb_easteregg_scream", "easteregg_scream_complete" );

    e_org waittill( "easteregg_scream_complete" );

    e_org delete();
    self notify( "hellhole_time" );

    self waittill( "tomahawk_in_hellhole" );

    if ( isdefined( self.retriever_trigger ) )
        self.retriever_trigger setinvisibletoplayer( self );
    else
    {
        trigger = getent( "retriever_pickup_trigger", "script_noteworthy" );
        self.retriever_trigger = trigger;
        self.retriever_trigger setinvisibletoplayer( self );
    }

    self takeweapon( "bouncing_tomahawk_zm" );
    self set_player_tactical_grenade( "none" );
    self notify( "tomahawk_upgraded_swap" );
    level thread maps\mp\zombies\_zm_audio::sndmusicstingerevent( "quest_generic" );
    e_org = spawn( "script_origin", self.origin + vectorscale( ( 0, 0, 1 ), 64.0 ) );
    e_org playsoundwithnotify( "zmb_easteregg_scream", "easteregg_scream_complete" );

    e_org waittill( "easteregg_scream_complete" );

    e_org delete();

    level waittill( "end_of_round" );

    tomahawk_pick = getent( "spinning_tomahawk_pickup", "targetname" );
    tomahawk_pick setclientfield( "play_tomahawk_fx", 2 );
    self.current_tomahawk_weapon = "upgraded_tomahawk_zm";
}

toggle_redeemer_trigger()
{
    self endon( "disconnect" );
    flag_wait( "tomahawk_pickup_complete" );
    upgraded_tomahawk_trigger = getent( "redeemer_pickup_trigger", "script_noteworthy" );
    upgraded_tomahawk_trigger setinvisibletoplayer( self );
    tomahawk_model = getent( "spinning_tomahawk_pickup", "targetname" );

    while ( true )
    {
        if ( isdefined( self.current_tomahawk_weapon ) && self.current_tomahawk_weapon == "upgraded_tomahawk_zm" )
            break;
        else
            wait 1;
    }

    while ( true )
    {
        if ( isdefined( self.afterlife ) && self.afterlife )
        {
            upgraded_tomahawk_trigger setvisibletoplayer( self );
            tomahawk_model setvisibletoplayer( self );
        }
        else
        {
            upgraded_tomahawk_trigger setinvisibletoplayer( self );
            tomahawk_model setinvisibletoplayer( self );
        }

        wait 1;
    }
}

hellhole_projectile_watch()
{
    self endon( "disconnect" );

    while ( true )
    {
        self waittill( "grenade_fire", grenade, weapname );

        if ( weapname == "frag_grenade_zm" )
            self thread hellhole_grenades( grenade );
    }
}

hellhole_tomahawk_watch()
{
    self endon( "disconnect" );

    self waittill( "hellhole_time" );

    while ( true )
    {
        self waittill( "grenade_fire", grenade, weapname );

        if ( weapname == "bouncing_tomahawk_zm" )
            self thread hellhole_tomahawk( grenade );
    }
}

hellhole_grenades( grenade )
{
    grenade endon( "death" );
    trig_hellhole = getent( "trig_cellblock_hellhole", "targetname" );

    while ( !grenade istouching( trig_hellhole ) )
        wait 0.05;

    self maps\mp\zombies\_zm_score::add_to_player_score( 20 );
    playfx( level._effect["tomahawk_hellhole"], grenade.origin );
    playsoundatposition( "wpn_grenade_poof", grenade.origin );
    grenade delete();
}

hellhole_tomahawk( grenade )
{
    grenade endon( "death" );
    trig_hellhole = getent( "trig_cellblock_hellhole", "targetname" );

    while ( !grenade istouching( trig_hellhole ) )
        wait 0.05;

    self notify( "tomahawk_in_hellhole" );
    grenade notify( "in_hellhole" );
    playfx( level._effect["tomahawk_hellhole"], grenade.origin );
    playsoundatposition( "wpn_grenade_poof", grenade.origin );
    grenade delete();
}

spawn_infinite_powerup_drop( v_origin, str_type )
{
    if ( isdefined( str_type ) )
        intro_powerup = maps\mp\zombies\_zm_powerups::specific_powerup_drop( str_type, v_origin );
    else
        intro_powerup = maps\mp\zombies\_zm_powerups::powerup_drop( v_origin );
}
