#include maps\mp\zm_transit_bus; #include common_scripts\utility; #include maps\mp\_utility; #include maps\mp\zombies\_zm_utility; #include maps\mp\zombies\_zm_weapons; #include maps\mp\zm_transit_utility; #include maps\mp\zm_transit_automaton; #include maps\mp\zm_transit_cling; #include maps\mp\zm_transit_openings; #include maps\mp\zombies\_zm_zonemgr; #include maps\mp\zm_transit_ambush; #include maps\mp\zombies\_zm; #include maps\mp\zombies\_zm_spawner; #include maps\mp\zombies\_zm_ai_basic; #include maps\mp\zombies\_zm_equipment; #include maps\mp\zombies\_zm_stats; #include maps\mp\zombies\_zm_laststand; #include maps\mp\zombies\_zm_powerups; #include maps\mp\zombies\_zm_buildables; #include maps\mp\zombies\_zm_weap_emp_bomb; #include maps\mp\zm_transit_lava; #include maps\mp\zombies\_zm_audio; #using_animtree("zombie_bus"); bussetup() { flag_init("ladder_attached"); flag_init("catcher_attached"); flag_init("hatch_attached"); self.immediatespeed = 0; self.currentspeed = 0; self.targetspeed = 0; self.ismoving = 0; self.isstopping = 0; self.gas = 100; self.accel = 20; self.decel = 60; self.radius = 88; self.height = 240; self.frontdist = 340; self.backdist = 55; self.floor = 36; self.frontlocal = (self.frontdist - self.radius / 2.0, 0, 0); self.backlocal = (self.backdist * -1 + self.radius / 2.0, 0, 0); self.drivepath = 0; self.zone = "zone_pri"; self.roadzone = self.zone; self.zombiesinside = 0; self.zombiesatwindow = 0; self.zombiesonroof = 0; self.numplayers = 0; self.numplayerson = 0; self.numplayersonroof = 0; self.numplayersinsidebus = 0; self.numplayersnear = 0; self.numaliveplayersridingbus = 0; self.numflattires = 0; self.doorsclosed = 1; self.doorsdisabledfortime = 0; self.stalled = 0; self.issafe = 1; self.waittimeatdestination = 0; self.gracetimeatdestination = 10; self.path_blocking = 0; self.chase_pos = self.origin; self.chase_pos_time = 0; self.istouchingignorewindowsvolume = 0; level.zm_mantle_over_40_move_speed_override = ::zm_mantle_over_40_move_speed_override; self setmovingplatformenabled(1); self.supportsanimscripted = 1; self setvehmaxspeed(50); self useanimtree(#animtree); level.callbackactordamage = ::transit_actor_damage_override_wrapper; self maps\mp\zm_transit_automaton::main(); maps\mp\zm_transit_cling::initializecling(); self maps\mp\zm_transit_openings::main(); self bus_upgrades(); self thread busplowsetup(); self buslightssetup(); self busdoorssetup(); self buspathblockersetup(); self bussetupbounds(); self bus_roof_watch(); self bus_set_nodes(); self bus_set_exit_triggers(); self thread bus_audio_setup(); level thread init_bus_door_anims(); level thread init_bus_props_anims(); self thread bususeanimtree(); self thread bususedoor(0); self thread busidledoor(); self thread play_lava_audio(); self thread busthink(); self thread busopeningscene(); busschedule(); self thread busschedulethink(); self thread bus_bridge_speedcontrol(); self.door_nodes_linked = 1; self thread bussetdoornodes(0); } busscheduleadd(stopname, isambush, maxwaittimebeforeleaving, busspeedleaving, gasusage) { assert(isdefined(stopname)); assert(isdefined(isambush)); assert(isdefined(maxwaittimebeforeleaving)); assert(isdefined(busspeedleaving)); destinationindex = self.destinations.size; self.destinations[destinationindex] = spawnstruct(); self.destinations[destinationindex].name = stopname; self.destinations[destinationindex].isambush = isambush; self.destinations[destinationindex].maxwaittimebeforeleaving = maxwaittimebeforeleaving; self.destinations[destinationindex].busspeedleaving = busspeedleaving * 2; self.destinations[destinationindex].gasusage = gasusage; } busschedulethink() { self endon("death"); while (true) { self waittill("noteworthy", noteworthy, noteworthynode); zoneisempty = 1; shouldremovegas = 0; destinationindex = level.busschedule busschedulegetdestinationindex(noteworthy); if (!isdefined(destinationindex) || !isdefined(noteworthynode)) { continue; } self.destinationindex = destinationindex; self.waittimeatdestination = level.busschedule busschedulegetmaxwaittimebeforeleaving(self.destinationindex); self.currentnode = noteworthynode; targetspeed = level.busschedule busschedulegetbusspeedleaving(self.destinationindex); foreach (zone in level.zones) { if (!isdefined(zone.volumes) || zone.volumes.size == 0) continue; zonename = zone.volumes[0].targetname; if (self maps\mp\zombies\_zm_zonemgr::entity_in_zone(zonename)) { self.zone = zonename; zonestocheck = []; zonestocheck[zonestocheck.size] = zonename; switch (zonename) { case "zone_station_ext": zonestocheck[zonestocheck.size] = "zone_trans_1"; zonestocheck[zonestocheck.size] = "zone_pri"; zonestocheck[zonestocheck.size] = "zone_pri2"; zonestocheck[zonestocheck.size] = "zone_amb_bridge"; zonestocheck[zonestocheck.size] = "zone_trans_2b"; break; case "zone_gas": zonestocheck[zonestocheck.size] = "zone_trans_2"; zonestocheck[zonestocheck.size] = "zone_amb_tunnel"; zonestocheck[zonestocheck.size] = "zone_gar"; zonestocheck[zonestocheck.size] = "zone_trans_diner"; zonestocheck[zonestocheck.size] = "zone_trans_diner2"; zonestocheck[zonestocheck.size] = "zone_diner_roof"; zonestocheck[zonestocheck.size] = "zone_din"; zonestocheck[zonestocheck.size] = "zone_roadside_west"; zonestocheck[zonestocheck.size] = "zone_roadside_east"; zonestocheck[zonestocheck.size] = "zone_trans_3"; break; case "zone_far": zonestocheck[zonestocheck.size] = "zone_amb_forest"; zonestocheck[zonestocheck.size] = "zone_far_ext"; zonestocheck[zonestocheck.size] = "zone_farm_house"; zonestocheck[zonestocheck.size] = "zone_brn"; zonestocheck[zonestocheck.size] = "zone_trans_5"; zonestocheck[zonestocheck.size] = "zone_trans_6"; break; case "zone_pow": zonestocheck[zonestocheck.size] = "zone_trans_6"; zonestocheck[zonestocheck.size] = "zone_amb_cornfield"; zonestocheck[zonestocheck.size] = "zone_trans_7"; zonestocheck[zonestocheck.size] = "zone_pow_ext1"; zonestocheck[zonestocheck.size] = "zone_prr"; zonestocheck[zonestocheck.size] = "zone_pcr"; zonestocheck[zonestocheck.size] = "zone_pow_warehouse"; break; case "zone_town_north": zonestocheck[zonestocheck.size] = "zone_trans_8"; zonestocheck[zonestocheck.size] = "zone_amb_power2town"; zonestocheck[zonestocheck.size] = "zone_tbu"; zonestocheck[zonestocheck.size] = "zone_town_church"; zonestocheck[zonestocheck.size] = "zone_bar"; zonestocheck[zonestocheck.size] = "zone_town_east"; zonestocheck[zonestocheck.size] = "zone_tow"; zonestocheck[zonestocheck.size] = "zone_ban"; zonestocheck[zonestocheck.size] = "zone_ban_vault"; zonestocheck[zonestocheck.size] = "zone_town_west"; zonestocheck[zonestocheck.size] = "zone_town_west2"; zonestocheck[zonestocheck.size] = "zone_town_barber"; zonestocheck[zonestocheck.size] = "zone_town_south"; zonestocheck[zonestocheck.size] = "zone_trans_9"; break; } foreach (zone in zonestocheck) { if (!(isdefined(zoneisempty) && zoneisempty)) continue; if (maps\mp\zombies\_zm_zonemgr::player_in_zone(zone)) { zoneisempty = 0; } } if (isdefined(zoneisempty) && zoneisempty) { continue; } } } if (isdefined(shouldremovegas) && shouldremovegas) self busgasremove(level.busschedule busschedulegetbusgasusage(self.destinationindex)); if (isdefined(zoneisempty) && zoneisempty) { self busstartmoving(targetspeed); continue; } if (isdefined(self.skip_next_destination) && self.skip_next_destination) { self notify("skipping_destination"); self busstartmoving(targetspeed); continue; } if (level.busschedule busschedulegetisambushstop(self.destinationindex)) { if (maps\mp\zm_transit_ambush::shouldstartambushround() && self.numplayersinsidebus != 0) { self busstopmoving(1); level.nml_zone_name = "zone_amb_" + noteworthy; thread maps\mp\zm_transit_ambush::ambushstartround(); thread automatonspeak("inform", "out_of_gas"); flag_waitopen("ambush_round"); shouldremovegas = 1; thread automatonspeak("inform", "refueled_gas"); } else { continue; } } else { self notify("reached_destination"); shouldremovegas = 1; thread do_automaton_arrival_vox(noteworthy); if (noteworthy == "diner" || noteworthy == "town" || noteworthy == "power") { self busstopmoving(1); if (noteworthy == "diner") self bussetdineropenings(0); else if (noteworthy == "power") self bussetpoweropenings(0); else if (noteworthy == "town") self bussettownopenings(0); } else self busstopmoving(); self thread busscheduledepartearly(); } waittimeatdestination = self.waittimeatdestination; self thread busshowleavinghud(waittimeatdestination); self waittill_any_timeout(waittimeatdestination, "depart_early"); self notify("ready_to_depart"); self thread buslightsflash(); self thread buslightsignal("turn_signal_left"); thread automatonspeak("inform", "leaving_warning"); self thread play_bus_audio("grace"); wait(self.gracetimeatdestination); thread automatonspeak("inform", "leaving"); self.accel = 2; self busstartmoving(targetspeed); self notify("departing"); self setclientfield("bus_flashing_lights", 0); } } busshowleavinghud(time) { self endon("depart_early"); self thread busshowleavinghud_destroy_on_depart_early(); while (time > 0) { players = get_players(); foreach (player in players) { if (!isDefined(player.busleavehud)) { hud = newclienthudelem(player); hud.alignx = "center"; hud.aligny = "middle"; hud.horzalign = "center"; hud.vertalign = "bottom"; hud.y = -75; hud.foreground = 1; hud.hidewheninmenu = 1; hud.font = "default"; hud.fontscale = 1; hud.alpha = 1; hud.color = (1, 1, 1); hud.label = &"ZM_TRANSIT_BUS_DEPART_TIME"; hud setTimer(time); player.busleavehud = hud; } if (!is_true(player.isonbus)) { player.busleavehud.alpha = 0; } else { player.busleavehud.alpha = 1; } } time -= 0.05; wait 0.05; } players = get_players(); foreach (player in players) { if (isDefined(player.busleavehud)) { player.busleavehud destroy(); player.busleavehud = undefined; } } } busshowleavinghud_destroy_on_depart_early() { self waittill("depart_early"); players = get_players(); foreach (player in players) { if (isDefined(player.busleavehud)) { player.busleavehud destroy(); player.busleavehud = undefined; } } } bus_bridge_speedcontrol() { while (true) { self waittill("reached_node", nextpoint); if (isdefined(nextpoint.script_string)) { if (nextpoint.script_string == "map_out_tunnel" || nextpoint.script_string == "map_out_1forest" || nextpoint.script_string == "map_out_corn" || nextpoint.script_string == "map_out_2forest" || nextpoint.script_string == "map_out_bridge") { self setspeed(self.targetspeed / 2, 10, 10); } } if (isdefined(nextpoint.script_string)) { if (nextpoint.script_string == "arrival_slowdown") self thread start_stopping_bus(); if (nextpoint.script_string == "arrival_slowdown_fast") self thread start_stopping_bus(1); } if (isdefined(nextpoint.script_noteworthy)) { if (nextpoint.script_noteworthy == "slow_down") { self.targetspeed = 20; if (isdefined(nextpoint.script_float)) { self.targetspeed = nextpoint.script_float * 2; } self setspeed(self.targetspeed, 160, 10); } else if (nextpoint.script_noteworthy == "turn_signal_left" || nextpoint.script_noteworthy == "turn_signal_right") self thread buslightsignal(nextpoint.script_noteworthy); else if (nextpoint.script_noteworthy == "resume_speed") { self.targetspeed = 24; if (isdefined(nextpoint.script_float)) { self.targetspeed = nextpoint.script_float * 2; } self setspeed(self.targetspeed, 120, 120); } else if (nextpoint.script_noteworthy == "emp_stop_point") self notify("reached_emp_stop_point"); else if (nextpoint.script_noteworthy == "start_lava") playfxontag(level._effect["bus_lava_driving"], self, "tag_origin"); else if (nextpoint.script_noteworthy == "stop_lava") { } else if (nextpoint.script_noteworthy == "bus_scrape") self playsound("zmb_bus_car_scrape"); else if (nextpoint.script_noteworthy == "arriving") { self thread begin_arrival_slowdown(); self thread play_bus_audio("arriving"); level thread do_player_bus_zombie_vox("bus_stop", 10); self thread buslightsignal("turn_signal_right"); } else if (nextpoint.script_noteworthy == "enter_transition") playfxontag(level._effect["fx_zbus_trans_fog"], self, "tag_headlights"); else if (nextpoint.script_noteworthy == "bridge") { level thread do_automaton_arrival_vox("bridge"); player_near = 0; node = getvehiclenode("bridge_accel_point", "script_noteworthy"); if (isdefined(node)) { players = get_players(); foreach (player in players) { if (player.isonbus) continue; if (distancesquared(player.origin, node.origin) < 6760000) player_near = 1; } } if (player_near) { trig = getent("bridge_trig", "targetname"); trig notify("trigger"); } } else if (nextpoint.script_noteworthy == "depot") { volume = getent("depot_lava_pit", "targetname"); traverse_volume = getent("depot_pit_traverse", "targetname"); if (isdefined(volume)) { zombies = getaiarray(level.zombie_team); for (i = 0; i < zombies.size; i++) { if (isdefined(zombies[i].depot_lava_pit)) { if (zombies[i] istouching(volume)) zombies[i] thread [[zombies[i].depot_lava_pit]](); continue; } if (zombies[i] istouching(volume)) { zombies[i] dodamage(zombies[i].health + 100, zombies[i].origin); continue; } if (zombies[i] istouching(traverse_volume)) zombies[i] dodamage(zombies[i].health + 100, zombies[i].origin); } } } } waittillframeend; } } start_stopping_bus(stop_fast) { if (isdefined(stop_fast) && stop_fast) self setspeed(4, 30); else self setspeed(4, 10); } begin_arrival_slowdown() { self setspeed(10, 10, 10); } buspathblockersetup() { self.path_blockers = getentarray("bus_path_blocker", "targetname"); for (i = 0; i < self.path_blockers.size; i++) self.path_blockers[i] linkto(self, "", self worldtolocalcoords(self.path_blockers[i].origin), self.path_blockers[i].angles + self.angles); cow_catcher_blocker = getent("cow_catcher_path_blocker", "targetname"); if (isdefined(cow_catcher_blocker)) cow_catcher_blocker linkto(self, "", self worldtolocalcoords(cow_catcher_blocker.origin), cow_catcher_blocker.angles + self.angles); self thread bus_buyable_weapon_unitrigger_setup(); } bus_buyable_weapon_unitrigger_setup() { weapon_model = getent("bus_buyable_weapon1", "script_noteworthy"); weapon_model enablelinkto(); weapon_model linkto(self, "", self worldtolocalcoords(weapon_model.origin), weapon_model.angles + self.angles); weapon_model setmovingplatformenabled(1); weapon_model._linked_ent = self; weapon_model hide(); unitrigger = undefined; while (!isDefined(unitrigger)) { for (i = 0; i < level._unitriggers.trigger_stubs.size; i++) { if (IsDefined(level._unitriggers.trigger_stubs[i].zombie_weapon_upgrade) && level._unitriggers.trigger_stubs[i].zombie_weapon_upgrade == "beretta93r_zm") { unitrigger = level._unitriggers.trigger_stubs[i]; break; } } wait 1; } unitrigger.require_look_at = 0; unitrigger.target = weapon_model; unitrigger.origin_parent = weapon_model; unitrigger.link_parent = self; unitrigger.originfunc = ::bus_buyable_weapon_get_unitrigger_origin; unitrigger.onspawnfunc = ::bus_buyable_weapon_on_spawn_trigger; while (1) { level waittill("weapon_bought", player, weapon); if (weapon == "beretta93r_zm") { break; } } weapon_model show(); } bus_buyable_weapon_get_unitrigger_origin() { return self.origin_parent.origin + (0, 0, -32); } bus_buyable_weapon_on_spawn_trigger(trigger) { trigger enablelinkto(); trigger linkto(self.link_parent); trigger setmovingplatformenabled(1); } busthink() { no_danger = 0; self thread busupdatechasers(); self thread busupdateplayers(); self thread busupdatenearzombies(); while (true) { waittillframeend; self busupdatespeed(); self busupdateignorewindows(); if (self.ismoving) self busupdatenearequipment(); if (!(isdefined(level.bus_zombie_danger) && level.bus_zombie_danger) && (self.numplayersonroof || self.numplayersinsidebus)) { no_danger++; if (no_danger > 40) { level thread do_player_bus_zombie_vox("bus_zom_none", 40, 60); no_danger = 0; } } else no_danger = 0; wait 0.1; } } busupdateplayers() { level endon("end_game"); while (true) { self.numplayers = 0; self.numplayerson = 0; self.numplayersonroof = 0; self.numplayersinsidebus = 0; self.numplayersnear = 0; self.numaliveplayersridingbus = 0; self.frontworld = self localtoworldcoords(self.frontlocal); self.backworld = self localtoworldcoords(self.backlocal); self.bus_riders_alive = []; players = get_players(); foreach (player in players) { if (!isalive(player)) continue; self.numplayers++; if (distance2d(player.origin, self.origin) < 1700) self.numplayersnear++; playerisinbus = 0; mover = player getmoverent(); if (isdefined(mover)) { if (isdefined(mover.targetname)) { if (mover.targetname == "the_bus" || mover.targetname == "bus_path_blocker" || mover.targetname == "hatch_clip" || mover.targetname == "ladder_mantle") playerisinbus = 1; } if (isdefined(mover.equipname)) { if (mover.equipname == "riotshield_zm") { if (isdefined(mover.isonbus) && mover.isonbus) playerisinbus = 1; } } if (isdefined(mover.is_zombie) && mover.is_zombie && (isdefined(mover.isonbus) && mover.isonbus)) playerisinbus = 1; } if (playerisinbus) { self.numplayerson++; if (is_player_valid(player)) { self.numaliveplayersridingbus++; self.bus_riders_alive[self.bus_riders_alive.size] = player; } } ground_ent = player getgroundent(); if (player isonladder()) ground_ent = mover; if (isdefined(ground_ent)) { if (isdefined(ground_ent.is_zombie) && ground_ent.is_zombie) player thread zombie_surf(ground_ent); else { if (playerisinbus && !(isdefined(player.isonbus) && player.isonbus)) { bbprint("zombie_events", "category %s type %s round %d playername %s", "BUS", "player_enter", level.round_number, player.name); player thread bus_audio_interior_loop(self); player clientnotify("OBS"); player setclientplayerpushamount(0); if (randomint(100) > 80 && level.automaton.greeting_timer == 0) { thread automatonspeak("convo", "player_enter"); level.automaton thread greeting_timer(); } } if (!playerisinbus && (isdefined(player.isonbus) && player.isonbus)) { bbprint("zombie_events", "category %s type %s round %d playername %s", "BUS", "player_exit", level.round_number, player.name); player setclientplayerpushamount(1); player notify("left bus"); player clientnotify("LBS"); if (randomint(100) > 80 && level.automaton.greeting_timer == 0) { thread automatonspeak("convo", "player_leave"); level.automaton thread greeting_timer(); } } player.isonbus = playerisinbus; player.isonbusroof = player _entityisonroof(); } } if (isdefined(player.isonbusroof) && player.isonbusroof) { self.numplayersonroof++; } else if (isdefined(player.isonbus) && player.isonbus) { self.numplayersinsidebus++; } wait 0.05; } wait 0.05; } } busplowkillzombieuntildeath() { self endon("death"); while (isdefined(self) && isalive(self)) { if (isdefined(self.health)) { self dodamage(self.health + 666, self.origin, self, self, "none", "MOD_SUICIDE"); } wait 1; } }