/*#===================================================================### ### ### ### ### ### Harry Bo21s Shields v2.2.0 ### ### ### ### ### ###===================================================================#*/ /*======================================================================= CREDITS ========================================================================= DTXPorter ProRevenge StevieWonder87 BluntStuffy RedSpace200 thezombieproject Smasher248 JiffyNoodles MZSlayer AndyWhelen HitmanVere ProGamerzFTW Scobalula GerardS0406 PCModder TomBMX =======================================================================*/ #include maps\_utility; #include common_scripts\utility; #include maps\_zombiemode_utility; #include maps\_hud_util; #include maps\_harrybo21_utilities; #include maps\_zombiemode_bo2_utility; #include maps\_zombiemode_custom_triggers; #using_animtree( "generic_human" ); init() { level._effect[ "dragon_shield_fire" ] = LoadFx( "harrys/fx_dragon_shield_fire" ); level._effect[ "dragon_shield_explode" ] = LoadFx( "harrys/fx_dragon_shield_explode" ); level._effect[ "dragon_shield_fire_body" ] = loadfx( "harrys/fx_dragon_shield_fire_body" ); level._effect[ "dragon_shield_fire_upgraded" ] = LoadFx( "harrys/fx_dragon_shield_fire_upgraded" ); level._effect[ "dragon_shield_explode_upgraded" ] = LoadFx( "harrys/fx_dragon_shield_explode_upgraded" ); level._effect[ "dragon_shield_fire_body_upgraded" ] = loadfx( "harrys/fx_blast_furnace_torso" ); // ================================= PRECACHE MDOELS SHADERS AND WEAPON FILES ================================= PrecacheModel( "collision_geo_32x32x32" ); PrecacheModel( "p7_zm_zod_nitrous_tank" ); // Comment to remove // Tranzit Shield // harrybo21_shield_load_shield( "bo2_zm_shield_tranzit", 15, -1, "bo2_t6_wpn_zmb_shield_stow", "bo2_t6_wpn_zmb_shield_dmg1_stow", "bo2_t6_wpn_zmb_shield_dmg2_stow", "t6_wpn_zmb_shield_world", "t6_wpn_zmb_shield_dmg1_world", "t6_wpn_zmb_shield_dmg2_world" ); // Alcatraz Shield // harrybo21_shield_load_shield( "bo2_zm_shield_motd", 15, -1, "bo2_t6_wpn_zmb_shield_dlc2_dmg0_stow", "bo2_t6_wpn_zmb_shield_dlc2_dmg1_stow", "bo2_t6_wpn_zmb_shield_dlc2_dmg2_stow", "t6_wpn_zmb_shield_dlc2_dmg0_world", "t6_wpn_zmb_shield_dlc2_dmg1_world", "t6_wpn_zmb_shield_dlc2_dmg2_world" ); // Alcatraz Shield harrybo21_shield_load_shield( "bo2_zm_shield_origins", 15, -1, "bo2_t6_wpn_zmb_shield_dlc4_dmg0_stow", "bo2_t6_wpn_zmb_shield_dlc4_dmg1_stow", "bo2_t6_wpn_zmb_shield_dlc4_dmg2_stow", "bo2_t6_wpn_zmb_shield_dlc4_dmg0_world", "bo2_t6_wpn_zmb_shield_dlc4_dmg0_world", "bo2_t6_wpn_zmb_shield_dlc4_dmg2_world" ); // Shadows of Evil Shield // harrybo21_shield_load_shield( "bo3_zm_shield_soe", 30, 3, "wpn_t7_zmb_zod_rocket_shield_stow", "wpn_t7_zmb_zod_rocket_shield_dmg1_stow", "wpn_t7_zmb_zod_rocket_shield_dmg2_stow", "wpn_t7_zmb_zod_rocket_shield_world", "wpn_t7_zmb_zod_rocket_shield_dmg1_world", "wpn_t7_zmb_zod_rocket_shield_dmg2_world", ::harrybo21_rocket_shield_activate ); // harrybo21_shield_load_shield( "bo3_zm_shield_soe_upgraded", 50, 4, "wpn_t7_zmb_zod_rocket_shield_stow", "wpn_t7_zmb_zod_rocket_shield_dmg1_stow", "wpn_t7_zmb_zod_rocket_shield_dmg2_stow", "wpn_t7_zmb_zod_rocket_shield_world", "wpn_t7_zmb_zod_rocket_shield_dmg1_world", "wpn_t7_zmb_zod_rocket_shield_dmg2_world", ::harrybo21_rocket_shield_activate ); // Zetsubou No Shima Shield // harrybo21_shield_load_shield( "bo3_zm_shield_zns", 30, -1, "wpn_t7_zmb_dlc2_shield_stow", "wpn_t7_zmb_dlc2_shield_dmg01_stow", "wpn_t7_zmb_dlc2_shield_dmg02_stow", "wpn_t7_zmb_dlc2_shield_world", "wpn_t7_zmb_dlc2_shield_dmg01_world", "wpn_t7_zmb_dlc2_shield_dmg02_world" ); // Gorod Krovi Shield // harrybo21_shield_load_shield( "bo3_zm_shield_gk", 30, 3, "wpn_t7_zmb_dlc3_dragon_shield_dmg0_stow", "wpn_t7_zmb_dlc3_dragon_shield_dmg1_stow", "wpn_t7_zmb_dlc3_dragon_shield_dmg2_stow", "wpn_t7_zmb_dlc3_dragon_shield_dmg0_world", "wpn_t7_zmb_dlc3_dragon_shield_dmg1_world", "wpn_t7_zmb_dlc3_dragon_shield_dmg2_world", ::harrybo21_shield_dragon_fire ); // harrybo21_shield_load_shield( "bo3_zm_shield_gk_upgraded", 50, 3, "wpn_t7_zmb_dlc3_dragon_shield_dmg0_stow", "wpn_t7_zmb_dlc3_dragon_shield_dmg1_stow", "wpn_t7_zmb_dlc3_dragon_shield_dmg2_stow", "wpn_t7_zmb_dlc3_dragon_shield_dmg0_world", "wpn_t7_zmb_dlc3_dragon_shield_dmg1_world", "wpn_t7_zmb_dlc3_dragon_shield_dmg2_world", ::harrybo21_shield_dragon_fire ); // ================================= PRECACHE MDOELS SHADERS AND WEAPON FILES ================================= // ================================= GENERAL SETTINGS =============================== set_zombie_var( "shield_cylinder_radius", 360 ); // Detection radius set_zombie_var( "shield_fling_range", 90 ); // Range to potentially fling a zombie set_zombie_var( "shield_knockdown_range", 120 ); // Range to potentially knock a zombie over set_zombie_var( "shield_gib_range", 120 ); // Range to potentially gib a zombie set_zombie_var( "shield_gib_damage", 75 ); // Damage shield will do if it gibs a zombie down set_zombie_var( "shield_knockdown_damage", 15 ); // Damage shield will do if it knocks a zombie down set_zombie_var( "shield_damage", 2500 ); // Damage shield will deal to a regular zombie set_zombie_var( "shield_boss_damage", 500 ); // Damage shield will deal to boss zombies set_zombie_var( "shield_actionslot", 2 ); // Which action slot the shield will occupy. 2 = dpad down, which will not display on the hud // ================================= GENERAL SETTINGS =============================== // ================================= SETUP ================================= level.shield_gib_refs = []; level.shield_gib_refs[ level.shield_gib_refs.size ] = "guts"; level.shield_gib_refs[ level.shield_gib_refs.size ] = "right_arm"; level.shield_gib_refs[ level.shield_gib_refs.size ] = "left_arm"; level thread harrybo21_shield_tank_refill_point_logic(); level thread harrybo21_shield_upgrade_point_logic(); level thread harrybo21_shield_on_player_connect(); // ================================= SETUP ================================= } harrybo21_shield_load_shield( weaponfile, max_health, max_ammo, stow_model0, stow_model1, stow_model2, dmg0_model, dmg1_model, dmg2_model, fire_function ) { if ( !isDefined( level.shields ) ) level.shields = []; if ( !isDefined( level.zombie_weapons ) || !isDefined( level.zombie_weapons[ weaponfile ] ) ) PrecacheItem( weaponfile ); if ( !isDefined( max_health ) ) max_health = 15; if ( !isDefined( max_ammo ) ) max_ammo = -1; if ( !isDefined( fire_function ) ) fire_function = ::harrybo21_shield_melee; PrecacheModel( stow_model0 ); PrecacheModel( stow_model1 ); PrecacheModel( stow_model2 ); PrecacheModel( dmg0_model ); PrecacheModel( dmg1_model ); PrecacheModel( dmg2_model ); struct = SpawnStruct(); struct.stow_model = []; struct.stow_model[ 0 ] = stow_model0; struct.stow_model[ 1 ] = stow_model1; struct.stow_model[ 2 ] = stow_model2; struct.world_model = []; struct.world_model[ 0 ] = dmg0_model; struct.world_model[ 1 ] = dmg1_model; struct.world_model[ 2 ] = dmg2_model; struct.max_health = max_health; struct.max_ammo = max_ammo; struct.fire_function = fire_function; level.shields[ weaponfile ] = struct; harrybo21_shield_spawn_trigger( weaponfile ); } harrybo21_shield_spawn_trigger( weaponfile ) { triggers = getStructArray( "shield_trigger", "script_noteworthy" ); if ( !isDefined( triggers ) && triggers.size < 1 ) return; for ( i = 0; i < triggers.size; i++ ) { if ( isDefined( triggers[ i ].script_string ) && triggers[ i ].script_string == weaponfile ) { shield_trigger = harrybo21_custom_trigger_spawn_trigger_use_model( level.shields[ weaponfile ].world_model[ 0 ], triggers[ i ].origin, triggers[ i ].angles, 80 ); shield_trigger thread harrybo21_shield_trigger( weaponfile ); } } } harrybo21_shield_trigger( shield_name ) { self harrybo21_custom_trigger_set_hintstring_for_all( "Press and hold ^6[{+activate}]^7 for Zombie Shield" ); while( 1 ) { self waittill( "trigger", player ); if ( !is_shield_weapon( player getCurrentWeapon() ) ) player thread harrybo21_shield_attach_to_player( shield_name ); } } harrybo21_shield_on_player_connect() { for( ;; ) { level waittill( "connecting", player ); player thread harrybo21_shield_model_watcher(); player thread harrybo21_shield_melee_watcher(); player thread harrybo21_shield_fired_watcher(); player thread harrybo21_shield_grenade_fired_watcher(); player thread harrybo21_shield_remove_on_death(); player thread harrybo21_shield_cleanup_on_disconnect(); player thread harrybo21_shield_bowie_watcher(); player thread harrybo21_shield_on_player_spawned(); player thread harrybo21_shield_refill_after_round_logic(); } } harrybo21_shield_on_player_spawned() { for( ;; ) { self waittill( "spawned_player" ); self.current_shield = undefined; self.zombie_shield_health = undefined; self harrybo21_shield_remove_placed_shield(); } } harrybo21_shield_refill_after_round_logic() { while( 1 ) { level waittill( "between_round_over" ); shield = self return_owned_shield(); if ( isDefined( shield ) && isDefined( self.current_shield_ammo ) && self.current_shield_ammo < level.shields[ shield ].max_ammo ) self.current_shield_ammo++; } } harrybo21_shield_upgrade_point_logic() { if ( !isDefined( level.shields[ "bo3_zm_shield_soe_upgraded" ] ) && !isDefined( level.shields[ "bo3_zm_shield_gk_upgraded" ] ) ) return; points = getStructArray( "shield_upgrade_point", "script_noteworthy" ); if ( !isDefined( points ) || points.size < 1 ) return; for ( i = 0; i < points.size; i++ ) points[ i ] thread harrybo21_shield_upgrade_watcher(); } harrybo21_shield_upgrade_watcher() { self harrybo21_custom_trigger_make_trigger_object( 80 ); while( 1 ) { self harrybo21_custom_trigger_set_hintstring_for_all( "Press and hold ^6[{+activate}]^7 to upgrade Shield" ); player = undefined; self waittill( "trigger", player ); current_weapon = player getCurrentWeapon(); if ( player hasWeapon( "bo3_zm_shield_gk" ) ) { player harrybo21_shield_complete_remove(); if ( current_weapon == "bo3_zm_shield_gk" ) player SwitchToWeapon( player.previous_weapon ); self harrybo21_custom_trigger_set_hintstring_for_all( "" ); model = spawn( "script_model", self.origin ); model.angles = self.angles; model setModel( "wpn_t7_zmb_dlc3_dragon_shield_dmg0_world" ); wait 1; model moveTo( model.origin - ( 0, 0, 100 ), 1, .5 ); wait 4; model moveTo( model.origin + ( 0, 0, 100 ), 1, .5 ); wait 4; player harrybo21_give_shield( "bo3_zm_shield_gk_upgraded" ); model delete(); } else if ( player hasWeapon( "bo3_zm_shield_soe" ) ) { player harrybo21_shield_complete_remove(); if ( current_weapon == "bo3_zm_shield_soe" ) player SwitchToWeapon( player.previous_weapon ); self harrybo21_custom_trigger_set_hintstring_for_all( "" ); model = spawn( "script_model", self.origin ); model.angles = self.angles; model setModel( "wpn_t7_zmb_zod_rocket_shield_world" ); wait 1; model moveTo( model.origin - ( 0, 0, 100 ), 1, .5 ); wait 4; model moveTo( model.origin + ( 0, 0, 100 ), 1, .5 ); wait 4; player harrybo21_give_shield( "bo3_zm_shield_soe_upgraded" ); model delete(); } } } harrybo21_shield_tank_refill_point_logic() { points = getStructArray( "shield_refill_point", "script_noteworthy" ); if ( !isDefined( points ) || points.size < 1 ) return; for ( i = 0; i < points.size; i++ ) points[ i ].occupied = 0; level.current_refill_points = 0; while( 1 ) { if ( level.current_refill_points < 4 ) { array = getStructArray( "shield_refill_point", "script_noteworthy" ); array = array_randomize( array ); while( array[ 0 ].occupied ) array = array_randomize( array ); level thread harrybo21_shield_tank_refill( array[ 0 ].origin, array[ 0 ].angles, array[ 0 ] ); level.current_refill_points++; } level waittill( "between_round_over" ); } } harrybo21_shield_tank_refill( origin, angles, parent ) { parent.occupied = 1; tank = harrybo21_custom_trigger_spawn_trigger_use_model( "p7_zm_zod_nitrous_tank", origin, angles, 64, 1 ); tank thread harrybo21_shield_tank_hintstring_watcher(); self harrybo21_custom_trigger_set_hintstring_for_all( "" ); player = undefined; while( 1 ) { player = undefined; tank waittill( "trigger", player ); shield = player return_owned_shield(); if ( isDefined( shield ) && isDefined( player.current_shield_ammo ) && player.current_shield_ammo < level.shields[ shield ].max_ammo ) break; } player.current_shield_ammo++; level.current_refill_points--; parent.occupied = 0; tank harrybo21_custom_trigger_delete(); } harrybo21_shield_tank_hintstring_watcher() { self endon( "delete" ); while( 1 ) { players = get_players(); for ( i = 0; i < players.size; i++ ) { shield = players[ i ] return_owned_shield(); if ( isDefined( shield ) && isDefined( players[ i ].current_shield_ammo ) && players[ i ].current_shield_ammo < level.shields[ shield ].max_ammo ) self harrybo21_custom_trigger_set_hintstring_to_player( "Press & hold ^6[{+activate}]^7 to refill Shield", players[ i ] ); else self harrybo21_custom_trigger_set_hintstring_to_player( "", players[ i ] ); } wait .05; } } harrybo21_give_shield( shield_name ) { self harrybo21_shield_attach_to_player( shield_name ); } harrybo21_shield_show_hint( gun ) { self endon( "death" ); self endon( "disconnect" ); if( !isDefined( self.hintelem ) ) self.hintelem = newclienthudelem( self ); self.hintelem.x = 320; self.hintelem.y = 220; self.hintelem.alignX = "center"; self.hintelem.alignY = "bottom"; self.hintelem.fontScale = 1.6; self.hintelem.alpha = 1; self.hintelem.sort = 20; self.hintelem setText( "Press [{+actionslot " + level.zombie_vars[ "shield_actionslot" ] + "}] to equip Zombie Shield" ); wait 3.5; self.hintelem settext( "" ); self.hintelem destroy(); } harrybo21_shield_complete_remove() { self.zombie_shield_health = undefined; self harrybo21_shield_remove_placed_shield(); self harrybo21_shield_remove_from_player_inventory(); } harrybo21_shield_remove_from_player_inventory() { shields = GetArrayKeys( level.shields ); for ( i = 0; i < shields.size; i++ ) { self setWeaponAmmoClip( shields[ i ], 0 ); self player_take_action_slot_weapon( shields[ i ] ); } self.current_shield = undefined; self harrybo21_shield_destroy_player_model(); self.current_shield_ammo = undefined; self SetClientDvar( "origins_hud_shield_ammo", 0 ); self SetClientDvar( "origins_hud_has_shield", 0 ); self SetClientDvar( "origins_hud_shield_damage", 0 ); self SetClientDvar( "origins_hud_shield_dpad", level.zombie_vars[ "shield_actionslot" ] ); } harrybo21_shield_disable() { self takeWeapon( self.current_shield ); } harrybo21_shield_enable() { self giveWeapon( self.current_shield ); } harrybo21_shield_attach_to_player( shield_name, health, ammo ) { if ( !isDefined( health ) ) health = level.shields[ shield_name ].max_health; if ( !isDefined( ammo ) ) ammo = level.shields[ shield_name ].max_ammo; index = int( ( ( level.shields[ shield_name ].max_health - health ) / level.shields[ shield_name ].max_health ) * 3 ); self thread harrybo21_shield_show_hint( shield_name ); self harrybo21_shield_complete_remove(); self.zombie_shield_health = health; self harrybo21_shield_attach_to_back( level.shields[ shield_name ].stow_model[ 0 ] ); self player_set_action_slot_weapon( shield_name, level.zombie_vars[ "shield_actionslot" ], undefined, index ); self.current_shield = shield_name; self.current_shield_ammo = ammo; self SetClientDvar( "origins_hud_shield_ammo", ammo ); current_shield_status = index; self SetClientDvar( "origins_hud_has_shield", 1 ); self SetClientDvar( "origins_hud_shield_damage", index ); self SetClientDvar( "origins_hud_shield_dpad", level.zombie_vars[ "shield_actionslot" ] ); self playSound( "zombie_shield_plant" ); } harrybo21_shield_bowie_watcher() { has_melee = 0; while( 1 ) { if ( isDefined( self return_owned_shield() ) ) { if ( is_shield_weapon( self getCurrentWeapon() ) ) { if ( self hasPerk( "specialty_altmelee" ) ) { self unSetPerk( "specialty_altmelee" ); has_melee = 1; } } else { if ( has_melee && !self hasPerk( "specialty_altmelee" ) ) { self setPerk( "specialty_altmelee" ); has_melee = 0; } } } wait .1; } } harrybo21_shield_valid_previous_weapon( weapon ) { if ( weaponclass( weapon ) == "pistol" || weaponclass( weapon ) == "mg" || weaponclass( weapon ) == "rifle" || weaponclass( weapon ) == "smg" || weaponclass( weapon ) == "spread" || weaponclass( weapon ) == "rocketlauncher" || weaponclass( weapon ) == "gas" ) { if ( !is_shield_weapon( weapon ) && weapontype( weapon ) == "primary" ) return 1; else return 0; } else return 0; } harrybo21_shield_model_watcher() { self.previous_weapon = self getCurrentWeapon(); while( 1 ) { self waittill_any( "weapon_change", "weapon_change_complete", "weapon_obtained" ); weapon = self getCurrentWeapon(); if ( isDefined( weapon ) && isDefined( level.zombie_weapons[ weapon ] ) ) self.previous_weapon = weapon; shield_weapons = getArrayKeys( level.shields ); if ( isDefined( shield_weapons ) && shield_weapons.size > 0 ) { for ( i = 0; i < shield_weapons.size; i++ ) { if ( self hasWeapon( shield_weapons[ i ] ) ) { if ( weapon == shield_weapons[ i ] ) { index = int( ( ( level.shields[ weapon ].max_health - self.zombie_shield_health ) / level.shields[ weapon ].max_health ) * 3 ); if ( !isDefined( self.shield_hand ) || ( isDefined( self.shield_hand ) && self.shield_hand != level.shields[ weapon ].world_model[ index ] ) ) { if ( isDefined( self.shield_hand ) ) { self detach( self.shield_hand, "tag_weapon_left" ); self.shield_hand = undefined; } if ( isDefined( self.shield_back ) ) { self detach( self.shield_back, "tag_stowed_back" ); self.shield_back = undefined; } self.shield_hand = level.shields[ weapon ].world_model[ index ]; self attach( level.shields[ weapon ].world_model[ index ], "tag_weapon_left" ); } break; } else { index = int( ( ( level.shields[ shield_weapons[ i ] ].max_health - self.zombie_shield_health ) / level.shields[ shield_weapons[ i ] ].max_health ) * 3 ); if ( !isDefined( self.shield_back ) || ( isDefined( self.shield_back ) && self.shield_back != level.shields[ shield_weapons[ i ] ].stow_model[ index ] ) ) { if ( isDefined( self.shield_hand ) ) { self detach( self.shield_hand, "tag_weapon_left" ); self.shield_hand = undefined; } if ( isDefined( self.shield_back ) ) { self detach( self.shield_back, "tag_stowed_back" ); self.shield_back = undefined; } self.shield_back = level.shields[ shield_weapons[ i ] ].stow_model[ index ]; self attach( self.shield_back, "tag_stowed_back" ); } break; } } } } } } harrybo21_shield_cleanup_on_disconnect() { while( 1 ) { self waittill( "disconnect" ); self harrybo21_shield_remove_placed_shield(); } } harrybo21_shield_remove_on_death() { while( 1 ) { self waittill( "death" ); self harrybo21_shield_complete_remove(); } } harrybo21_shield_destroy_player_model() { temp_size = self getAttachSize(); if ( !isDefined( temp_size ) || temp_size < 1 ) return; temp = GetArrayKeys( level.shields ); for ( s = 0; s < temp.size; s++ ) { for ( i = 0; i < temp_size; i++ ) { if ( self GetAttachModelName( i ) == level.shields[ temp[ s ] ].world_model[ 0 ] ) self detach( level.shields[ temp[ s ] ].world_model[ 0 ], "tag_weapon_left" ); else if ( self GetAttachModelName( i ) == level.shields[ temp[ s ] ].world_model[ 1 ] ) self detach( level.shields[ temp[ s ] ].world_model[ 1 ], "tag_weapon_left" ); else if ( self GetAttachModelName( i ) == level.shields[ temp[ s ] ].world_model[ 2 ] ) self detach( level.shields[ temp[ s ] ].world_model[ 2 ], "tag_weapon_left" ); else if ( self GetAttachModelName( i ) == level.shields[ temp[ s ] ].stow_model[ 0 ] ) self detach( level.shields[ temp[ s ] ].stow_model[ 0 ], "tag_stowed_back" ); else if ( self GetAttachModelName( i ) == level.shields[ temp[ s ] ].stow_model[ 1 ] ) self detach( level.shields[ temp[ s ] ].stow_model[ 1 ], "tag_stowed_back" ); else if ( self GetAttachModelName( i ) == level.shields[ temp[ s ] ].stow_model[ 2 ] ) self detach( level.shields[ temp[ s ] ].stow_model[ 2 ], "tag_stowed_back" ); } } self.shield_hand = undefined; self.shield_back = undefined; } harrybo21_shield_attach_to_back( shield_model ) { if ( isDefined( self.shield_back ) ) self detach( self.shield_back, "tag_stowed_back" ); self.shield_back = shield_model; self attach( self.shield_back, "tag_stowed_back" ); } harrybo21_shield_attach_to_hand( shield_model ) { if ( isDefined( self.shield_hand ) ) self detach( self.shield_hand, "tag_weapon_left" ); self.shield_hand = shield_model; self attach( self.shield_hand, "tag_weapon_left" ); } harrybo21_shield_block_damage_check( zombie ) { block = 0; block_back = 0; owned_shield = self return_owned_shield(); if ( isDefined( owned_shield ) && isDefined( self.zombie_shield_health ) && self.zombie_shield_health > 0 ) { if ( self getCurrentWeapon() == owned_shield && within_fov( self getEye(), self getPlayerAngles(), zombie.origin, cos( 65 ) ) ) block = 1; else if ( self getCurrentWeapon() != owned_shield && !within_fov( self getEye(), self getPlayerAngles(), zombie.origin, cos( 65 ) ) ) block_back = 1; } if ( block || block_back ) { if ( block_back ) self harrybo21_shield_take_damage( 0 ); if ( block ) self harrybo21_shield_take_damage( 1 ); return 1; } return 0; } harrybo21_shield_take_damage( weapon_in_hand ) { self.zombie_shield_health -= 1; shield_name = self return_owned_shield(); index = int( ( ( level.shields[ shield_name ].max_health - self.zombie_shield_health ) / level.shields[ shield_name ].max_health ) * 3 ); if ( isDefined( self.zombie_shield_health ) && self.zombie_shield_health > 0 ) { self playsound( "zombie_shield_impact" ); if ( isDefined( weapon_in_hand ) && weapon_in_hand && ( self isMeleeing() || self isFiring() ) ) { while( self isMeleeing() || self isFiring() ) wait .05; } self setweaponammoclip( shield_name, 0 ); self takeWeapon( shield_name ); self giveWeapon( shield_name, index ); self setweaponammoclip( shield_name, 0 ); if ( weapon_in_hand ) self harrybo21_shield_attach_to_hand( level.shields[ shield_name ].stow_model[ index ] ); else self harrybo21_shield_attach_to_back( level.shields[ shield_name ].world_model[ index ] ); wait .05; self setweaponammoclip( shield_name, 1 ); } else { while( isDefined( weapon_in_hand ) && weapon_in_hand && ( self isMeleeing() || self isFiring() ) ) wait .05; self harrybo21_shield_complete_remove(); earthquake( 10, 1, self.origin, 20 ); playsoundatposition( "zombie_shield_destroy", self.origin ); if ( isDefined( weapon_in_hand ) && weapon_in_hand ) { if ( isDefined( self.previous_weapon ) ) self switchToWeapon( self.previous_weapon ); else { primaryWeapons = self GetWeaponsListPrimaries(); self switchToWeapon( primaryWeapons[ 0 ] ); } } } } harrybo21_shield_fired_watcher() { self endon( "disconnect" ); while( 1 ) { self waittill( "weapon_fired" ); weapname = self getCurrentWeapon(); if ( !is_shield_weapon( weapname ) ) continue; self AllowMelee( 0 ); self setweaponammoclip( weapname, 0 ); if ( !self is_busy() && !self isMeleeing() && isDefined( self.current_shield_ammo ) && self.current_shield_ammo > 0 && isDefined( level.shields[ weapname ].fire_function ) ) { self.current_shield_ammo--; self [[ level.shields[ weapname ].fire_function ]](); } else if ( weaponType( weapname ) != "grenade" ) self harrybo21_shield_melee(); self allowMelee( 1 ); self setWeaponAmmoClip( weapname, 1 ); } } harrybo21_shield_grenade_fired_watcher() { self endon( "disconnect" ); while( 1 ) { self waittill( "grenade_fire", shield, weapname ); if ( !self is_shield_weapon( weapname ) ) continue; self harrybo21_shield_place( shield, weapname ); } } // ========================= SHIELD MELEE ============================ harrybo21_shield_melee_watcher() { self endon( "disconnect" ); while( 1 ) { current_weapon = self GetCurrentWeapon(); if ( self isMeleeing() ) { self notify( "weapon_fired" ); while( self isMeleeing() ) wait .05; } wait .05; } } harrybo21_shield_melee() { physicsExplosionCylinder( self.origin, 600, 240, 1 ); if ( !IsDefined( level.shield_knockdown_enemies ) ) { level.shield_knockdown_enemies = []; level.shield_knockdown_gib = []; level.shield_fling_enemies = []; level.shield_fling_vecs = []; } self harrybo21_shield_get_enemies_in_range(); level.harrybo21_shield_network_choke_count = 0; i = 0; hit = 0; while ( i < level.shield_fling_enemies.size ) { if ( isDefined( level.shield_fling_enemies[ i ] ) ) { hit = 1; level.shield_fling_enemies[ i ] thread harrybo21_shield_fling_zombie( self, level.shield_fling_vecs[ i ], i ); } i++; } i = 0; while ( i < level.shield_knockdown_enemies.size ) { hit = 1; level.shield_knockdown_enemies[ i ] thread harrybo21_shield_knockdown_zombie( self, level.shield_knockdown_gib[ i ] ); i++; } if ( hit ) self thread harrybo21_shield_take_damage( 1 ); level.shield_knockdown_enemies = []; level.shield_knockdown_gib = []; level.shield_fling_enemies = []; level.shield_fling_vecs = []; wait .08; } harrybo21_shield_get_enemies_in_range() { origin = self.origin + ( anglesToForward( self getPlayerAngles() ) * 5 ); view_pos = origin + ( 0, 0, 72 / 2 + 10 ); zombies = get_array_of_closest( view_pos, GetAiSpeciesArray( "axis", "all" ), undefined, undefined, 2 * level.zombie_vars[ "shield_knockdown_range" ] ); if ( !isDefined( zombies ) ) return; knockdown_range_squared = level.zombie_vars[ "shield_knockdown_range" ] * level.zombie_vars[ "shield_knockdown_range" ]; gib_range_squared = level.zombie_vars[ "shield_gib_range" ] * level.zombie_vars[ "shield_gib_range" ]; fling_range_squared = level.zombie_vars[ "shield_fling_range" ] * level.zombie_vars[ "shield_fling_range" ]; cylinder_radius_squared = level.zombie_vars[ "shield_cylinder_radius" ] * level.zombie_vars[ "shield_cylinder_radius" ]; forward_view_angles = anglesToForward(self getPlayerAngles()); end_pos = view_pos + ( forward_view_angles * level.zombie_vars[ "shield_knockdown_range" ] ); for ( i = 0; i < zombies.size; i++ ) { if ( !IsDefined( zombies[ i ] ) || !IsAlive( zombies[ i ] ) ) continue; test_origin = zombies[ i ] getcentroid(); test_range_squared = DistanceSquared( view_pos, test_origin ); if ( test_range_squared > knockdown_range_squared ) return; normal = VectorNormalize( test_origin - view_pos ); dot = VectorDot( forward_view_angles, normal ); if ( 0 > dot ) continue; radial_origin = PointOnSegmentNearestToPoint( view_pos, end_pos, test_origin ); if ( DistanceSquared( test_origin, radial_origin ) > cylinder_radius_squared ) continue; if ( 0 == zombies[i] DamageConeTrace( view_pos, self ) ) continue; if ( test_range_squared < fling_range_squared ) { level.shield_fling_enemies[level.shield_fling_enemies.size] = zombies[i]; dist_mult = (fling_range_squared - test_range_squared) / fling_range_squared; fling_vec = VectorNormalize( test_origin - view_pos ); if ( 5000 < test_range_squared ) fling_vec = fling_vec + VectorNormalize( test_origin - radial_origin ); fling_vec = ( fling_vec[ 0 ], fling_vec[ 1 ], abs( fling_vec[ 2 ] ) ); fling_vec = ( fling_vec * ( 100 + 100 * dist_mult ) ); level.shield_fling_vecs[ level.shield_fling_vecs.size ] = fling_vec; } else if ( test_range_squared < gib_range_squared ) { level.shield_knockdown_enemies[ level.shield_knockdown_enemies.size ] = zombies[ i ]; level.shield_knockdown_gib[ level.shield_knockdown_gib.size ] = 1; } else { level.shield_knockdown_enemies[ level.shield_knockdown_enemies.size ] = zombies[ i ]; level.shield_knockdown_gib[ level.shield_knockdown_gib.size ] = 0; } } } harrybo21_shield_fling_zombie( player, fling_vec, index ) { if( ( isdefined( self.boss ) && self.boss ) || self.animname == "jnaut_melee" || self.animname == "jnaut_gunner" ) { self DoDamage( level.zombie_vars[ "shield_boss_damage" ], player.origin, player ); return; } if( !IsDefined( self ) || !IsAlive( self ) ) return; dmg = level.zombie_vars[ "shield_damage" ]; if ( isDefined( level.zombie_vars[ "zombie_powerup_insta_kill_on" ] ) && level.zombie_vars[ "zombie_powerup_insta_kill_on" ] ) dmg = self.health + 666; self DoDamage( dmg, player.origin ); if ( self.health <= 0 ) { self StartRagdoll(); self LaunchRagdoll( fling_vec ); self.shield_death = 1; } else { score = 10; if ( isDefined( level.zombie_vars[ "zombie_powerup_point_doubler_on" ] ) && level.zombie_vars[ "zombie_powerup_point_doubler_on" ] ) score = score * 2; player.score += score; player maps\_zombiemode_score::set_player_score_hud(); } } harrybo21_shield_knockdown_zombie( player, gib ) { self endon( "death" ); playsoundatposition ( "vox_thundergun_forcehit", self.origin ); if( !IsDefined( self ) || !IsAlive( self ) ) return; if ( IsDefined( self.shield_knockdown_func ) ) self [[ self.shield_knockdown_func ]]( player, gib ); else self DoDamage( level.zombie_vars[ "shield_knockdown_damage" ], player.origin, player ); if ( gib ) { self.a.gib_ref = random( level.shield_gib_refs ); self thread animscripts\death::do_gib(); } self doDamage( level.zombie_vars[ "shield_knockdown_damage" ], player.origin, player ); self.shield_knockdown = 1; self.thundergun_knockdown = 1; self playsound( "fly_thundergun_forcehit" ); wait .15; self.shield_knockdown = undefined; } // ========================= SHIELD MELEE ============================ // ========================= SHIELD PLACE / PICKUP ============================ harrybo21_shield_place( shield, weapname ) { destination1 = self.origin + ( anglesToForward( self.angles ) * 40 ); destination = playerPhysicsTrace( self.origin, destination1 ) + ( anglesToForward( self.angles ) * 40 ); destination3 = playerPhysicsTrace( destination, destination + ( 0, 0, -1000 ) ); if ( self getVelocity() != ( 0, 0, 0 ) || destination != ( destination1 + ( anglesToForward( self.angles ) * 40 ) ) || self GetStance() == "prone" || distance( destination3, destination ) > 50 ) { shield delete(); self setweaponammoclip( weapname, 1 ); return; } index = int( ( ( level.shields[ weapname ].max_health - self.zombie_shield_health ) / level.shields[ weapname ].max_health ) * 3 ); // index = harrybo21_harrybo21_shield_get_model_index( weapname, self.zombie_shield_health ); fake_model = harrybo21_custom_trigger_spawn_trigger_use_model( level.shields[ weapname ].world_model[ index ], destination3 + ( 0, 0, 27 ), self.angles, 64, 1 ); fake_model harrybo21_custom_trigger_set_hintstring_for_all( "Press & hold ^6[{+activate}]^7 to take Shield" ); if ( !isDefined( self.zombie_shield_health ) ) fake_model.zombie_shield_health = level.shields[ weapname ].max_health; else fake_model.zombie_shield_health = self.zombie_shield_health; self.zombie_shield_health = undefined; fake_model.owner = self; fake_model.targetname = weapname; fake_model.weap_name = weapname; fake_model thread harrybo21_shield_pickup_watcher( weapname, self ); fake_model.clip = spawnCollision("collision_geo_32x32x32", "collider", fake_model.origin + ( 0, 0, 25 ), fake_model.angles + ( 0, 45, 45 ) ); fake_model.clip2 = spawnCollision("collision_geo_32x32x32", "collider", fake_model.origin + ( 0, 0, 5 ), fake_model.angles + ( 0, 0, 0 ) ); playsoundatposition ( "zombie_shield_plant", fake_model.origin ); shield delete(); self harrybo21_shield_destroy_player_model(); self harrybo21_shield_remove_from_player_inventory(); self SwitchToWeapon( self.previous_weapon ); } harrybo21_shield_pickup_watcher( shield_name, shield_owner ) { self endon( "shield_destroyed" ); self endon( "disconnect" ); while( 1 ) { player = undefined; self waittill( "trigger", player ); if ( !player is_busy() && player == shield_owner && player isOnGround() && !player maps\_laststand::player_is_in_laststand() ) { self playsound ( "zombie_shield_destroy" ); player harrybo21_shield_attach_to_player( shield_name, self.zombie_shield_health ); player harrybo21_shield_remove_placed_shield(); player switchToWeapon( shield_name ); break; } } self harrybo21_custom_trigger_delete(); } harrybo21_shield_think_attack() { self endon( "death" ); self endon( "delete" ); if( ( isdefined( self.boss ) && self.boss ) || self.animname == "jnaut_melee" || self.animname == "jnaut_gunner" ) return; while( 1 ) { path = 0; temp = GetArrayKeys( level.shields ); for ( s = 0; s < temp.size; s++ ) { shields = getEntArray( temp[ s ], "targetname" ); for ( i = 0; i < shields.size; i++ ) { if ( distance( self.origin, shields[ i ].origin ) && distance( self.origin, shields[ i ].origin ) < 200 ) { self.favoriteenemy = shields[ i ]; if ( distance( self.origin, shields[ i ].origin ) < 64 ) self harrybo21_shield_zombie_attack( shields[ i ] ); else { path = 1; self SetGoalPos( shields[ i ].origin ); } } } } if ( path ) { wait .1; continue; } else break; } } harrybo21_shield_zombie_attack( shield ) { self endon( "death" ); self endon( "delete" ); if ( isDefined( self.attacking_shield ) && self.attacking_shield ) return; self.attacking_shield = 1; angles = VectorToAngles( shield.origin - self.origin ); self OrientMode( "face angle", angles[ 1 ] ); animation = undefined; if ( !self.has_legs ) animation = %ai_zombie_crawl_riotshield_loop_v1; else animation = %ai_zombie_riotshield_loop_v1; self animscripted( "attack_shield", self.origin, self.angles, animation ); while ( 1 ) { self waittill( "attack_shield", note ); if ( note == "fire" ) { if ( isDefined( shield ) && isDefined( shield.zombie_shield_health ) && shield.zombie_shield_health - 1 > 0 ) { shield playsound ( "zombie_shield_impact" ); shield.zombie_shield_health -= 1; index = int( ( ( level.shields[ shield.weap_name ].max_health - shield.zombie_shield_health ) / level.shields[ shield.weap_name ].max_health ) * 3 ); shield setmodel( level.shields[ shield.weap_name ].world_model[ index ] ); continue; } else if ( isDefined( shield ) && isDefined( shield.zombie_shield_health ) && shield.zombie_shield_health - 1 <= 0 ) { animation = undefined; if ( !self.has_legs ) animation = %ai_zombie_crawl_riotshield_breakthrough_v1; else animation = %ai_zombie_riotshield_breakthrough_v1; self animscripted( "break_shield", self.origin, self.angles, animation ); earthquake( 10, 1, shield.origin, 20 ); playsoundatposition( "zombie_shield_destroy", shield.origin ); shield notify( "shield_destroyed" ); shield.trigger delete(); shield.clip delete(); shield.clip2 delete(); shield delete(); break; } else { self stopAnimScripted(); break; } } } self.attacking_shield = undefined; } harrybo21_shield_remove_placed_shield() { shields = GetArrayKeys( level.shields ); for ( s = 0; s < shields.size; s++ ) { placed_shields = getEntArray( shields[ s ], "targetname" ); for ( i = 0; i < placed_shields.size; i++ ) { if ( placed_shields[ i ].owner == self ) { earthquake( 10, 1, placed_shields[ i ].origin, 20 ); playsoundatposition( "zombie_shield_destroy", placed_shields[ i ].origin ); placed_shields[ i ] notify( "shield_destroyed" ); placed_shields[ i ].trigger delete(); placed_shields[ i ].clip delete(); placed_shields[ i ].clip2 delete(); placed_shields[ i ] delete(); } } } } // ========================= SHIELD PLACE / PICKUP ============================ // ========================= ROCKET SHIELD ============================ harrybo21_rocket_shield_activate() { if ( !self isOnGround() ) { self.current_shield_ammo++; self harrybo21_shield_melee(); return; } self allowSprint( 0 ); self setStance( "stand" ); self enableInvulnerability(); self disableWeaponCycling(); self _disableOffHandWeapons(); self freezeControls( 1 ); fx_obj = spawn( "script_model", self.origin ); fx_obj.angles = self.angles; fx_obj setModel( "tag_origin" ); forward_angles = anglesToForward( self.angles ); self linkTo( fx_obj ); self thread harrybo21_rocket_shield_blast(); self playSound( "zombie_rocket_shield_start" ); trace_origin = self.origin + vectorScale( forward_angles, 500 ); trace = playerPhysicsTrace( self.origin, trace_origin ); move_wait = distance( trace, self.origin ) / 500; // .5; // if ( distance( trace, self.origin ) > 200 ) // move_wait = 1; self.fell = 0; fx_obj thread harrybo21_rocket_shield_watch_for_fall( self ); fx_obj moveTo( trace, 1, .3, .2 ); wait 1; if ( !self.fell ) { self notify( "rocket_blast_complete" ); self playSound( "zombie_rocket_shield_end" ); self unlink(); self allowSprint( 1 ); self disableInvulnerability(); self enableWeaponCycling(); self _enableOffhandWeapons(); self freezeControls( 0 ); } fx_obj delete(); self.fell = undefined; } harrybo21_rocket_shield_watch_for_fall( player ) { self endon( "rocket_blast_complete" ); while( 1 ) { upAngles = anglesToUp( self.angles ); trace_origin = self.origin + vectorScale( upAngles, -500 ); trace = playerPhysicsTrace( self.origin, trace_origin ); iPrintLnBold( distance( trace, self.origin ) ); if ( distance( trace, self.origin ) > 64 ) break; wait .05; } player.fell = 1; player playSound( "zombie_rocket_shield_end" ); player unlink(); player allowSprint( 1 ); player DisableInvulnerability(); player EnableWeaponCycling(); player _enableOffhandWeapons(); player freezecontrols( 0 ); player notify( "rocket_blast_complete" ); } harrybo21_rocket_shield_blast() { self endon( "rocket_blast_complete" ); self endon( "death" ); self endon( "disconnect" ); while( 1 ) { ai = GetAiSpeciesArray( "axis", "all" ); if ( isDefined( ai ) && ai.size > 0 ) { for( i = 0; i < ai.size; i++ ) { if( within_fov( self getEye(), self getPlayerAngles(), ai[ i ].origin, cos( 90 ) ) && distance( self.origin, ai[ i ].origin ) <= 64 ) { ai[ i ].shield_hit = 1; self playsound( "zombie_shield_impact" ); ai[ i ] thread harrybo21_shield_point_fling( self.origin, self ); } } } wait .05; } } // ========================= ROCKET SHIELD ============================ // ========================= DRAGON SHIELD ============================ harrybo21_shield_dragon_fire() { weapname = self return_owned_shield(); if ( issubstr( weapname, "_upgraded" ) ) fx = level._effect[ "dragon_shield_fire" ]; else fx = level._effect[ "dragon_shield_fire_upgraded" ]; origin = self GetTagOrigin( "j_spineupper" ) + ( 0, 0, 10 ); forward_angles = anglesToForward( self getPlayerAngles() ); fx_obj = spawn( "script_model", origin ); fx_obj setModel( "tag_origin" ); if ( issubstr( weapname, "_upgraded" ) ) playFxOnTag( level._effect[ "dragon_shield_fire_upgraded" ], fx_obj, "tag_origin" ); else playFxOnTag( level._effect[ "dragon_shield_fire" ], fx_obj, "tag_origin" ); trace_origin = origin + vectorScale( forward_angles, 10000 ); trace = BulletTrace( origin, trace_origin, 1, self ); fx_obj playSound( "zombie_dragon_shield_fire" ); move_wait = .5; if ( distance( trace[ "position" ], origin ) > 24 ) move_wait = 1; fx_obj moveTo( trace[ "position" ], move_wait ); ai = GetAiSpeciesArray( "axis", "all" ); wait move_wait; playSoundAtPosition( "zombie_dragon_shield_explode", fx_obj.origin ); fx_obj delete(); if ( issubstr( weapname, "_upgraded" ) ) playFx( level._effect[ "dragon_shield_explode_upgraded" ], trace[ "position" ] ); else playFx( level._effect[ "dragon_shield_explode" ], trace[ "position" ] ); if ( !isDefined( ai ) || ai.size < 1 ) return; if ( issubstr( weapname, "_upgraded" ) ) radius = 20000 * 2; else radius = 20000 * 1; for( i = 0; i < ai.size; i++ ) { can_trace = bulletTracePassed( trace[ "position" ], ai[ i ] getTagOrigin( "tag_origin" ), 0, self ); if ( !can_trace ) can_trace = bulletTracePassed( trace[ "position" ], ai[ i ] getTagOrigin( "j_head" ), 0, self ); if ( !can_trace ) can_trace = bulletTracePassed( trace[ "position" ], ai[ i ] getTagOrigin( "j_spineupper" ), 0, self ); if ( !can_trace ) continue; if ( distanceSquared( trace[ "position" ], ai[ i ].origin ) <= radius ) { if ( issubstr( weapname, "_upgraded" ) ) ai[ i ] thread harrybo21_shield_dragon_fire_body_fx( level._effect[ "dragon_shield_fire_body_upgraded" ] ); else ai[ i ] thread harrybo21_shield_dragon_fire_body_fx( level._effect[ "dragon_shield_fire_body" ] ); ai[ i ] thread harrybo21_shield_point_fling( trace[ "position" ], self ); } else if ( distanceSquared( trace[ "position" ], ai[ i ].origin ) <= ( radius * 2 ) ) { ai[ i ] doDamage( int( ai[ i ].health / 2 ), trace[ "position" ], self ); ai[ i ] thread harrybo21_shield_knockdown_zombie( self, level.shield_knockdown_gib[ randomInt( 2 ) ] ); if ( issubstr( weapname, "_upgraded" ) ) ai[ i ] thread harrybo21_shield_dragon_fire_body_fx( level._effect[ "dragon_shield_fire_body_upgraded" ] ); else ai[ i ] thread harrybo21_shield_dragon_fire_body_fx( level._effect[ "dragon_shield_fire_body" ] ); } } } harrybo21_shield_dragon_fire_body_fx( fx ) { self endon( "delete" ); self.health = 1; joints = []; joints[ 0 ] = "j_spinelower"; joints[ 1 ] = "j_spineupper"; joints[ 2 ] = "j_shoulder_le"; joints[ 3 ] = "j_shoulder_ri"; joints[ 4 ] = "j_elbow_ri"; joints[ 5 ] = "j_elbow_le"; joints[ 6 ] = "j_knee_le"; joints[ 7 ] = "j_knee_ri"; for ( i = 0; i < 30; i++ ) { index = randomInt( 8 ); playfxontag( fx, self, joints[ index ] ); wait RandomFloatRange( .05, .35 ); } } harrybo21_shield_point_fling( origin, player ) { angle = vectorToAngles( origin - self.origin ); angle = anglesToForward( angle - ( 0, 180, 0 ) ) + anglesToUp( angle ); self.shield_death = 1; self startRagdoll(); fling_vec = vectorScale( angle, 200 ); self launchRagdoll( fling_vec ); self doDamage( self.maxHealth + 666, self.origin, player ); player maps\_zombiemode_score::add_to_player_score( 50 ); } // ========================= DRAGON SHIELD ============================