diff --git a/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc b/patch_zm/maps/mp/gametypes_zm/MajorErrors/_zm_gametype.gsc similarity index 100% rename from patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc rename to patch_zm/maps/mp/gametypes_zm/MajorErrors/_zm_gametype.gsc diff --git a/patch_zm/maps/mp/gametypes_zm/_clientids.gsc b/patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_clientids.gsc similarity index 100% rename from patch_zm/maps/mp/gametypes_zm/_clientids.gsc rename to patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_clientids.gsc diff --git a/patch_zm/maps/mp/gametypes_zm/_globalentities.gsc b/patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_globalentities.gsc similarity index 100% rename from patch_zm/maps/mp/gametypes_zm/_globalentities.gsc rename to patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_globalentities.gsc diff --git a/patch_zm/maps/mp/gametypes_zm/_scoreboard.gsc b/patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_scoreboard.gsc similarity index 100% rename from patch_zm/maps/mp/gametypes_zm/_scoreboard.gsc rename to patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_scoreboard.gsc diff --git a/patch_zm/maps/mp/gametypes_zm/_shellshock.gsc b/patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_shellshock.gsc similarity index 100% rename from patch_zm/maps/mp/gametypes_zm/_shellshock.gsc rename to patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_shellshock.gsc diff --git a/patch_zm/maps/mp/gametypes_zm/zclassic.gsc b/patch_zm/maps/mp/gametypes_zm/NoKnownErrors/zclassic.gsc similarity index 100% rename from patch_zm/maps/mp/gametypes_zm/zclassic.gsc rename to patch_zm/maps/mp/gametypes_zm/NoKnownErrors/zclassic.gsc diff --git a/patch_zm/maps/mp/zombies/MajorErrors/_zm_chugabud.gsc b/patch_zm/maps/mp/zombies/MajorErrors/_zm_chugabud.gsc new file mode 100644 index 0000000..2ca218a --- /dev/null +++ b/patch_zm/maps/mp/zombies/MajorErrors/_zm_chugabud.gsc @@ -0,0 +1,847 @@ +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_weap_cymbal_monkey; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_clone; +#include maps/mp/zombies/_zm_chugabud; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; +#include maps/mp/zombies/_zm_perks; + +init() +{ + level.chugabud_laststand_func = ::chugabud_laststand; + level thread chugabud_hostmigration(); + level._effect[ "chugabud_revive_fx" ] = loadfx( "weapon/quantum_bomb/fx_player_position_effect" ); + level._effect[ "chugabud_bleedout_fx" ] = loadfx( "weapon/quantum_bomb/fx_player_position_effect" ); + add_custom_limited_weapon_check( ::is_weapon_available_in_chugabud_corpse ); +} + +chugabug_precache() +{ +} + +chugabud_player_init() +{ +} + +chugabud_laststand() +{ + self endon( "player_suicide" ); + self endon( "disconnect" ); + self endon( "chugabud_bleedout" ); + self maps/mp/zombies/_zm_laststand::increment_downed_stat(); + self.ignore_insta_kill = 1; + self.health = self.maxhealth; + self maps/mp/zombies/_zm_chugabud::chugabud_save_loadout(); + self maps/mp/zombies/_zm_chugabud::chugabud_fake_death(); + wait 3; + if ( isDefined( self.insta_killed ) || self.insta_killed && isDefined( self.disable_chugabud_corpse ) ) + { + create_corpse = 0; + } + else + { + create_corpse = 1; + } + if ( create_corpse == 1 ) + { + if ( isDefined( level._chugabug_reject_corpse_override_func ) ) + { + reject_corpse = self [[ level._chugabug_reject_corpse_override_func ]]( self.origin ); + if ( reject_corpse ) + { + create_corpse = 0; + } + } + } + if ( create_corpse == 1 ) + { + self thread activate_chugabud_effects_and_audio(); + corpse = self chugabud_spawn_corpse(); + corpse thread chugabud_corpse_revive_icon( self ); + self.e_chugabud_corpse = corpse; + corpse thread chugabud_corpse_cleanup_on_spectator( self ); + if ( isDefined( level.whos_who_client_setup ) ) + { + corpse setclientfield( "clientfield_whos_who_clone_glow_shader", 1 ); + } + } + self chugabud_fake_revive(); + wait 0.1; + self.ignore_insta_kill = undefined; + self.disable_chugabud_corpse = undefined; + if ( create_corpse == 0 ) + { + self notify( "chugabud_effects_cleanup" ); + return; + } + bleedout_time = getDvarFloat( "player_lastStandBleedoutTime" ); + self thread chugabud_bleed_timeout( bleedout_time, corpse ); + self thread chugabud_handle_multiple_instances( corpse ); + corpse waittill( "player_revived", e_reviver ); + if ( isDefined( e_reviver ) && e_reviver == self ) + { + self notify( "whos_who_self_revive" ); + } + self perk_abort_drinking( 0.1 ); + self maps/mp/zombies/_zm_perks::perk_set_max_health_if_jugg( "health_reboot", 1, 0 ); + self setorigin( corpse.origin ); + self setplayerangles( corpse.angles ); + if ( self player_is_in_laststand() ) + { + self thread chugabud_laststand_cleanup( corpse, "player_revived" ); + self enableweaponcycling(); + self enableoffhandweapons(); + self auto_revive( self, 1 ); + return; + } + self chugabud_laststand_cleanup( corpse, undefined ); +} + +chugabud_laststand_cleanup( corpse, str_notify ) +{ + if ( isDefined( str_notify ) ) + { + self waittill( str_notify ); + } + self chugabud_give_loadout(); + self chugabud_corpse_cleanup( corpse, 1 ); +} + +chugabud_bleed_timeout( delay, corpse ) +{ + self endon( "player_suicide" ); + self endon( "disconnect" ); + corpse endon( "death" ); + wait delay; + while ( isDefined( corpse.revivetrigger ) ) + { + while ( corpse.revivetrigger.beingrevived ) + { + wait 0.01; + } + } + while ( isDefined( self.loadout.perks ) && flag( "solo_game" ) ) + { + i = 0; + while ( i < self.loadout.perks.size ) + { + perk = self.loadout.perks[ i ]; + if ( perk == "specialty_quickrevive" ) + { + arrayremovevalue( self.loadout.perks, self.loadout.perks[ i ] ); + corpse notify( "player_revived" ); + return; + } + i++; + } + } + self chugabud_corpse_cleanup( corpse, 0 ); +} + +chugabud_corpse_cleanup( corpse, was_revived ) +{ + self notify( "chugabud_effects_cleanup" ); + if ( was_revived ) + { + playsoundatposition( "evt_ww_appear", corpse.origin ); + playfx( level._effect[ "chugabud_revive_fx" ], corpse.origin ); + } + else + { + playsoundatposition( "evt_ww_disappear", corpse.origin ); + playfx( level._effect[ "chugabud_bleedout_fx" ], corpse.origin ); + self notify( "chugabud_bleedout" ); + } + if ( isDefined( corpse.revivetrigger ) ) + { + corpse notify( "stop_revive_trigger" ); + corpse.revivetrigger delete(); + corpse.revivetrigger = undefined; + } + if ( isDefined( corpse.revive_hud_elem ) ) + { + corpse.revive_hud_elem destroy(); + corpse.revive_hud_elem = undefined; + } + self.loadout = undefined; + wait 0.1; + corpse delete(); + self.e_chugabud_corpse = undefined; +} + +chugabud_handle_multiple_instances( corpse ) +{ + corpse endon( "death" ); + self waittill( "perk_chugabud_activated" ); + self chugabud_corpse_cleanup( corpse, 0 ); +} + +chugabud_spawn_corpse() +{ + corpse = maps/mp/zombies/_zm_clone::spawn_player_clone( self, self.origin, undefined, self.whos_who_shader ); + corpse.angles = self.angles; + corpse maps/mp/zombies/_zm_clone::clone_give_weapon( "m1911_zm" ); + corpse maps/mp/zombies/_zm_clone::clone_animate( "laststand" ); + corpse.revive_hud = self chugabud_revive_hud_create(); + corpse thread maps/mp/zombies/_zm_laststand::revive_trigger_spawn(); + return corpse; +} + +chugabud_revive_hud_create() +{ + self.revive_hud = newclienthudelem( self ); + self.revive_hud.alignx = "center"; + self.revive_hud.aligny = "middle"; + self.revive_hud.horzalign = "center"; + self.revive_hud.vertalign = "bottom"; + self.revive_hud.y = -50; + self.revive_hud.foreground = 1; + self.revive_hud.font = "default"; + self.revive_hud.fontscale = 1.5; + self.revive_hud.alpha = 0; + self.revive_hud.color = ( 1, 1, 1 ); + self.revive_hud settext( "" ); + return self.revive_hud; +} + +chugabud_save_loadout() +{ + primaries = self getweaponslistprimaries(); + currentweapon = self getcurrentweapon(); + self.loadout = spawnstruct(); + self.loadout.player = self; + self.loadout.weapons = []; + self.loadout.score = self.score; + self.loadout.current_weapon = -1; + _a376 = primaries; + index = getFirstArrayKey( _a376 ); + while ( isDefined( index ) ) + { + weapon = _a376[ index ]; + self.loadout.weapons[ index ] = maps/mp/zombies/_zm_weapons::get_player_weapondata( self, weapon ); + if ( weapon == currentweapon || self.loadout.weapons[ index ][ "alt_name" ] == currentweapon ) + { + self.loadout.current_weapon = index; + } + index = getNextArrayKey( _a376, index ); + } + self.loadout.equipment = self get_player_equipment(); + if ( isDefined( self.loadout.equipment ) ) + { + self equipment_take( self.loadout.equipment ); + } + self.loadout save_weapons_for_chugabud( self ); + if ( self hasweapon( "claymore_zm" ) ) + { + self.loadout.hasclaymore = 1; + self.loadout.claymoreclip = self getweaponammoclip( "claymore_zm" ); + } + self.loadout.perks = chugabud_save_perks( self ); + self chugabud_save_grenades(); + if ( maps/mp/zombies/_zm_weap_cymbal_monkey::cymbal_monkey_exists() ) + { + self.loadout.zombie_cymbal_monkey_count = self getweaponammoclip( "cymbal_monkey_zm" ); + } +} + +chugabud_save_grenades() +{ + if ( self hasweapon( "emp_grenade_zm" ) ) + { + self.loadout.hasemp = 1; + self.loadout.empclip = self getweaponammoclip( "emp_grenade_zm" ); + } + lethal_grenade = self get_player_lethal_grenade(); + if ( self hasweapon( lethal_grenade ) ) + { + self.loadout.lethal_grenade = lethal_grenade; + self.loadout.lethal_grenade_count = self getweaponammoclip( lethal_grenade ); + } + else + { + self.loadout.lethal_grenade = undefined; + } +} + +chugabud_give_loadout() +{ + self takeallweapons(); + loadout = self.loadout; + primaries = self getweaponslistprimaries(); + while ( loadout.weapons.size > 1 || primaries.size > 1 ) + { + _a458 = primaries; + _k458 = getFirstArrayKey( _a458 ); + while ( isDefined( _k458 ) ) + { + weapon = _a458[ _k458 ]; + self takeweapon( weapon ); + _k458 = getNextArrayKey( _a458, _k458 ); + } + } + i = 0; + while ( i < loadout.weapons.size ) + { + if ( !isDefined( loadout.weapons[ i ] ) ) + { + i++; + continue; + } + else if ( loadout.weapons[ i ][ "name" ] == "none" ) + { + i++; + continue; + } + else + { + self maps/mp/zombies/_zm_weapons::weapondata_give( loadout.weapons[ i ] ); + } + i++; + } + if ( loadout.current_weapon >= 0 && isDefined( loadout.weapons[ loadout.current_weapon ][ "name" ] ) ) + { + self switchtoweapon( loadout.weapons[ loadout.current_weapon ][ "name" ] ); + } + self giveweapon( "knife_zm" ); + self maps/mp/zombies/_zm_equipment::equipment_give( self.loadout.equipment ); + loadout restore_weapons_for_chugabud( self ); + self chugabud_restore_claymore(); + self.score = loadout.score; + self.pers[ "score" ] = loadout.score; + perk_array = maps/mp/zombies/_zm_perks::get_perk_array( 1 ); + i = 0; + while ( i < perk_array.size ) + { + perk = perk_array[ i ]; + self unsetperk( perk ); + self.num_perks--; + + self set_perk_clientfield( perk, 0 ); + i++; + } + while ( isDefined( loadout.perks ) && loadout.perks.size > 0 ) + { + i = 0; + while ( i < loadout.perks.size ) + { + if ( self hasperk( loadout.perks[ i ] ) ) + { + i++; + continue; + } + else if ( loadout.perks[ i ] == "specialty_quickrevive" && flag( "solo_game" ) ) + { + level.solo_game_free_player_quickrevive = 1; + } + if ( loadout.perks[ i ] == "specialty_finalstand" ) + { + i++; + continue; + } + else + { + maps/mp/zombies/_zm_perks::give_perk( loadout.perks[ i ] ); + } + i++; + } + } + self chugabud_restore_grenades(); + if ( maps/mp/zombies/_zm_weap_cymbal_monkey::cymbal_monkey_exists() ) + { + if ( loadout.zombie_cymbal_monkey_count ) + { + self maps/mp/zombies/_zm_weap_cymbal_monkey::player_give_cymbal_monkey(); + self setweaponammoclip( "cymbal_monkey_zm", loadout.zombie_cymbal_monkey_count ); + } + } +} + +chugabud_restore_grenades() +{ + if ( isDefined( self.loadout.hasemp ) && self.loadout.hasemp ) + { + self giveweapon( "emp_grenade_zm" ); + self setweaponammoclip( "emp_grenade_zm", self.loadout.empclip ); + } + if ( isDefined( self.loadout.lethal_grenade ) ) + { + self giveweapon( self.loadout.lethal_grenade ); + self setweaponammoclip( self.loadout.lethal_grenade, self.loadout.lethal_grenade_count ); + } +} + +chugabud_restore_claymore() +{ + if ( isDefined( self.loadout.hasclaymore ) && self.loadout.hasclaymore && !self hasweapon( "claymore_zm" ) ) + { + self giveweapon( "claymore_zm" ); + self set_player_placeable_mine( "claymore_zm" ); + self setactionslot( 4, "weapon", "claymore_zm" ); + self setweaponammoclip( "claymore_zm", self.loadout.claymoreclip ); + } +} + +chugabud_fake_death() +{ + level notify( "fake_death" ); + self notify( "fake_death" ); + self takeallweapons(); + self allowstand( 0 ); + self allowcrouch( 0 ); + self allowprone( 1 ); + self.ignoreme = 1; + self enableinvulnerability(); + wait 0.1; + self freezecontrols( 1 ); + wait 0.9; +} + +chugabud_fake_revive() +{ + level notify( "fake_revive" ); + self notify( "fake_revive" ); + playsoundatposition( "evt_ww_disappear", self.origin ); + playfx( level._effect[ "chugabud_revive_fx" ], self.origin ); + spawnpoint = chugabud_get_spawnpoint(); + if ( isDefined( level._chugabud_post_respawn_override_func ) ) + { + self [[ level._chugabud_post_respawn_override_func ]]( spawnpoint.origin ); + } + if ( isDefined( level.chugabud_force_corpse_position ) ) + { + if ( isDefined( self.e_chugabud_corpse ) ) + { + self.e_chugabud_corpse forceteleport( level.chugabud_force_corpse_position ); + } + level.chugabud_force_corpse_position = undefined; + } + if ( isDefined( level.chugabud_force_player_position ) ) + { + spawnpoint.origin = level.chugabud_force_player_position; + level.chugabud_force_player_position = undefined; + } + self setorigin( spawnpoint.origin ); + self setplayerangles( spawnpoint.angles ); + playsoundatposition( "evt_ww_appear", spawnpoint.origin ); + playfx( level._effect[ "chugabud_revive_fx" ], spawnpoint.origin ); + self allowstand( 1 ); + self allowcrouch( 1 ); + self allowprone( 1 ); + self.ignoreme = 0; + self setstance( "stand" ); + self freezecontrols( 0 ); + self giveweapon( "knife_zm" ); + self give_start_weapon( 1 ); + self.score = self.loadout.score; + self.pers[ "score" ] = self.loadout.score; + self giveweapon( "frag_grenade_zm" ); + self setweaponammoclip( "frag_grenade_zm", 2 ); + self chugabud_restore_claymore(); + wait 1; + self disableinvulnerability(); +} + +chugabud_get_spawnpoint() +{ + spawnpoint = undefined; + if ( get_chugabug_spawn_point_from_nodes( self.origin, 500, 700, 64, 1 ) ) + { + spawnpoint = level.chugabud_spawn_struct; + } + if ( !isDefined( spawnpoint ) ) + { + if ( get_chugabug_spawn_point_from_nodes( self.origin, 100, 400, 64, 1 ) ) + { + spawnpoint = level.chugabud_spawn_struct; + } + } + if ( !isDefined( spawnpoint ) ) + { + if ( get_chugabug_spawn_point_from_nodes( self.origin, 50, 400, 256, 0 ) ) + { + spawnpoint = level.chugabud_spawn_struct; + } + } + if ( !isDefined( spawnpoint ) ) + { + spawnpoint = maps/mp/zombies/_zm::check_for_valid_spawn_near_team( self, 1 ); + } + if ( !isDefined( spawnpoint ) ) + { + match_string = ""; + location = level.scr_zm_map_start_location; + if ( location != "default" && location == "" && isDefined( level.default_start_location ) ) + { + location = level.default_start_location; + } + match_string = ( level.scr_zm_ui_gametype + "_" ) + location; + spawnpoints = []; + structs = getstructarray( "initial_spawn", "script_noteworthy" ); + while ( isDefined( structs ) ) + { + _a744 = structs; + _k744 = getFirstArrayKey( _a744 ); + while ( isDefined( _k744 ) ) + { + struct = _a744[ _k744 ]; + while ( isDefined( struct.script_string ) ) + { + tokens = strtok( struct.script_string, " " ); + _a750 = tokens; + _k750 = getFirstArrayKey( _a750 ); + while ( isDefined( _k750 ) ) + { + token = _a750[ _k750 ]; + if ( token == match_string ) + { + spawnpoints[ spawnpoints.size ] = struct; + } + _k750 = getNextArrayKey( _a750, _k750 ); + } + } + _k744 = getNextArrayKey( _a744, _k744 ); + } + } + if ( !isDefined( spawnpoints ) || spawnpoints.size == 0 ) + { + spawnpoints = getstructarray( "initial_spawn_points", "targetname" ); + } + /* +/# + assert( isDefined( spawnpoints ), "Could not find initial spawn points!" ); +#/ + */ + spawnpoint = maps/mp/zombies/_zm::getfreespawnpoint( spawnpoints, self ); + } + return spawnpoint; +} + +get_chugabug_spawn_point_from_nodes( v_origin, min_radius, max_radius, max_height, ignore_targetted_nodes ) +{ + if ( !isDefined( level.chugabud_spawn_struct ) ) + { + level.chugabud_spawn_struct = spawnstruct(); + } + found_node = undefined; + a_nodes = getnodesinradiussorted( v_origin, max_radius, min_radius, max_height, "pathnodes" ); + while ( isDefined( a_nodes ) && a_nodes.size > 0 ) + { + a_player_volumes = getentarray( "player_volume", "script_noteworthy" ); + index = a_nodes.size - 1; + i = index; + while ( i >= 0 ) + { + n_node = a_nodes[ i ]; + if ( ignore_targetted_nodes == 1 ) + { + if ( isDefined( n_node.target ) ) + { + i--; + continue; + } + } + else if ( !positionwouldtelefrag( n_node.origin ) ) + { + if ( maps/mp/zombies/_zm_utility::check_point_in_enabled_zone( n_node.origin, 1, a_player_volumes ) ) + { + v_start = ( n_node.origin[ 0 ], n_node.origin[ 1 ], n_node.origin[ 2 ] + 30 ); + v_end = ( n_node.origin[ 0 ], n_node.origin[ 1 ], n_node.origin[ 2 ] - 30 ); + trace = bullettrace( v_start, v_end, 0, undefined ); + if ( trace[ "fraction" ] < 1 ) + { + override_abort = 0; + if ( isDefined( level._chugabud_reject_node_override_func ) ) + { + override_abort = [[ level._chugabud_reject_node_override_func ]]( v_origin, n_node ); + } + if ( !override_abort ) + { + found_node = n_node; + break; + } + } + } + } + else + { + i--; + + } + } + } + if ( isDefined( found_node ) ) + { + level.chugabud_spawn_struct.origin = found_node.origin; + v_dir = vectornormalize( v_origin - level.chugabud_spawn_struct.origin ); + level.chugabud_spawn_struct.angles = vectorToAngles( v_dir ); + return 1; + } + return 0; +} + +force_corpse_respawn_position( forced_corpse_position ) +{ + level.chugabud_force_corpse_position = forced_corpse_position; +} + +force_player_respawn_position( forced_player_position ) +{ + level.chugabud_force_player_position = forced_player_position; +} + +save_weapons_for_chugabud( player ) +{ + self.chugabud_melee_weapons = []; + i = 0; + while ( i < level._melee_weapons.size ) + { + self save_weapon_for_chugabud( player, level._melee_weapons[ i ].weapon_name ); + i++; + } +} + +save_weapon_for_chugabud( player, weapon_name ) +{ + if ( player hasweapon( weapon_name ) ) + { + self.chugabud_melee_weapons[ weapon_name ] = 1; + } +} + +restore_weapons_for_chugabud( player ) +{ + i = 0; + while ( i < level._melee_weapons.size ) + { + self restore_weapon_for_chugabud( player, level._melee_weapons[ i ].weapon_name ); + i++; + } + self.chugabud_melee_weapons = undefined; +} + +restore_weapon_for_chugabud( player, weapon_name ) +{ + if ( isDefined( weapon_name ) || !isDefined( self.chugabud_melee_weapons ) && !isDefined( self.chugabud_melee_weapons[ weapon_name ] ) ) + { + return; + } + if ( isDefined( self.chugabud_melee_weapons[ weapon_name ] ) && self.chugabud_melee_weapons[ weapon_name ] ) + { + player giveweapon( weapon_name ); + player set_player_melee_weapon( weapon_name ); + self.chugabud_melee_weapons[ weapon_name ] = 0; + } +} + +chugabud_save_perks( ent ) +{ + perk_array = ent get_perk_array( 1 ); + _a941 = perk_array; + _k941 = getFirstArrayKey( _a941 ); + while ( isDefined( _k941 ) ) + { + perk = _a941[ _k941 ]; + ent unsetperk( perk ); + _k941 = getNextArrayKey( _a941, _k941 ); + } + return perk_array; +} + +playchugabudtimeraudio() +{ + self endon( "chugabud_grabbed" ); + self endon( "chugabud_timedout" ); + player = self.player; + self thread playchugabudtimerout( player ); + while ( 1 ) + { + player playsoundtoplayer( "zmb_chugabud_timer_count", player ); + wait 1; + } +} + +playchugabudtimerout( player ) +{ + self endon( "chugabud_grabbed" ); + self waittill( "chugabud_timedout" ); + player playsoundtoplayer( "zmb_chugabud_timer_out", player ); +} + +chugabud_hostmigration() +{ + level endon( "end_game" ); + level notify( "chugabud_hostmigration" ); + level endon( "chugabud_hostmigration" ); + while ( 1 ) + { + level waittill( "host_migration_end" ); + chugabuds = getentarray( "player_chugabud_model", "script_noteworthy" ); + _a1000 = chugabuds; + _k1000 = getFirstArrayKey( _a1000 ); + while ( isDefined( _k1000 ) ) + { + model = _a1000[ _k1000 ]; + playfxontag( level._effect[ "powerup_on" ], model, "tag_origin" ); + _k1000 = getNextArrayKey( _a1000, _k1000 ); + } + } +} + +player_revived_cleanup_chugabud_corpse() +{ +} + +player_has_chugabud_corpse() +{ + if ( isDefined( self.e_chugabud_corpse ) ) + { + return 1; + } + return 0; +} + +is_weapon_available_in_chugabud_corpse( weapon, player_to_check ) +{ + count = 0; + upgradedweapon = weapon; + if ( isDefined( level.zombie_weapons[ weapon ] ) && isDefined( level.zombie_weapons[ weapon ].upgrade_name ) ) + { + upgradedweapon = level.zombie_weapons[ weapon ].upgrade_name; + } + players = getplayers(); + while ( isDefined( players ) ) + { + player_index = 0; + while ( player_index < players.size ) + { + player = players[ player_index ]; + if ( isDefined( player_to_check ) && player != player_to_check ) + { + player_index++; + continue; + } + else + { + while ( player player_has_chugabud_corpse() ) + { + while ( isDefined( player.loadout ) && isDefined( player.loadout.weapons ) ) + { + i = 0; + while ( i < player.loadout.weapons.size ) + { + chugabud_weapon = player.loadout.weapons[ i ]; + if ( isDefined( chugabud_weapon ) || chugabud_weapon[ "name" ] == weapon && chugabud_weapon[ "name" ] == upgradedweapon ) + { + count++; + } + i++; + } + } + } + } + player_index++; + } + } + return count; +} + +chugabud_corpse_cleanup_on_spectator( player ) +{ + self endon( "death" ); + player endon( "disconnect" ); + while ( 1 ) + { + if ( player.sessionstate == "spectator" ) + { + break; + } + else + { + wait 0.01; + } + } + player chugabud_corpse_cleanup( self, 0 ); +} + +chugabud_corpse_revive_icon( player ) +{ + self endon( "death" ); + height_offset = 30; + index = player.clientid; + hud_elem = newhudelem(); + self.revive_hud_elem = hud_elem; + hud_elem.x = self.origin[ 0 ]; + hud_elem.y = self.origin[ 1 ]; + hud_elem.z = self.origin[ 2 ] + height_offset; + hud_elem.alpha = 1; + hud_elem.archived = 1; + hud_elem setshader( "waypoint_revive", 5, 5 ); + hud_elem setwaypoint( 1 ); + hud_elem.hidewheninmenu = 1; + hud_elem.immunetodemogamehudsettings = 1; + while ( 1 ) + { + if ( !isDefined( self.revive_hud_elem ) ) + { + return; + } + else + { + hud_elem.x = self.origin[ 0 ]; + hud_elem.y = self.origin[ 1 ]; + hud_elem.z = self.origin[ 2 ] + height_offset; + wait 0.01; + } + } +} + +activate_chugabud_effects_and_audio() +{ + if ( isDefined( level.whos_who_client_setup ) ) + { + if ( !isDefined( self.whos_who_effects_active ) ) + { + if ( isDefined( level.chugabud_shellshock ) ) + { + self shellshock( "whoswho", 60 ); + } + if ( isDefined( level.vsmgr_prio_visionset_zm_whos_who ) ) + { + maps/mp/_visionset_mgr::vsmgr_activate( "visionset", "zm_whos_who", self ); + } + self setclientfieldtoplayer( "clientfield_whos_who_audio", 1 ); + self setclientfieldtoplayer( "clientfield_whos_who_filter", 1 ); + self.whos_who_effects_active = 1; + self thread deactivate_chugabud_effects_and_audio(); + } + } +} + +deactivate_chugabud_effects_and_audio() +{ + self waittill_any( "death", "chugabud_effects_cleanup" ); + if ( isDefined( level.whos_who_client_setup ) ) + { + if ( isDefined( self.whos_who_effects_active ) && self.whos_who_effects_active == 1 ) + { + if ( isDefined( level.chugabud_shellshock ) ) + { + self stopshellshock(); + } + if ( isDefined( level.vsmgr_prio_visionset_zm_whos_who ) ) + { + maps/mp/_visionset_mgr::vsmgr_deactivate( "visionset", "zm_whos_who", self ); + } + self setclientfieldtoplayer( "clientfield_whos_who_audio", 0 ); + self setclientfieldtoplayer( "clientfield_whos_who_filter", 0 ); + } + self.whos_who_effects_active = undefined; + } +} + + diff --git a/patch_zm/maps/mp/zombies/_zm_magicbox.gsc b/patch_zm/maps/mp/zombies/MajorErrors/_zm_magicbox.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_zm_magicbox.gsc rename to patch_zm/maps/mp/zombies/MajorErrors/_zm_magicbox.gsc diff --git a/patch_zm/maps/mp/zombies/_zm_perks.gsc b/patch_zm/maps/mp/zombies/MajorErrors/_zm_perks.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_zm_perks.gsc rename to patch_zm/maps/mp/zombies/MajorErrors/_zm_perks.gsc diff --git a/patch_zm/maps/mp/zombies/_zm_powerups.gsc b/patch_zm/maps/mp/zombies/MajorErrors/_zm_powerups.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_zm_powerups.gsc rename to patch_zm/maps/mp/zombies/MajorErrors/_zm_powerups.gsc diff --git a/patch_zm/maps/mp/zombies/_zm_weapons.gsc b/patch_zm/maps/mp/zombies/MajorErrors/_zm_weapons.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_zm_weapons.gsc rename to patch_zm/maps/mp/zombies/MajorErrors/_zm_weapons.gsc diff --git a/patch_zm/maps/mp/zombies/_zm_timer.gsc b/patch_zm/maps/mp/zombies/MinorErrors/_zm_timer.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_zm_timer.gsc rename to patch_zm/maps/mp/zombies/MinorErrors/_zm_timer.gsc diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_clone.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_clone.gsc new file mode 100644 index 0000000..d9417c9 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_clone.gsc @@ -0,0 +1,143 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +//#using_animtree( "zm_ally" ); + +init() +{ + init_mover_tree(); +} + +spawn_player_clone( player, origin, forceweapon, forcemodel ) +{ + if ( !isDefined( origin ) ) + { + origin = player.origin; + } + primaryweapons = player getweaponslistprimaries(); + if ( isDefined( forceweapon ) ) + { + weapon = forceweapon; + } + else if ( primaryweapons.size ) + { + weapon = primaryweapons[ 0 ]; + } + else + { + weapon = player getcurrentweapon(); + } + weaponmodel = getweaponmodel( weapon ); + spawner = getent( "fake_player_spawner", "targetname" ); + if ( isDefined( spawner ) ) + { + clone = spawner spawnactor(); + clone.origin = origin; + clone.isactor = 1; + } + else + { + clone = spawn( "script_model", origin ); + clone.isactor = 0; + } + if ( isDefined( forcemodel ) ) + { + clone setmodel( forcemodel ); + } + else + { + clone setmodel( self.model ); + if ( isDefined( player.headmodel ) ) + { + clone.headmodel = player.headmodel; + clone attach( clone.headmodel, "", 1 ); + } + } + if ( weaponmodel != "" && weaponmodel != "none" ) + { + clone attach( weaponmodel, "tag_weapon_right" ); + } + clone.team = player.team; + clone.is_inert = 1; + clone.zombie_move_speed = "walk"; + clone.script_noteworthy = "corpse_clone"; + clone.actor_damage_func = ::clone_damage_func; + return clone; +} + +clone_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + idamage = 0; + if ( sweapon != "knife_ballistic_upgraded_zm" && sweapon != "knife_ballistic_bowie_upgraded_zm" || sweapon == "knife_ballistic_no_melee_upgraded_zm" && sweapon == "knife_ballistic_sickle_upgraded_zm" ) + { + self notify( "player_revived" ); + } + return idamage; +} + +clone_give_weapon( weapon ) +{ + weaponmodel = getweaponmodel( weapon ); + if ( weaponmodel != "" && weaponmodel != "none" ) + { + self attach( weaponmodel, "tag_weapon_right" ); + } +} + +clone_animate( animtype ) +{ + if ( self.isactor ) + { + self thread clone_actor_animate( animtype ); + } + else + { + self thread clone_mover_animate( animtype ); + } +} + +clone_actor_animate( animtype ) +{ + wait 0.1; + switch( animtype ) + { + case "laststand": + self setanimstatefromasd( "laststand" ); + break; + case "idle": + default: + self setanimstatefromasd( "idle" ); + break; + } +} + +init_mover_tree() +{ + scriptmodelsuseanimtree( -1 ); +} + +clone_mover_animate( animtype ) +{ + self useanimtree( -1 ); + switch( animtype ) + { + case "laststand": + self setanim( %pb_laststand_idle ); + break; + case "afterlife": + self setanim( %pb_afterlife_laststand_idle ); + break; + case "chair": + self setanim( %ai_actor_elec_chair_idle ); + break; + case "falling": + self setanim( %pb_falling_loop ); + break; + case "idle": + default: + self setanim( %pb_stand_alert ); + break; + } +} + diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_gasmask.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_gasmask.gsc new file mode 100644 index 0000000..b1364d4 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_gasmask.gsc @@ -0,0 +1,201 @@ +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_gasmask_zm" ) ) + { + return; + } + registerclientfield( "toplayer", "gasmaskoverlay", 16000, 1, "int" ); + maps/mp/zombies/_zm_equipment::register_equipment( "equip_gasmask_zm", &"ZOMBIE_EQUIP_GASMASK_PICKUP_HINT_STRING", &"ZOMBIE_EQUIP_GASMASK_HOWTO", undefined, "gasmask", ::gasmask_activation_watcher_thread ); + level.deathcard_spawn_func = ::remove_gasmask_on_player_bleedout; + precacheitem( "lower_equip_gasmask_zm" ); + onplayerconnect_callback( ::gasmask_on_player_connect ); +} + +gasmask_on_player_connect() +{ +} + +gasmask_removed_watcher_thread() +{ + self notify( "only_one_gasmask_removed_thread" ); + self endon( "only_one_gasmask_removed_thread" ); + self endon( "disconnect" ); + self waittill( "equip_gasmask_zm_taken" ); + if ( isDefined( level.zombiemode_gasmask_reset_player_model ) ) + { + ent_num = self.characterindex; + if ( isDefined( self.zm_random_char ) ) + { + ent_num = self.zm_random_char; + } + self [[ level.zombiemode_gasmask_reset_player_model ]]( ent_num ); + } + if ( isDefined( level.zombiemode_gasmask_reset_player_viewmodel ) ) + { + ent_num = self.characterindex; + if ( isDefined( self.zm_random_char ) ) + { + ent_num = self.zm_random_char; + } + self [[ level.zombiemode_gasmask_reset_player_viewmodel ]]( ent_num ); + } + self setclientfieldtoplayer( "gasmaskoverlay", 0 ); +} + +gasmask_activation_watcher_thread() +{ + self endon( "zombified" ); + self endon( "disconnect" ); + self endon( "equip_gasmask_zm_taken" ); + self thread gasmask_removed_watcher_thread(); + self thread remove_gasmask_on_game_over(); + if ( isDefined( level.zombiemode_gasmask_set_player_model ) ) + { + ent_num = self.characterindex; + if ( isDefined( self.zm_random_char ) ) + { + ent_num = self.zm_random_char; + } + self [[ level.zombiemode_gasmask_set_player_model ]]( ent_num ); + } + if ( isDefined( level.zombiemode_gasmask_set_player_viewmodel ) ) + { + ent_num = self.characterindex; + if ( isDefined( self.zm_random_char ) ) + { + ent_num = self.zm_random_char; + } + self [[ level.zombiemode_gasmask_set_player_viewmodel ]]( ent_num ); + } + for ( ;; ) + { + while ( 1 ) + { + self waittill_either( "equip_gasmask_zm_activate", "equip_gasmask_zm_deactivate" ); + if ( self maps/mp/zombies/_zm_equipment::is_equipment_active( "equip_gasmask_zm" ) ) + { + self increment_is_drinking(); + self setactionslot( 1, "" ); + if ( isDefined( level.zombiemode_gasmask_set_player_model ) ) + { + ent_num = self.characterindex; + if ( isDefined( self.zm_random_char ) ) + { + ent_num = self.zm_random_char; + } + self [[ level.zombiemode_gasmask_change_player_headmodel ]]( ent_num, 1 ); + } + clientnotify( "gmsk2" ); + self waittill( "weapon_change_complete" ); + self setclientfieldtoplayer( "gasmaskoverlay", 1 ); + } + else + { + self increment_is_drinking(); + self setactionslot( 1, "" ); + if ( isDefined( level.zombiemode_gasmask_set_player_model ) ) + { + ent_num = self.characterindex; + if ( isDefined( self.zm_random_char ) ) + { + ent_num = self.zm_random_char; + } + self [[ level.zombiemode_gasmask_change_player_headmodel ]]( ent_num, 0 ); + } + self takeweapon( "equip_gasmask_zm" ); + self giveweapon( "lower_equip_gasmask_zm" ); + self switchtoweapon( "lower_equip_gasmask_zm" ); + wait 0.05; + self setclientfieldtoplayer( "gasmaskoverlay", 0 ); + self waittill( "weapon_change_complete" ); + self takeweapon( "lower_equip_gasmask_zm" ); + self giveweapon( "equip_gasmask_zm" ); + } + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + if ( self is_multiple_drinking() ) + { + self decrement_is_drinking(); + self setactionslot( 1, "weapon", "equip_gasmask_zm" ); + self notify( "equipment_select_response_done" ); + } + } + else if ( isDefined( self.prev_weapon_before_equipment_change ) && self hasweapon( self.prev_weapon_before_equipment_change ) ) + { + if ( self.prev_weapon_before_equipment_change != self getcurrentweapon() ) + { + self switchtoweapon( self.prev_weapon_before_equipment_change ); + self waittill( "weapon_change_complete" ); + } + break; + } + else + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + if ( primaryweapons[ 0 ] != self getcurrentweapon() ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + self waittill( "weapon_change_complete" ); + } + break; + } + else + { + self switchtoweapon( get_player_melee_weapon() ); + } + } + } + self setactionslot( 1, "weapon", "equip_gasmask_zm" ); + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( self.intermission ) && !self.intermission ) + { + self decrement_is_drinking(); + } + self notify( "equipment_select_response_done" ); + } +} + +remove_gasmask_on_player_bleedout() +{ + self setclientfieldtoplayer( "gasmaskoverlay", 0 ); + wait_network_frame(); + wait_network_frame(); + self setclientfieldtoplayer( "gasmaskoverlay", 1 ); +} + +remove_gasmask_on_game_over() +{ + self endon( "equip_gasmask_zm_taken" ); + level waittill( "pre_end_game" ); + self setclientfieldtoplayer( "gasmaskoverlay", 0 ); +} + +gasmask_active() +{ + return self maps/mp/zombies/_zm_equipment::is_equipment_active( "equip_gasmask_zm" ); +} + +gasmask_debug_print( msg, color ) +{ +/* +/# + if ( !getDvarInt( #"4D1BCA99" ) ) + { + return; + } + if ( !isDefined( color ) ) + { + color = ( 0, 0, 1 ); + } + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 60 ), msg, color, 1, 1, 40 ); +#/ +*/ +} + diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ffotd.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ffotd.gsc new file mode 100644 index 0000000..5aa98ca --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ffotd.gsc @@ -0,0 +1,238 @@ +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +main_start() +{ + mapname = tolower( getDvar( "mapname" ) ); + gametype = getDvar( "ui_gametype" ); + if ( tolower( getDvar( "mapname" ) ) == "zm_transit" && getDvar( "ui_gametype" ) == "zclassic" ) + { + level thread transit_navcomputer_remove_card_on_success(); + } + if ( tolower( getDvar( "mapname" ) ) == "zm_prison" && getDvar( "ui_gametype" ) == "zgrief" ) + { + level.zbarrier_script_string_sets_collision = 1; + } + if ( mapname != "zm_transit" && mapname == "zm_highrise" && gametype == "zclassic" ) + { + level.pers_upgrade_sniper = 1; + level.pers_upgrade_pistol_points = 1; + level.pers_upgrade_perk_lose = 1; + level.pers_upgrade_double_points = 1; + level.pers_upgrade_nube = 1; + } +} + +main_end() +{ + onfinalizeinitialization_callback( ::force_navcomputer_trigger_think ); + level.original_melee_miss_func = level.melee_miss_func; + level.melee_miss_func = ::ffotd_melee_miss_func; +} + +force_navcomputer_trigger_think() +{ + if ( !isDefined( level.zombie_include_buildables ) || !level.zombie_include_buildables.size ) + { + return; + } + _a52 = level.zombie_include_buildables; + _k52 = getFirstArrayKey( _a52 ); + while ( isDefined( _k52 ) ) + { + buildable = _a52[ _k52 ]; + if ( buildable.name == "sq_common" ) + { + if ( isDefined( buildable.triggerthink ) ) + { + level [[ buildable.triggerthink ]](); + trigger_think_func = buildable.triggerthink; + buildable.triggerthink = undefined; + level waittill( "buildables_setup" ); + buildable.triggerthink = trigger_think_func; + return; + } + } + _k52 = getNextArrayKey( _a52, _k52 ); + } +} + +transit_navcomputer_remove_card_on_success() +{ + wait_for_buildable( "sq_common" ); + wait_network_frame(); + trig_pos = getstruct( "sq_common_key", "targetname" ); + trigs = getentarray( "trigger_radius_use", "classname" ); + nav_trig = undefined; + _a81 = trigs; + _k81 = getFirstArrayKey( _a81 ); + while ( isDefined( _k81 ) ) + { + trig = _a81[ _k81 ]; + if ( trig.origin == trig_pos.origin ) + { + nav_trig = trig; + } + _k81 = getNextArrayKey( _a81, _k81 ); + } + if ( isDefined( nav_trig ) ) + { + while ( 1 ) + { + nav_trig waittill( "trigger", who ); + if ( isplayer( who ) && is_player_valid( who ) && does_player_have_correct_navcard( who ) ) + { + break; + } + } + players = get_players(); + _a101 = players; + _k101 = getFirstArrayKey( _a101 ); + while ( isDefined( _k101 ) ) + { + player = _a101[ _k101 ]; + player maps/mp/zombies/_zm_stats::set_global_stat( level.navcard_needed, 0 ); + _k101 = getNextArrayKey( _a101, _k101 ); + } + level thread sq_refresh_player_navcard_hud(); + } +} + +sq_refresh_player_navcard_hud() +{ + if ( !isDefined( level.navcards ) ) + { + return; + } + players = get_players(); + _a116 = players; + _k116 = getFirstArrayKey( _a116 ); + while ( isDefined( _k116 ) ) + { + player = _a116[ _k116 ]; + navcard_bits = 0; + i = 0; + while ( i < level.navcards.size ) + { + hasit = player maps/mp/zombies/_zm_stats::get_global_stat( level.navcards[ i ] ); + if ( isDefined( player.navcard_grabbed ) && player.navcard_grabbed == level.navcards[ i ] ) + { + hasit = 1; + } + if ( hasit ) + { + navcard_bits = navcard_bits + 1; + } + i++; + } + wait_network_frame(); + player setclientfield( "navcard_held", 0 ); + if ( navcard_bits > 0 ) + { + wait_network_frame(); + player setclientfield( "navcard_held", navcard_bits ); + } + _k116 = getNextArrayKey( _a116, _k116 ); + } +} + +player_in_exploit_area( player_trigger_origin, player_trigger_radius ) +{ + if ( distancesquared( player_trigger_origin, self.origin ) < ( player_trigger_radius * player_trigger_radius ) ) + { + /* +/# + iprintlnbold( "player exploit detectect" ); +#/ + */ + return 1; + } + return 0; +} + +path_exploit_fix( zombie_trigger_origin, zombie_trigger_radius, zombie_trigger_height, player_trigger_origin, player_trigger_radius, zombie_goto_point ) +{ + spawnflags = 9; + zombie_trigger = spawn( "trigger_radius", zombie_trigger_origin, spawnflags, zombie_trigger_radius, zombie_trigger_height ); + zombie_trigger setteamfortrigger( level.zombie_team ); + /* +/# + thread debug_exploit( zombie_trigger_origin, zombie_trigger_radius, player_trigger_origin, player_trigger_radius, zombie_goto_point ); +#/ + */ + while ( 1 ) + { + zombie_trigger waittill( "trigger", who ); + if ( !is_true( who.reroute ) ) + { + who thread exploit_reroute( zombie_trigger, player_trigger_origin, player_trigger_radius, zombie_goto_point ); + } + } +} + +exploit_reroute( zombie_trigger, player_trigger_origin, player_trigger_radius, zombie_goto_point ) +{ + self endon( "death" ); + self.reroute = 1; + while ( 1 ) + { + if ( self istouching( zombie_trigger ) ) + { + player = self.favoriteenemy; + if ( isDefined( player ) && player player_in_exploit_area( player_trigger_origin, player_trigger_radius ) ) + { + self.reroute_origin = zombie_goto_point; + } + else + { + break; + } + } + else + { + break; + } + wait 0.2; + } + self.reroute = 0; +} + +debug_exploit( player_origin, player_radius, enemy_origin, enemy_radius, zombie_goto_point ) +{ +/* +/# + while ( isDefined( self ) ) + { + circle( player_origin, player_radius, ( 1, 1, 0 ), 0, 1, 1 ); + circle( enemy_origin, enemy_radius, ( 1, 1, 0 ), 0, 1, 1 ); + line( player_origin, enemy_origin, ( 1, 1, 0 ), 1 ); + line( enemy_origin, zombie_goto_point, ( 1, 1, 0 ), 1 ); + wait 0.05; +#/ + } +*/ +} + +ffotd_melee_miss_func() +{ + if ( isDefined( self.enemy ) ) + { + if ( isplayer( self.enemy ) && self.enemy getcurrentweapon() == "claymore_zm" ) + { + dist_sq = distancesquared( self.enemy.origin, self.origin ); + melee_dist_sq = self.meleeattackdist * self.meleeattackdist; + if ( dist_sq < melee_dist_sq ) + { + self.enemy dodamage( self.meleedamage, self.origin, self, self, "none", "MOD_MELEE" ); + return; + } + } + } + if ( isDefined( level.original_melee_miss_func ) ) + { + self [[ level.original_melee_miss_func ]](); + } +} + diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_net.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_net.gsc new file mode 100644 index 0000000..4081f4a --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_net.gsc @@ -0,0 +1,105 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +network_choke_init( id, max ) +{ + if ( !isDefined( level.zombie_network_choke_ids_max ) ) + { + level.zombie_network_choke_ids_max = []; + level.zombie_network_choke_ids_count = []; + } + level.zombie_network_choke_ids_max[ id ] = max; + level.zombie_network_choke_ids_count[ id ] = 0; + level thread network_choke_thread( id ); +} + +network_choke_thread( id ) +{ + while ( 1 ) + { + wait_network_frame(); + wait_network_frame(); + level.zombie_network_choke_ids_count[ id ] = 0; + } +} + +network_choke_safe( id ) +{ + return level.zombie_network_choke_ids_count[ id ] < level.zombie_network_choke_ids_max[ id ]; +} + +network_choke_action( id, choke_action, arg1, arg2, arg3 ) +{ +/* +/# + assert( isDefined( level.zombie_network_choke_ids_max[ id ] ), "Network Choke: " + id + " undefined" ); +#/ +*/ + while ( !network_choke_safe( id ) ) + { + wait 0.05; + } + level.zombie_network_choke_ids_count[ id ]++; + if ( !isDefined( arg1 ) ) + { + return [[ choke_action ]](); + } + if ( !isDefined( arg2 ) ) + { + return [[ choke_action ]]( arg1 ); + } + if ( !isDefined( arg3 ) ) + { + return [[ choke_action ]]( arg1, arg2 ); + } + return [[ choke_action ]]( arg1, arg2, arg3 ); +} + +network_entity_valid( entity ) +{ + if ( !isDefined( entity ) ) + { + return 0; + } + return 1; +} + +network_safe_init( id, max ) +{ + if ( !isDefined( level.zombie_network_choke_ids_max ) || !isDefined( level.zombie_network_choke_ids_max[ id ] ) ) + { + network_choke_init( id, max ); + } + /* +/# + assert( max == level.zombie_network_choke_ids_max[ id ] ); +#/ + */ +} + +_network_safe_spawn( classname, origin ) +{ + return spawn( classname, origin ); +} + +network_safe_spawn( id, max, classname, origin ) +{ + network_safe_init( id, max ); + return network_choke_action( id, ::_network_safe_spawn, classname, origin ); +} + +_network_safe_play_fx_on_tag( fx, entity, tag ) +{ + if ( network_entity_valid( entity ) ) + { + playfxontag( fx, entity, tag ); + } +} + +network_safe_play_fx_on_tag( id, max, fx, entity, tag ) +{ + network_safe_init( id, max ); + network_choke_action( id, ::_network_safe_play_fx_on_tag, fx, entity, tag ); +} + diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_server_throttle.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_server_throttle.gsc new file mode 100644 index 0000000..a00508d --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_server_throttle.gsc @@ -0,0 +1,100 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; + +server_choke_init( id, max ) +{ + if ( !isDefined( level.zombie_server_choke_ids_max ) ) + { + level.zombie_server_choke_ids_max = []; + level.zombie_server_choke_ids_count = []; + } + level.zombie_server_choke_ids_max[ id ] = max; + level.zombie_server_choke_ids_count[ id ] = 0; + level thread server_choke_thread( id ); +} + +server_choke_thread( id ) +{ + while ( 1 ) + { + wait 0.05; + level.zombie_server_choke_ids_count[ id ] = 0; + } +} + +server_choke_safe( id ) +{ + return level.zombie_server_choke_ids_count[ id ] < level.zombie_server_choke_ids_max[ id ]; +} + +server_choke_action( id, choke_action, arg1, arg2, arg3 ) +{ +/* +/# + assert( isDefined( level.zombie_server_choke_ids_max[ id ] ), "server Choke: " + id + " undefined" ); +#/ +*/ + while ( !server_choke_safe( id ) ) + { + wait 0.05; + } + level.zombie_server_choke_ids_count[ id ]++; + if ( !isDefined( arg1 ) ) + { + return [[ choke_action ]](); + } + if ( !isDefined( arg2 ) ) + { + return [[ choke_action ]]( arg1 ); + } + if ( !isDefined( arg3 ) ) + { + return [[ choke_action ]]( arg1, arg2 ); + } + return [[ choke_action ]]( arg1, arg2, arg3 ); +} + +server_entity_valid( entity ) +{ + if ( !isDefined( entity ) ) + { + return 0; + } + return 1; +} + +server_safe_init( id, max ) +{ + if ( !isDefined( level.zombie_server_choke_ids_max ) || !isDefined( level.zombie_server_choke_ids_max[ id ] ) ) + { + server_choke_init( id, max ); + } + /* +/# + assert( max == level.zombie_server_choke_ids_max[ id ] ); +#/ + */ +} + +_server_safe_ground_trace( pos ) +{ + return groundpos( pos ); +} + +server_safe_ground_trace( id, max, origin ) +{ + server_safe_init( id, max ); + return server_choke_action( id, ::_server_safe_ground_trace, origin ); +} + +_server_safe_ground_trace_ignore_water( pos ) +{ + return groundpos_ignore_water( pos ); +} + +server_safe_ground_trace_ignore_water( id, max, origin ) +{ + server_safe_init( id, max ); + return server_choke_action( id, ::_server_safe_ground_trace_ignore_water, origin ); +} + diff --git a/patch_zm/maps/mp/zombies/_load.gsc b/patch_zm/maps/mp/zombies/SevereErrors/_load.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_load.gsc rename to patch_zm/maps/mp/zombies/SevereErrors/_load.gsc diff --git a/patch_zm/maps/mp/zombies/_zm.gsc b/patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_zm.gsc rename to patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm.gsc diff --git a/patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm_equipment.gsc b/patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm_equipment.gsc new file mode 100644 index 0000000..a405923 --- /dev/null +++ b/patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm_equipment.gsc @@ -0,0 +1,1953 @@ +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + init_equipment_upgrade(); + onplayerconnect_callback( ::equipment_placement_watcher ); + level._equipment_disappear_fx = loadfx( "maps/zombie/fx_zmb_tranzit_electrap_explo" ); + if ( isDefined( level.disable_fx_zmb_tranzit_shield_explo ) && !level.disable_fx_zmb_tranzit_shield_explo ) + { + level._riotshield_dissapear_fx = loadfx( "maps/zombie/fx_zmb_tranzit_shield_explo" ); + } + level.placeable_equipment_destroy_fn = []; + if ( isDefined( level._no_equipment_activated_clientfield ) && !level._no_equipment_activated_clientfield ) + { + registerclientfield( "scriptmover", "equipment_activated", 12000, 4, "int" ); + } +} + +signal_equipment_activated( val ) +{ + if ( !isDefined( val ) ) + { + val = 1; + } + if ( isDefined( level._no_equipment_activated_clientfield ) && level._no_equipment_activated_clientfield ) + { + return; + } + self endon( "death" ); + self setclientfield( "equipment_activated", val ); + i = 0; + while ( i < 2 ) + { + wait_network_frame(); + i++; + } + self setclientfield( "equipment_activated", 0 ); +} + +register_equipment( equipment_name, hint, howto_hint, hint_icon, equipmentvo, watcher_thread, transfer_fn, drop_fn, pickup_fn, place_fn ) +{ + if ( !isDefined( level.zombie_include_equipment ) || isDefined( level.zombie_include_equipment[ equipment_name ] ) && !level.zombie_include_equipment[ equipment_name ] ) + { + return; + } + precachestring( hint ); + if ( isDefined( hint_icon ) ) + { + precacheshader( hint_icon ); + } + struct = spawnstruct(); + if ( !isDefined( level.zombie_equipment ) ) + { + level.zombie_equipment = []; + } + struct.equipment_name = equipment_name; + struct.hint = hint; + struct.howto_hint = howto_hint; + struct.hint_icon = hint_icon; + struct.vox = equipmentvo; + struct.triggers = []; + struct.models = []; + struct.watcher_thread = watcher_thread; + struct.transfer_fn = transfer_fn; + struct.drop_fn = drop_fn; + struct.pickup_fn = pickup_fn; + struct.place_fn = place_fn; + level.zombie_equipment[ equipment_name ] = struct; +} + +is_equipment_included( equipment_name ) +{ + if ( !isDefined( level.zombie_include_equipment ) ) + { + return 0; + } + return isDefined( level.zombie_include_equipment[ equipment_name ] ); +} + +include_zombie_equipment( equipment_name ) +{ + if ( !isDefined( level.zombie_include_equipment ) ) + { + level.zombie_include_equipment = []; + } + level.zombie_include_equipment[ equipment_name ] = 1; + precacheitem( equipment_name ); +} + +limit_zombie_equipment( equipment_name, limited ) +{ + if ( !isDefined( level._limited_equipment ) ) + { + level._limited_equipment = []; + } + if ( limited ) + { + level._limited_equipment[ level._limited_equipment.size ] = equipment_name; + } + else + { + arrayremovevalue( level._limited_equipment, equipment_name, 0 ); + } +} + +init_equipment_upgrade() +{ + equipment_spawns = []; + equipment_spawns = getentarray( "zombie_equipment_upgrade", "targetname" ); + i = 0; + while ( i < equipment_spawns.size ) + { + hint_string = get_equipment_hint( equipment_spawns[ i ].zombie_equipment_upgrade ); + equipment_spawns[ i ] sethintstring( hint_string ); + equipment_spawns[ i ] setcursorhint( "HINT_NOICON" ); + equipment_spawns[ i ] usetriggerrequirelookat(); + equipment_spawns[ i ] add_to_equipment_trigger_list( equipment_spawns[ i ].zombie_equipment_upgrade ); + equipment_spawns[ i ] thread equipment_spawn_think(); + i++; + } +} + +get_equipment_hint( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + return level.zombie_equipment[ equipment_name ].hint; +} + +get_equipment_howto_hint( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + return level.zombie_equipment[ equipment_name ].howto_hint; +} + +get_equipment_icon( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + return level.zombie_equipment[ equipment_name ].hint_icon; +} + +add_to_equipment_trigger_list( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + level.zombie_equipment[ equipment_name ].triggers[ level.zombie_equipment[ equipment_name ].triggers.size ] = self; + level.zombie_equipment[ equipment_name ].models[ level.zombie_equipment[ equipment_name ].models.size ] = getent( self.target, "targetname" ); +} + +equipment_spawn_think() +{ + for ( ;; ) + { + self waittill( "trigger", player ); + if ( player in_revive_trigger() || player.is_drinking > 0 ) + { + wait 0.1; + continue; + } + else + { + if ( is_limited_equipment( self.zombie_equipment_upgrade ) ) + { + player setup_limited_equipment( self.zombie_equipment_upgrade ); + if ( isDefined( level.hacker_tool_positions ) ) + { + new_pos = random( level.hacker_tool_positions ); + self.origin = new_pos.trigger_org; + model = getent( self.target, "targetname" ); + model.origin = new_pos.model_org; + model.angles = new_pos.model_ang; + } + } + player equipment_give( self.zombie_equipment_upgrade ); + } + } +} + +set_equipment_invisibility_to_player( equipment, invisible ) +{ + triggers = level.zombie_equipment[ equipment ].triggers; + i = 0; + while ( i < triggers.size ) + { + if ( isDefined( triggers[ i ] ) ) + { + triggers[ i ] setinvisibletoplayer( self, invisible ); + } + i++; + } + models = level.zombie_equipment[ equipment ].models; + i = 0; + while ( i < models.size ) + { + if ( isDefined( models[ i ] ) ) + { + models[ i ] setinvisibletoplayer( self, invisible ); + } + i++; + } +} + +equipment_take( equipment ) +{ + if ( !isDefined( equipment ) ) + { + equipment = self get_player_equipment(); + } + if ( !isDefined( equipment ) ) + { + return; + } + if ( !self has_player_equipment( equipment ) ) + { + return; + } + current = 0; + current_weapon = 0; + if ( isDefined( self get_player_equipment() ) && equipment == self get_player_equipment() ) + { + current = 1; + } + if ( equipment == self getcurrentweapon() ) + { + current_weapon = 1; + } + /* +/# + println( "ZM EQUIPMENT: " + self.name + " lost " + equipment + "\n" ); +#/ + */ + if ( isDefined( self.current_equipment_active[ equipment ] ) && self.current_equipment_active[ equipment ] ) + { + self.current_equipment_active[ equipment ] = 0; + self notify( equipment + "_deactivate" ); + } + self notify( equipment + "_taken" ); + self takeweapon( equipment ); + if ( !is_limited_equipment( equipment ) || is_limited_equipment( equipment ) && !limited_equipment_in_use( equipment ) ) + { + self set_equipment_invisibility_to_player( equipment, 0 ); + } + if ( current ) + { + self set_player_equipment( undefined ); + self setactionslot( 1, "" ); + } + else + { + arrayremovevalue( self.deployed_equipment, equipment ); + } + if ( current_weapon ) + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } +} + +equipment_give( equipment ) +{ + if ( !isDefined( equipment ) ) + { + return; + } + if ( !isDefined( level.zombie_equipment[ equipment ] ) ) + { + return; + } + if ( self has_player_equipment( equipment ) ) + { + return; + } + /* +/# + println( "ZM EQUIPMENT: " + self.name + " got " + equipment + "\n" ); +#/ + */ + curr_weapon = self getcurrentweapon(); + curr_weapon_was_curr_equipment = self is_player_equipment( curr_weapon ); + self equipment_take(); + self set_player_equipment( equipment ); + self giveweapon( equipment ); + self setweaponammoclip( equipment, 1 ); + self thread show_equipment_hint( equipment ); + self notify( equipment + "_given" ); + self set_equipment_invisibility_to_player( equipment, 1 ); + self setactionslot( 1, "weapon", equipment ); + if ( isDefined( level.zombie_equipment[ equipment ].watcher_thread ) ) + { + self thread [[ level.zombie_equipment[ equipment ].watcher_thread ]](); + } + self thread equipment_slot_watcher( equipment ); + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", level.zombie_equipment[ equipment ].vox ); +} + +equipment_slot_watcher( equipment ) +{ + self notify( "kill_equipment_slot_watcher" ); + self endon( "kill_equipment_slot_watcher" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "weapon_change", curr_weapon, prev_weapon ); + self.prev_weapon_before_equipment_change = undefined; + if ( isDefined( prev_weapon ) && prev_weapon != "none" ) + { + prev_weapon_type = weaponinventorytype( prev_weapon ); + if ( prev_weapon_type == "primary" || prev_weapon_type == "altmode" ) + { + self.prev_weapon_before_equipment_change = prev_weapon; + } + } + if ( isDefined( level.zombie_equipment[ equipment ].watcher_thread ) ) + { + if ( curr_weapon == equipment ) + { + if ( self.current_equipment_active[ equipment ] == 1 ) + { + self notify( equipment + "_deactivate" ); + self.current_equipment_active[ equipment ] = 0; + } + else + { + if ( self.current_equipment_active[ equipment ] == 0 ) + { + self notify( equipment + "_activate" ); + self.current_equipment_active[ equipment ] = 1; + } + } + self waittill( "equipment_select_response_done" ); + } + continue; + } + else if ( curr_weapon == equipment && !self.current_equipment_active[ equipment ] ) + { + self notify( equipment + "_activate" ); + self.current_equipment_active[ equipment ] = 1; + continue; + } + else + { + if ( curr_weapon != equipment && self.current_equipment_active[ equipment ] ) + { + self notify( equipment + "_deactivate" ); + self.current_equipment_active[ equipment ] = 0; + } + } + } +} + +is_limited_equipment( equipment ) +{ + while ( isDefined( level._limited_equipment ) ) + { + i = 0; + while ( i < level._limited_equipment.size ) + { + if ( level._limited_equipment[ i ] == equipment ) + { + return 1; + } + i++; + } + } + return 0; +} + +limited_equipment_in_use( equipment ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + current_equipment = players[ i ] get_player_equipment(); + if ( isDefined( current_equipment ) && current_equipment == equipment ) + { + return 1; + } + i++; + } + if ( isDefined( level.dropped_equipment ) && isDefined( level.dropped_equipment[ equipment ] ) ) + { + return 1; + } + return 0; +} + +setup_limited_equipment( equipment ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] set_equipment_invisibility_to_player( equipment, 1 ); + i++; + } + self thread release_limited_equipment_on_disconnect( equipment ); + self thread release_limited_equipment_on_equipment_taken( equipment ); +} + +release_limited_equipment_on_equipment_taken( equipment ) +{ + self endon( "disconnect" ); + self waittill_either( equipment + "_taken", "spawned_spectator" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] set_equipment_invisibility_to_player( equipment, 0 ); + i++; + } +} + +release_limited_equipment_on_disconnect( equipment ) +{ + self endon( equipment + "_taken" ); + self waittill( "disconnect" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isalive( players[ i ] ) ) + { + players[ i ] set_equipment_invisibility_to_player( equipment, 0 ); + } + i++; + } +} + +is_equipment_active( equipment ) +{ + if ( !isDefined( self.current_equipment_active ) || !isDefined( self.current_equipment_active[ equipment ] ) ) + { + return 0; + } + return self.current_equipment_active[ equipment ]; +} + +init_equipment_hint_hudelem( x, y, alignx, aligny, fontscale, alpha ) +{ + self.x = x; + self.y = y; + self.alignx = alignx; + self.aligny = aligny; + self.fontscale = fontscale; + self.alpha = alpha; + self.sort = 20; +} + +setup_equipment_client_hintelem() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( !isDefined( self.hintelem ) ) + { + self.hintelem = newclienthudelem( self ); + } + if ( level.splitscreen ) + { + self.hintelem init_equipment_hint_hudelem( 160, 90, "center", "middle", 1.6, 1 ); + } + else + { + self.hintelem init_equipment_hint_hudelem( 320, 220, "center", "bottom", 1.6, 1 ); + } +} + +show_equipment_hint( equipment ) +{ + self notify( "kill_previous_show_equipment_hint_thread" ); + self endon( "kill_previous_show_equipment_hint_thread" ); + self endon( "death" ); + self endon( "disconnect" ); + if ( isDefined( self.do_not_display_equipment_pickup_hint ) && self.do_not_display_equipment_pickup_hint ) + { + return; + } + wait 0.5; + text = get_equipment_howto_hint( equipment ); + self show_equipment_hint_text( text ); +} + +show_equipment_hint_text( text ) +{ + self notify( "hide_equipment_hint_text" ); + wait 0.05; + self setup_equipment_client_hintelem(); + self.hintelem settext( text ); + self.hintelem.alpha = 1; + self.hintelem.font = "small"; + self.hintelem.fontscale = 1.25; + self.hintelem.hidewheninmenu = 1; + time = self waittill_notify_or_timeout( "hide_equipment_hint_text", 3.2 ); + if ( isDefined( time ) ) + { + self.hintelem fadeovertime( 0.25 ); + self.hintelem.alpha = 0; + self waittill_notify_or_timeout( "hide_equipment_hint_text", 0.25 ); + } + self.hintelem settext( "" ); + self.hintelem destroy(); +} + +equipment_onspawnretrievableweaponobject( watcher, player ) +{ + self.plant_parent = self; + if ( isDefined( level.placeable_equipment_type[ self.name ] ) ) + { + iswallmount = level.placeable_equipment_type[ self.name ] == "wallmount"; + } + if ( !isDefined( player.turret_placement ) || !player.turret_placement[ "result" ] ) + { + if ( iswallmount /*|| !getDvarInt( #"B3416C1D" )*/ ) + { + self waittill( "stationary" ); + waittillframeend; + if ( iswallmount ) + { + if ( isDefined( player.planted_wallmount_on_a_zombie ) && player.planted_wallmount_on_a_zombie ) + { + equip_name = self.name; + thread equipment_disappear_fx( self.origin, undefined, self.angles ); + self delete(); + if ( player hasweapon( equip_name ) ) + { + player setweaponammoclip( equip_name, 1 ); + } + player.planted_wallmount_on_a_zombie = undefined; + return; + } + } + } + else + { + self.plant_parent = player; + self.origin = player.origin; + self.angles = player.angles; + wait_network_frame(); + } + } + equipment = watcher.name + "_zm"; + /* +/# + if ( !isDefined( player.current_equipment ) || player.current_equipment != equipment ) + { + assert( player has_deployed_equipment( equipment ) ); + assert( !isDefined( player.current_equipment ) ); +#/ + } + */ + if ( isDefined( player.current_equipment ) && player.current_equipment == equipment ) + { + player equipment_to_deployed( equipment ); + } + if ( isDefined( level.zombie_equipment[ equipment ].place_fn ) ) + { + if ( isDefined( player.turret_placement ) && player.turret_placement[ "result" ] ) + { + plant_origin = player.turret_placement[ "origin" ]; + plant_angles = player.turret_placement[ "angles" ]; + } + else + { + if ( isDefined( level.placeable_equipment_type[ self.name ] ) && level.placeable_equipment_type[ self.name ] == "wallmount" ) + { + plant_origin = self.origin; + plant_angles = self.angles; + } + else + { + plant_origin = self.origin; + plant_angles = self.angles; + } + } + if ( isDefined( level.check_force_deploy_origin ) ) + { + if ( player [[ level.check_force_deploy_origin ]]( self, plant_origin, plant_angles ) ) + { + plant_origin = player.origin; + plant_angles = player.angles; + self.plant_parent = player; + } + } + else + { + if ( isDefined( level.check_force_deploy_z ) ) + { + if ( player [[ level.check_force_deploy_z ]]( self, plant_origin, plant_angles ) ) + { + plant_origin = ( plant_origin[ 0 ], plant_origin[ 1 ], player.origin[ 2 ] + 10 ); + } + } + } + if ( isDefined( iswallmount ) && iswallmount ) + { + self ghost(); + } + replacement = player [[ level.zombie_equipment[ equipment ].place_fn ]]( plant_origin, plant_angles ); + if ( isDefined( replacement ) ) + { + replacement.owner = player; + replacement.original_owner = player; + replacement.name = self.name; + player notify( "equipment_placed" ); + if ( isDefined( level.equipment_planted ) ) + { + player [[ level.equipment_planted ]]( replacement, equipment, self.plant_parent ); + } + player maps/mp/zombies/_zm_buildables::track_buildables_planted( self ); + } + if ( isDefined( self ) ) + { + self delete(); + } + } +} + +equipment_retrieve( player ) +{ + if ( isDefined( self ) ) + { + self stoploopsound(); + original_owner = self.original_owner; + weaponname = self.name; + if ( !isDefined( original_owner ) ) + { + player equipment_give( weaponname ); + self.owner = player; + } + else + { + if ( player != original_owner ) + { + equipment_transfer( weaponname, original_owner, player ); + self.owner = player; + } + player equipment_from_deployed( weaponname ); + } + if ( isDefined( self.requires_pickup ) && self.requires_pickup ) + { + if ( isDefined( level.zombie_equipment[ weaponname ].pickup_fn ) ) + { + self.owner = player; + if ( isDefined( self.damage ) ) + { + player player_set_equipment_damage( weaponname, self.damage ); + } + player [[ level.zombie_equipment[ weaponname ].pickup_fn ]]( self ); + } + } + self.playdialog = 0; + weaponname = self.name; + self delete(); + if ( !player hasweapon( weaponname ) ) + { + player giveweapon( weaponname ); + clip_ammo = player getweaponammoclip( weaponname ); + clip_max_ammo = weaponclipsize( weaponname ); + if ( clip_ammo < clip_max_ammo ) + { + clip_ammo++; + } + player setweaponammoclip( weaponname, clip_ammo ); + } + player maps/mp/zombies/_zm_buildables::track_planted_buildables_pickedup( weaponname ); + } +} + +equipment_drop_to_planted( equipment, player ) +{ +/* +/# + if ( !isDefined( player.current_equipment ) || player.current_equipment != equipment ) + { + assert( player has_deployed_equipment( equipment ) ); + assert( !isDefined( player.current_equipment ) ); +#/ + } +*/ + if ( isDefined( player.current_equipment ) && player.current_equipment == equipment ) + { + player equipment_to_deployed( equipment ); + } + if ( isDefined( level.zombie_equipment[ equipment ].place_fn ) ) + { + replacement = player [[ level.zombie_equipment[ equipment ].place_fn ]]( player.origin, player.angles ); + if ( isDefined( replacement ) ) + { + replacement.owner = player; + replacement.original_owner = player; + replacement.name = equipment; + if ( isDefined( level.equipment_planted ) ) + { + player [[ level.equipment_planted ]]( replacement, equipment, player ); + } + player notify( "equipment_placed" ); + player maps/mp/zombies/_zm_buildables::track_buildables_planted( replacement ); + } + } +} + +equipment_transfer( weaponname, fromplayer, toplayer ) +{ + if ( is_limited_equipment( weaponname ) ) + { +/* +/# + println( "ZM EQUIPMENT: " + weaponname + " transferred from " + fromplayer.name + " to " + toplayer.name + "\n" ); +#/ +*/ + toplayer equipment_orphaned( weaponname ); + wait 0.05; +/* +/# + assert( !toplayer has_player_equipment( weaponname ) ); +#/ +/# + assert( fromplayer has_player_equipment( weaponname ) ); +#/ +*/ + toplayer equipment_give( weaponname ); + toplayer equipment_to_deployed( weaponname ); + if ( isDefined( level.zombie_equipment[ weaponname ].transfer_fn ) ) + { + [[ level.zombie_equipment[ weaponname ].transfer_fn ]]( fromplayer, toplayer ); + } + fromplayer equipment_release( weaponname ); +/* +/# + assert( toplayer has_player_equipment( weaponname ) ); +#/ +/# + assert( !fromplayer has_player_equipment( weaponname ) ); +#/ +*/ + equipment_damage = 0; + toplayer player_set_equipment_damage( weaponname, fromplayer player_get_equipment_damage( weaponname ) ); + fromplayer player_set_equipment_damage( equipment_damage ); + } + else + { +/* +/# + println( "ZM EQUIPMENT: " + weaponname + " swapped from " + fromplayer.name + " to " + toplayer.name + "\n" ); +#/ +*/ + toplayer equipment_give( weaponname ); + if ( isDefined( toplayer.current_equipment ) && toplayer.current_equipment == weaponname ) + { + toplayer equipment_to_deployed( weaponname ); + } + if ( isDefined( level.zombie_equipment[ weaponname ].transfer_fn ) ) + { + [[ level.zombie_equipment[ weaponname ].transfer_fn ]]( fromplayer, toplayer ); + } + equipment_damage = toplayer player_get_equipment_damage( weaponname ); + toplayer player_set_equipment_damage( weaponname, fromplayer player_get_equipment_damage( weaponname ) ); + fromplayer player_set_equipment_damage( weaponname, equipment_damage ); + } +} + +equipment_release( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " release " + equipment + "\n" ); +#/ +*/ + self equipment_take( equipment ); +} + +equipment_drop( equipment ) +{ + if ( isDefined( level.zombie_equipment[ equipment ].place_fn ) ) + { + equipment_drop_to_planted( equipment, self ); +/* +/# + println( "ZM EQUIPMENT: " + self.name + " drop to planted " + equipment + "\n" ); +#/ +*/ + } + else if ( isDefined( level.zombie_equipment[ equipment ].drop_fn ) ) + { + if ( isDefined( self.current_equipment ) && self.current_equipment == equipment ) + { + self equipment_to_deployed( equipment ); + } + item = self [[ level.zombie_equipment[ equipment ].drop_fn ]](); + if ( isDefined( item ) ) + { + if ( isDefined( level.equipment_planted ) ) + { + self [[ level.equipment_planted ]]( item, equipment, self ); + } + item.owner = undefined; + item.damage = self player_get_equipment_damage( equipment ); + } +/* +/# + println( "ZM EQUIPMENT: " + self.name + " dropped " + equipment + "\n" ); +#/ +*/ + } + else + { + self equipment_take(); + } + self notify( "equipment_dropped" ); +} + +equipment_grab( equipment, item ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " picked up " + equipment + "\n" ); +#/ +*/ + self equipment_give( equipment ); + if ( isDefined( level.zombie_equipment[ equipment ].pickup_fn ) ) + { + item.owner = self; + self player_set_equipment_damage( equipment, item.damage ); + self [[ level.zombie_equipment[ equipment ].pickup_fn ]]( item ); + } +} + +equipment_orphaned( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " orphaned " + equipment + "\n" ); +#/ +*/ + self equipment_take( equipment ); +} + +equipment_to_deployed( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " deployed " + equipment + "\n" ); +#/ +*/ + if ( !isDefined( self.deployed_equipment ) ) + { + self.deployed_equipment = []; + } +/* +/# + assert( self.current_equipment == equipment ); +#/ +*/ + self.deployed_equipment[ self.deployed_equipment.size ] = equipment; + self.current_equipment = undefined; + if ( !isDefined( level.riotshield_name ) || equipment != level.riotshield_name ) + { + self takeweapon( equipment ); + } + self setactionslot( 1, "" ); +} + +equipment_from_deployed( equipment ) +{ + if ( !isDefined( equipment ) ) + { + equipment = "none"; + } +/* +/# + println( "ZM EQUIPMENT: " + self.name + " retrieved " + equipment + "\n" ); +#/ +*/ + if ( isDefined( self.current_equipment ) && equipment != self.current_equipment ) + { + self equipment_drop( self.current_equipment ); + } +/* +/# + assert( self has_deployed_equipment( equipment ) ); +#/ +*/ + self.current_equipment = equipment; + if ( isDefined( level.riotshield_name ) && equipment != level.riotshield_name ) + { + self giveweapon( equipment ); + } + if ( self hasweapon( equipment ) ) + { + self setweaponammoclip( equipment, 1 ); + } + self setactionslot( 1, "weapon", equipment ); + arrayremovevalue( self.deployed_equipment, equipment ); + self notify( equipment + "_pickup" ); +} + +eqstub_get_unitrigger_origin() +{ + if ( isDefined( self.origin_parent ) ) + { + return self.origin_parent.origin; + } + tup = anglesToUp( self.angles ); + eq_unitrigger_offset = 12 * tup; + return self.origin + eq_unitrigger_offset; +} + +eqstub_on_spawn_trigger( trigger ) +{ + if ( isDefined( self.link_parent ) ) + { + trigger enablelinkto(); + trigger linkto( self.link_parent ); + trigger setmovingplatformenabled( 1 ); + } +} + +equipment_buy( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " bought " + equipment + "\n" ); +#/ +*/ + if ( isDefined( self.current_equipment ) && equipment != self.current_equipment ) + { + self equipment_drop( self.current_equipment ); + } + if ( equipment != "riotshield_zm" && equipment == "alcatraz_shield_zm" && isDefined( self.player_shield_reset_health ) ) + { + self [[ self.player_shield_reset_health ]](); + } + else + { + self player_set_equipment_damage( equipment, 0 ); + } + self equipment_give( equipment ); +} + +generate_equipment_unitrigger( classname, origin, angles, flags, radius, script_height, hint, icon, think, moving ) +{ + if ( !isDefined( radius ) ) + { + radius = 64; + } + if ( !isDefined( script_height ) ) + { + script_height = 64; + } + script_width = script_height; + if ( !isDefined( script_width ) ) + { + script_width = 64; + } + script_length = script_height; + if ( !isDefined( script_length ) ) + { + script_length = 64; + } + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = origin; + if ( isDefined( angles ) ) + { + unitrigger_stub.angles = angles; + } + if ( isDefined( script_length ) ) + { + unitrigger_stub.script_length = script_length; + } + else + { + unitrigger_stub.script_length = 13.5; + } + if ( isDefined( script_width ) ) + { + unitrigger_stub.script_width = script_width; + } + else + { + unitrigger_stub.script_width = 27.5; + } + if ( isDefined( script_height ) ) + { + unitrigger_stub.script_height = script_height; + } + else + { + unitrigger_stub.script_height = 24; + } + unitrigger_stub.radius = radius; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + unitrigger_stub.hint_string = hint; + /* + if ( getDvarInt( #"1F0A2129" ) ) + { + unitrigger_stub.cursor_hint = "HINT_WEAPON"; + unitrigger_stub.cursor_hint_weapon = icon; + } + */ + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + unitrigger_stub.require_look_at = 0; + switch( classname ) + { + case "trigger_radius": + unitrigger_stub.script_unitrigger_type = "unitrigger_radius"; + break; + case "trigger_radius_use": + unitrigger_stub.script_unitrigger_type = "unitrigger_radius_use"; + break; + case "trigger_box": + unitrigger_stub.script_unitrigger_type = "unitrigger_box"; + break; + case "trigger_box_use": + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + break; + } + unitrigger_stub.originfunc = ::eqstub_get_unitrigger_origin; + unitrigger_stub.onspawnfunc = ::eqstub_on_spawn_trigger; + if ( isDefined( moving ) && moving ) + { + maps/mp/zombies/_zm_unitrigger::register_unitrigger( unitrigger_stub, think ); + } + else + { + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, think ); + } + return unitrigger_stub; +} + +can_pick_up_equipment( equipment_name, equipment_trigger ) +{ + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || self in_revive_trigger() ) + { + return 0; + } + if ( self isthrowinggrenade() ) + { + return 0; + } + if ( isDefined( self.screecher_weapon ) ) + { + return 0; + } + if ( self is_jumping() ) + { + return 0; + } + if ( self is_player_equipment( equipment_name ) ) + { + return 0; + } + if ( isDefined( self.pickup_equipment ) && self.pickup_equipment ) + { + return 0; + } + if ( isDefined( level.equipment_team_pick_up ) && level.equipment_team_pick_up && !self same_team_placed_equipment( equipment_trigger ) ) + { + return 0; + } + return 1; +} + +same_team_placed_equipment( equipment_trigger ) +{ + if ( isDefined( equipment_trigger ) && isDefined( equipment_trigger.stub ) && isDefined( equipment_trigger.stub.model ) && isDefined( equipment_trigger.stub.model.owner ) ) + { + return equipment_trigger.stub.model.owner.pers[ "team" ] == self.pers[ "team" ]; + } +} + +placed_equipment_think( model, equipname, origin, angles, tradius, toffset ) +{ + pickupmodel = spawn( "script_model", origin ); + if ( isDefined( angles ) ) + { + pickupmodel.angles = angles; + } + pickupmodel setmodel( model ); + if ( isDefined( level.equipment_safe_to_drop ) ) + { + if ( !( self [[ level.equipment_safe_to_drop ]]( pickupmodel ) ) ) + { + equipment_disappear_fx( pickupmodel.origin, undefined, pickupmodel.angles ); + pickupmodel delete(); + self equipment_take( equipname ); + return undefined; + } + } + watchername = getsubstr( equipname, 0, equipname.size - 3 ); + if ( isDefined( level.retrievehints[ watchername ] ) ) + { + hint = level.retrievehints[ watchername ].hint; + } + else + { + hint = &"MP_GENERIC_PICKUP"; + } + icon = get_equipment_icon( equipname ); + if ( !isDefined( tradius ) ) + { + tradius = 32; + } + torigin = origin; + if ( isDefined( toffset ) ) + { + tforward = anglesToForward( angles ); + torigin += toffset * tforward; + } + tup = anglesToUp( angles ); + eq_unitrigger_offset = 12 * tup; + if ( isDefined( pickupmodel.canmove ) ) + { + pickupmodel.stub = generate_equipment_unitrigger( "trigger_radius_use", torigin + eq_unitrigger_offset, angles, 0, tradius, 64, hint, equipname, ::placed_equipment_unitrigger_think, pickupmodel.canmove ); + } + pickupmodel.stub.model = pickupmodel; + pickupmodel.stub.equipname = equipname; + pickupmodel.equipname = equipname; + pickupmodel thread item_attract_zombies(); + pickupmodel thread item_watch_explosions(); + if ( is_limited_equipment( equipname ) ) + { + if ( !isDefined( level.dropped_equipment ) ) + { + level.dropped_equipment = []; + } + if ( isDefined( level.dropped_equipment[ equipname ] ) && isDefined( level.dropped_equipment[ equipname ].model ) ) + { + level.dropped_equipment[ equipname ].model dropped_equipment_destroy( 1 ); + } + level.dropped_equipment[ equipname ] = pickupmodel.stub; + } + destructible_equipment_list_add( pickupmodel ); + return pickupmodel; +} + +watch_player_visibility( equipment ) +{ + self endon( "kill_trigger" ); + self setinvisibletoall(); + while ( isDefined( self ) ) + { + players = getplayers(); + _a1142 = players; + _k1142 = getFirstArrayKey( _a1142 ); + while ( isDefined( _k1142 ) ) + { + player = _a1142[ _k1142 ]; + if ( !isDefined( player ) ) + { + } + else + { + invisible = !player can_pick_up_equipment( equipment, self ); + if ( isDefined( self ) ) + { + self setinvisibletoplayer( player, invisible ); + } + wait 0.05; + } + _k1142 = getNextArrayKey( _a1142, _k1142 ); + } + wait 1; + } +} + +placed_equipment_unitrigger_think() +{ + self endon( "kill_trigger" ); + self thread watch_player_visibility( self.stub.equipname ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( !player can_pick_up_equipment( self.stub.equipname, self ) ) + { + continue; + } + self thread pickup_placed_equipment( player ); + return; + } +} + +pickup_placed_equipment( player ) +{ +/* +/# + if ( isDefined( player.pickup_equipment )assert( !player.pickup_equipment ); +#/ +*/ + player.pickup_equipment = 1; + stub = self.stub; + if ( isDefined( player.current_equipment ) && stub.equipname != player.current_equipment ) + { + player equipment_drop( player.current_equipment ); + } + if ( is_limited_equipment( stub.equipname ) ) + { + if ( isDefined( level.dropped_equipment ) && isDefined( level.dropped_equipment[ stub.equipname ] ) && level.dropped_equipment[ stub.equipname ] == stub ) + { + } + } + if ( isDefined( stub.model ) ) + { + stub.model equipment_retrieve( player ); + } + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( stub ); + wait 3; + player.pickup_equipment = 0; +} + +dropped_equipment_think( model, equipname, origin, angles, tradius, toffset ) +{ + pickupmodel = spawn( "script_model", origin ); + if ( isDefined( angles ) ) + { + pickupmodel.angles = angles; + } + pickupmodel setmodel( model ); + if ( isDefined( level.equipment_safe_to_drop ) ) + { + if ( !( self [[ level.equipment_safe_to_drop ]]( pickupmodel ) ) ) + { + equipment_disappear_fx( pickupmodel.origin, undefined, pickupmodel.angles ); + pickupmodel delete(); + self equipment_take( equipname ); + return; + } + } + watchername = getsubstr( equipname, 0, equipname.size - 3 ); + if ( isDefined( level.retrievehints[ watchername ] ) ) + { + hint = level.retrievehints[ watchername ].hint; + } + else + { + hint = &"MP_GENERIC_PICKUP"; + } + icon = get_equipment_icon( equipname ); + if ( !isDefined( tradius ) ) + { + tradius = 32; + } + torigin = origin; + if ( isDefined( toffset ) ) + { + offset = 64; + tforward = anglesToForward( angles ); + torigin = torigin + ( toffset * tforward ) + vectorScale( ( 0, 0, 0 ), 8 ); + } + if ( isDefined( pickupmodel.canmove ) ) + { + pickupmodel.stub = generate_equipment_unitrigger( "trigger_radius_use", torigin, angles, 0, tradius, 64, hint, equipname, ::dropped_equipment_unitrigger_think, pickupmodel.canmove ); + } + pickupmodel.stub.model = pickupmodel; + pickupmodel.stub.equipname = equipname; + pickupmodel.equipname = equipname; + if ( isDefined( level.equipment_planted ) ) + { + self [[ level.equipment_planted ]]( pickupmodel, equipname, self ); + } + if ( !isDefined( level.dropped_equipment ) ) + { + level.dropped_equipment = []; + } + if ( isDefined( level.dropped_equipment[ equipname ] ) ) + { + level.dropped_equipment[ equipname ].model dropped_equipment_destroy( 1 ); + } + level.dropped_equipment[ equipname ] = pickupmodel.stub; + destructible_equipment_list_add( pickupmodel ); + pickupmodel thread item_attract_zombies(); + return pickupmodel; +} + +dropped_equipment_unitrigger_think() +{ + self endon( "kill_trigger" ); + self thread watch_player_visibility( self.stub.equipname ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( !player can_pick_up_equipment( self.stub.equipname, self ) ) + { + continue; + } + self thread pickup_dropped_equipment( player ); + return; + } +} + +pickup_dropped_equipment( player ) +{ + player.pickup_equipment = 1; + stub = self.stub; + if ( isDefined( player.current_equipment ) && stub.equipname != player.current_equipment ) + { + player equipment_drop( player.current_equipment ); + } + player equipment_grab( stub.equipname, stub.model ); + stub.model dropped_equipment_destroy(); + wait 3; + player.pickup_equipment = 0; +} + +dropped_equipment_destroy( gusto ) +{ + stub = self.stub; + if ( isDefined( gusto ) && gusto ) + { + equipment_disappear_fx( self.origin, undefined, self.angles ); + } + if ( isDefined( level.dropped_equipment ) ) + { + } + if ( isDefined( stub.model ) ) + { + stub.model delete(); + } + if ( isDefined( self.original_owner ) || is_limited_equipment( stub.equipname ) && maps/mp/zombies/_zm_weapons::is_weapon_included( stub.equipname ) ) + { + self.original_owner equipment_take( stub.equipname ); + } + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( stub ); +} + +add_placeable_equipment( equipment, modelname, destroy_fn, type ) +{ + if ( !isDefined( level.placeable_equipment ) ) + { + level.placeable_equipment = []; + } + level.placeable_equipment[ equipment ] = modelname; + precachemodel( modelname ); + precacheitem( equipment + "_turret" ); + if ( !isDefined( level.placeable_equipment_destroy_fn ) ) + { + level.placeable_equipment_destroy_fn = []; + } + level.placeable_equipment_destroy_fn[ equipment ] = destroy_fn; + if ( !isDefined( level.placeable_equipment_type ) ) + { + level.placeable_equipment_type = []; + } + level.placeable_equipment_type[ equipment ] = type; +} + +is_placeable_equipment( equipment ) +{ + if ( isDefined( level.placeable_equipment ) && isDefined( level.placeable_equipment[ equipment ] ) ) + { + return 1; + } + return 0; +} + +equipment_placement_watcher() +{ + self endon( "death_or_disconnect" ); + for ( ;; ) + { + self waittill( "weapon_change", weapon ); + if ( self.sessionstate != "spectator" && is_placeable_equipment( weapon ) ) + { + self thread equipment_watch_placement( weapon ); + } + } +} + +equipment_watch_placement( equipment ) +{ + self.turret_placement = undefined; + carry_offset = vectorScale( ( 0, 0, 0 ), 22 ); + carry_angles = ( 0, 0, 0 ); + placeturret = spawnturret( "auto_turret", self.origin, equipment + "_turret" ); + placeturret.angles = self.angles; + placeturret setmodel( level.placeable_equipment[ equipment ] ); + placeturret setturretcarried( 1 ); + placeturret setturretowner( self ); + if ( isDefined( level.placeable_equipment_type[ equipment ] ) ) + { + placeturret setturrettype( level.placeable_equipment_type[ equipment ] ); + } + self carryturret( placeturret, carry_offset, carry_angles ); + if ( isDefined( level.use_swipe_protection ) ) + { + self thread watch_melee_swipes( equipment, placeturret ); + } + self notify( "create_equipment_turret" ); + ended = self waittill_any_return( "weapon_change", "grenade_fire", "death_or_disconnect" ); + if ( isDefined( level.use_legacy_equipment_placement ) && !level.use_legacy_equipment_placement ) + { + self.turret_placement = self canplayerplaceturret( /*placeturret*/ ); + } + if ( ended == "weapon_change" ) + { + self.turret_placement = undefined; + if ( self hasweapon( equipment ) ) + { + self setweaponammoclip( equipment, 1 ); + } + } + self notify( "destroy_equipment_turret" ); + self stopcarryturret( placeturret ); + placeturret setturretcarried( 0 ); + placeturret delete(); +} + +watch_melee_swipes( equipment, turret ) +{ + self endon( "weapon_change" ); + self endon( "grenade_fire" ); + self endon( "death" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "melee_swipe", zombie ); + while ( distancesquared( zombie.origin, self.origin ) > ( zombie.meleeattackdist * zombie.meleeattackdist ) ) + { + continue; + } + tpos = turret.origin; + tangles = turret.angles; + self player_damage_equipment( equipment, 200, zombie.origin ); + if ( self.equipment_damage[ equipment ] >= 1500 ) + { + thread equipment_disappear_fx( tpos, undefined, tangles ); + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons[ 0 ] ) ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + if ( isalive( self ) ) + { + self playlocalsound( level.zmb_laugh_alias ); + } + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + self equipment_release( equipment ); + return; + } + } +} + +player_get_equipment_damage( equipment ) +{ + if ( isDefined( self.equipment_damage ) && isDefined( self.equipment_damage[ equipment ] ) ) + { + return self.equipment_damage[ equipment ]; + } + return 0; +} + +player_set_equipment_damage( equipment, damage ) +{ + if ( !isDefined( self.equipment_damage ) ) + { + self.equipment_damage = []; + } + self.equipment_damage[ equipment ] = damage; +} + +player_damage_equipment( equipment, damage, origin ) +{ + if ( !isDefined( self.equipment_damage ) ) + { + self.equipment_damage = []; + } + if ( !isDefined( self.equipment_damage[ equipment ] ) ) + { + self.equipment_damage[ equipment ] = 0; + } + self.equipment_damage[ equipment ] += damage; + if ( self.equipment_damage[ equipment ] > 1500 ) + { + if ( isDefined( level.placeable_equipment_destroy_fn[ equipment ] ) ) + { + self [[ level.placeable_equipment_destroy_fn[ equipment ] ]](); + } + else + { + equipment_disappear_fx( origin ); + } + self equipment_release( equipment ); + } +} + +item_damage( damage ) +{ + if ( isDefined( self.isriotshield ) && self.isriotshield ) + { + if ( isDefined( level.riotshield_damage_callback ) && isDefined( self.owner ) ) + { + self.owner [[ level.riotshield_damage_callback ]]( damage, 0 ); + } + else + { + if ( isDefined( level.deployed_riotshield_damage_callback ) ) + { + self [[ level.deployed_riotshield_damage_callback ]]( damage ); + } + } + } + else + { + if ( isDefined( self.owner ) ) + { + self.owner player_damage_equipment( self.equipname, damage, self.origin ); + return; + } + else + { + if ( !isDefined( self.damage ) ) + { + self.damage = 0; + } + self.damage += damage; + if ( self.damage > 1500 ) + { + self thread dropped_equipment_destroy( 1 ); + } + } + } +} + +item_watch_damage() +{ + self endon( "death" ); + self setcandamage( 1 ); + self.health = 1500; + while ( 1 ) + { + self waittill( "damage", amount ); + self item_damage( amount ); + } +} + +item_watch_explosions() +{ + self endon( "death" ); + while ( 1 ) + { + level waittill( "grenade_exploded", position, radius, idamage, odamage ); + wait randomfloatrange( 0.05, 0.3 ); + distsqrd = distancesquared( self.origin, position ); + if ( distsqrd < ( radius * radius ) ) + { + dist = sqrt( distsqrd ); + dist /= radius; + damage = odamage + ( ( idamage - odamage ) * ( 1 - dist ) ); + self item_damage( damage * 5 ); + } + } +} + +get_item_health() +{ +/* +/# + damage = 0; + if ( isDefined( self.isriotshield ) && self.isriotshield ) + { + damagemax = level.zombie_vars[ "riotshield_hit_points" ]; + if ( isDefined( self.owner ) ) + { + damage = self.owner.shielddamagetaken; + } + else + { + if ( isDefined( level.deployed_riotshield_damage_callback ) ) + { + damage = self.shielddamagetaken; + } + } + } + else + { + if ( isDefined( self.owner ) ) + { + damagemax = 1500; + damage = self.owner player_get_equipment_damage( self.equipname ); + } + else + { + damagemax = 1500; + if ( isDefined( self.damage ) ) + { + damage = self.damage; + } + } + } + return ( damagemax - damage ) / damagemax; +#/ +*/ +} + +debughealth() +{ +/* +/# + self endon( "death" ); + self endon( "stop_attracting_zombies" ); + while ( 1 ) + { + if ( getDvarInt( #"EB512CB7" ) ) + { + health = self get_item_health(); + color = ( 1 - health, health, 0 ); + text = "" + ( health * 100 ) + ""; + print3d( self.origin, text, color, 1, 0,5, 1 ); + } + wait 0.05; +#/ + } +*/ +} + +item_choke() +{ + if ( !isDefined( level.item_choke_count ) ) + { + level.item_choke_count = 0; + } + level.item_choke_count++; + if ( level.item_choke_count >= 10 ) + { + wait 0.05; + level.item_choke_count = 0; + } +} + +is_equipment_ignored( equipname ) +{ + if ( isDefined( level.equipment_ignored_by_zombies ) && isDefined( equipname ) && isDefined( level.equipment_ignored_by_zombies[ equipname ] ) ) + { + return 1; + } + return 0; +} + +enemies_ignore_equipment( equipname ) +{ + if ( !isDefined( level.equipment_ignored_by_zombies ) ) + { + level.equipment_ignored_by_zombies = []; + } + level.equipment_ignored_by_zombies[ equipname ] = equipname; +} + +item_attract_zombies() +{ + self endon( "death" ); + self notify( "stop_attracting_zombies" ); + self endon( "stop_attracting_zombies" ); +/* +/# + self thread debughealth(); +#/ +*/ + if ( is_equipment_ignored( self.equipname ) ) + { + return; + } + while ( 1 ) + { + if ( isDefined( level.vert_equipment_attack_range ) ) + { + vdistmax = level.vert_equipment_attack_range; + } + else + { + vdistmax = 36; + } + if ( isDefined( level.max_equipment_attack_range ) ) + { + distmax = level.max_equipment_attack_range * level.max_equipment_attack_range; + } + else + { + distmax = 4096; + } + if ( isDefined( level.min_equipment_attack_range ) ) + { + distmin = level.min_equipment_attack_range * level.min_equipment_attack_range; + } + else + { + distmin = 2025; + } + ai = getaiarray( level.zombie_team ); + i = 0; + while ( i < ai.size ) + { + if ( !isDefined( ai[ i ] ) ) + { + i++; + continue; + } + else if ( isDefined( ai[ i ].ignore_equipment ) && ai[ i ].ignore_equipment ) + { + i++; + continue; + } + else + { + if ( isDefined( level.ignore_equipment ) ) + { + if ( self [[ level.ignore_equipment ]]( ai[ i ] ) ) + { + i++; + continue; + } + } + else if ( isDefined( ai[ i ].is_inert ) && ai[ i ].is_inert ) + { + i++; + continue; + } + else + { + if ( isDefined( ai[ i ].is_traversing ) && ai[ i ].is_traversing ) + { + i++; + continue; + } + else + { + vdist = abs( ai[ i ].origin[ 2 ] - self.origin[ 2 ] ); + distsqrd = distance2dsquared( ai[ i ].origin, self.origin ); + if ( isDefined( self.equipname ) || self.equipname == "riotshield_zm" && self.equipname == "alcatraz_shield_zm" ) + { + vdistmax = 108; + } + should_attack = 0; + if ( isDefined( level.should_attack_equipment ) ) + { + should_attack = self [[ level.should_attack_equipment ]]( distsqrd ); + } + if ( distsqrd < distmax && distsqrd > distmin || vdist < vdistmax && should_attack ) + { + if ( isDefined( ai[ i ].isscreecher ) && !ai[ i ].isscreecher && !ai[ i ] is_quad() && !ai[ i ] is_leaper() ) + { + ai[ i ] thread attack_item( self ); + item_choke(); + } + } + item_choke(); + } + } + } + i++; + } + wait 0.1; + } +} + +attack_item( item ) +{ + self endon( "death" ); + item endon( "death" ); + self endon( "start_inert" ); + if ( isDefined( self.doing_equipment_attack ) && self.doing_equipment_attack ) + { + return 0; + } + if ( isDefined( self.not_interruptable ) && self.not_interruptable ) + { + return 0; + } + self thread attack_item_stop( item ); + self thread attack_item_interrupt( item ); + if ( getDvar( "zombie_equipment_attack_freq" ) == "" ) + { + setdvar( "zombie_equipment_attack_freq", "15" ); + } + freq = getDvarInt( "zombie_equipment_attack_freq" ); + self.doing_equipment_attack = 1; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 1 - " + getTime() ); + self.item = item; + if ( !isDefined( self ) || !isalive( self ) ) + { + return; + } + if ( isDefined( item.zombie_attack_callback ) ) + { + item [[ item.zombie_attack_callback ]]( self ); + } + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "attack", self.animname ); + if ( isDefined( level.attack_item ) ) + { + self [[ level.attack_item ]](); + } + melee_anim = "zm_window_melee"; + if ( !self.has_legs ) + { + melee_anim = "zm_walk_melee_crawl"; + if ( self.a.gib_ref == "no_legs" ) + { + melee_anim = "zm_stumpy_melee"; + } + else + { + if ( self.zombie_move_speed == "run" || self.zombie_move_speed == "sprint" ) + { + melee_anim = "zm_run_melee_crawl"; + } + } + } + self orientmode( "face point", item.origin ); + self animscripted( self.origin, flat_angle( vectorToAngles( item.origin - self.origin ) ), melee_anim ); + self notify( "item_attack" ); + if ( isDefined( self.custom_item_dmg ) ) + { + item thread item_damage( self.custom_item_dmg ); + } + else + { + item thread item_damage( 100 ); + } + item playsound( "fly_riotshield_zm_impact_flesh" ); + wait ( randomint( 100 ) / 100 ); + self.doing_equipment_attack = 0; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 0 from wait - " + getTime() ); + self orientmode( "face default" ); +} + +attack_item_interrupt( item ) +{ + if ( isDefined( self.has_legs ) && !self.has_legs ) + { + return; + } + self notify( "attack_item_interrupt" ); + self endon( "attack_item_interrupt" ); + self endon( "death" ); + while ( isDefined( self.has_legs ) && self.has_legs ) + { + self waittill( "damage" ); + } + self stopanimscripted(); + self.doing_equipment_attack = 0; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 0 from death - " + getTime() ); + self.item = undefined; +} + +attack_item_stop( item ) +{ + self notify( "attack_item_stop" ); + self endon( "attack_item_stop" ); + self endon( "death" ); + item waittill( "death" ); + self stopanimscripted(); + self.doing_equipment_attack = 0; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 0 from death - " + getTime() ); + self.item = undefined; + if ( isDefined( level.attack_item_stop ) ) + { + self [[ level.attack_item_stop ]](); + } +} + +window_notetracks( msg, equipment ) +{ + self endon( "death" ); + equipment endon( "death" ); + while ( self.doing_equipment_attack ) + { + self waittill( msg, notetrack ); + if ( notetrack == "end" ) + { + return; + } + if ( notetrack == "fire" ) + { + equipment item_damage( 100 ); + } + } +} + +destructible_equipment_list_check() +{ + if ( !isDefined( level.destructible_equipment ) ) + { + level.destructible_equipment = []; + } + i = 0; + while ( i < level.destructible_equipment.size ) + { + if ( !isDefined( level.destructible_equipment[ i ] ) ) + { + arrayremoveindex( level.destructible_equipment, i ); + continue; + } + else + { + i++; + } + } +} + +destructible_equipment_list_add( item ) +{ + destructible_equipment_list_check(); + level.destructible_equipment[ level.destructible_equipment.size ] = item; +} + +get_destructible_equipment_list() +{ + destructible_equipment_list_check(); + return level.destructible_equipment; +} + +equipment_disappear_fx( origin, fx, angles ) +{ + effect = level._equipment_disappear_fx; + if ( isDefined( fx ) ) + { + effect = fx; + } + if ( isDefined( angles ) ) + { + playfx( effect, origin, anglesToForward( angles ) ); + } + else + { + playfx( effect, origin ); + } + wait 1.1; +} + diff --git a/patch_zm/maps/mp/zombies/_zm_gump.gsc b/patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm_gump.gsc similarity index 100% rename from patch_zm/maps/mp/zombies/_zm_gump.gsc rename to patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm_gump.gsc diff --git a/patch_zm/readme.md b/patch_zm/readme.md index fb1a72b..de14a17 100644 --- a/patch_zm/readme.md +++ b/patch_zm/readme.md @@ -1,5 +1,7 @@ ### The following gscs compile and run successfully with no known errors: ``` +patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_clientids.gsc +patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_globalentities.gsc patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_scoreboard.gsc patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_shellshock.gsc patch_zm/maps/mp/gametypes_zm/NoKnownErrors/zclassic.gsc @@ -7,7 +9,10 @@ patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_basic.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_dogs.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_faller.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_bot.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_clone.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_hacker.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_gasmask.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ffotd.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_boards.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_box.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_doors.gsc @@ -15,10 +20,12 @@ patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_packapunch.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_perks.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_powerups.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_wallbuys.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_net.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_perk_electric_cherry.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_functions.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_system.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_server_throttle.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_score.gsc patch_zm/maps/mp/zombies/NoKnownErrors/_zm_tombstone.gsc ``` @@ -29,6 +36,7 @@ patch_zm/maps/mp/zombies/MinorErorrs/_zm_timer.gsc ### The following scripts compile and run successfully with major errors: ``` patch_zm/maps/mp/gametypes_zm/MajorErrors/_zm_gametype.gsc +patch_zm/maps/mp/zombies/MajorErrors/_zm_chugabud.gsc patch_zm/maps/mp/zombies/MajorErrors/_zm_magicbox.gsc patch_zm/maps/mp/zombies/MajorErrors/_zm_perks.gsc patch_zm/maps/mp/zombies/MajorErrors/_zm_powerups.gsc diff --git a/zm_highrise_patch/maps/mp/zombies/_zm_weap_slipgun.gsc b/zm_highrise_patch/maps/mp/zombies/MajorErrors/_zm_weap_slipgun.gsc similarity index 100% rename from zm_highrise_patch/maps/mp/zombies/_zm_weap_slipgun.gsc rename to zm_highrise_patch/maps/mp/zombies/MajorErrors/_zm_weap_slipgun.gsc diff --git a/zm_transit_patch/maps/mp/zm_transit_utility.gsc b/zm_transit_patch/maps/mp/NoKnownErrors/zm_transit_utility.gsc similarity index 100% rename from zm_transit_patch/maps/mp/zm_transit_utility.gsc rename to zm_transit_patch/maps/mp/NoKnownErrors/zm_transit_utility.gsc diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc b/zm_transit_patch/maps/mp/zombies/MajorErrors/_zm_weap_jetgun.gsc similarity index 100% rename from zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc rename to zm_transit_patch/maps/mp/zombies/MajorErrors/_zm_weap_jetgun.gsc