From b677cec1af5d1209617e9a07563b514fd2b6e349 Mon Sep 17 00:00:00 2001 From: squeek Date: Tue, 11 Nov 2014 18:32:26 -0800 Subject: [PATCH] Initial commit --- FortressForever.ico | Bin 0 -> 176712 bytes cfg/civilian.cfg | 7 + cfg/config_default.cfg | 70 + cfg/demoman.cfg | 7 + cfg/detail_settings_default.cfg | 6 + cfg/detail_settings_max.cfg | 6 + cfg/engineer.cfg | 7 + cfg/ff_dustbowl.cfg | 4 + cfg/ff_hunted.cfg | 2 + cfg/ff_training.cfg | 3 + cfg/hwguy.cfg | 7 + cfg/medic.cfg | 7 + cfg/pyro.cfg | 7 + cfg/scout.cfg | 7 + cfg/settings_default.scr | 169 + cfg/sniper.cfg | 7 + cfg/soldier.cfg | 7 + cfg/spy.cfg | 7 + cfg/userconfig.cfg | 21 + cfg/valve.rc | 23 + cfg/waypoint.cfg | 79 + credits.wri | Bin 0 -> 7951 bytes detail.vbsp | 1500 +++++ ff_base.fgd | 5787 +++++++++++++++++ fortressforever.fgd | 125 + gameinfo.txt | 49 + maplist.txt | 11 + maps/default.lua | 18 + maps/ff_2fort.lua | 181 + maps/ff_2fort.txt | 9 + maps/ff_2fort_soundscapes.txt | 267 + maps/ff_aardvark.lua | 301 + maps/ff_aardvark.txt | 6 + maps/ff_aardvark_soundscapes.txt | 38 + maps/ff_bases.lua | 276 + maps/ff_bases.txt | 7 + maps/ff_bases_soundscapes.txt | 229 + maps/ff_cz2.lua | 21 + maps/ff_cz2.txt | 22 + maps/ff_destroy.lua | 316 + maps/ff_destroy.txt | 6 + maps/ff_dm.lua | 172 + maps/ff_dustbowl.lua | 295 + maps/ff_dustbowl.txt | 10 + maps/ff_fusion.lua | 377 ++ maps/ff_genesis.lua | 141 + maps/ff_hunted.lua | 145 + maps/ff_hunted.txt | 17 + maps/ff_hunted__classic__.lua | 71 + maps/ff_hunted_level_sounds.txt | 106 + maps/ff_hunted_soundscapes.txt | 64 + maps/ff_ksour.lua | 404 ++ maps/ff_monkey.lua | 233 + maps/ff_monkey.txt | 7 + maps/ff_napoli.lua | 425 ++ maps/ff_openfire.lua | 251 + maps/ff_palermo.lua | 189 + maps/ff_palermo.txt | 21 + maps/ff_push.lua | 48 + maps/ff_push.txt | 4 + maps/ff_push_soundscapes.txt | 211 + maps/ff_schtop.lua | 250 + maps/ff_schtop.txt | 7 + maps/ff_schtop_soundscapes.txt | 200 + maps/ff_shutdown2.lua | 126 + maps/ff_shutdown2.txt | 5 + maps/ff_shutdown2_level_sounds.txt | 32 + maps/ff_shutdown2_soundscapes.txt | 240 + maps/ff_training.lua | 1934 ++++++ maps/ff_warpath.lua | 592 ++ maps/ff_waterpolo.lua | 20 + maps/ff_waterpolo.txt | 30 + maps/ff_waterpolo_level_sounds.txt | 58 + maps/ff_waterpolo_soundscapes.txt | 55 + maps/ff_well.lua | 193 + maps/ff_well.txt | 5 + maps/ff_well_soundscapes.txt | 165 + maps/includes/base.lua | 198 + maps/includes/base_ad.lua | 833 +++ maps/includes/base_adzone.lua | 1105 ++++ maps/includes/base_chatcommands.lua | 457 ++ maps/includes/base_cp.lua | 1620 +++++ maps/includes/base_cp_default.lua | 234 + maps/includes/base_cp_sequential.lua | 1735 +++++ maps/includes/base_ctf.lua | 151 + maps/includes/base_ctf4.lua | 34 + maps/includes/base_fortball.lua | 689 ++ maps/includes/base_fortball_default.lua | 101 + maps/includes/base_hunted.lua | 471 ++ maps/includes/base_id.lua | 926 +++ maps/includes/base_id_new.lua | 1189 ++++ maps/includes/base_idzone.lua | 898 +++ maps/includes/base_location.lua | 222 + maps/includes/base_push.lua | 351 + maps/includes/base_respawnturret.lua | 41 + maps/includes/base_shutdown.lua | 193 + maps/includes/base_soldierarena.lua | 111 + maps/includes/base_teamplay.lua | 872 +++ maps/includes/base_test.lua | 5 + maps/includes/base_training.lua | 658 ++ motd.txt | 1 + pure_server_whitelist.txt | 60 + resource/ClientScheme.res | 2814 ++++++++ resource/CrosshairScheme.res | 127 + resource/Crosshairs.ttf | Bin 0 -> 18160 bytes resource/Font Layouts.txt | 222 + resource/FortressForever_english.txt | Bin 0 -> 92038 bytes resource/GameMenu.res | 62 + resource/HUDGlyphs.ttf | Bin 0 -> 30612 bytes resource/HUDfont.ttf | Bin 0 -> 11144 bytes resource/HUDfont_caps.ttf | Bin 0 -> 10352 bytes resource/ItemGlyphs.ttf | Bin 0 -> 51256 bytes resource/LoadingDialogNoBanner.res | 85 + resource/LoadingDialogNoBannerSingle.res | 85 + resource/LoadingDialogVAC.res | 101 + resource/ModEvents.res | 222 + resource/MultiplayerAdvancedDialog.res | 83 + resource/Options1.vdf | 28 + resource/Options2.vdf | 67 + resource/Options3.vdf | 85 + resource/Options4.vdf | 90 + resource/OptionsSubMultiplayer.res | 552 ++ resource/PlayerListDialog.res | 72 + resource/RedOctoberff.ttf | Bin 0 -> 18400 bytes resource/SOVIET4.TTF | Bin 0 -> 10048 bytes resource/SourceScheme.res | 1007 +++ resource/StatusGlyphs.ttf | Bin 0 -> 80032 bytes resource/TrackerScheme.res | 1210 ++++ resource/classes/civilian.html | 58 + resource/classes/civilian.jpg | Bin 0 -> 22843 bytes resource/classes/default.html | 41 + resource/classes/demoman.html | 57 + resource/classes/demoman.jpg | Bin 0 -> 37831 bytes resource/classes/engineer.html | 60 + resource/classes/engineer.jpg | Bin 0 -> 36677 bytes resource/classes/ffheader.jpg | Bin 0 -> 12450 bytes resource/classes/hwguy.html | 57 + resource/classes/hwguy.jpg | Bin 0 -> 40490 bytes resource/classes/medic.html | 58 + resource/classes/medic.jpg | Bin 0 -> 43782 bytes resource/classes/pyro.html | 57 + resource/classes/pyro.jpg | Bin 0 -> 40794 bytes resource/classes/random.html | 45 + resource/classes/randompc.jpg | Bin 0 -> 16003 bytes resource/classes/scout.html | 59 + resource/classes/scout.jpg | Bin 0 -> 55366 bytes resource/classes/sniper.html | 55 + resource/classes/sniper.jpg | Bin 0 -> 49507 bytes resource/classes/soldier.html | 55 + resource/classes/soldier.jpg | Bin 0 -> 37785 bytes resource/classes/spy.html | 60 + resource/classes/spy.jpg | Bin 0 -> 47288 bytes resource/ff_version_client.txt | 13 + resource/ff_version_server.txt | 13 + resource/game_menu.tga | Bin 0 -> 25132 bytes resource/game_menu_mouseover.tga | Bin 0 -> 25132 bytes resource/gameui_english.txt | Bin 0 -> 50944 bytes resource/halflife2.ttf | Bin 0 -> 141032 bytes resource/icon_ff-original.tga | Bin 0 -> 57644 bytes resource/icon_ff.tga | Bin 0 -> 1068 bytes resource/overviews/ff_hunted_a08.txt | 9 + resource/spectatormenu.res | 130 + resource/spectatormodes.res | 53 + resource/ui/BottomSpectator.res | 105 + resource/ui/ClassMenu.res | 602 ++ resource/ui/FFGameModes.res | 65 + resource/ui/FFGameModesScenario.res | 409 ++ .../ui/FFGamemodesScenarioAllowedClasses.res | 483 ++ resource/ui/FFGamemodesTraining.res | 91 + resource/ui/FFOptions.res | 81 + resource/ui/FFOptionsSubCrosshairs.res | 804 +++ resource/ui/FFOptionsSubDLights.res | 679 ++ resource/ui/FFOptionsSubMisc.res | 17 + resource/ui/FFOptionsSubTimer.res | 151 + resource/ui/FFSplash.res | 275 + resource/ui/FFTraining.res | 119 + resource/ui/FFUpdates.res | 100 + resource/ui/MOTD.res | 70 + resource/ui/MapGuideMenu.res | 202 + resource/ui/MapScreenshotMenu.res | 56 + resource/ui/ScoreBoard.res | 84 + resource/ui/Spectator.res | 91 + resource/ui/TeamMenu.res | 360 + resource/ui/TextWindow.res | 106 + scripts/HudAnimations.txt | 1082 +++ scripts/HudLayout.res | 1416 ++++ scripts/_hl2_HudAnimations.txt | 628 ++ scripts/_hl2_hud_textures.txt | 434 ++ scripts/decals_subrect.txt | 413 ++ scripts/dsp_presets.txt | 1198 ++++ scripts/ff_grenade_caltrop.txt | 25 + scripts/ff_grenade_concussion.txt | 26 + scripts/ff_grenade_emp.txt | 25 + scripts/ff_grenade_gas.txt | 25 + scripts/ff_grenade_laser.txt | 25 + scripts/ff_grenade_mirv.txt | 25 + scripts/ff_grenade_nail.txt | 25 + scripts/ff_grenade_napalm.txt | 25 + scripts/ff_grenade_normal.txt | 25 + scripts/ff_grenade_slowfield.txt | 26 + scripts/ff_hud_genericammo.txt | 48 + scripts/ff_hud_statusicons.txt | 106 + scripts/ff_hud_textures.txt | 428 ++ scripts/ff_playerclass_civilian.ctx | Bin 0 -> 1181 bytes scripts/ff_playerclass_demoman.ctx | Bin 0 -> 1349 bytes scripts/ff_playerclass_engineer.ctx | Bin 0 -> 1369 bytes scripts/ff_playerclass_hwguy.ctx | Bin 0 -> 1266 bytes scripts/ff_playerclass_medic.ctx | Bin 0 -> 1263 bytes scripts/ff_playerclass_pyro.ctx | Bin 0 -> 1255 bytes scripts/ff_playerclass_scout.ctx | Bin 0 -> 1357 bytes scripts/ff_playerclass_sniper.ctx | Bin 0 -> 1250 bytes scripts/ff_playerclass_soldier.ctx | Bin 0 -> 1265 bytes scripts/ff_playerclass_spy.ctx | Bin 0 -> 1320 bytes scripts/ff_weapon_assaultcannon.ctx | Bin 0 -> 2625 bytes scripts/ff_weapon_autorifle.ctx | Bin 0 -> 2255 bytes scripts/ff_weapon_crowbar.ctx | Bin 0 -> 1547 bytes scripts/ff_weapon_deploydetpack.ctx | Bin 0 -> 1557 bytes scripts/ff_weapon_deploydispenser.ctx | Bin 0 -> 1629 bytes scripts/ff_weapon_deploymancannon.ctx | Bin 0 -> 1561 bytes scripts/ff_weapon_deploysentrygun.ctx | Bin 0 -> 1629 bytes scripts/ff_weapon_flamethrower.ctx | Bin 0 -> 2469 bytes scripts/ff_weapon_grenadelauncher.ctx | Bin 0 -> 2447 bytes scripts/ff_weapon_ic.ctx | Bin 0 -> 2273 bytes scripts/ff_weapon_knife.ctx | Bin 0 -> 1682 bytes scripts/ff_weapon_medkit.ctx | Bin 0 -> 1793 bytes scripts/ff_weapon_nailgun.ctx | Bin 0 -> 2305 bytes scripts/ff_weapon_pipelauncher.ctx | Bin 0 -> 2291 bytes scripts/ff_weapon_railgun.ctx | Bin 0 -> 2742 bytes scripts/ff_weapon_rpg.ctx | Bin 0 -> 2281 bytes scripts/ff_weapon_shotgun.ctx | Bin 0 -> 2300 bytes scripts/ff_weapon_sniperrifle.ctx | Bin 0 -> 2557 bytes scripts/ff_weapon_spanner.ctx | Bin 0 -> 1879 bytes scripts/ff_weapon_supernailgun.ctx | Bin 0 -> 2400 bytes scripts/ff_weapon_supershotgun.ctx | Bin 0 -> 2278 bytes scripts/ff_weapon_tommygun.ctx | Bin 0 -> 2238 bytes scripts/ff_weapon_tranq.ctx | Bin 0 -> 2239 bytes scripts/ff_weapon_umbrella.ctx | Bin 0 -> 1554 bytes scripts/game.txt | 2 + scripts/game_sounds_ff.txt | 111 + scripts/game_sounds_ff_buildable.txt | 293 + scripts/game_sounds_ff_grenades.txt | 217 + scripts/game_sounds_ff_items.txt | 55 + scripts/game_sounds_ff_misc.txt | 545 ++ scripts/game_sounds_ff_player.txt | 230 + scripts/game_sounds_ff_radio.txt | 237 + scripts/game_sounds_ff_training.txt | 520 ++ scripts/game_sounds_ff_weapons.txt | 807 +++ scripts/game_sounds_items.txt | 227 + scripts/game_sounds_manifest.txt | 104 + scripts/game_sounds_weapons.txt | 1476 +++++ scripts/gameinfo.txt | 13 + scripts/hl2_scripts.dsp | 304 + scripts/kb_act.lst | 62 + scripts/kb_def.lst | 63 + scripts/kb_keys.lst | 256 + scripts/liblist.gam | 9 + scripts/sentences.txt | 102 + scripts/sentences_bully.txt | 100 + scripts/sentences_common.txt | 22 + scripts/sentences_female.txt | 100 + scripts/sentences_robot.txt | 100 + scripts/sentences_tfc.txt | 100 + scripts/soundmixers.txt | 236 + scripts/soundscapes_ff.txt | 197 + scripts/soundscapes_ff_anticitizen.txt | 241 + scripts/soundscapes_ff_tiger.txt | 272 + scripts/soundscapes_manifest.txt | 31 + scripts/vehicles/jeep_test.txt | 269 + scripts/vehicles/jeep_test_hl2.txt | 269 + scripts/vehicles/jeep_test_old.txt | 269 + scripts/weapon_cubemap.txt | 72 + sprays/FF_logo.tga | Bin 0 -> 262162 bytes sprays/blue_logo_no_sign.tga | Bin 0 -> 262162 bytes sprays/blue_logo_sign.tga | Bin 0 -> 262162 bytes sprays/green_logo_no_sign.tga | Bin 0 -> 262162 bytes sprays/green_logo_sign.tga | Bin 0 -> 262162 bytes sprays/mulch_face.tga | Bin 0 -> 262162 bytes sprays/red_logo_no_sign.tga | Bin 0 -> 262162 bytes sprays/red_logo_sign.tga | Bin 0 -> 262188 bytes sprays/yellow_logo_no_sign.tga | Bin 0 -> 262188 bytes sprays/yellow_logo_sign.tga | Bin 0 -> 262188 bytes stats.txt | 0 steam.inf | 2 + tfcxhairs.vdf | 378 ++ 284 files changed, 56918 insertions(+) create mode 100644 FortressForever.ico create mode 100644 cfg/civilian.cfg create mode 100644 cfg/config_default.cfg create mode 100644 cfg/demoman.cfg create mode 100644 cfg/detail_settings_default.cfg create mode 100644 cfg/detail_settings_max.cfg create mode 100644 cfg/engineer.cfg create mode 100644 cfg/ff_dustbowl.cfg create mode 100644 cfg/ff_hunted.cfg create mode 100644 cfg/ff_training.cfg create mode 100644 cfg/hwguy.cfg create mode 100644 cfg/medic.cfg create mode 100644 cfg/pyro.cfg create mode 100644 cfg/scout.cfg create mode 100644 cfg/settings_default.scr create mode 100644 cfg/sniper.cfg create mode 100644 cfg/soldier.cfg create mode 100644 cfg/spy.cfg create mode 100644 cfg/userconfig.cfg create mode 100644 cfg/valve.rc create mode 100644 cfg/waypoint.cfg create mode 100644 credits.wri create mode 100644 detail.vbsp create mode 100644 ff_base.fgd create mode 100644 fortressforever.fgd create mode 100644 gameinfo.txt create mode 100644 maplist.txt create mode 100644 maps/default.lua create mode 100644 maps/ff_2fort.lua create mode 100644 maps/ff_2fort.txt create mode 100644 maps/ff_2fort_soundscapes.txt create mode 100644 maps/ff_aardvark.lua create mode 100644 maps/ff_aardvark.txt create mode 100644 maps/ff_aardvark_soundscapes.txt create mode 100644 maps/ff_bases.lua create mode 100644 maps/ff_bases.txt create mode 100644 maps/ff_bases_soundscapes.txt create mode 100644 maps/ff_cz2.lua create mode 100644 maps/ff_cz2.txt create mode 100644 maps/ff_destroy.lua create mode 100644 maps/ff_destroy.txt create mode 100644 maps/ff_dm.lua create mode 100644 maps/ff_dustbowl.lua create mode 100644 maps/ff_dustbowl.txt create mode 100644 maps/ff_fusion.lua create mode 100644 maps/ff_genesis.lua create mode 100644 maps/ff_hunted.lua create mode 100644 maps/ff_hunted.txt create mode 100644 maps/ff_hunted__classic__.lua create mode 100644 maps/ff_hunted_level_sounds.txt create mode 100644 maps/ff_hunted_soundscapes.txt create mode 100644 maps/ff_ksour.lua create mode 100644 maps/ff_monkey.lua create mode 100644 maps/ff_monkey.txt create mode 100644 maps/ff_napoli.lua create mode 100644 maps/ff_openfire.lua create mode 100644 maps/ff_palermo.lua create mode 100644 maps/ff_palermo.txt create mode 100644 maps/ff_push.lua create mode 100644 maps/ff_push.txt create mode 100644 maps/ff_push_soundscapes.txt create mode 100644 maps/ff_schtop.lua create mode 100644 maps/ff_schtop.txt create mode 100644 maps/ff_schtop_soundscapes.txt create mode 100644 maps/ff_shutdown2.lua create mode 100644 maps/ff_shutdown2.txt create mode 100644 maps/ff_shutdown2_level_sounds.txt create mode 100644 maps/ff_shutdown2_soundscapes.txt create mode 100644 maps/ff_training.lua create mode 100644 maps/ff_warpath.lua create mode 100644 maps/ff_waterpolo.lua create mode 100644 maps/ff_waterpolo.txt create mode 100644 maps/ff_waterpolo_level_sounds.txt create mode 100644 maps/ff_waterpolo_soundscapes.txt create mode 100644 maps/ff_well.lua create mode 100644 maps/ff_well.txt create mode 100644 maps/ff_well_soundscapes.txt create mode 100644 maps/includes/base.lua create mode 100644 maps/includes/base_ad.lua create mode 100644 maps/includes/base_adzone.lua create mode 100644 maps/includes/base_chatcommands.lua create mode 100644 maps/includes/base_cp.lua create mode 100644 maps/includes/base_cp_default.lua create mode 100644 maps/includes/base_cp_sequential.lua create mode 100644 maps/includes/base_ctf.lua create mode 100644 maps/includes/base_ctf4.lua create mode 100644 maps/includes/base_fortball.lua create mode 100644 maps/includes/base_fortball_default.lua create mode 100644 maps/includes/base_hunted.lua create mode 100644 maps/includes/base_id.lua create mode 100644 maps/includes/base_id_new.lua create mode 100644 maps/includes/base_idzone.lua create mode 100644 maps/includes/base_location.lua create mode 100644 maps/includes/base_push.lua create mode 100644 maps/includes/base_respawnturret.lua create mode 100644 maps/includes/base_shutdown.lua create mode 100644 maps/includes/base_soldierarena.lua create mode 100644 maps/includes/base_teamplay.lua create mode 100644 maps/includes/base_test.lua create mode 100644 maps/includes/base_training.lua create mode 100644 motd.txt create mode 100644 pure_server_whitelist.txt create mode 100644 resource/ClientScheme.res create mode 100644 resource/CrosshairScheme.res create mode 100644 resource/Crosshairs.ttf create mode 100644 resource/Font Layouts.txt create mode 100644 resource/FortressForever_english.txt create mode 100644 resource/GameMenu.res create mode 100644 resource/HUDGlyphs.ttf create mode 100644 resource/HUDfont.ttf create mode 100644 resource/HUDfont_caps.ttf create mode 100644 resource/ItemGlyphs.ttf create mode 100644 resource/LoadingDialogNoBanner.res create mode 100644 resource/LoadingDialogNoBannerSingle.res create mode 100644 resource/LoadingDialogVAC.res create mode 100644 resource/ModEvents.res create mode 100644 resource/MultiplayerAdvancedDialog.res create mode 100644 resource/Options1.vdf create mode 100644 resource/Options2.vdf create mode 100644 resource/Options3.vdf create mode 100644 resource/Options4.vdf create mode 100644 resource/OptionsSubMultiplayer.res create mode 100644 resource/PlayerListDialog.res create mode 100644 resource/RedOctoberff.ttf create mode 100644 resource/SOVIET4.TTF create mode 100644 resource/SourceScheme.res create mode 100644 resource/StatusGlyphs.ttf create mode 100644 resource/TrackerScheme.res create mode 100644 resource/classes/civilian.html create mode 100644 resource/classes/civilian.jpg create mode 100644 resource/classes/default.html create mode 100644 resource/classes/demoman.html create mode 100644 resource/classes/demoman.jpg create mode 100644 resource/classes/engineer.html create mode 100644 resource/classes/engineer.jpg create mode 100644 resource/classes/ffheader.jpg create mode 100644 resource/classes/hwguy.html create mode 100644 resource/classes/hwguy.jpg create mode 100644 resource/classes/medic.html create mode 100644 resource/classes/medic.jpg create mode 100644 resource/classes/pyro.html create mode 100644 resource/classes/pyro.jpg create mode 100644 resource/classes/random.html create mode 100644 resource/classes/randompc.jpg create mode 100644 resource/classes/scout.html create mode 100644 resource/classes/scout.jpg create mode 100644 resource/classes/sniper.html create mode 100644 resource/classes/sniper.jpg create mode 100644 resource/classes/soldier.html create mode 100644 resource/classes/soldier.jpg create mode 100644 resource/classes/spy.html create mode 100644 resource/classes/spy.jpg create mode 100644 resource/ff_version_client.txt create mode 100644 resource/ff_version_server.txt create mode 100644 resource/game_menu.tga create mode 100644 resource/game_menu_mouseover.tga create mode 100644 resource/gameui_english.txt create mode 100644 resource/halflife2.ttf create mode 100644 resource/icon_ff-original.tga create mode 100644 resource/icon_ff.tga create mode 100644 resource/overviews/ff_hunted_a08.txt create mode 100644 resource/spectatormenu.res create mode 100644 resource/spectatormodes.res create mode 100644 resource/ui/BottomSpectator.res create mode 100644 resource/ui/ClassMenu.res create mode 100644 resource/ui/FFGameModes.res create mode 100644 resource/ui/FFGameModesScenario.res create mode 100644 resource/ui/FFGamemodesScenarioAllowedClasses.res create mode 100644 resource/ui/FFGamemodesTraining.res create mode 100644 resource/ui/FFOptions.res create mode 100644 resource/ui/FFOptionsSubCrosshairs.res create mode 100644 resource/ui/FFOptionsSubDLights.res create mode 100644 resource/ui/FFOptionsSubMisc.res create mode 100644 resource/ui/FFOptionsSubTimer.res create mode 100644 resource/ui/FFSplash.res create mode 100644 resource/ui/FFTraining.res create mode 100644 resource/ui/FFUpdates.res create mode 100644 resource/ui/MOTD.res create mode 100644 resource/ui/MapGuideMenu.res create mode 100644 resource/ui/MapScreenshotMenu.res create mode 100644 resource/ui/ScoreBoard.res create mode 100644 resource/ui/Spectator.res create mode 100644 resource/ui/TeamMenu.res create mode 100644 resource/ui/TextWindow.res create mode 100644 scripts/HudAnimations.txt create mode 100644 scripts/HudLayout.res create mode 100644 scripts/_hl2_HudAnimations.txt create mode 100644 scripts/_hl2_hud_textures.txt create mode 100644 scripts/decals_subrect.txt create mode 100644 scripts/dsp_presets.txt create mode 100644 scripts/ff_grenade_caltrop.txt create mode 100644 scripts/ff_grenade_concussion.txt create mode 100644 scripts/ff_grenade_emp.txt create mode 100644 scripts/ff_grenade_gas.txt create mode 100644 scripts/ff_grenade_laser.txt create mode 100644 scripts/ff_grenade_mirv.txt create mode 100644 scripts/ff_grenade_nail.txt create mode 100644 scripts/ff_grenade_napalm.txt create mode 100644 scripts/ff_grenade_normal.txt create mode 100644 scripts/ff_grenade_slowfield.txt create mode 100644 scripts/ff_hud_genericammo.txt create mode 100644 scripts/ff_hud_statusicons.txt create mode 100644 scripts/ff_hud_textures.txt create mode 100644 scripts/ff_playerclass_civilian.ctx create mode 100644 scripts/ff_playerclass_demoman.ctx create mode 100644 scripts/ff_playerclass_engineer.ctx create mode 100644 scripts/ff_playerclass_hwguy.ctx create mode 100644 scripts/ff_playerclass_medic.ctx create mode 100644 scripts/ff_playerclass_pyro.ctx create mode 100644 scripts/ff_playerclass_scout.ctx create mode 100644 scripts/ff_playerclass_sniper.ctx create mode 100644 scripts/ff_playerclass_soldier.ctx create mode 100644 scripts/ff_playerclass_spy.ctx create mode 100644 scripts/ff_weapon_assaultcannon.ctx create mode 100644 scripts/ff_weapon_autorifle.ctx create mode 100644 scripts/ff_weapon_crowbar.ctx create mode 100644 scripts/ff_weapon_deploydetpack.ctx create mode 100644 scripts/ff_weapon_deploydispenser.ctx create mode 100644 scripts/ff_weapon_deploymancannon.ctx create mode 100644 scripts/ff_weapon_deploysentrygun.ctx create mode 100644 scripts/ff_weapon_flamethrower.ctx create mode 100644 scripts/ff_weapon_grenadelauncher.ctx create mode 100644 scripts/ff_weapon_ic.ctx create mode 100644 scripts/ff_weapon_knife.ctx create mode 100644 scripts/ff_weapon_medkit.ctx create mode 100644 scripts/ff_weapon_nailgun.ctx create mode 100644 scripts/ff_weapon_pipelauncher.ctx create mode 100644 scripts/ff_weapon_railgun.ctx create mode 100644 scripts/ff_weapon_rpg.ctx create mode 100644 scripts/ff_weapon_shotgun.ctx create mode 100644 scripts/ff_weapon_sniperrifle.ctx create mode 100644 scripts/ff_weapon_spanner.ctx create mode 100644 scripts/ff_weapon_supernailgun.ctx create mode 100644 scripts/ff_weapon_supershotgun.ctx create mode 100644 scripts/ff_weapon_tommygun.ctx create mode 100644 scripts/ff_weapon_tranq.ctx create mode 100644 scripts/ff_weapon_umbrella.ctx create mode 100644 scripts/game.txt create mode 100644 scripts/game_sounds_ff.txt create mode 100644 scripts/game_sounds_ff_buildable.txt create mode 100644 scripts/game_sounds_ff_grenades.txt create mode 100644 scripts/game_sounds_ff_items.txt create mode 100644 scripts/game_sounds_ff_misc.txt create mode 100644 scripts/game_sounds_ff_player.txt create mode 100644 scripts/game_sounds_ff_radio.txt create mode 100644 scripts/game_sounds_ff_training.txt create mode 100644 scripts/game_sounds_ff_weapons.txt create mode 100644 scripts/game_sounds_items.txt create mode 100644 scripts/game_sounds_manifest.txt create mode 100644 scripts/game_sounds_weapons.txt create mode 100644 scripts/gameinfo.txt create mode 100644 scripts/hl2_scripts.dsp create mode 100644 scripts/kb_act.lst create mode 100644 scripts/kb_def.lst create mode 100644 scripts/kb_keys.lst create mode 100644 scripts/liblist.gam create mode 100644 scripts/sentences.txt create mode 100644 scripts/sentences_bully.txt create mode 100644 scripts/sentences_common.txt create mode 100644 scripts/sentences_female.txt create mode 100644 scripts/sentences_robot.txt create mode 100644 scripts/sentences_tfc.txt create mode 100644 scripts/soundmixers.txt create mode 100644 scripts/soundscapes_ff.txt create mode 100644 scripts/soundscapes_ff_anticitizen.txt create mode 100644 scripts/soundscapes_ff_tiger.txt create mode 100644 scripts/soundscapes_manifest.txt create mode 100644 scripts/vehicles/jeep_test.txt create mode 100644 scripts/vehicles/jeep_test_hl2.txt create mode 100644 scripts/vehicles/jeep_test_old.txt create mode 100644 scripts/weapon_cubemap.txt create mode 100644 sprays/FF_logo.tga create mode 100644 sprays/blue_logo_no_sign.tga create mode 100644 sprays/blue_logo_sign.tga create mode 100644 sprays/green_logo_no_sign.tga create mode 100644 sprays/green_logo_sign.tga create mode 100644 sprays/mulch_face.tga create mode 100644 sprays/red_logo_no_sign.tga create mode 100644 sprays/red_logo_sign.tga create mode 100644 sprays/yellow_logo_no_sign.tga create mode 100644 sprays/yellow_logo_sign.tga create mode 100644 stats.txt create mode 100644 steam.inf create mode 100644 tfcxhairs.vdf diff --git a/FortressForever.ico b/FortressForever.ico new file mode 100644 index 0000000000000000000000000000000000000000..2060323d721f389e0f754d24db4efdc30ddb4e75 GIT binary patch literal 176712 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 literal 0 HcmV?d00001 diff --git a/cfg/civilian.cfg b/cfg/civilian.cfg new file mode 100644 index 0000000..6f08222 --- /dev/null +++ b/cfg/civilian.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any civilian specific commands below this line. \ No newline at end of file diff --git a/cfg/config_default.cfg b/cfg/config_default.cfg new file mode 100644 index 0000000..42d2a90 --- /dev/null +++ b/cfg/config_default.cfg @@ -0,0 +1,70 @@ +// YWB (mailto:yahn@valvesoftware.com) 10/10/03: +// If the user doesn't have a config.cfg when they run, +// this gets executed the first time they run the engine +// It doesn't execute if they have their own config.cfg saved out. +unbindall + +bind "ESCAPE" "cancelselect" +bind "`" "toggleconsole" +bind "~" "toggleconsole" +bind "w" "+forward" +bind "s" "+back" +bind "a" "+moveleft" +bind "d" "+moveright" +bind "SPACE" "+jump" +bind "CTRL" "+duck" +bind "TAB" "+showscores" +bind "e" "+use" +bind "c" "dropitems" +bind "z" "+medengymenu" +bind "r" "+reload" +bind "x" "discard" +bind "h" "+hintcenter" +bind "m" "+mapshot" +bind "k" "+voicerecord" +bind "ALT" "+speed" +bind "y" "say" +bind "u" "say_team" +bind "t" "impulse 201" +bind "SHIFT" "+speed" +bind "MOUSE1" "+attack" +bind "MOUSE2" "+attack2" +bind "ENTER" "+attack" +bind "f" "+gren1" +bind "g" "+gren2" +bind "l" "impulse 100" +bind "0" "slot10" +bind "1" "slot1" +bind "2" "slot2" +bind "3" "slot3" +bind "4" "slot4" +bind "5" "slot5" +bind "6" "slot6" +bind "7" "slot7" +bind "8" "slot8" +bind "9" "slot9" +bind "MWHEELUP" "invprev" +bind "MWHEELDOWN" "invnext" +bind "[" "invprev" +bind "]" "invnext" +bind "q" "lastinv" +bind "F5" "jpeg" +bind "F6" "save quick" +bind "F9" "load quick" +bind "PAUSE" "pause" +bind "b" "changeclass" +bind "n" "changeteam" +bind "." "changeteam" +bind "," "changeclass" +cl_autoreload "1" +cl_classautokill "1" +cl_dynamicblur "0" +cl_dynamicfov "0" +cl_teamcolourhud "1" +cl_cmdrate "66" +cl_updaterate "66" +con_enable 1 +//cl_interp "0.03" + +name "WhenFFwillOut" + diff --git a/cfg/demoman.cfg b/cfg/demoman.cfg new file mode 100644 index 0000000..b106b59 --- /dev/null +++ b/cfg/demoman.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any demoman specific commands below this line. \ No newline at end of file diff --git a/cfg/detail_settings_default.cfg b/cfg/detail_settings_default.cfg new file mode 100644 index 0000000..00c6329 --- /dev/null +++ b/cfg/detail_settings_default.cfg @@ -0,0 +1,6 @@ +cl_detaildist "1200" +cl_detailfade "400" +cl_effectsdetail "1" +lod_Enable "1" +lod_TransitionDist "800" +r_lod "-1" diff --git a/cfg/detail_settings_max.cfg b/cfg/detail_settings_max.cfg new file mode 100644 index 0000000..d4ccf2c --- /dev/null +++ b/cfg/detail_settings_max.cfg @@ -0,0 +1,6 @@ +cl_detaildist "65536" +cl_detailfade "-1" +cl_effectsdetail "2" +lod_Enable "0" +lod_TransitionDist "65536" +r_lod "0" diff --git a/cfg/engineer.cfg b/cfg/engineer.cfg new file mode 100644 index 0000000..c0a136a --- /dev/null +++ b/cfg/engineer.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any engineer specific commands below this line. \ No newline at end of file diff --git a/cfg/ff_dustbowl.cfg b/cfg/ff_dustbowl.cfg new file mode 100644 index 0000000..11f758d --- /dev/null +++ b/cfg/ff_dustbowl.cfg @@ -0,0 +1,4 @@ +echo FF_DUSTBOWL CFG LOADED +mat_autoexposure_max 2.5 +mat_autoexposure_min .25 +mat_bloomscale .5 \ No newline at end of file diff --git a/cfg/ff_hunted.cfg b/cfg/ff_hunted.cfg new file mode 100644 index 0000000..64af693 --- /dev/null +++ b/cfg/ff_hunted.cfg @@ -0,0 +1,2 @@ +echo FF_HUNTED CFG LOADED +sv_alltalk 0 diff --git a/cfg/ff_training.cfg b/cfg/ff_training.cfg new file mode 100644 index 0000000..21ed980 --- /dev/null +++ b/cfg/ff_training.cfg @@ -0,0 +1,3 @@ +echo FF_TRAINING CFG LOADED +mp_timelimit 0 +sv_cheats 0 diff --git a/cfg/hwguy.cfg b/cfg/hwguy.cfg new file mode 100644 index 0000000..a1251b4 --- /dev/null +++ b/cfg/hwguy.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any hwguy specific commands below this line. \ No newline at end of file diff --git a/cfg/medic.cfg b/cfg/medic.cfg new file mode 100644 index 0000000..5f69c55 --- /dev/null +++ b/cfg/medic.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any medic specific commands below this line. \ No newline at end of file diff --git a/cfg/pyro.cfg b/cfg/pyro.cfg new file mode 100644 index 0000000..28d4df6 --- /dev/null +++ b/cfg/pyro.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any pryo specific commands below this line. \ No newline at end of file diff --git a/cfg/scout.cfg b/cfg/scout.cfg new file mode 100644 index 0000000..344b8aa --- /dev/null +++ b/cfg/scout.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any scout specific commands below this line. \ No newline at end of file diff --git a/cfg/settings_default.scr b/cfg/settings_default.scr new file mode 100644 index 0000000..0cd5931 --- /dev/null +++ b/cfg/settings_default.scr @@ -0,0 +1,169 @@ +// NOTE: THIS FILE IS AUTOMATICALLY REGENERATED, +//DO NOT EDIT THIS HEADER, YOUR COMMENTS WILL BE LOST IF YOU DO +// Multiplayer options script +// +// Format: +// Version [float] +// Options description followed by +// Options defaults +// +// Option description syntax: +// +// "cvar" { "Prompt" { type [ type info ] } { default } } +// +// type = +// BOOL (a yes/no toggle) +// STRING +// NUMBER +// LIST +// +// type info: +// BOOL no type info +// NUMBER min max range, use -1 -1 for no limits +// STRING no type info +// LIST delimited list of options value pairs +// +// +// default depends on type +// BOOL is "0" or "1" +// NUMBER is "value" +// STRING is "value" +// LIST is "index", where index "0" is the first element of the list + + +// Half-Life Server Configuration Layout Script (stores last settings chosen, too) +// File generated: Mon Jul 12 05:28:33 PM +// +// +// Cvar - Setting + +VERSION 1.0 + +DESCRIPTION SERVER_OPTIONS +{ + "hostname" + { + "#Valve_Hostname" + { STRING } + { "Fortress Forever" } + } + + "maxplayers" + { + "#Valve_Max_Players" + { NUMBER 1 22 } + { "16" } + } + + "sv_password" + { + "#Valve_Server_Password" + { STRING } + { "" } + } + + "mp_timelimit" + { + "#FF_Timelimit" + { NUMBER 0 -1 } + { "20" } + } + + "mp_friendlyfire" + { + "#Valve_Friendly_Fire" + { BOOL } + { "0" } + } + + "sv_lan" + { + "sv_lan" + { BOOL } + { "0" } + } + + "sv_alltalk" + { + "sv_alltalk" + { BOOL } + { "0" } + } + + "sv_cheats" + { + "sv_cheats" + { BOOL } + { "0" } + } + + "cr_scout" + { + "cr_scout" + { NUMBER -1 -1 } + { "0" } + } + + "cr_sniper" + { + "cr_sniper" + { NUMBER -1 -1 } + { "0" } + } + + "cr_soldier" + { + "cr_soldier" + { NUMBER -1 -1 } + { "0" } + } + + "cr_demoman" + { + "cr_demoman" + { NUMBER -1 -1 } + { "0" } + } + + "cr_medic" + { + "cr_medic" + { NUMBER -1 -1 } + { "0" } + } + + "cr_hwguy" + { + "cr_hwguy" + { NUMBER -1 -1 } + { "0" } + } + + "cr_pyro" + { + "cr_pyro" + { NUMBER -1 -1 } + { "0" } + } + + "cr_spy" + { + "cr_spy" + { NUMBER -1 -1 } + { "0" } + } + + "cr_engineer" + { + "cr_engineer" + { NUMBER -1 -1 } + { "0" } + } + + "cr_civilian" + { + "cr_civilian" + { NUMBER -1 -1 } + { "0" } + } +} diff --git a/cfg/sniper.cfg b/cfg/sniper.cfg new file mode 100644 index 0000000..b99fa81 --- /dev/null +++ b/cfg/sniper.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any sniper specific commands below this line. \ No newline at end of file diff --git a/cfg/soldier.cfg b/cfg/soldier.cfg new file mode 100644 index 0000000..3db328b --- /dev/null +++ b/cfg/soldier.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any soldier specific commands below this line. \ No newline at end of file diff --git a/cfg/spy.cfg b/cfg/spy.cfg new file mode 100644 index 0000000..af68a5e --- /dev/null +++ b/cfg/spy.cfg @@ -0,0 +1,7 @@ +exec userconfig.cfg + // Place any global binds/aliases/scripts into the userconfig.cfg file and specifics into each .cfg +// IMPORTANT: The userconfig.cfg file DOES NOT auto-execute. +// It can only be executed in console with "exec userconfig.cfg" or by the .cfg files using that command as above. +// If you are reading this line, then just leave this file in the cfg folder and the userconfig.cfg file will work fine. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + // Place any spy specific commands below this line. \ No newline at end of file diff --git a/cfg/userconfig.cfg b/cfg/userconfig.cfg new file mode 100644 index 0000000..8326762 --- /dev/null +++ b/cfg/userconfig.cfg @@ -0,0 +1,21 @@ +// userconfig.cfg + +// Place all general binds/aliases/scripts into this file. +// Create the following files and put class specific binds/aliases/scripts into them. +// "demoman.cfg" +// "engineer.cfg" +// "hwguy.cfg" +// "medic.cfg" +// "pyro.cfg" +// "scout.cfg" +// "sniper.cfg" +// "soldier.cfg" +// "spy.cfg" + +// IMPORTANT: This file DOES NOT auto-execute. +// It must be executed in the developer console with "exec userconfig.cfg" OR in the .cfg files. +// The first line of each .cfg should be "exec userconfig.cfg". +// Remove any "echo" commands you may have at the start of that file. +// For more information, see our tutorials on the Fortress-Forever Wiki. http://www.fortress-forever.com/wiki/Main_Page + +// Place all global commands below this line. \ No newline at end of file diff --git a/cfg/valve.rc b/cfg/valve.rc new file mode 100644 index 0000000..49107cd --- /dev/null +++ b/cfg/valve.rc @@ -0,0 +1,23 @@ +// load the base configuration +//exec default.cfg + +// Setup custom controller +exec joystick.cfg + +// run a user script file if present +exec autoexec.cfg + +// +// stuff command line statements +// +stuffcmds + +//disable this for now. +//startupmenu + +hostname "Insert witty phrase here!" +sv_password "gazellenegation" + +mp_prematch 0 +mp_forcerespawn 0 + diff --git a/cfg/waypoint.cfg b/cfg/waypoint.cfg new file mode 100644 index 0000000..417b141 --- /dev/null +++ b/cfg/waypoint.cfg @@ -0,0 +1,79 @@ +//This config is used for keybindings when waypointing +//It is best used with conjuction with the default.cfg +//which will reset your keybindings back to your standard binds + +//Author: GoaT_RopeR +//Version: 0.1 +//Date: 20070916 + + +//Enable Waypoint and Developer Modes +sv_cheats 1 +developer 1 +mp_timelimit 999 +bot waypoint_view 1 +bot waypoint_viewfacing 1 + + +//Waypoint Color Options +bot waypoint_color team1 0 0 255 //Set team1 waypoints Blue +bot waypoint_color team2 255 0 0 //Set team2 waypoints Red +bot waypoin`t_color waypoint_selected 226 132 20 //Set selected waypoints Orange +bot waypoint_color link_2way 0 0 0 //Set 2way connections Black +bot waypoint_color link_1way 255 255 0 //Set 1way connections Yellow +bot waypoint_color radius 0 255 25 //Set radii Green + + +//File Load Binds +bind "F1" "exec addbot_team1.cfg" +bind "F2" "exec addbot_team2.cfg" +bind "F3" "exec addbot_engi.cfg" +bind "F4" "exec addbot_scout1.cfg" +bind "F5" "exec addbot_scout2.cfg" +bind "F6" "exec addbot_sniper.cfg" +bind "F12" "exec default.cfg" + + +//Keyboard Binds +bind "=" "bot waypoint_changeradius +10" +bind "-" "bot waypoint_changeradius -10" +bind "kp_plus" "bot waypoint_changeradius +10" +bind "kp_minus" "bot waypoint_changeradius -10" +bind "del" "bot kickall" +bind "c" "bot waypoint_addflag cappoint" +bind "j" "bot waypoint_addflag jump" +bind "r" "bot waypoint_addflag rocketjump" +bind "t" "bot waypoint_addflag teleport" +bind "p" "bot waypoint_addflag pipetrap" +bind "l" "bot waypoint_load" +bind "v" "bot waypoint_save" +bind "shift" "bot waypoint_move" +bind "f" "bot waypoint_setfacing" + + +//Mouse Binds +bind "mouse1" "bot waypoint_add" +bind "mouse2" "bot waypoint_connect" +bind "mouse3" "middleclick" +bind "mouse4" "bot waypoint_del" +bind "mouse5" "bot waypoint_clearcon" + +bind "mwheelup" "mup" +bind "mwheeldown" "mdown" + +alias "middleclick" "" +alias "mup" "echo Mouse 3: Set Waypoint Red Team;alias middleclick bot waypoint_addflag team2;alias mup snipe;alias mdown blue" +alias "mdown" "echo Mouse 3: Set Waypoint Blue Team;alias middleclick bot waypoint_addflag team1;alias mup red;alias mdown ammo" + +alias "red" "echo Mouse 3: Set Waypoint Red Team;alias middleclick bot waypoint_addflag team2;alias mup snipe;alias mdown blue" +alias "blue" "echo Mouse 3: Set Waypoint Blue Team;alias middleclick bot waypoint_addflag team1;alias mup red;alias mdown ammo" +alias "ammo" "echo Mouse 3: Set Waypoint Ammo;alias middleclick bot waypoint_addflag ammo;alias mup blue;alias mdown armor" +alias "armor" "echo Mouse 3: Set Waypoint Armor;alias middleclick bot waypoint_addflag armor;alias mup ammo;alias mdown climb" +alias "climb" "echo Mouse 3: Set Waypoint Climb, Note:Set both begining and ending CLIMB tags!;alias middleclick bot waypoint_addflag climb;alias mup armor;alias mdown crouch" +alias "crouch" "echo Mouse 3: Set Waypoint Crouch;alias middleclick bot waypoint_addflag crouch;alias mup climb;alias mdown detpack" +alias "detpack" "echo Mouse 3: Set Waypoint Detpack;alias middleclick bot waypoint_addflag detpack;alias mup crouch;alias mdown dispenser" +alias "dispenser" "echo Mouse 3: Set Waypoint Dispenser;alias middleclick bot waypoint_addflag dispenser;alias mup detpack;alias mdown grenades" +alias "grenades" "echo Mouse 3: Set Waypoint Grenades;alias middleclick bot waypoint_addflag grenades;alias mup crouch;alias mdown health" +alias "health" "echo Mouse 3: Set Waypoint Health;alias middleclick bot waypoint_addflag health;alias mup grenades;alias mdown sentry" +alias "sentry" "echo Mouse 3: Set Waypoint Sentry, Note:Set facing also!;alias middleclick bot waypoint_addflag sentry;alias mup health;alias mdown snipe" +alias "snipe" "echo Mouse 3: Set Waypoint Snipe, Note:Set facing also!;alias middleclick bot waypoint_addflag snipe;alias mup sentry;alias mdown red" diff --git a/credits.wri b/credits.wri new file mode 100644 index 0000000000000000000000000000000000000000..8647134bcf384acff49844ab7f1aac79a83d163a GIT binary patch literal 7951 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 literal 0 HcmV?d00001 diff --git a/detail.vbsp b/detail.vbsp new file mode 100644 index 0000000..0531701 --- /dev/null +++ b/detail.vbsp @@ -0,0 +1,1500 @@ +detail +{ + swamp_land_001 + { + "density" "800.0" + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/props_foliage/grass_swamp_001a.mdl" + "amount" "0.3" + } + + Model2 + { + "model" "models/props_foliage/grass_swamp_001b.mdl" + "amount" "0.3" + } + + } + + Group2 + { + "alpha" "0.0" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_003a.mdl" + "amount" "0.05" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_004b.mdl" + "amount" "0.05" + } + } + } + + swamp_land_002 + { + "density" "800.0" + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/props_foliage/grass_swamp_001a.mdl" + "amount" "0.3" + } + + Model2 + { + "model" "models/props_foliage/grass_swamp_001b.mdl" + "amount" "0.3" + } + + } + + Group2 + { + "alpha" "0.0" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_001a.mdl" + "amount" "0.1" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_001b.mdl" + "amount" "0.1" + } + } + } + + swamp_water_001 + { + "density" "200.0" + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_001a.mdl" + "amount" "0.3" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_001b.mdl" + "amount" "0.3" + } + } + + Group2 + { + "alpha" "0.0" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_003a.mdl" + "amount" "0.1" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_004b.mdl" + "amount" "0.3" + } + } + } + + grassland1 + { + "density" "500.0" + + + Group1 + { + "alpha" "0.0" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_004a.mdl" + "amount" "0.1" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_004b.mdl" + "amount" "0.1" + } + Model3 + { + "model" "models/props_foliage/Grass_tuft_004c.mdl" + "amount" "0.1" + } + Model4 + { + "model" "models/props_foliage/Grass_tuft_004d.mdl" + "amount" "0.1" + } + } + Group2 + { + "alpha" "0.3" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_001a.mdl" + "amount" "0.1" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_001b.mdl" + "amount" "0.1" + } + + } + Group3 + { + "alpha" "0.7" + + } + Group4 + { + "alpha" "1.0" + + } + + + } + + grassland2 + { + "density" "1000.0" + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/junk/w_traffcone.mdl" + "amount" "0.4" + } + } + } + + rocks1 + { + "density" "500.0" + + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/props_wasteland/rocksground01a.mdl" + "amount" "0.1" + } + + Model2 + { + "model" "models/props_wasteland/rocksground01b.mdl" + "amount" "0.1" + } + Model3 + { + "model" "models/props_wasteland/rocksground01c.mdl" + "amount" "0.1" + } + Model4 + { + "model" "models/props_wasteland/rocksground01d.mdl" + "amount" "0.1" + } + Model5 + { + "model" "models/props_wasteland/rocksground01e.mdl" + "amount" "0.1" + } + Model6 + { + "model" "models/props_wasteland/rocksground02a.mdl" + "amount" "0.1" + } + Model7 + { + "model" "models/props_wasteland/rocksground02b.mdl" + "amount" "0.1" + } + Model8 + { + "model" "models/props_wasteland/rocksground02c.mdl" + "amount" "0.1" + } + + } + Group2 + { + "alpha" "0.8" + + Model1 + { + "model" "models/props_wasteland/rocksground01a.mdl" + "amount" "0.1" + } + + Model2 + { + "model" "models/props_wasteland/rocksground01b.mdl" + "amount" "0.1" + } + Model3 + { + "model" "models/props_wasteland/rocksground01c.mdl" + "amount" "0.1" + } + Model4 + { + "model" "models/props_wasteland/rocksground01d.mdl" + "amount" "0.1" + } + Model5 + { + "model" "models/props_wasteland/rocksground01e.mdl" + "amount" "0.1" + } + Model6 + { + "model" "models/props_wasteland/rocksground02a.mdl" + "amount" "0.1" + } + Model7 + { + "model" "models/props_wasteland/rocksground02b.mdl" + "amount" "0.1" + } + Model8 + { + "model" "models/props_wasteland/rocksground02c.mdl" + "amount" "0.1" + } + + } + Group3 + { + "alpha" "0.3" + + } + Group4 + { + "alpha" "0.0" + + } + + + } + + grassland3 + { + "density" "1500.0" + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/props_foliage/shrub_01a.mdl" + "amount" "0.2" + } + + Model2 + { + "model" "models/props_foliage/shrub_03a.mdl" + "amount" "0.1" + } + Model4 + { + "model" "models/props_foliage/shrub_03c.mdl" + "amount" "0.1" + } + } + + + Group2 + { + "alpha" "0.0" + + Model1 + { + "model" "models/props_foliage/grass_tuft_001.mdl" + "amount" "0.2" + } + } + } + + test + { + "density" "600.0" + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_001a.mdl" + "amount" "0.3" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_001b.mdl" + "amount" "0.3" + } + } + + Group2 + { + "alpha" "0.0" + + Model1 + { + "model" "models/props_foliage/Grass_tuft_003a.mdl" + "amount" "0.1" + } + + Model2 + { + "model" "models/props_foliage/Grass_tuft_004b.mdl" + "amount" "0.3" + } + Model3 + { + "model" "models/props_foliage/Grass_tuft_004a.mdl" + "amount" "0.05" + } + Model4 + { + "model" "models/props_foliage/Grass_tuft_004c.mdl" + "amount" "0.05" + } + } + } + + grass01 + { + "density" "600.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 25 33" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 40 50" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 23 28" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model4 + { + "sprite" "288 144 128 128 512" + "spritesize" "0.5 0.0 50 50" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + "alpha" "0.5" + Model1 + { + "sprite" "0 144 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "1" + "detailOrientation" "2" + } + } + + Group4 + { + "alpha" "0.3" + + } + + Group5 + { + "alpha" "0.0" + + } + } + + grass02 + { + "density" "600.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 25 33" + "spriterandomscale" "0.2" + "amount" "0.6" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 30 40" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + } + + Group3 + { + "alpha" "0.5" + } + + Group4 + { + "alpha" "0.3" + + } + + Group5 + { + "alpha" "0.0" + + } + } + + grass03 + { + "density" "600.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 25 33" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 40 50" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + "alpha" "0.5" + Model1 + { + "sprite" "0 144 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "1" + "detailOrientation" "2" + } + } + + Group4 + { + "alpha" "0.3" + + } + + Group5 + { + "alpha" "0.0" + + } + } + + coastline_grass01 + //reduced size to 0.75 + // density was 600 until 7/7/04. Reduced for global coast perf reasons - Sawyer + { + "density" "300.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 30 38" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 18" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model4 + { + "sprite" "288 144 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "0.0" + } + } + + coastline_grass02 + // Should be the same as coastline_grass01, but with less density for large areas. + //reduced size by 0.75 + { + "density" "50.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 30 37.5" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 21" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model4 + { + "sprite" "288 144 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "0.0" + } + } + coastline_redgrass01 + //reduced size by 0.75 + { + "density" "600.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 23 30" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.15" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 21" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model5 + { + "sprite" "144 288 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model6 + { + "sprite" "0 288 128 128 512" + "spritesize" "0.5 0.0 23 23" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model7 + { + "sprite" "288 288 128 128 512" + "spritesize" "0.5 0.0 42 42" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "0.0" + } + } + + coastline_redgrass02 + //reduced size by 0.75 + { + "density" "600.0" + + Group1 + { + "alpha" "0" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 23 30" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.15" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 21" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model5 + { + "sprite" "144 288 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model6 + { + "sprite" "0 288 128 128 512" + "spritesize" "0.5 0.0 23 23" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model7 + { + "sprite" "288 288 128 128 512" + "spritesize" "0.5 0.0 42 42" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "1" + } + } + + coastline_redgrass03 + //reduced size by 0.75 + { + "density" "300.0" + + Group1 + { + "alpha" "0" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 23 30" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.15" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 21" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model5 + { + "sprite" "144 288 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model6 + { + "sprite" "0 288 128 128 512" + "spritesize" "0.5 0.0 23 23" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model7 + { + "sprite" "288 288 128 128 512" + "spritesize" "0.5 0.0 42 42" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "1" + } + } + + + + citygrass01 + { + "density" "3000.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 25 33" + "spriterandomscale" "0.2" + "amount" "0.6" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 30 40" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "0.3" + "detailOrientation" "2" + } + } + + Group3 + { + "alpha" "0.5" + } + + Group4 + { + "alpha" "0.3" + + } + + Group5 + { + "alpha" "0.0" + + } + } + redgrass + //reduced size by 0.75 + { + "density" "2000.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 23 30" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.15" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 21" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model5 + { + "sprite" "144 288 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model6 + { + "sprite" "0 288 128 128 512" + "spritesize" "0.5 0.0 23 23" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model7 + { + "sprite" "288 288 128 128 512" + "spritesize" "0.5 0.0 29 29" + "spriterandomscale" "0.3" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "0.0" + } + } + + + redgrass_light + //reduced size by 0.75 + { + "density" "700.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 23 30" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.15" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 21" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model5 + { + "sprite" "144 288 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model6 + { + "sprite" "0 288 128 128 512" + "spritesize" "0.5 0.0 23 23" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model7 + { + "sprite" "288 288 128 128 512" + "spritesize" "0.5 0.0 29 29" + "spriterandomscale" "0.3" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "0.0" + } + } + + + short_redgrass + + { + "density" "2000.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 10 13" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 12 15" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 8 8" + "spriterandomscale" "0.2" + "amount" "0.15" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 9 11" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model5 + { + "sprite" "144 288 128 128 512" + "spritesize" "0.5 0.0 19 19" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model6 + { + "sprite" "0 288 128 128 512" + "spritesize" "0.5 0.0 12 12" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model7 + { + "sprite" "288 288 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.3" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + + "alpha" "0.0" + } + } + + PerfTest1 + { + "density" "9000.0" + + + Group1 + { + "alpha" "1.0" + + Model1 + { + "model" "models/PerfTest/Grass_tuft_004a.mdl" + "amount" "0.25" + } + + Model2 + { + "model" "models/PerfTest/Grass_tuft_004b.mdl" + "amount" "0.25" + } + Model3 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 25 33" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model4 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 40 50" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model5 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model6 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 23 28" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + + } + Group2 + { + "alpha" "1.0" + + } + Group3 + { + "alpha" "1.0" + + } + Group4 + { + "alpha" "0.5" + } + + } +canal_reeds + { + "density" "750.0" + + + Group1 + { + + "alpha" "0.0" + } + Group2 + { + + "alpha" "0.2" + } + Group2a + { + + "alpha" "0.35" + Model1 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 15 25" + "spriterandomscale" "0.2" + "amount" "0.8" + "detailOrientation" "2" + } + } + Group3 + { + + "alpha" "0.75" + Model1 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 20 35" + "spriterandomscale" "0.2" + "amount" "0.8" + "detailOrientation" "2" + } + } + Group4 + { + "alpha" "1.0" + Model1 + { + "upright" "1.0" + "model" "models/props_foliage/cattails.mdl" + "amount" "0.2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 40 65" + "spriterandomscale" "0.1" + "amount" "0.8" + "detailOrientation" "2" + } + } + } +rocks_redgrass +//rocks in red grass + { + "density" "2000.0" + + Group1 + { + "alpha" "1" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 19 25" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 23 30" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 15 15" + "spriterandomscale" "0.2" + "amount" "0.15" + "detailOrientation" "2" + } + Model4 + { + "sprite" "144 144 128 128 512" + "spritesize" "0.5 0.0 18 21" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + //shrub + Model5 + { + "sprite" "144 288 128 128 512" + "spritesize" "0.5 0.0 38 38" + "spriterandomscale" "0.2" + "amount" "0.2" + "detailOrientation" "2" + } + Model6 + { + "sprite" "0 288 128 128 512" + "spritesize" "0.5 0.0 23 23" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model7 + { + "sprite" "288 288 128 128 512" + "spritesize" "0.5 0.0 29 29" + "spriterandomscale" "0.3" + "amount" "0.1" + "detailOrientation" "2" + } + Model8 + { + "model" "models/props_foliage/detail_rocks01a.mdl" + "amount" "0.05" + } + } + + Group2 + { + + "alpha" "0.0" + } + } +street_junk +//trash on streets + { + "density" "60.0" + + + Group1 + { + + "alpha" "0.0" + } + Group2 + { + "alpha" "1.0" + + Model1 + { + "model" "models/props_junk/detail_junk01.mdl" + "amount" "0.33" + } + Model2 + { + "model" "models/props_junk/detail_junk02.mdl" + "amount" "0.33" + } + Model3 + { + "model" "models/props_junk/detail_junk03.mdl" + "amount" "0.33" + } + } + } + +// new stuff for FF +// we usually have our grass first in the blend, so change the 0 alpha part if you want to change the grass detail prop + +FFgrass01 + { + "density" "600.0" + + Group1 + { + "alpha" "0.0" + Model1 + { + "sprite" "288 0 128 128 512" + "spritesize" "0.5 0.0 25 33" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model2 + { + "sprite" "0 0 128 128 512" + "spritesize" "0.5 0.0 40 50" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + Model3 + { + "sprite" "144 0 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "0.1" + "detailOrientation" "2" + } + } + + Group2 + { + "alpha" "0.5" + Model1 + { + "sprite" "0 144 128 128 512" + "spritesize" "0.5 0.0 20 20" + "spriterandomscale" "0.2" + "amount" "0.05" + "detailOrientation" "2" + } + } + + + Group3 + { + "alpha" "1.0" + } + } +} + + diff --git a/ff_base.fgd b/ff_base.fgd new file mode 100644 index 0000000..4440225 --- /dev/null +++ b/ff_base.fgd @@ -0,0 +1,5787 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: General game definition file (.fgd) +// +//============================================================================= + +@mapsize(-16384, 16384) + + +//------------------------------------------------------------------------- +// +// Base Classes +// +//------------------------------------------------------------------------- + +@BaseClass = Angles +[ + angles(angle) : "Pitch Yaw Roll (Y Z X)" : "0 0 0" : "This entity's orientation in the world. Pitch is rotation around the Y axis, " + + "yaw is the rotation around the Z axis, roll is the rotation around the X axis." +] + +@BaseClass = Origin +[ + origin(origin) : "Origin (X Y Z)" : : "The position of this entity's center in the world. Rotating entities typically rotate around their origin." +] + +@BaseClass = Studiomodel +[ + model(studio) : "World Model" + skin(integer) : "Skin" : 0 : "Some models have multiple versions of their textures, called skins. Set this to a number other than 0 to use that skin instead of the default." + + disableshadows(choices) : "Disable Shadows" : 0 : "Used to disable dynamic shadows on this entity." = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Skin(integer) : "Changes the model skin to the specified number." + input DisableShadow(void) : "Turn shadow off." + input EnableShadow(void) : "Turn shadow on." + input AlternativeSorting(bool) : "Used to attempt to fix sorting problems when rendering. True activates, false deactivates" + + // Outputs + output OnIgnite(void) : "Fired when this object catches fire." +] + +@BaseClass = BasePlat +[ + input Toggle(void) : "Toggles the platform's state." + input GoUp(void) : "Tells the platform to go up." + input GoDown(void) : "Tells the platform to go down." +] + +@BaseClass = Targetname +[ + targetname(target_source) : "Name" : : "The name that other entities refer to this entity by." + + // Inputs + input Kill(void) : "Removes this entity from the world." + input KillHierarchy(void) : "Removes this entity and all its children from the world." + input AddOutput(string) : "Adds an entity I/O connection to this entity. Format: ::::. Very dangerous, use with care." + input FireUser1(void) : "Causes this entity's OnUser1 output to be fired." + input FireUser2(void) : "Causes this entity's OnUser2 output to be fired." + input FireUser3(void) : "Causes this entity's OnUser3 output to be fired." + input FireUser4(void) : "Causes this entity's OnUser4 output to be fired." + + // Outputs + output OnUser1(void) : "Fired in response to FireUser1 input." + output OnUser2(void) : "Fired in response to FireUser2 input." + output OnUser3(void) : "Fired in response to FireUser3 input." + output OnUser4(void) : "Fired in response to FireUser4 input." +] + +@BaseClass = Parentname +[ + parentname(target_destination) : "Parent" : : "The name of this entity's parent in the movement hierarchy. Entities with parents move with their parent." + + // Inputs + input SetParent(string) : "Changes the entity's parent in the movement hierarchy." + input SetParentAttachment(string) : "Change this entity to attach to a specific attachment point on its parent. Entities must be parented before being sent this input. The parameter passed in should be the name of the attachment." + input SetParentAttachmentMaintainOffset(string) : "Change this entity to attach to a specific attachment point on it's parent. Entities must be parented before being sent this input. The parameter passed in should be the name of the attachment. The entity will maintain it's position relative to the parent at the time it is attached." + input ClearParent(void) : "Removes this entity from the the movement hierarchy, leaving it free to move independently." +] + +@BaseClass = BaseBrush +[ + // Inputs + input SetTextureIndex(integer) : "Used by HL1Port. Sets the brush texture index. Use a material_modify_control entity instead." + input IncrementTextureIndex(void) : "Used by HL1Port. Increments the brush texture index. Use a material_modify_control entity instead." +] + +@BaseClass = EnableDisable +[ + StartDisabled(choices) : "Start Disabled" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Enable(void) : "Enable this entity." + input Disable(void) : "Disable this entity." +] + +@BaseClass = RenderFxChoices +[ + renderfx(choices) :"Render FX" : 0 = + [ + 0: "Normal" + 1: "Slow Pulse" + 2: "Fast Pulse" + 3: "Slow Wide Pulse" + 4: "Fast Wide Pulse" + 9: "Slow Strobe" + 10: "Fast Strobe" + 11: "Faster Strobe" + 12: "Slow Flicker" + 13: "Fast Flicker" + 5: "Slow Fade Away" + 6: "Fast Fade Away" + 7: "Slow Become Solid" + 8: "Fast Become Solid" + 14: "Constant Glow" + 15: "Distort" + 16: "Hologram (Distort + fade)" + 23: "Cull By Distance (TEST)" + 24: "Spotlight FX" + 26: "Fade Near" + ] +] + +@BaseClass = Shadow +[ + disableshadows(choices) : "Disable shadows" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + input DisableShadow(void) : "Turn shadow off." + input EnableShadow(void) : "Turn shadow on." +] + +@BaseClass base(RenderFxChoices) = RenderFields +[ + rendermode(choices) : "Render Mode" : 0 : "Used to set a non-standard rendering mode on this entity. See also 'FX Amount' and 'FX Color'." = + [ + 0: "Normal" + 1: "Color" + 2: "Texture" + 3: "Glow" + 4: "Solid" + 5: "Additive" + 7: "Additive Fractional Frame" + 9: "World Space Glow" + 10: "Dont Render" + ] + renderamt(integer) : "FX Amount (0 - 255)" : 255 : "The FX amount is used by the selected Render Mode." + rendercolor(color255) : "FX Color (R G B)" : "255 255 255" : "The FX color is used by the selected Render Mode." + + disablereceiveshadows(choices) : "Disable Receiving Shadows" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + input Alpha(integer) : "Set the sprite's alpha (0 - 255)." + input Color(color255) : "Set the sprite's color (R G B)." +] + + +// Inherit from this to get the ability to only include an object in a range of dx levels. +// NOTE!!: MAKE SURE THAT YOU DON'T USE THIS WITH ANYTHING THAT WILL BREAK SAVE-GAMES SWITCHING +// BETWEEN DXLEVELS!!!! +@BaseClass = DXLevelChoice +[ + mindxlevel(choices) : "Minimum DX Level" : 0 = + [ + 0 : "default (lowest)" + 70 : "dx7" + ] + maxdxlevel(choices) : "Maximum DX Level" : 0 = + [ + 0 : "default (highest)" + 60 : "dx6" + ] +] + +@BaseClass = Inputfilter +[ + InputFilter(choices) : "Input Filter" : 0 : "Used to specify which inputs this entity will accept." = + [ + 0 : "Allow all inputs" + 8 : "Ignore Touch/Untouch" + 16 : "Ignore Use" + 32 : "Ignore All" + ] +] + +@BaseClass = Global +[ + globalname(string) : "Global Entity Name" : "" : "Name by which this entity is linked to another entity in a different map. When the player transitions to a new map, entities in the new map with globalnames matching entities in the previous map will have the previous map's state copied over their state." +] + +@BaseClass base(Targetname) = EnvGlobal : + "An entity to control a global game state." +[ + initialstate(choices) : "Initial State" : 0 = + [ + 0 : "Off" + 1 : "On" + 2 : "Dead" + ] + spawnflags(flags) = + [ + 1 : "Set Initial State" : 0 + ] + + // Inputs + input TurnOn(void) : "Set state of global to ON." + input TurnOff(void) : "Set state of global to OFF." + input Toggle(void) : "Toggles state of global between ON and OFF." + input Remove(void) : "Set state of global to DEAD." +] + +@BaseClass = DamageFilter +[ + damagefilter(target_destination) : "Damage Filter" : "" : "Name of the filter entity that controls which entities can damage us." + input SetDamageFilter(string) : "Sets the entity to use as damage filter. Pass in an empty string to clear the damage filter." +] + +@BaseClass = ResponseContext +[ + // Inputs + input AddContext(string) : "Adds a context to this entity's list of response contexts. The format should be 'key:value'." + input RemoveContext(string) : "Remove a context from this entity's list of response contexts. The name should match the 'key' of a previously added context." + input ClearContext(void) : "Removes all contexts in this entity's list of response contexts." + + // Pre-defined contexts at server startup time (set by mapper) + ResponseContext(string) : "Response Contexts" : "" : "Response system context(s) for this entity. Format should be: 'key:value,key2:value2,etc'. When this entity speaks, the list of keys & values will be passed to the response rules system." +] + +@BaseClass base(Targetname, DamageFilter, Shadow) = Breakable +[ + ExplodeDamage(float) : "Explosion Damage" : 0 : "If non-zero, when this entity breaks it will create an explosion that causes the specified amount of damage. See also 'Explosion Radius'." + ExplodeRadius(float) : "Explosion Radius" : 0 : "If non-zero, when this entity breaks it will create an explosion with a radius of the specified amount. See also 'Explosion Damage'." + PerformanceMode(choices) : "Performance Mode" : 0 : "Used to limit the amount of gibs produced when this entity breaks, for performance reasons." = + [ + 0 : "Normal" + 1 : "No Gibs" + 2 : "Full Gibs on All Platforms" + ] + + // Inputs + input Break(void) : "Breaks the breakable." + input SetHealth(integer) : "Sets a new value for the breakable's health. If the breakable's health reaches zero it will break." + input AddHealth(integer) : "Adds health to the breakable. If the breakable's health reaches zero it will break." + input RemoveHealth(integer) : "Removes health from the breakable. If the breakable's health reaches zero it will break." + input EnablePhyscannonPickup(void) : "Makes the breakable able to picked up by the physcannon." + input DisablePhyscannonPickup(void) : "Makes the breakable not able to picked up by the physcannon." + + // Outputs + output OnBreak(void) : "Fired when this breakable breaks." + output OnHealthChanged(float) : "Fired when the health of this breakable changes, passing the new value of health as a percentage of max health, from [0..1]." + output OnPhysCannonDetach(void) : "Fired when the physcannon has ripped this breakable off of the wall. Only fired if ACT_PHYSCANNON_DETACH is defined in the model this breakable is using." + output OnPhysCannonAnimatePreStarted(void) : "Fired when this prop starts playing the Pre physcannon-pull activity, caused by the player trying to grab this prop with the physcannon. Only fired if the ACT_PHYSCANNON_ANIMATE_PRE activity is defined in the model this breakable is using." + output OnPhysCannonAnimatePullStarted(void) : "Fired when this prop starts playing the physcannon-pull activity, caused by the player trying to grab this prop with the physcannon. Only fired if the ACT_PHYSCANNON_ANIMATE activity is defined in the model this breakable is using. If the prop has Pre pull anim, this will be fired after the Pre anim has finished playing." + output OnPhysCannonPullAnimFinished(void) : "Fired when this prop has finished playing the physcannon-pull activity, caused by the player trying to grab this prop with the physcannon. Only fired if the ACT_PHYSCANNON_ANIMATE activity is defined in the model this breakable is using. If the prop has Pre & Post pull anims, this will be fired after the Post anim has finished playing." + output OnPhysCannonAnimatePostStarted(void) : "Fired when this prop starts playing the Post physcannon-pull activity. Only fired if the ACT_PHYSCANNON_ANIMATE_POST activity is defined in the model this breakable is using." +] + +@BaseClass base(Breakable, Parentname, Global) = BreakableBrush +[ + spawnflags(flags) = + [ + 1 : "Only Break on Trigger" : 0 + 2 : "Break on Touch" : 0 + 4 : "Break on Pressure" : 0 + 512: "Break immediately on Physics" : 0 + 1024: "Don't take physics damage" : 0 + ] + + propdata(choices) : "Prop Data" : 0 : "Set to the best approximation of the size and material of this entity's brushes. If set, it will override this entity's health and damage taken from various weapons. See the propdata.txt file in the scripts directory of your MOD to get a detailed list of what each entry specifies." = + [ + 0 : "None" + 1 : "Wooden.Tiny" + 2 : "Wooden.Small" + 3 : "Wooden.Medium" + 4 : "Wooden.Large" + 5 : "Wooden.Huge" + 6 : "Metal.Small" + 7 : "Metal.Medium" + 8 : "Metal.Large" + 9 : "Cardboard.Small" + 10 : "Cardboard.Medium" + 11 : "Cardboard.Large" + 12 : "Stone.Small" + 13 : "Stone.Medium" + 14 : "Stone.Large" + 15 : "Stone.Huge" + 16 : "Glass.Small" + 17 : "Plastic.Small" + 18 : "Plastic.Medium" + 19 : "Plastic.Large" + 20 : "Pottery.Small" + 21 : "Pottery.Medium" + 22 : "Pottery.Large" + 23 : "Pottery.Huge" + 24 : "Glass.Window" + ] + + health(integer) : "Strength" : 1 : "Number of points of damage to take before breaking. 0 means don't break." + material(choices) :"Material Type" : 0 : "Set to the material type of the brush. Used to decide what sounds to make when damaged, and what gibs to produce when broken." = + [ + 0: "Glass" + 1: "Wood" + 2: "Metal" + 3: "Flesh" + 4: "CinderBlock" + 5: "Ceiling Tile" + 6: "Computer" + 7: "Unbreakable Glass" + 8: "Rocks" + ] + explosion(choices) : "Gibs Direction" : 0 : "Used to decide which direction to throw gibs when broken." = + [ + 0: "Random" + 1: "Relative to Attack" + 2: "Use Precise Gib Dir" + ] + + gibdir(angle) : "Precise Gib Direction" : "0 0 0" : "Specifies the direction to throw gibs when this breakable breaks. Be sure to select Use Precise Gib Dir in the Gibs Direction field!" + + nodamageforces(choices) : "Damaging it Doesn't Push It" : 0 : "Used to determine whether or not damage should cause the brush to move." = + [ + 0: "No" + 1: "Yes" + ] + + // Inputs + input EnableDamageForces(void) : "Damaging the entity applies physics forces to it." + input DisableDamageForces(void) : "Damaging the entity does *not* apply physics forces to it." + + gibmodel(string) : "Gib Model" : "" : "Used by HL1Port to specify a custom gib model to break into, overriding the 'Material Type'." + spawnobject(choices) : "Spawn On Break" : 0 : "When broken, an entity of the selected type will be created." = + [ + 1: "item_battery" + 2: "item_healthkit" + 3: "item_ammo_pistol" + 4: "item_ammo_pistol_large" + 5: "item_ammo_smg1" + 6: "item_ammo_smg1_large" + 7: "item_ammo_ar2" + 8: "item_ammo_ar2_large" + 9: "item_box_buckshot" + 10: "item_flare_round" + 11: "item_box_flare_rounds" + 12: "item_ml_grenade" + 13: "item_smg1_grenade" + 14: "item_box_sniper_rounds" + 15: "unused1" + 16: "weapon_stunstick" + 17: "weapon_ar1" + 18: "weapon_ar2" + 19: "unused2" + 20: "weapon_ml" + 21: "weapon_smg1" + 22: "weapon_smg2" + 23: "weapon_slam" + 24: "weapon_shotgun" + 25: "weapon_molotov" + 26: "item_dynamic_resupply" + ] + explodemagnitude(integer) : "Explode Magnitude" : 0 : "If non-zero, when this entity breaks it will create an explosion that causes the specified amount of damage." + pressuredelay(float) : "Pressure Delay" : 0 : "Delay, in seconds, after 'broken' by pressure before breaking apart (allows for sound to play before breaking apart)." +] + +@BaseClass base(Breakable) = BreakableProp +[ + spawnflags(flags) = + [ + 16 : "Break on Touch" : 0 + 32 : "Break on Pressure" : 0 + ] + pressuredelay(float) : "Pressure Delay" : 0 : "Delay, in seconds, after 'broken' by pressure before breaking apart (allows for sound to play before breaking apart)." +] + +@BaseClass base(Targetname, Angles, RenderFields, DamageFilter, ResponseContext, Shadow) color(0 200 200) = BaseNPC +[ + target(target_destination) : "Target Path Corner" : : "If set, the name of a path corner entity that this NPC will walk to, after spawning." + squadname(String) : "Squad Name" : : "NPCs that are in the same squad (i.e. have matching squad names) will share information about enemies, and will take turns attacking and covering each other." + hintgroup(String) : "Hint Group" : "" : "Hint groups are used by NPCs to restrict their hint-node searching to a subset of the map's hint nodes. Only hint nodes with matching hint group names will be considered by this NPC." + hintlimiting(choices) : "Hint Limit Nav" : 0 : "Limits NPC to using specified hint group for navigation requests, but does not limit local navigation." = + [ + 0 : "No" + 1 : "Yes" + ] + + spawnflags(Flags) = + [ + 1 : "Wait Till Seen" : 0 + 2 : "Gag (No IDLE sounds until angry)" : 0 + 4 : "Fall to ground (unchecked means *teleport* to ground)" : 1 + 8 : "Drop Healthkit" : 0 + 16 : "Efficient - Don't acquire enemies or avoid obstacles" : 0 + 128: "Wait For Script" : 0 + 256: "Long Visibility/Shoot" : 0 + 512: "Fade Corpse" : 0 + 1024: "Think outside PVS" : 0 + 2048: "Template NPC (used by npc_maker, will not spawn)" : 0 + 4096: "Do Alternate collision for this NPC (player avoidance)" : 0 + 8192: "Don't drop weapons" : 0 + 16384 : "Ignore player push (dont give way to player)" : 0 + ] + + //initialidle(string) : "Initial Idle Activity" :: "Activity the NPC should use to idle until becomes alert" + sleepstate(choices) : "Sleep State" : 0 : "Holds the NPC in stasis until specified condition. See also 'Wake Radius' and 'Wake Squad'." = + [ + 0 : "None" + 1 : "Waiting for threat" + 2 : "Waiting for PVS" + 3 : "Waiting for input, ignore PVS" + 4 : "Auto PVS" + 5 : "Auto PVS after PVS" + ] + + wakeradius(float) : "Wake Radius" : 0 : "Auto-wake if player within this distance" + wakesquad(choices) : "Wake Squad" : 0 : "Wake all of the NPCs squadmates if the NPC is woken" = + [ + 0 : "No" + 1 : "Yes" + ] + + physdamagescale(float) : "Physics Impact Damage Scale" : "1.0" : "Scales damage energy when this character is hit by a physics object. With a value of 0 the NPC will take no damage from physics." + + // Outputs + output OnDamaged(void) : "Fired when this NPC takes damage." + output OnDeath(void) : "Fired when this NPC is killed." + output OnHalfHealth(void) : "Fired when this NPC reaches half of its maximum health." + output OnHearWorld(void) : "Fired when this NPC hears a sound (other than combat or the player)." + output OnHearPlayer(void) : "Fired when this NPC hears the player." + output OnHearCombat(void) : "Fired when this NPC hears combat sounds." + output OnFoundEnemy(string) : "Fired when this NPC establishes line of sight to its enemy (outputs entity)." + output OnLostEnemyLOS(void) : "Fired when this NPC loses line of sight to its enemy." + output OnLostEnemy(void) : "Fired when this NPC loses its enemy. Usually due to the enemy being killed/removed, or because this NPC has selected a newer, more dangerous enemy." + output OnFoundPlayer(string) : "Fired when this NPC establishes line of sight to its enemy, and that enemy is a player (outputs player entity)." + output OnLostPlayerLOS(void) : "Fired when this NPC loses line of sight to its enemy, and that enemy is a player." + output OnLostPlayer(void) : "Fired when this NPC loses its enemy, and that enemy was a player. Usually due to the enemy being killed/removed, or because this NPC has selected a newer, more dangerous enemy." + output OnDamagedByPlayer(void) : "Fired when this NPC is hurt by a player." + output OnDamagedByPlayerSquad(void) : "Fired when this NPC is hurt by a player OR by one of the player's squadmates." + output OnDenyCommanderUse(void) : "Fired when this NPC has refused to join the player's squad." + output OnSleep(void) : "Fired when this NPC enters a sleep state." + output OnWake(void) : "Fired when this NPC comes out of a sleep state." + output OnForcedInteractionAborted(void) : "Fired when the NPC aborts a forced interaction for some reason (target NPC died, couldn't be pathed to, etc)" + output OnForcedInteractionFinished(void) : "NPCs in actbusies can no longer perform dynamic interactions." + + // Inputs + input SetRelationship(string) : "Changes this entity's relationship with another entity or class. Format: " + input SetHealth(integer) : "Set this NPC's health." + input SetBodyGroup(integer) : "HACK: Sets this NPC's body group (from 0 - n). You'd better know what you are doing!" + input physdamagescale(float) : "Sets the value that scales damage energy when this character is hit by a physics object. NOTE: 0 means this feature is disabled for backwards compatibility." + input Ignite(void) : "Ignite, burst into flames" + input Break(void) : "Break, smash into pieces" + input StartScripting(void) : "Enter scripting state. In this state, NPCs ignore a variety of stimulus that would make them break out of their scripts: They ignore danger sounds, ignore +USE, don't idle speak or respond to other NPC's idle speech, and so on." + input StopScripting(void) : "Exit scripting state." + input Assault(string) : "Start an assault. Parameter passed in should be the name of the rally point." + input SetSquad(string) : "Set the name of this NPC's squad. It will be removed from any existing squad automatically. Leaving the parameter blank will remove the NPC from any existing squad." + input Wake(void) : "Wakes up the NPC if it is sleeping." + input ForgetEntity(string) : "Clears out the NPC's knowledge of a named entity." + input GagEnable(void) : "Turn on the NPC Gag flag. NPC won't speak outside of choreographed scenes." + input GagDisable(void) : "Turn off the NPC Gag flag." + input IgnoreDangerSounds(float) : "Ignore danger sounds for the specified number of seconds." + input HolsterWeapon(void) : "Force the NPC to holster their weapon. Ignored if the NPC is scripting, if the NPC's weapon is already holstered, or if the NPC doesn't use weapons." + input HolsterAndDestroyWeapon(void) : "Identical to HolsterWeapon, except the weapon is destroyed once it has been holstered and concealed." + input UnholsterWeapon(void) : "Force the NPC to draw their weapon. Ignored if the NPC is scripting, if the NPC's weapon is already drawn, or if the NPC doesn't use weapons." + input ForceInteractionWithNPC(string) : "Force the NPC to use a dynamic interaction with another NPC. Parameter format: " + input UpdateEnemyMemory(string) : "Update (or Create) this NPC's memory of an enemy and its location" +] + +@PointClass base(Targetname, Parentname, Angles) iconsprite("editor/info_target.vmt") = info_npc_spawn_destination : + "NPC Spawn Destination. (Consult npc_template_maker help for more info)" +[ + ReuseDelay(float) : "Reuse Delay" : 1 : "After an NPC is spawned at this destination, the delay before this destination is eligible for selection again." + RenameNPC(string) : "New NPC Name" : "" : "If an NPC spawns at this destination, change that NPC's targetname to this." + + // Outputs + output OnSpawnNPC(void) : "Fired when an NPC spawns at this destination." +] + +@BaseClass base(Targetname, Angles, EnableDisable) iconsprite("editor/npc_maker.vmt") color(0 0 255) = BaseNPCMaker +[ + StartDisabled(choices) : "Start Disabled" : 1 = + [ + 0 : "No" + 1 : "Yes" + ] + + spawnflags(Flags) = + [ + // Only in npc__maker, npc_template_maker uses flag from template NPC + 16 : "Fade Corpse" : 0 + 32 : "Infinite Children" : 0 + 64 : "Do Not Drop" : 0 + 128 : "Don't Spawn While Visible" : 0 + ] + + MaxNPCCount(integer) : "Num. of NPCs" : 1 : "Number of NPCs that will spawn before this spawner is exhausted." + SpawnFrequency(string) : "Frequency" : "5" : "How often (in seconds) a new NPC will be spawned. If set to -1, a new NPC will be made when the last NPC dies." + MaxLiveChildren(integer) : "Max Live NPCs" : 5 : "Maximum number of live children allowed at any one time (new ones will not be made until one dies). If set to -1, no limit is applied." + + // Outputs + output OnSpawnNPC(string) : "Fired when an NPC is spawned. The activator is the NPC, and the string is the name of the NPC." + output OnAllSpawned(void) : "Fired when the spawned is exhausted (all children have been spawned)." + output OnAllSpawnedDead(void) : "Fired when the spawner is exhausted (all children have been spawned) and all spawned children have died." + output OnAllLiveChildrenDead(void) : "Fired when all spawned children have died. This does not mean the spawned is exhausted, so a new child may be spawned any time after this (unless the maker is disabled)." + + // Inputs + input Spawn(void) : "Spawns an NPC." + input Toggle(void) : "Toggles the spawner enabled/disabled state." + input Enable(void) : "Enables the spawner." + input Disable(void) : "Disables the spawner." + input AddMaxChildren(integer) : "Adds to the number of NPCs that can spawn before the spawner is exhausted. If an exhausted spawner is given some children to spawn, it still wont begin spawning until it is re-enabled with the Enable input." + input SetMaxChildren(integer) : "Sets the number of NPCs that can spawn before the spawner is exhausted. If an exhausted spawner is given some children to spawn, it still won't begin spawning until it is re-enabled with the Enable input." + input SetMaxLiveChildren(integer) : "Sets the maximum number of NPCs that can be alive at any one time from this spawner." + input SetSpawnFrequency(float) : "Sets how often (in seconds) a new NPC will be spawned." +] + +@PointClass base(BaseNPCMaker) iconsprite("editor/npc_maker.vmt") = npc_template_maker : + "An entity that creates NPCs. The NPCs it creates are clones of a template NPC. NPCs are spawned around this maker's origin, or at specified destination points." +[ + spawnflags(Flags) = + [ + 256 : "Always use radius spawn" : 0 + 512 : "Don't preload template models" : 0 + ] + + TemplateName(target_destination) : "Name of template NPC" : "" : "Template NPC that this maker should be creating clones of." + + Radius(float) : "Radius" : 256 : "Radius around this maker within which NPCs are to be placed. Spawned NPCs will try and find empty space within this radius to spawn." + + DestinationGroup(target_destination) : "Name of Destination Group" : : "If you'd like spawned NPCs to be created at an info_npc_spawn_destination entity, enter the name of that entity here. If you have more than one destination entity by that name, the Destination Criteria will be used to select one from the group." + CriterionVisibility(Choices) : "Dest. Criterion: Visible to player?" : 2 : "Should the NPC try to spawn at a destination that the player can see? Only applicable if a Destination Group is being used." = + [ + 0 : "Yes" + 1 : "No" + 2 : "Don't Care" + ] + CriterionDistance(Choices) : "Dest. Criterion: Distance to player?" : 2 : "Should the NPC try to spawn nearest to or farthest from the player's current location? Only applicable if a Destination Group is being used." = + [ + 0 : "Nearest" + 1 : "Farthest" + 2 : "Don't Care" + ] + + MinSpawnDistance(integer) : "Minimum spawn distance from player" : 0 : "The spawn destination node distance to the player will have to be further or equal than this value." + + //Inputs + input SpawnNPCInRadius(void) : "Spawn an NPC somewhere within the maker's radius." + input SpawnNPCInLine(void) : "Spawn an NPC somewhere within a line behind the maker." + input ChangeDestinationGroup(string) : "Switch to a different set of Destination entities." + input SetMinimumSpawnDistance(integer) : "Set the minimum spawn distance from player to destination node." +] + +@BaseClass base( BaseNPC ) = BaseHelicopter +[ + InitialSpeed(string) : "Initial Speed" : "0" : "Sets the helicopter's desired speed that it should try to reach as soon as it's spawned." + target(target_destination) : "Target path_track" : : "(Optional) The name of a path_track entity that this NPC will fly to after spawning." + + // Inputs + input MoveTopSpeed(void) : "The helicopter will immediately move at top speed toward its current goal, or in its current orientation if it's on top of its goal." + input ChangePathCorner(target_destination) : "Tell the helicopter to move to a path corner on a new path." + input SelfDestruct(void) : "Self Destruct." + input Activate(void) : "Activate. Use to wake up a helicopter that spawned with the 'Await Input' spawnflag on." + input SetTrack(target_destination) : "Set a track for the helicopter to adhere to. The helicopter will do nothing if he's on the same path, and will move to the closest point on the specified track if he's on a different path." + input FlyToSpecificTrackViaPath(target_destination) : "The helicopter will first fly to the closest point on the path if he's on a different path. Then he'll fly along the path to the specified track point." + input StartPatrol(void) : "Start patrolling back and forth along the current track." + input StopPatrol(void) : "Stop patrolling back and forth along the track. This will cause the helicopter to come to rest at the track which he's currently flying toward." + input ChooseFarthestPathPoint(void) : "When tracking an enemy, choose the point on the path furthest from the enemy, but still in firing range." + input ChooseNearestPathPoint(void) : "When tracking an enemy, choose the point on the path nearest from the enemy." + input StartBreakableMovement(void) : "The helicopter is now allowed to disobey direct commands to go to particular points if he senses an enemy. He will move to the closest point (or farthest point, if ChooseFarthestPathPoint is used), on the path if he senses an enemy." + input StopBreakableMovement(void) : "The helicopter can not disobey direct commands. He will continue to fly along his patrol path or to his specified target even if he senses an enemy." + + spawnflags(Flags) = + [ + // AWAIT INPUT will make the helicopter spawn disabled, awaiting + // the "Activate" input to start acting. + 32 : "No Rotorwash" : 0 + 64 : "Await Input" : 0 + ] +] + +@BaseClass color(0 255 0) = PlayerClass [] + +@BaseClass color(180 10 180) = Light +[ + _light(color255) : "Brightness" : "255 255 255 200" + _lightHDR(color255) : "BrightnessHDR" : "-1 -1 -1 1" + style(Choices) : "Appearance" : 0 = + [ + 0 : "Normal" + 10: "Fluorescent flicker" + 2 : "Slow, strong pulse" + 11: "Slow pulse, noblack" + 5 : "Gentle pulse" + 1 : "Flicker A" + 6 : "Flicker B" + 3 : "Candle A" + 7 : "Candle B" + 8 : "Candle C" + 4 : "Fast strobe" + 9 : "Slow strobe" + ] + pattern(string) : "Custom Appearance" : "" : "Set a custom pattern of light brightness for this light. Pattern format is a string of characters, where 'a' is total darkness, 'z' fully bright. i.e. 'aaggnnttzz' would be a steppy fade in from dark to light." + _constant_attn(string) : "Constant" : "0" + _linear_attn(string) : "Linear" : "0" + _quadratic_attn(string) : "Quadratic" : "1" + _fifty_percent_distance(string) : "50 percent falloff distance" : "0": "Distance at which brightness should fall off to 50%. If set, overrides linear constant and quadratic paramaters." + _zero_percent_distance(string) : "0 percent falloff distance" : "0": "Distance at which brightness should fall off to negligible (1/256)%. Must set _fifty_percent_distance to use." + + // Inputs + input TurnOn(void) : "Turn the light on." + input TurnOff(void) : "The the light off." + input Toggle(void) : "Toggle the light's current state." + input SetPattern(string) : "Set a custom pattern of light brightness for this light. Pattern format is a string of characters, where 'a' is total darkness, 'z' fully bright. i.e. 'aaggnnttzz' would be a steppy fade in from dark to light." + input FadeToPattern(string) : "Fades from first value in old pattern, to first value in the new given pattern. Pattern format is a string of characters, where 'a' is total darkness, 'z' fully bright. i.e. 'aaggnnttzz' would be a steppy fade in from dark to light." +] + +@BaseClass = Node +[ + nodeid(integer) readonly : "Node ID" +] + +@BaseClass base(Node) = HintNode +[ + hinttype(choices) : "Hint" : 0 = + [ + 0 : "None" + + 2: "World: Window" + 12: "World: Act Busy Hint" + 13: "World: Visually Interesting" + 14: "World: Visually Interesting (Don't aim at)" + 15: "World: Inhibit Combine Mines within 15 feet" + 16: "World: Visually Interesting (Stealth mode)" + + 100: "Crouch Cover Medium" + 101: "Crouch Cover Low" + 102: "Waste Scanner Spawn" + 103: "Entrance / Exit Pinch" +// 104: "Guard Point" + 105: "Enemy Disadvantage Point" + 106: "Health Kit" + + 400: "Antlion: Burrow Point" + 401: "Antlion: Thumper Flee Point" + + 450: "Headcrab: Burrow Point" + 451: "Headcrab: Exit Pod Point" + + 500: "Roller: Patrol Point" + 501: "Roller: Cleanup Spot" + + 700: "Crow: Fly to point" + 701: "Crow: Perch point" + + 900: "Follower: Wait point" + 901: "Override jump permission" + 902: "Player squad transition point" + 903: "NPC exit point" + 904: "Strider node" + + 950: "Player Ally: Push away destination" + + 1000: "HL1 World: Machinery" + 1001: "HL1 World: Blinking Light" + 1002: "HL1 World: Human Blood" + 1003: "HL1 World: Alien Blood" + +// 1100: "CS Hostage: Escape Point" + ] + + hintactivity(string) : "Hint Activity" : "" : "Activity associated with this hint node. Various parts of the NPC AI play this activity at times. i.e. Actbusy nodes will play this activity when an NPC acts busy on the node." + + nodeFOV(choices) : "Node FOV" : 180 : "Imagine this node requires that an NPC be in the node's field of view in order to use this hint." = + [ + 45 : "45 Degrees" + 90 : "90 Degrees" + 180 : "180 Degrees" + 360 : "360 Degrees" + ] + + // Does not inherit from EnableDisable, as node itself will + // use that. This is enabling/disabling of the hint only + StartHintDisabled(choices) : "Start Hint Disabled" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + Group(string) : "Hint Group" : "" : "If specified, gives the hint a specific group name. Useful for hint nodes that need to be logically grouped together. NPCs may also refuse to use hint nodes that don't match their hint group." + + TargetNode(node_dest) : "Target node" : -1 : "The node ID of an associated target node, if any." + + IgnoreFacing(choices) : "Ignore Facing" : 2 : "Don't pay attention to the facing of the node. May not apply to a given hint type." = + [ + 0 : "No" + 1 : "Yes" + 2 : "Default" + ] + + MinimumState(choices) : "Minimum State" : 1 : "Require an NPC have a minimum state to use the hint." = + [ + 1 : "Idle" + 2 : "Alert" + 3 : "Combat" + ] + + MaximumState(choices) : "Maximum State" : 3 : "Require an NPC have a maximum state to use the hint." = + [ + 1 : "Idle" + 2 : "Alert" + 3 : "Combat" + ] + + // Inputs + input EnableHint(void) : "Enable hint." + input DisableHint(void) : "Disable hint." +] + +@BaseClass base(Targetname, Parentname, Origin, EnableDisable, Global) = TriggerOnce +[ + spawnflags(flags) = + [ + 1: "Clients" : 1 + 2: "NPCs" : 0 + 4: "Pushables": 0 + 8: "Physics Objects" : 0 + 16: "Only player ally NPCs" : 0 + 32: "Only clients in vehicles" : 0 + 64: "Everything" : 0 + 512: "Only clients *not* in vehicles" : 0 + 1024: "Physics debris" : 0 + 8192: "FF Grenades" : 0 + 16384: "FF Buildables" : 0 + //32768: "FF info_ff_scripts" : 0 + ] + + filtername(filterclass) : "Filter Name" : : "Filter to use to see if activator triggers me. See filter_activator_name for more explanation." + + // Inputs + input Toggle(void) : "Toggles this trigger between enabled and disabled states." + + // Outputs + output OnStartTouch(void) : "Fired when an entity starts touching this trigger. The touching entity must pass this trigger's filters to cause this output to fire." +] + +@BaseClass base(Targetname, Parentname, Origin, EnableDisable, TriggerOnce) = Trigger +[ + output OnEndTouch(void) : "Fired when an entity stops touching this trigger. Only entities that passed this trigger's filters will cause this output to fire." + output OnEndTouchAll(void) : "Fires when an entity stops touching this trigger, and no other entities are touching it. Only entities that passed this trigger's filters are considered." +] + +@BaseClass = worldbase +[ + message(string) : "Map Description / Title" + skyname(string) : "SkyBox Texture Name" : "sky_day01_01" + chaptertitle(string) : "Chapter Title Message" : "" : "Chapter Title that appears onscreen when this level starts." + startdark(choices) : "Level Fade In" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + gametitle(choices) : "Display Game Title" : 0 : "Game Title that appears onscreen when this level starts." = + [ + 0 : "No" + 1 : "Yes" + ] + newunit(choices) : "New Level Unit" : 0 : "Used to clear out savegame data of previous levels to keep the savegame size as small as possible. Only set it to Yes if the player cannot return to any previous levels." = + [ + 0 : "No, keep current" + 1 : "Yes, clear previous levels" + ] + maxoccludeearea(float) : "Max occludee area" : "0" : "Prevents occlusion testing for entities that take up more than X% of the screen." + minoccluderarea(float) : "Min occluder area" : "0" : "Prevents this occluder from being used if it takes up less than X% of the screen." + maxpropscreenwidth(float) : "Start Fade Pixels" : -1 : "Number of pixels wide at which all props in the level start to fade (<0 = use fademaxdist). This number is ignored if the prop has a specific fade distance specified." + minpropscreenwidth(float) : "End Fade Pixels" : 0 : "Minimum number of pixels wide at which the prop is visible (0 = don't fade out). This number is ignored if the prop has a specific fade distance specified." + detailvbsp(string) : "Detail.vbsp file" : "detail.vbsp" : "Detail.vbsp file to use for emitting detail props (found in directory /modname)" + detailmaterial(string) : "Detail material file" : "detail/detailsprites" : "Material for detail sprites to use for drawing detail props" + coldworld(choices) : "World is cold" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] +] + + +//------------------------------------------------------------------------- +// +// World +// +//------------------------------------------------------------------------- + +@SolidClass base(Targetname, worldbase, ResponseContext) = worldspawn : + "This is the world entity. Each map can only contain one, and it's automatically created for you." +[ +] + +@PointClass base(Targetname) iconsprite("editor/ambient_generic.vmt") sphere() = ambient_generic : "Universal ambient sound. Use it to play and control a single sound." +[ + message(sound) : "Sound Name" : "" : "Name of the GameSound entry for the sound to play. Also supports direct .wav filenames." + health(integer) : "Volume" : 10 : "Sound volume, expressed as a range from 0 to 10, where 10 is the loudest." + preset(choices) :"Dynamic Presets" : 0 = // NEEDHELP + [ + 0: "None" + 1: "Huge Machine" + 2: "Big Machine" + 3: "Machine" + 4: "Slow Fade in" + 5: "Fade in" + 6: "Quick Fade in" + 7: "Slow Pulse" + 8: "Pulse" + 9: "Quick pulse" + 10: "Slow Oscillator" + 11: "Oscillator" + 12: "Quick Oscillator" + 13: "Grunge pitch" + 14: "Very low pitch" + 15: "Low pitch" + 16: "High pitch" + 17: "Very high pitch" + 18: "Screaming pitch" + 19: "Oscillate spinup/down" + 20: "Pulse spinup/down" + 21: "Random pitch" + 22: "Random pitch fast" + 23: "Incremental Spinup" + 24: "Alien" + 25: "Bizzare" + 26: "Planet X" + 27: "Haunted" + ] + volstart(integer) : "Start Volume" : 0 // NEEDHELP + fadeinsecs(integer) : "Fade in time in seconds (0-100)" : 0 // NEEDHELP + fadeoutsecs(integer) : "Fade out time in seconds (0-100)" : 0 // NEEDHELP + pitch(integer) : "Pitch" : 100 : "Sound pitch, expressed as a range from 1 to 255, where 100 is the sound's default pitch." + pitchstart(integer) : "Start Pitch" : 100 // NEEDHELP + spinup(integer) : "Spin up time (0-100)" : 0 // NEEDHELP + spindown(integer) : "Spin down time (0-100)" : 0 // NEEDHELP + lfotype(integer) : "LFO type 0)off 1)sqr 2)tri 3)rnd" : 0 // NEEDHELP + lforate(integer) : "LFO rate (0-1000)" : 0 // NEEDHELP + lfomodpitch(integer) : "LFO mod pitch (0-100)" : 0 // NEEDHELP + lfomodvol(integer) : "LFO mod vol (0-100)" : 0 // NEEDHELP + cspinup(integer) : "Incremental Spinup Count" : 0 // NEEDHELP + radius(string) : "Max Audible Distance" : "1250" : "Maximum distance at which this sound is audible." + spawnflags(flags) = + [ + 1: "Play everywhere" : 0 + 16:"Start Silent": 1 + 32:"Is NOT Looped": 1 + ] + SourceEntityName(target_destination) : "SourceEntityName" : : "If an entity is specified, sound will come from this named entity instead of the location of ambient_generic." + + // Inputs + input Pitch(integer) : "Sets the sound pitch, expressed as a range from 1 to 255, where 100 is the sound's default pitch." + input PlaySound(void) : "Starts the sound." + input StopSound(void) : "Stops the sound if it is playing." + input ToggleSound(void) : "Toggles the sound between playing and stopping." + input Volume(integer) : "Sets the sound volume, expressed as a range from 0 to 10, where 10 is the loudest." + input FadeIn(integer) : "Fades the sound up to full volume over a specified number of seconds, with a range from 0 to 100 seconds." + input FadeOut(integer) : "Fades the sound to silence over a specified number of seconds, with a range from 0 to 100 seconds." +] + +@SolidClass base(Targetname) = func_lod : + "Brush-built model that fades out over a specified distance. Useful for creating world detail that doesn't need to be drawn far away, for performance reasons." +[ + DisappearDist(integer) : "Disappear Distance" : 2000 : "Distance at which these brushes should fade out." + Solid(choices) : "Solid" : 0 : "Set whether or not these brushes should collide with other entities." = + [ + 0: "Solid" + 1: "Nonsolid" + ] +] + +@PointClass base(Targetname) = env_zoom : + "An entity that can be used to control the player's FOV. Useful for scenes where the player's view is being controlled, or player-usable binoculars/telescopes, etc." +[ + Rate(float) : "Seconds to reach target" : "1.0" : "Amount of time it should take to reach the specified FOV." + FOV(integer) : "Target FOV" : 75 : "FOV that this entity should set the player's FOV to when active." + + // Inputs + input Zoom(void) : "Start controlling the player's FOV." + input UnZoom(void) : "Stop controlling the player's FOV." + + spawnflags(flags) = + [ + 1: "Allow Suit Zoom" : 0 + ] +] + +@PointClass base(Targetname) = env_screenoverlay: + "An entity that can display and control a set of screen overlays, to be displayed over the player's view. Useful for view effects like drunkenness, or teleporter afterimages, etc." +[ + OverlayName1(string) : "Overlay Name 1" : "" : "Name of the first overlay material to display." + OverlayTime1(float) : "Overlay Duration 1" : "1.0" : "Amount of time that the first overlay should be displayed for, after which it will begin showing the second overlay." + OverlayName2(string) : "Overlay Name 2" : "" : "Name of the second overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime2(float) : "Overlay Duration 2" : "1.0" : "Amount of time that the second overlay should be displayed for, after which it will begin showing the third overlay." + OverlayName3(string) : "Overlay Name 3" : "" : "Name of the third overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime3(float) : "Overlay Duration 3" : "1.0" : "Amount of time that the third overlay should be displayed for, after which it will begin showing the fourth overlay." + OverlayName4(string) : "Overlay Name 4" : "" : "Name of the fourth overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime4(float) : "Overlay Duration 4" : "1.0" : "Amount of time that the fourth overlay should be displayed for, after which it will begin showing the fifth overlay." + OverlayName5(string) : "Overlay Name 5" : "" : "Name of the fifth overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime5(float) : "Overlay Duration 5" : "1.0" : "Amount of time that the fifth overlay should be displayed for, after which it will begin showing the sixth overlay." + OverlayName6(string) : "Overlay Name 6" : "" : "Name of the sixth overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime6(float) : "Overlay Duration 6" : "1.0" : "Amount of time that the sixth overlay should be displayed for, after which it will begin showing the seventh overlay." + OverlayName7(string) : "Overlay Name 7" : "" : "Name of the seventh overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime7(float) : "Overlay Duration 7" : "1.0" : "Amount of time that the seventh overlay should be displayed for, after which it will begin showing the eighth overlay." + OverlayName8(string) : "Overlay Name 8" : "" : "Name of the eighth overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime8(float) : "Overlay Duration 8" : "1.0" : "Amount of time that the eighth overlay should be displayed for, after which it will begin showing the ninth overlay." + OverlayName9(string) : "Overlay Name 9" : "" : "Name of the ninth overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime9(float) : "Overlay Duration 9" : "1.0" : "Amount of time that the ninth overlay should be displayed for, after which it will begin showing the tenth overlay." + OverlayName10(string) : "Overlay Name 10" : "" : "Name of the tenth overlay material to display. If left blank, overlay displaying will finish, and this entity will consider itself done." + OverlayTime10(float) : "Overlay Duration 10" : "1.0" : "Amount of time that the tenth overlay should be displayed for, after which this entity will stop displaying overlays." + + // Inputs + input StartOverlays(void) : "Start displaying the first overlay." + input StopOverlays(void) : "Stop displaying any overlays." + input SwitchOverlay(float) : "Switch to displaying a specific overlay. Pass in the desired overlay number in the parameter." +] + +@PointClass base(Targetname) = env_screeneffect : + "Allows screenspace effects to be played on the player's view." +[ + type(choices) : "Effect Type" : 0 : "Which effect to use." = + [ + 0 : "Advisor Stun" + 1 : "Intro Blur" + ] + + // Inputs + input StartEffect(float) : "Start the effect with the duration in seconds as the passed parameter." + input StopEffect(float) : "Stop the effect." +] + +@PointClass base(Targetname) = env_texturetoggle : + "An entity that allows you to change the textures on other brush-built entities." +[ + target(target_destination) : "Target Brush(es)." + + // Inputs + input IncrementTextureIndex(void) : "Increments target brush's current texture frame by one." + input SetTextureIndex(integer) : "Sets target brush's texture frame to the specified index." +] + +@PointClass base(Targetname, Angles) = env_splash : + "An entity that creates a splash effect at its origin. If the 'find water surface' spawnflag is set, it will instead trace down below itself to find the water surface on which to create splashes." +[ + scale(float) : "Scale of the splash" : "8.0" + + // Inputs + input Splash(void) : "Create a splash effect." + + spawnflags(flags) = + [ + 1: "Automatically find water surface (place entity above water)" : 0 + 2: "Diminish with depth (diminished completely in 10 feet of water)" : 1 + ] +] + +@PointClass base(Parentname) color(180 10 180) = env_particlelight : + "An entity that can be used to light the smoke particles emitted by env_smokestack entities. Does not light any other particle types." +[ + Color(color255) : "Color" : "255 0 0" : "Color emitted by this light." + Intensity(integer) : "Intensity" : 5000 + + directional(choices) : "Directional" : 0 : "If this is specified, then this light will use the bump map on the particles. Each particle system can have one ambient and one directional light." = + [ + 0 : "No" + 1 : "Yes" + ] + + PSName(string) : "Particle System Entity" : "" : "Set this to the name of the env_smokestack that you want this light to affect." +] + +@PointClass base(Angles) color(255 0 0) = env_sun : + "An entity to control & draw a sun effect in the sky." +[ + target(target_destination) : "Viewer entity" : : "Name of an entity used to determine where the sun is in the skybox. The sun should be lined up on a line from this entity to the env_sun entity." + + use_angles(choices) : "UseAngles" : 0 : "The old way to orient env_sun is to point it at a target. The new way is to specify the angles. If you use the new way, set this property to YES." = + [ + 0 : "No" + 1 : "Yes" + ] + + pitch(integer) : "Pitch" : 0 + + rendercolor(color255) : "Sun Color (R G B)" : "100 80 80" + overlaycolor(color255) : "Overlay Color (R G B)" : "0 0 0" : "A value of 0 0 0 will act the old way." + + size(integer) : "Size" : 16 + overlaysize(integer) : "Overlay Size" : -1 : "A value of -1 means the overlay will act the old way." + + material(sprite) : "Material Name" : "sprites/light_glow02_add_noz" : "Material of the inner glow." + overlaymaterial(sprite) : "Overlay Material Name" : "sprites/light_glow02_add_noz" : "Material of the overlay glow." + + HDRColorScale(float) : "HDR color scale." : "1.0" : "float value to multiply sprite color by when running in HDR mode." + + // Inputs + input TurnOn(void) : "Enable sun rendering." + input TurnOff(void) : "Disable sun rendering." + input SetColor(color255) : "Change the sun's color. Format: " +] + +@PointClass base(Targetname) = game_ragdoll_manager : + "An entity to control the number of ragdolls in the world, for performance reasons." +[ + MaxRagdollCount(integer) : "Max Ragdoll Count" : -1 : "Sets the max number of ragdolls that can be in the world at a time (if they are flagged to fade). Set to -1 if you want to use the default value (g_ragdoll_maxcount)." + + SaveImportant(choices) : "Save Important Ragdolls" : 0 : "Should the ragdoll manager make sure ally ragdolls aren't deleted?" = + [ + 0 : "No" + 1 : "Yes" + ] + + + // Inputs + input SetMaxRagdollCount(integer) : "Set the Max Ragdoll Count." +] + +@PointClass base(Targetname) = game_gib_manager : "An entity to control the number of gibs in the world, for performance reasons." +[ + maxpieces(integer) : "Max Gib Count" : -1 : "Sets the max number of gib that can be spawned at a time. Set to -1 if you want to use the default value (func_break_max_pieces)." + input InputSetMaxPieces(integer) : "Set the Max gibs Count." +] + +@PointClass base(Parentname, Targetname, Angles) color(255 128 0) = env_lightglow : + "An entity that puts an additive glow in the world, mostly used over light sources." +[ + rendercolor(color255) : "Color (R G B)" : "255 255 255" + VerticalGlowSize(integer) : "Vertical Size" : 30 + HorizontalGlowSize(integer) : "Horizontal Size" : 30 + MinDist(integer) : "Minimum Distance" : 500 : "The distance at which this effect will be fully translucent." + MaxDist(integer) : "Maximum Distance" : 2000 : "The distance at which this effect will be at full intensity." + OuterMaxDist(integer) : "Outer Maximum Distance" : 0 : "If larger than the maximum distance, this is the length at which the glow will fade completely out, between the span of the maximum distance and this length." + GlowProxySize(float) : "Glow Proxy Geometry Size" : "2.0" : "Size of the glow to be rendered for visibility testing. Must be larger than the distance from the sprite center to empty space. So if this glow is inside geometry (like a light bulb), set this value to be bigger than the bulb's radius. Any time a sphere of this radius would be visible (poking through any nearby geometry), the glow will be rendered." + HDRColorScale(float) : "HDR color scale." : "1.0" : "float value to multiply sprite color by when running in HDR mode." + + // Inputs + input Color(color255) : "Change the render color of the glow. Format: " + + spawnflags(flags) = + [ + 1: "Visible only from front" : 0 + ] +] + +@PointClass base(Parentname, Angles) color(255 255 255) = env_smokestack : + "An entity that spits out a constant stream of smoke. See particlezoo.vmf for sample usage. You can place up to two env_particlelight entities near the smoke stack to add ambient light to its particles." +[ + targetname(target_source) : "Name" : : "The name that other entities refer to this entity by." + + InitialState(choices) : "Initial State" : 0 = + [ + 0 : "Off" + 1 : "On" + ] + + BaseSpread(integer) : "Spread at the base" : 20 : "Amount of random spread in the origins of the smoke particles when they're spawned." + SpreadSpeed(integer) : "Spread Speed" : 15 : "Amount of random spread in the velocity of the smoke particles after they're spawned." + Speed(integer) : "Speed" : 30 : "The speed at which the smoke particles move after they're spawned." + StartSize(integer) : "Particle start size" : 20 : "Size of the smoke particles when they're first emitted." + EndSize(integer) : "Particle end size" : 30 : "Size of the smoke particles at the point they fade out completely." + Rate(integer) : "Emission rate" : 20 : "Rate at which to emit smoke particles (i.e. particles to emit per second)." + JetLength(integer) : "Length of smoke trail" : 180 : "Length of the smokestack. Lifetime of the smoke particles is derived from this & particle speed." + WindAngle(integer) : "Wind X/Y Angle" : 0 : "This specifies the wind direction. It is an angle in the XY plane. WindSpeed specifies the strength of the wind." + WindSpeed(integer) : "Wind Speed" : 0 : "The strength of the wind." + SmokeMaterial(string) : "Particle material" : "particle/SmokeStack.vmt" : "Material of the smoke particles emitted by this stack." + twist(integer) : "Twist" : 0 : "The amount, in degrees per second, that the smoke particles twist around the origin." + roll(float) : "Roll Speed": 0 : "Amount of roll in degrees per second." + + rendercolor(color255) : "Base Color (R G B)" : "255 255 255" + + renderamt(integer) : "Translucency" : 255 + + // Inputs + input TurnOn(void) : "Turn on the smokestack." + input TurnOff(void) : "Turn off the smokestack." + input Toggle(void) : "Toggles the smokestack between on and off state." + input JetLength(integer): "Set the length of the smoke trail." + input Rate(integer) : "Set the rate at which to emit smoke particles (particles per second)." + input Speed(integer) : "Set the speed at which the smoke particles move after they're spawned." + input SpreadSpeed(integer) : "Set the amount of random spread in the velocity of the smoke particles after they're spawned." +] + +@PointClass base(Targetname) iconsprite("editor/env_fade") = env_fade : + "An entity that controls screen fades." +[ + spawnflags(flags) = + [ + 1: "Fade From" : 0 + 2: "Modulate" : 0 + 8: "Stay Out" : 0 + ] + duration(string) : "Duration (seconds)" : "2" : "The time that it will take to fade the screen in or out." + holdtime(string) : "Hold Fade (seconds)" : "0" : "The time to hold the faded in/out state." + renderamt(integer) : "Fade Alpha" : 255 : "Alpha of the fade, where 0 = fully transparent and 255 = fully opaque." + rendercolor(color255) : "Fade Color (R G B)" : "0 0 0" + + // Inputs + input Fade(void) : "Start the screen fade." + + // Outputs + output OnBeginFade(void) : "Fired when the fade has begun." +] + +@PointClass base(Targetname) = env_player_surface_trigger : + "An entity that monitors the material of the surface the player is standing on, and fires outputs whenever it changes to/from a specific material." +[ + gamematerial(choices) : "Game Material to Watch" : "0" : "The material to watch. When the player stands on/off this material, this entity's outputs will be fired." = + [ + 0 : "None (player's in the air)" + 67 : "Concrete" + 77 : "Metal" + 68 : "Dirt" + 86 : "Vent" + 71 : "Grate" + 84 : "Tile" + 83 : "Slosh" + 87 : "Wood" + 80 : "Computer" + 89 : "Glass" + 70 : "Flesh" + 73 : "Clip" + 79 : "Foliage" + 78 : "Sand" + ] + + // Inputs + input Enable(void) : "Start watching the player's surface." + input Disable(void) : "Stop watching the player's surface." + + // Outputs + output OnSurfaceChangedToTarget(void) : "Fired when the player moves onto the specified game material." + output OnSurfaceChangedFromTarget(void) : "Fired when the player moves off the specified game material." +] + +@PointClass base(Targetname) iconsprite("editor/env_tonemap_controller.vmt") = env_tonemap_controller : + "An entity that controls the HDR tonemapping for the player. Think of it as a method of controlling the exposure of the player's eyes." +[ + // Inputs + input SetTonemapScale(void) : "Set the player's tonemap scale. It should be a value between 0 and 2, where 0 is the eyes fully closed, 1 is use the unchanged autoexposure (default), and 2 is the eye fully wide open." + input BlendTonemapScale(string) : "Blend from the player's current tonemap scale to a new one. The parameter syntax is as follows: . For example: '0.5 10' would blend from the current tonemap scale to 0.5 over a period of 10 seconds. Tonemap scale is a value between 0 and 2, where 0 is the eyes fully closed, 1 is use the unchanged autoexposure (default), and 2 is the eye fully wide open." + input UseDefaultAutoExposure(void) : "Revert to using the default tonemap auto exposure." + input SetAutoExposureMin(float) : "Set a custom tonemap auto exposure minimum." + input SetAutoExposureMax(float) : "Set a custom tonemap auto exposure maximum." + input SetBloomScale(float) : "Set a custom bloom scale." + input SetTonemapRate(float) : "Set the rate for autoexposure adjustment." +] + +@PointClass base(Targetname, Parentname) sweptplayerhull() = func_useableladder : + "A Half-Life 2 ladder. Handles player auto mount/unmount, as well as +use to get onto the ladder. \n\n" + + "See also 'info_ladder_dismount', used to specify ladder auto-dismount points.\n\n" + + "Note: This entity is non-functional in Counter-Strike: Source. Use func_ladder instead." +[ + spawnflags(flags) = + [ + 1: "Fake Ladder" : 0 + ] + + point0(vector) : "Start" : : "Ladder end point." + point1(vector) : "End" : : "Ladder end point." + + StartDisabled(choices) : "Start Disabled" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Enable(void) : "Enable this ladder." + input Disable(void) : "Disable this ladder." + + output OnPlayerGotOnLadder(void) : "Fired whenever a player gets on this ladder." + output OnPlayerGotOffLadder(void) : "Fired whenever a player gets off this ladder." +] + +@PointClass base(Targetname, Parentname, Angles) size( -16 -16 0, 16 16 72 ) color(127 127 127) = func_ladderendpoint : + "An entity used to specify the endpoints of a ladder. This entity is functional, but has been replaced by the " + + "easier-to-use func_useableladder entity. Left in only for backwards-compatibility!\n\n" + + "To be valid, a full sized player hull traced between the start and end points must not be obstructed at level " + + "activation time. The angle determines in which direction the player leaves the ladder if the player presses the " + + "+jump button.\n\n" + + "Note: This entity is non-functional in Counter-Strike: Source. In CS:S, use func_ladder instead." +[ + target(target_destination) : "Other" : : "A ladder goes between any two func_ladderendpoints pointing at each other." + // TODO: Allow individual ladder end points to be enabled, disabled + // TODO: Allow ladder to specify movement speed or a speed scale while on ladder + // TODO: Allow specifying radius within with you must be in order to +use to get on the ladder +] + +@PointClass base(Parentname) size( -16 -16 0, 16 16 4 ) color(255 128 255)= info_ladder_dismount : + "An entity to handle endpoints for multiple ladders that are too close to each other." +[ + target(target_destination) : "LadderName" : : "If multiple ladders are near multiple endpoints, use this to stop them from interfering with each other." +] + +@SolidClass base(Targetname) color(0 128 255) = func_areaportalwindow : + "An entity that can be used to optimize the visibility in a map. If you seal off an area with them, when the viewer moves the specified distance away from them, they will go opaque and the parts inside the area will not be drawn. The 'target' brush model should enclose the func_areaportal window so no parts of it are culled by the window. If you use the optional foreground brush model, then it should enclose the 'target' brush model." +[ + target(target_destination) : "Rendered Window" : : "The name of a brush model to render as the window." + FadeStartDist(integer) : "Fade Start Distance" : 128 : "When the viewer is closer than this distance, the alpha is set to 'TranslucencyLimit'." + FadeDist(integer) : "Fade End Distance" : 512 : "When the viewer is at this distance, the portal becomes solid and closes off." + TranslucencyLimit(string) : "Translucency limit" : "0.2" : "This value limits the translucency of the bmodel and prevents it from becoming invisible when the viewer is right on top of it." + BackgroundBModel(string) : "Foreground bmodel" : "" : "(Optional) brush model that is drawn after the fading brush model. This model should have alpha in its textures so you can see through it." + PortalVersion(integer) readonly : "Portal Version" : 1 : "(Don't change). Differentiates between shipping HL2 maps and maps using new engine features." +] + +@SolidClass base(Targetname, RenderFields, Global, Shadow) = func_wall : + "Legacy support. Use func_brush instead." +[ + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." +] + +@SolidClass base(Targetname) = func_clip_vphysics : + "A brush entity that's considered solid to vphysics." +[ + filtername(filterclass) : "Filter Name" : : "Filter to use to see if activator collides with me. See filter_activator_name for more explanation. Allow means 'Allow to Block' for this entity." +] + +@SolidClass base(Targetname, Parentname, Origin, RenderFields, Global, Inputfilter, EnableDisable, Shadow) = func_brush : + "An brush built entity with various features." +[ + spawnflags(flags) = + [ + 2: "Ignore player +USE" : 0 + ] + + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + Solidity(choices) : "Solidity" : 0 : "Used to control the solidity/collision of these brushes." = + [ + 0 : "Toggle" + 1 : "Never Solid" + 2 : "Always Solid" + ] + excludednpc(string) : "NPC class excluded from collisions" : "" : "If an NPC classname is specified here, NPCs of that type won't collide with these brushes." + invert_exclusion(choices) : "Invert NPC class exclusion" : 0 : "If set, then the excluded NPC class will consider this brush solid, and all other NPC classes will consider it non-solid." = + [ + 0 : "No" + 1 : "Yes" + ] + + solidbsp(choices) : "Solid BSP" : 0 : "Set this if this brush is in heirarchy with a moving object of some kind, and the player can stand on this brush." = + [ + 0 : "No" + 1 : "Yes" + ] +] + +//------------------------------------------------------------------------- +// +// A Vgui screen in 3D +// +//------------------------------------------------------------------------- + +@BaseClass base(Targetname, Parentname, Angles) = vgui_screen_base +[ + panelname(string) : "Panel Name" + overlaymaterial(string) : "Overlay Material" : "" : "Name of a material to overlay over the top of the VGUI screen. NOTE: This material must write Z for the VGUI screen to work." + width(integer) : "Panel Width in World" : 32 : "Width of the panel in units." + height(integer) : "Panel Height in World" : 32 : "Height of the panel in units." + + // Inputs + input SetActive(void) : "Make the vgui screen visible." + input SetInactive(void) : "Make the vgui screen invisible." +] + +@PointClass base(vgui_screen_base) size(-4 -4 -4, 4 4 4) = vgui_screen : + "A VGUI screen. Useful for in-world monitors." +[ +] + +//------------------------------------------------------------------------- +// +// Cyclers +// +//------------------------------------------------------------------------- + +@PointClass base(Targetname, Parentname, Angles, RenderFxChoices, RenderFields) studio() = cycler : + "An entity used to display a model for testing purposes. Shooting it with cycle through the model's animations." +[ + spawnflags(flags) = + [ + 1: "Not Solid" : 0 + ] + model(studio) : "Model" + skin(integer) : "Skin" : 0 : "Some models have multiple versions of their textures, called skins. Set this to a number other than 0 to use that skin instead of the default." + + sequence(integer) : "Sequence" : 0 : "Default animation sequence for the model to be playing after spawning." + + // Inputs + input SetSequence(string) : "Sets the cycler's sequence." +] + +//------------------------------------------------------------------------- +// +// Environmental effects +// +//------------------------------------------------------------------------- + +@BaseClass base(Targetname, Parentname) = gibshooterbase +[ + angles(string) : "Gib Direction (Pitch Yaw Roll)" : "0 0 0" : "The direction the gibs will fly." + m_iGibs(integer) : "Number of Gibs" : 3 : "Total number of gibs to shoot each time it's activated." + delay(string) : "Delay between shots" : "0" : "Delay (in seconds) between shooting each gib. If 0, all gibs shoot at once." + gibangles(string) : "Gib Angles (Pitch Yaw Roll)" : "0 0 0" : "The orientation of the spawned gibs." + gibanglevelocity(string) : "Max angular velocity" : "0" : "How fast (degrees/sec) the gib pieces should spin. They will spin on x and y axis at between 10% and 100% of this speed." + m_flVelocity(integer) : "Gib Velocity" : 200 : "Speed of the fired gibs" + m_flVariance(string) : "Course Variance" : "0.15" : "How much variance in the direction gibs are fired." + m_flGibLife(string) : "Gib Life" : "4" : "Time in seconds for gibs to live +/- 5%" + lightingorigin(target_destination) : "Lighting Origin" : "" : "Select an info_lighting to specify a location to sample lighting from for all gibs spawned by this shooter, instead of their own origins." + + spawnflags(Flags) = + [ + 1 : "Repeatable" : 0 + ] + + // Inputs + input Shoot(void) : "Force the gibshooter to create and shoot a gib." +] + +@PointClass base(Targetname, Parentname, RenderFxChoices) size(-4 -4 -4, 4 4 4) line(255 255 255, targetname, LightningStart, targetname, LightningEnd) = env_beam : + "An entity that creates a visible beam between two points. The points can be attached to entities to make the beam move around." +[ + renderamt(integer) : "Brightness (1 - 255)" : 100 + rendercolor(color255) : "Beam Color (R G B)" : "255 255 255" + Radius(integer) : "Radius" : 256 : "If the 'Random Strike' spawnflag is set, this radius determines the area within which the endpoints will randomly strike." + life(string) : "Life (seconds 0 = infinite)" : "1" : "Amount of time before the beam dies. Setting to zero will make the beam stay forever." + BoltWidth(float) : "Width of beam" : 2 : "Pixel width of the beam." + NoiseAmplitude(float) : "Amount of noise (0-255)" : 0 : "The amount of noise in the beam. 0 is a perfectly straight beam." + texture(sprite) : "Sprite Name" : "sprites/laserbeam.spr" : "The material used to draw the beam." + TextureScroll(integer) : "Texture Scroll Rate (0-100)" : 35 : "Rate at which the beam texture should scroll along the beam." + framerate(integer) : "Frames per 10 seconds" : 0 : "Framerate at which the beam texture should animate, if it has multiple frames." + framestart(integer) : "Starting Frame" : 0 : "The frame to start the beam texture on." + StrikeTime(string) : "Strike again time (secs)" : "1" : "Refire time between random strikes of the beam. Only used if the 'Random Strike' spawnflag is set." + damage(string) : "Damage / second" : "0" : "How much damage this beam does per second to things it hits when it is continually on, or instantaneously if it strikes. For continuous damage, the value should be greater than 10 or it may not work." + LightningStart(target_destination) : "Start Entity" : "" : "Entity that the beam starts at." + LightningEnd(target_destination) : "Ending Entity" : "" : "Entity that the beam ends at." + decalname(string) : "Decal Name" : "Bigshot" : "Decal to be applied at the end of the beam" + HDRColorScale(float) : "HDR color scale." : "1.0" : "float value to multiply sprite color by when running in HDR mode." + + + spawnflags(flags) = + [ + 1 : "Start On" : 0 + 2 : "Toggle" : 0 + 4 : "Random Strike" : 0 + 8 : "Ring" : 0 + 16: "StartSparks" : 0 + 32: "EndSparks" : 0 + 64: "Decal End" : 0 + 128: "Shade Start" : 0 + 256: "Shade End" : 0 + 512: "Taper Out" : 0 + ] + + TouchType(choices) : "Touch Type (tripwire)" : 0 : "If you want the beam to fire an output when touched by entities, choose the entity type here." = + [ + 0 : "Not a tripwire" + 1 : "Player Only" + 2 : "NPC Only" + 3 : "Player or NPC" + 4 : "Player or NPC or Physprop" + ] + + filtername(filterclass) : "Filter Name" : : "Filter to use to see if activator triggers me. See filter_activator_name for more explanation." + + // Inputs + input TurnOn(void) : "Turns the beam on." + input TurnOff(void) : "Turns the beam off." + input Toggle(void) : "Toggles the beam between on and off." + input StrikeOnce(void) : "Causes the beam to strike once. It will stay on for its set Life and then turn off (it will never turn off if Life is set to zero)." + input Alpha(integer) : "Sets the beam's alpha (0 - 255)." + input Color(color255) : "Sets the beam's render color (R G B)." + input Amplitude(float) : "Set the amplitude of beam noise (0 - 255)." + input ScrollSpeed(float) : "Set the scroll speed in units per second (0 - 100)." + input Width(float) : "Set the width of the beam, in pixels." + + // Outputs + output OnTouchedByEntity(void) : "Fired when an entity touches the beam. Only fired if the entity passes the 'Touch Type' choice." +] + +@PointClass base(Targetname, Parentname) size(-4 -4 -4, 4 4 4) = env_beverage : + "HL1 Legacy: Beverage Dispenser." +[ + health(integer) : "Capacity" : 10 : "Number of cans in the dispenser." + beveragetype(choices) : "Beverage Type" : 0 = + [ + 0 : "Coca-Cola" + 1 : "Sprite" + 2 : "Diet Coke" + 3 : "Orange" + 4 : "Surge" + 5 : "Moxie" + 6 : "Random" + ] + + input Activate(void) : "Enable this dispenser." +] + +@SolidClass base(Targetname, Parentname, Angles) = env_embers : + "An entity used to create a volume in which to spawn fire embers." +[ + particletype(choices) : "Ember type" : 0 = + [ + 0 : "Normal" + 1 : "Smooth Fade" + 2 : "Pulled" + ] + + density(integer) : "Density (particles per second)" : 50 + lifetime(integer) : "Particle Lifetime (seconds)" : 4 + speed(integer) : "Particle Speed (units per second)" : 32 + rendercolor(color255) : "Ember Color (R G B)" : "255 255 255" + + spawnflags(Flags) = + [ + 1 : "Start On" : 0 + 2 : "Toggle" : 0 + ] +] + +@PointClass base(Targetname, Parentname) size(-16 -16 -16, 16 16 16) = env_funnel : + "HL1 Legacy: Large Portal Funnel" +[ + spawnflags(flags) = + [ + 1: "Reverse" : 0 + ] +] + +@PointClass base(Targetname, Parentname) size(-16 -16 -16, 16 16 16) color(255 0 0) = env_blood : + "An entity used to spawn blood effects." +[ + spraydir(angle) : "Spray Direction (Pitch Yaw Roll)" : "0 0 0" : "The general direction that the blood should spray and the direction to trace to apply the decal." + color(choices) : "Blood Color" : 0 = + [ + 0 : "Red (Human)" + 1 : "Yellow (Alien)" + ] + amount(string) : "Amount of blood (damage to simulate)" : "100" + spawnflags(flags) = + [ + 1: "Random Direction" : 0 + 2: "Blood Stream" : 0 + 4: "On Player" : 0 + 8: "Spray decals" : 0 + // dvs: support these flags + //16: "Cloud" : 0 + //32: "Drops" : 0 + //64: "Gore" : 0 + ] + + // Inputs + input EmitBlood(void) : "Triggers the blood effect." +] + +@SolidClass base(Targetname, Parentname) = env_bubbles : + "An entity used to create a volume in which to spawn bubbles." +[ + density(integer) : "Bubble density" : 2 + frequency(integer) : "Bubble frequency" : 2 + current(integer) : "Speed of Current" : 0 : "The speed of the water current in the volume, used to move the bubbles." + spawnflags(Flags) = + [ + 1 : "Start Off" : 0 + ] + + // Inputs + input Activate(void) : "Activates the bubbles." + input Deactivate(void) : "Deactivates the bubbles." + input Toggle(void) : "Toggles the bubbles on and off." + input SetDensity(integer) : "Sets the bubble density." + input SetFrequency(integer) : "Sets bubble emission rate in bubbles per second." + input SetCurrent(integer) : "Sets current speed in inches per second." +] + +@PointClass base(Targetname, Parentname) iconsprite("editor/env_explosion.vmt") = env_explosion : + "An entity that creates an explosion at its origin." +[ + iMagnitude(Integer) : "Magnitude" : 100 : "The amount of damage done by the explosion." + // If no radius override, magnitude will determine radius. + iRadiusOverride(Integer) : "Radius Override" : 0 : "If specified, the radius in which the explosion damages entities. If unspecified, the radius will be based on the magnitude." + fireballsprite(sprite) : "Fireball Sprite" : "sprites/zerogxplode.spr" + rendermode(choices) : "Render Mode" : 5 = + [ + 0: "Normal" + 4: "Solid" + 5: "Additive" + ] + spawnflags(flags) = + [ + 1: "No Damage" : 0 + 2: "Repeatable" : 0 + 4: "No Fireball" : 0 + 8: "No Smoke" : 0 + 16: "No Decal" : 0 + 32: "No Sparks" : 0 + 64: "No Sound" : 0 + 128: "Random Orientation" : 0 + 256: "No Fireball Smoke" : 0 + 512: "No particles" : 0 + 1024: "No DLights" : 0 + 2048: "Don't clamp Min" : 0 + 4096: "Don't clamp Max" : 0 + ] + + // Inputs + input Explode(void) : "Triggers the explosion." +] + +@PointClass base(Targetname, Parentname) color(200 50 0) size(-8 -8 -8, 8 8 8) = env_smoketrail : + "An entity that creates a smoke trail." +[ + opacity(float) : "Sprite Opacity" : "0.75" : "Opacity of the sprites (range from 0 - 1)." + spawnrate(float) : "Spawn Rate" : "20" : "Number of particles to emit each second." + lifetime(float) : "Particle Life Time" : "5.0" : "Number of seconds until each particle dies." + startcolor(color255) : "Start Color" : "192 192 192" : "Starting color of the emitted particles." + endcolor(color255) : "End Color" : "160 160 160" : "Ending color of the emitted particles." + emittime(float) : "Emitter Life Time" : "0" : "Number of seconds until the env_smoketrail stops emitting particles. 0 means never stop emitting particles." + minspeed(float) : "Minimum Random Speed" : "10" : "Minimum randomly-directed speed to use for emitted particles." + maxspeed(float) : "Maximum Random Speed" : "20" : "Maximum randomly-directed speed to use for emitted particles." + mindirectedspeed(float) : "Minimum Directed Speed" : "0" : "Minimum speed along the env_smoketrail's forward direction (x axis) to use for emitted particles." + maxdirectedspeed(float) : "Maximum Directed Speed" : "0" : "Maximum speed along the env_smoketrail's forward direction (x axis) to use for emitted particles." + startsize(float) : "Starting particle size" : "15" : "Starting particle size." + endsize(float) : "Ending particle size" : "50" : "Ending particle size." + spawnradius(float) : "Spawn radius" : "15" : "Distance from env_smoketrail at which particles are emitted." + + firesprite(sprite) : "Fire Sprite" : "sprites/firetrail.spr" + smokesprite(sprite) : "Smoke Puff" : "sprites/whitepuff.spr" +] + +@PointClass base(Targetname, Parentname) sphere() sphere(inner_radius) iconsprite("editor/env_physexplosion.vmt") = env_physexplosion : + "An entity that creates an explosion at its origin. If the no-damage spawnflag is set, the explosion won't be visible, but will apply force to any physics objects within its radius." +[ + magnitude(string) : "Magnitude" : "100" : "Amount of physics force applied by the explosion." + radius(string) : "Clamp Radius (0 = auto)" : "0" : "If specified, the radius in which the explosion damages entities. If unspecified, the radius will be based on the magnitude." + targetentityname(target_destination) : "Limit to Entity" : "" : "If specified, the explosion will only affect the matching entity." + + spawnflags(flags) = + [ + 1 : "No Damage - Only Force" : 1 + 2 : "Push players" : 0 + 4 : "Push radially - not as a sphere" : 0 + 8 : "Test LOS before pushing" : 0 + 16 : "Disorient player if pushed" : 0 + ] + + inner_radius(float) : "Inner radius" : "0" : "If not zero, the LOS is calculated from a point intersecting this sphere." + + // Inputs + input Explode(void) : "Trigger the explosion." + + // Outputs + output OnPushedPlayer(void) : "Fires when the player is pushed by the explosion." +] + +@PointClass base(Targetname, Parentname) line(255 255 255, targetname, directionentityname) iconsprite("editor/env_physexplosion.vmt") = env_physimpact : + "An entity that will cause a physics impact on another entity." +[ + angles(string) : "Pitch Yaw Roll (Y Z X)" : "0 0 0" : "Direction to project the impact." + magnitude(integer) : "Magnitude" : 100 : "Strength of the impact." + distance(integer) : "Distance" : 0 : "How far to project the impact (if 0 uses a default value)." + directionentityname(target_destination) : "Point to Entity" : "" : "If set, 'Distance' and Angle settings are ignored and the direction and distance to the target entity will be used." + + spawnflags(flags) = + [ + 1: "No fall-off" : 0 + 2: "Infinite Length" : 0 + 4: "Ignore Mass" : 0 + ] + + // Inputs + input Impact(void) : "Trigger the impact" +] + + +// This has been disabled until it can be reimplemented, destroyed, or renamed - jdw +//@PointClass base(Targetname, Parentname) size(-4 -4 -4, 4 4 4) = env_splash : +// "Can be used to create either a spash effect or a stream of falling or spurting liquid." + +// "Will create a splash decal on the collided surface the same color as the liquid" +//[ +// spawnrate(float) : "SpawnRate" : "10" : "How many particles some out" +// startcolor(color255) : "StartColor" : "100 100 100" : "Color of particles when the are emitted" +// endcolor(color255) : "EndColor" : "240 110 0" : "Color that particles approach" +// speed(float) : "Speed" : 3 : "Averate speed of an emitted particles" +// speedrange(float) : "SpeedRange" : 1 : "Speed range of an emitted particles" +// widthmin(float) : "WidthMin" : 2 : "Width of smallest particle emitted" +// widthmax(float) : "WidthMax" : 8 : "Width of largest particle emitted" +// noise(float) : "Noise" : "0.1" : "Amount of directional noise in stream" +// lifetime(float) : "Lifetime" : 5 : "Lifetime of particles (in secs)" +// numdecals(integer) : "Num Decals" : 1 : "Number of decals used (keep small)" +// startactive(choices) : "Start On" : 1 = +// [ +// 0 : "No" +// 1 : "Yes" +// ] +// +// // Inputs +// input SetSpawnRate(float) : "Sets how many particles come out" +// input SetSpeed(float) : "Sets speed of emitted particle" +// input SetNoise(float) : "Sets noise of emitted particle (0-1)" +// input SetLifetime(float) : "Sets lifetime of emitted particles (in seconds)" +// input TurnOn(void) : "Turns particles on" +// input TurnOff(void) : "Turns particles off" +//] + +@PointClass base(Targetname, Parentname, EnableDisable) iconsprite("editor/env_fire") color(0 180 0) = env_fire : + "An entity that handles a single flame at its origin. The flame causes heat 'damage' to other env_fire entities around it, and will eventually ignite non-flaming env_fire entities nearby, causing the fire to spread." +[ + health(integer) : "Duration" : 30 : "Amount of time the fire will burn." + firesize(integer) : "Size" : 64 : "Height (in world units) of the flame." + fireattack(integer) : "Attack" : 4 : "Amount of time the fire takes to grow to full strength." + firetype(choices) : "Type" : 0 = + [ + 0 : "Natural" + 1 : "Plasma" + ] + spawnflags(flags) = + [ + 1: "Infinite Duration" : 0 + 2: "Smokeless" : 0 + 4: "Start On" : 0 + 8: "Start Full" : 0 + 16: "Don't drop" : 0 + 32: "No glow" : 0 + 128: "Delete when out" : 0 + 256: "Visible from above" : 0 + ] + + ignitionpoint(float) : "Ignition Point" : 32 : "Amount of heat 'damage' to take before this flame should ignite." + damagescale(float) : "Damage Scale" : "1.0" : "Multiplier of the burn damage done by the flame." + + // Inputs + input StartFire(void) : "Start the fire." + input Extinguish(float) : "Puts out the fire permanently in the number of seconds specified." + input ExtinguishTemporary(float): "Puts out the fire temporarily in the number of seconds specified." + + // Outputs + output OnIgnited(void) : "Fires when the fire is first ignited." + output OnExtinguished(void) : "Fires when the fire is fully extinguished." +] + +@PointClass base(Targetname, Parentname) iconsprite("editor/env_firesource") color(255 255 0) sphere(fireradius) = env_firesource : + "An entity that provides heat to all nearby env_fire entities. Cannot be extinguished." +[ + spawnflags(flags) = + [ + 1: "Start On" : 0 + ] + + fireradius(float) : "Radius" : 128 : "The radius around this entity in which to provide heat." + firedamage(float) : "Intensity / Damage" : 10 : "Amount of heat 'damage' to apply to env_fire entities within the radius." + + // Inputs + input Enable(void) : "Enable fire source." + input Disable(void) : "Disable fire source." +] + +@PointClass base(Targetname, Parentname) size(-4 -4 -4, 4 4 4) color(255 255 0) sphere(fireradius) = env_firesensor : + "An entity that detects changes in heat nearby." +[ + spawnflags(flags) = + [ + 1: "Start On" : 1 + ] + + fireradius(float) : "Radius" : 128 : "The radius around this entity in which to detect heat changes." + heatlevel(float) : "Heat level" : 32 : "The target heat level to check for. Outputs are fired when the heat moves over this target level (increasing or decreasing)." + heattime(float) : "Time at level" : 0 : "The amount of time the heat level must spend over the target level before the 'OnHeatLevelStart' output is fired." + + // Inputs + input Enable(void) : "Enable fire sensor." + input Disable(void) : "Disable fire sensor." + output OnHeatLevelStart(void) : "Fires when the heat level has been sustained for the specified length of time." + output OnHeatLevelEnd(void) : "Fires when the heat level drops below the target level." +] + +@PointClass base(Targetname) size(-4 -4 -4, 4 4 4) color(0 180 0) = env_entity_igniter : + "An entity that catches a target entity on fire. If the entity is an animating model, it will have sprite flames attached to its skeleton. Otherwise the entity will emit particle flame puffs." +[ + target(target_destination) : "Entity to ignite" : : "Name of the entity to catch on fire." + lifetime(float) : "Lifetime in seconds" : 10 : "Duration of flames." + + // Inputs + input Ignite(void) : "Ignite the target entity." +] + +@PointClass base(Targetname, DXLevelChoice, Angles) iconsprite("editor/fog_controller.vmt") color(255 255 255) = env_fog_controller : + "An entity that controls the fog and view distance in the map." +[ + // Inputs + input SetStartDist(float) : "Set the fog start distance." + input SetEndDist(float) : "Set the fog end distance." + input TurnOn(void) : "Turn the fog on." + input TurnOff(void) : "Turn the fog off." + input SetColor(color255) : "Set the primary fog color." + input SetColorSecondary(color255) : "Set the secondary fog color." + input SetFarZ(integer): "Set the far clip plane distance." + input SetAngles(string) : "Set the angles to use for the secondary fog direction." + + input SetColorLerpTo(color255) : "Set the primary fog color." + input SetColorSecondaryLerpTo(color255) : "Set the secondary fog color." + input SetStartDistLerpTo(float) : "Set the fog start distance." + input SetEndDistLerpTo(float) : "Set the fog end distance." + input StartFogTransition(void) : "Start fog transition." + + // Starting fog parameters for the level. These are selectable per LOD. + fogenable(choices) : "Fog Enable" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + fogblend(choices) : "Fog Blend" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + use_angles(choices) : "Use Angles for Fog Dir" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + fogcolor(color255) : "Primary Fog Color" : "255 255 255" + fogcolor2(color255) : "Secondary Fog Color" : "255 255 255" + fogdir(string) : "Primary Fog Direction" : "1 0 0" + fogstart(string) : "Fog Start" : "500.0" + fogend(string) : "Fog End" : "2000.0" + + foglerptime(float) : "Interpolate time" : "0" + + farz(string) : "Far Z Clip Plane" : "-1" +] + +@PointClass base(Targetname, Parentname, Angles) studioprop("models/editor/spot_cone.mdl") color(255 255 255) = env_steam : + "An entity used to create a jet of steam." +[ + spawnflags(flags) = + [ + 1 : "Emissive" : 0 + ] + + InitialState(choices) : "Initial State" : 0 = + [ + 0 : "Off" + 1 : "On" + ] + + //Type of particle to spew out + type(choices) : "Particle Type" : 0 = + [ + 0 : "Normal" + 1 : "Heat Wave" + ] + + SpreadSpeed(integer) : "Spread Speed" : 15 : "The amount of random spread in the particle's velocity after they spawn." + Speed(integer) : "Speed" : 120 : "The default speed at which the particles move after they spawn." + StartSize(integer) : "Particle start size" : 10 : "The initial size of the particles after they spawn." + EndSize(integer) : "Particle end size" : 25 : "The size of the particles at the point at which they are removed." + Rate(integer) : "Emission rate" : 26 : "The rate of particle emission. i.e. particles per second." + rendercolor(color255) : "Color (R G B)" : "255 255 255" + JetLength(integer) : "Length of steam jet" : 80 : "The length of the jet determines the lifetime of each particle." + renderamt(integer) : "Translucency" : 255 + rollspeed(float) : "How fast does the particles spin" : 8 + + // Inputs + input TurnOn(void) : "Turns the steam jet on." + input TurnOff(void) : "Turns the steam jet off." + input Toggle(void) : "Toggles the steam jet between on and off." + input JetLength(integer) : "Sets the length of steam jet." + input Rate(integer) : "Sets the particle emission rate in particles per second." + input Speed(integer) : "Sets the default speed of the particles in units per second." + input SpreadSpeed(integer) : "Sets the spread speed in units per second." +] + +@PointClass base(Targetname, Parentname, RenderFxChoices) size(-4 -4 -4, 4 4 4) line(255 255 255, targetname, LaserTarget) = env_laser : + "An entity that creates a laser beam between itself and a given target." +[ + LaserTarget(target_destination) : "Target of Laser" : : "Name of entity, or entities, to strike at. The target is randomly chosen if there are multiple entities matching the given name." + renderamt(integer) : "Brightness (1 - 255)" : 100 + rendercolor(color255) : "Beam Color (R G B)" : "255 255 255" + width(float) : "Width of Beam" : 2 : "The width of the laser beam, in pixels." + NoiseAmplitude(integer) : "Amount of noise (0-255)" : 0 : "The amount of noise in the beam. 0 is a perfectly straight beam." + texture(sprite) : "Sprite Name" : "sprites/laserbeam.spr" : "The material used to draw the laser beam." + EndSprite(sprite) : "End Sprite" : "" : "If specified, this sprite will be drawn at the end of the laser beam." + TextureScroll(integer) : "Texture Scroll Rate (0-100)" : 35 : "Rate at which the beam texture should scroll along the beam." + framestart(integer) : "Starting Frame" : 0 : "The frame to start the beam texture on." + damage(string) : "Damage / second" : "100" : "How much damage this laser does. per second. to things it hits." + dissolvetype(choices) : "Dissolve Type" : "None" = + [ + -1 : "None" + 0 : "Energy" + 1 : "Heavy electrical" + 2 : "Light electrical" + ] + spawnflags(flags) = + [ + 1 : "Start On" : 0 + 16: "StartSparks" : 0 + 32: "EndSparks" : 0 + 64: "Decal End" : 0 + ] + + // Inputs + input TurnOn(void) : "Turns the laser on." + input TurnOff(void) : "Turns the laser off." + input Toggle(void) : "Toggles the laser between on and off." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = env_message : + "An entity that draws a text message on player's HUDs." +[ + message(string) : "Message Text" + spawnflags(flags) = + [ + 1: "Play Once" : 0 + 2: "All Clients" : 0 + ] + messagesound(sound) : "Sound Effect" : "" : "When the message is shown, this sound effect will be played, originating from this entity." + messagevolume(string) : "Volume 0-10" : "10" : "Volume of the sound effect." + messageattenuation(Choices) : "Sound Radius" : 0 = + [ + 0 : "Small Radius" + 1 : "Medium Radius" + 2 : "Large Radius" + 3 : "Play Everywhere" + ] + + // Inputs + input ShowMessage(void) : "Shows the message and plays the sound." + + // Outputs + output OnShowMessage(void) : "Fired when the message is activated." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = env_hudhint : + "An entity to control the display of HUD hints. HUD hints are used to show the player what key is bound to a particular command." +[ + message(string) : "Hint Text (localized)" : "" : "This should be set to match the desired HUD hint entry in the hl2\resource\valve_english.txt." + + // Inputs + input ShowHudHint(void) : "Shows the hint message." + input HideHudHint(void) : "Hides the hint message." +] + +@PointClass sphere() iconsprite("editor/env_shake.vmt") base(Targetname, Parentname) = env_shake : + "An entity to control screen shake on players." +[ + spawnflags(flags) = + [ + 1: "GlobalShake" : 0 + //2: "Disrupt player control" : 0 // doesn't work + 4: "In Air" : 0 // shakes objects even if they are not onground + 8: "Physics" : 0 // shakes physically as well as the camera + 16: "Ropes" : 0 // shakes ropes too. + 32: "DON'T shake view (for shaking ropes or physics only)" : 0 + ] + + amplitude(float) : "Amplitude (0-16)" : "4" : "The amount of noise in the screen shake. Should be a range between 0 and 16." + radius(float) : "Effect Radius" : "500" : "The radius around this entity in which to affect players." + duration(float) : "Duration (seconds)" : "1" : "The length of time in which to shake the player's screens." + frequency(float) : "Frequency" : "2.5" : "The frequency used to apply the screen shake. Should be a value between 0 and 255, where 0.1 = jerk, and 255.0 = rumble." + + // Inputs + input Amplitude(string) : "Set the amplitude (0-16)" + input Frequency(string) : "Set the frequence. Should be a value between 0 and 255, where 0.1 = jerk, and 255.0 = rumble." + input StartShake(void) : "Start the shake." + input StopShake(void) : "Stop the shake." +] + +@PointClass sphere() size(-4 -4 -4, 4 4 4) base(Targetname, Parentname) = env_viewpunch : + "Causes a view punch on players." +[ + spawnflags(flags) = + [ + 1: "Punch all players (ignore radius)" : 0 + 2: "Punch players in the air" : 0 + ] + + punchangle(angle) : "Punch angles" : "0 0 90" : "The punch angles to apply." + radius(float) : "Effect Radius" : "500" : "The radius around this entity in which to affect players." + + // Inputs + input ViewPunch(void) : "Performs the view punch." +] + +@PointClass base(Targetname, Parentname) = env_rotorwash_emitter : + "Creates rotorwash." +[ + altitude(float) : "Altitude" : "1024" : "Altitude the rotorwash will show up." +] + +@PointClass base(gibshooterbase) iconsprite("editor/gibshooter.vmt") = gibshooter : + "An entity that shoots out gibs. Style of body part depends on language type." +[ +] + +@PointClass base(gibshooterbase, RenderFields) iconsprite("editor/env_shooter.vmt") = env_shooter : + "An entity that shoots models, or sprites, out of its origin." +[ + shootmodel(studio) : "Model" : "" : "Thing to shoot out. Can be a .mdl or a .vmt." + shootsounds(choices) :"Material Sound" : -1 = + [ + -1: "None" + 0: "Glass" + 1: "Wood" + 2: "Metal" + 3: "Flesh" + 4: "Concrete" + ] + simulation(choices) :"Simulate" : 0 = + [ + 0: "Point" + 1: "Physics" + 2: "Ragdoll" + ] + + skin(integer) : "Gib Skin" : 0 : "Some models have multiple versions of their textures, called skins. Set this to a number other than 0 to use that skin on all gibs produced by this shooter." + + spawnflags(flags) = + [ + 2 : "On fire" : 0 + 4 : "strict remove after lifetime" : 0 + ] + + nogibshadows(choices) :"Disable Shadows on Gibs" : 0 = + [ + 0: "No" + 1: "Yes" + ] + + gibgravityscale(float) : "Gib gravity scale" : "1" : "ONLY WORKS FOR POINT GIBS. This field allows you to scale gravity so that gibs fall faster, slower, or not at all." +] + +@PointClass base(gibshooterbase, RenderFields) iconsprite("editor/env_shooter.vmt") = env_rotorshooter : + "An entity that creates gibs when it's within the influence of a helicopter's rotor wash." +[ + shootmodel(studio) : "Model" : "" : "Thing to shoot out. Can be a .mdl or a .vmt." + shootsounds(choices) :"Material Sound" : -1 = + [ + -1: "None" + 0: "Glass" + 1: "Wood" + 2: "Metal" + 3: "Flesh" + 4: "Concrete" + ] + simulation(choices) :"Simulate" : 0 = + [ + 0: "Point" + 1: "Physics" + 2: "Ragdoll" + ] + + skin(integer) : "Gib Skin" : 0 : "Some models have multiple versions of their textures, called skins. Set this to a number other than 0 to use that skin on all gibs produced by this shooter." + + spawnflags(flags) = + [ + 2 : "On fire" : 0 + ] + + rotortime(float) : "Time Under Rotor" : "1" : "The average time it has to be under the rotor before it shoots a gib." + rotortimevariance(float) : "Time variance" : "0.3" : "The random amount to vary the time it has to be under the rotor before it shoots a gib." +] + +@PointClass base(Targetname,Parentname) sphere() iconsprite("editor/env_soundscape.vmt") = env_soundscape_proxy : + "An entity that acts like a soundscape but gets all of its sound parameters from another env_soundscape entity." +[ + MainSoundscapeName(target_destination) : "Soundscape Entity" : "" : "The soundscape to get all sound parameters from." + + radius(integer) : "Radius" : 128 // NEEDHELP: The datadesc doesn't include this entry. Probably not used. +] + +@PointClass base(Targetname,Parentname,EnableDisable) sphere() iconsprite("editor/env_soundscape.vmt") line(255 255 255, targetname, position0) line(255 255 255, targetname, position1) line(255 255 255, targetname, position2) line(255 255 255, targetname, position3) line(255 255 255, targetname, position4) line(255 255 255, targetname, position5) line(255 255 255, targetname, position6) line(255 255 255, targetname, position7) = env_soundscape : + "An entity to control sound in an area. The active soundscape at any time is the last one that had line-of-sight to the player, and was within the radius." +[ + radius(integer) : "Radius" : 128 : "If set to -1, then the player can hear the soundscape as long as he can see it (regardless of distance to it)." + soundscape(choices) : "Soundscape" : "Nothing" : "The name of the soundscape to use. Corresponds to an entry in the soundscapes*.txt file in the hl2\scripts directory." = + [ + "Nothing" : "Nothing" + "Automatic" : "Automatic" + "Automatic_Dialog" : "Automatic (dialog)" + "GenericIndoor" : "Indoor" + "GenericOutdoor" : "Outdoor" + ] + position0(target_destination) : "Sound Position 0" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + position1(target_destination) : "Sound Position 1" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + position2(target_destination) : "Sound Position 2" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + position3(target_destination) : "Sound Position 3" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + position4(target_destination) : "Sound Position 4" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + position5(target_destination) : "Sound Position 5" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + position6(target_destination) : "Sound Position 6" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + position7(target_destination) : "Sound Position 7" : "" : "A sound position that will be referenced inside the soundscape text file. Usually used to position a set of sounds within the world." + + // Inputs + input Enable(void) : "Enable the soundscape." + input Disabled(void) : "Disable the soundscape." + input ToggleEnabled(void) : "Toggle the soundscape enabled state." + + // Outputs + output OnPlay(void) : "Fired when this soundscape becomes the active one." +] + +@PointClass base(env_soundscape) sphere() iconsprite("editor/env_soundscape.vmt") = env_soundscape_triggerable : + "An entity that works like env_soundscape except that it works in conjunction with trigger_soundscape to determine when a player hears it." +[ +] + +@PointClass base(Targetname, Parentname, Angles) iconsprite("editor/env_spark.vmt") = env_spark : + "An entity used to create sparks at its origin." +[ + MaxDelay(string) : "Max Delay" : "0" : "The longest delay between sparks (in seconds)." + Magnitude(choices) : "Magnitude" : 1 : "The size of the sparks." = + [ + 1 : "Small" + 2 : "Medium" + 5 : "Large" + 8 : "Huge" + ] + + TrailLength(choices) : "Spark Trail Length" : 1 = + [ + 1 : "Short" + 2 : "Medium" + 3 : "Long" + ] + + spawnflags(flags) = + [ + 64: "Start ON" : 0 + 128: "Glow" : 0 + 256: "Silent" : 0 + 512: "Directional" : 0 + ] + + // Inputs + input StartSpark(void) : "Start the spark effect." + input StopSpark(void) : "Stop the spark effect." + input ToggleSpark(void) : "Toggle the on/off state of the spark effect." + input SparkOnce(void) : "Spark once." +] + +@PointClass base(Targetname, Parentname, RenderFields,DXLevelChoice) size(-2 -2 -2, 2 2 2) sprite() color(20 140 20) = env_sprite : + "An entity that controls the drawing of a sprite in the world." +[ + framerate(string) : "Framerate" : "10.0" : "Rate at which the sprite should animate, if at all." + model(sprite) : "Sprite Name" : "sprites/glow01.spr" : "Material of the sprite to be drawn." + scale(string) : "Scale" : "" : "Scale multiplier of the sprite." + spawnflags(flags) = + [ + 1: "Start on" : 0 + 2: "Play Once" : 0 + ] + + GlowProxySize(float) : "Size of Glow Proxy Geometry." : "2.0" : "Size of the glow to be rendered for visibility testing. Must be larger than the distance from the sprite center to empty space. So if this glow is inside geometry (like a light bulb), set this value to be bigger than the bulb's radius. Any time a sphere of this radius would be visible (poking through any nearby geometry), the glow will be rendered." + + HDRColorScale(float) : "HDR color scale." : "1.0" : "float value to multiply sprite color by when running in HDR mode." + + // Inputs + input SetScale(float) : "Set the sprite's scale (0 - 8.0)." + input HideSprite(void) : "Hide the sprite. Won't be drawn until the 'ShowSprite' input is received." + input ShowSprite(void) : "Show the sprite." + input ToggleSprite(void) : "Toggle the sprite between hidden and shown." +] + +@PointClass base(Targetname, Angles) iconsprite("editor/env_wind.vmt") = env_wind : + "An entity to control wind in the map. Partially functional." +[ + //gustsound(sound) : "Gust Sound Filename" : "" : "Sound to be played to simulate the gusting wind." + minwind(integer) : "Min normal speed" : 20 : "Minimum speed of the wind while idling." + maxwind(integer) : "Max normal speed" : 50 : "Maximum speed of the wind while idling." + + mingust(integer) : "Min gust speed" : 100 : "Minimum speed of wind gusts." + maxgust(integer) : "Max gust speed" : 250 : "Maximum speed of wind gusts." + + mingustdelay(integer) : "Min gust delay" : 10 : "Minimum time delay between random gusts." + maxgustdelay(integer) : "Max gust delay" : 20 : "Maximum time delay between random gusts." + + gustduration(integer) : "Gust Duration" : 5 : "How long will the wind gust for." + + gustdirchange(integer) : "Max gust dir change (degrees)" : 20 : "Maximum amount that the wind's direction changes due to a gust." + + output OnGustStart(void) : "Fired when a wind gust begins." + output OnGustEnd(void) : "Fired when a wind gust ends." +] + +@PointClass base(Angles) size(-16 -16 -16, 16 16 16) color(0 0 255) = sky_camera : + "An entity used to control the 3D Skybox. Its origin is used to determine the 3D Skybox's position relative to the map. Place this entity, in the 3D Skybox, at the point where the origin of the map should be." +[ + scale(integer) : "3D Skybox scale" : 16 : "Scale of the skybox." + fogenable(choices) : "Fog Enable" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + fogblend(choices) : "Fog Blend" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + use_angles(choices) : "Use Angles for Fog Dir" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + fogcolor(color255) : "Primary Fog Color" : "255 255 255" + fogcolor2(color255) : "Secondary Fog Color" : "255 255 255" + fogdir(string) : "Primary Fog Dir" : "1 0 0" + fogstart(string) : "Fog Start" : "500.0" : "Distance at which the skybox fog should start." + fogend(string) : "Fog End" : "2000.0" : "Distance at which the skybox fog should be fully opaque." +] + +@BaseClass base(Targetname, ResponseContext) = BaseSpeaker +[ + delaymin(string) : "Min Delay Between Announcements" : "15" + delaymax(string) : "Max Delay Between Announcements" : "135" + spawnflags(flags) = + [ + 1: "Start Silent" : 0 + 2: "Play Everywhere" : 0 + ] + rulescript(string) : "Context rule script" : "" : "Script file containing rules for playing appropriate sounds." + concept(string) : "Concept name" : "" : "High level concept name used as primary search key." + + // Inputs + input TurnOn(void) : "Turn on the random announcements." + input TurnOff(void) : "Turn off the random announcements." + input Toggle(void) : "Toggle the random announcements off and on." +] + +//------------------------------------------------------------------------- +// +// Game Entities +// +//------------------------------------------------------------------------- + +@PointClass base(Targetname) = game_weapon_manager : + "An entity used to limit the number of a particular weapon type in the world. Useful in places where NPCs are spawning rapidly, dying, and dropping weapons." +[ + weaponname(string) : "Weapon Classname" : "" : "Classname of the weapon type to limit." + maxpieces(integer) : "Max Allowed in Level" : 0 : "The maximum amount of the specified weapon type allowed in the world." + ammomod(float) : "Ammo modifier" : 1 : "Modifier for ammount of ammo dropped by a weapon." + + // Inputs + input SetAmmoModifier(float): "Adjust the ammo modifier." +] + +@PointClass base(Targetname) iconsprite("editor/game_end.vmt") = game_end : + "An entity that ends a multiplayer game." +[ + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this entity will not activate." + input EndGame(void) : "End the multiplayer game." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = game_player_equip : + "An entity that gives equipment to the player who activates it. To use, add new keys to this entity, where each key is the classname of a weapon/item, and the corresponding value is the number of those weapons/items to give to the player who uses this entity. If the 'Use Only' spawnflag isn't set, then players can just touch this entity to get the equipment." +[ + spawnflags(flags) = + [ + 1: "Use Only" : 0 + ] + master(string) : "Team Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this entity will not activate." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = game_player_team : + "An entity that changes the team of the player who activates it." +[ + spawnflags(flags) = + [ + 1 : "Remove On fire" : 0 + 2 : "Kill Player" : 0 + 4 : "Gib Player" : 0 + ] + target(string) : "game_team_master to use" + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this entity will not activate." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = game_score : + "An entity that awards/deducts points from the player who activates it." +[ + spawnflags(flags) = + [ + 1: "Allow Negative" : 0 + 2: "Team Points" : 0 + ] + + points(integer) : "Points to add (+/-)" : 1 + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this entity will not activate." + + // Inputs + input ApplyScore(void) : "Add score to player." +] + +@PointClass base(Targetname) iconsprite("editor/game_text.vmt") = game_text : + "An entity that displays text on player's screens." +[ + spawnflags(flags) = + [ + 1: "All Players" : 0 + ] + + message(string) : "Message Text" : "" : "Message to display onscreen." + x(string) : "X (0 - 1.0 = left to right) (-1 centers)" : "-1" : "Horizontal position on the player's screens to draw the text. The value should be between 0 and 1, where 0 is the far left of the screen and 1 is the far right. -1 centers the text." + y(string) : "Y (0 - 1.0 = top to bottom) (-1 centers)" : "-1" : "Vertical position on the player's screens to draw the text. The value should be between 0 and 1, where 0 is the top of the screen and 1 is the bottom. -1 centers the text." + effect(Choices) : "Text Effect" : 0 = + [ + 0 : "Fade In/Out" + 1 : "Credits" + 2 : "Scan Out" + ] + color(color255) : "Color1" : "100 100 100" + color2(color255) : "Color2" : "240 110 0" + fadein(string) : "Fade in Time (or character scan time)" : "1.5" : "The time it should take for the text to fully fade in." + fadeout(string) : "Fade Out Time" : "0.5" : "The time it should take for the text to fade out, after the hold time has expired." + holdtime(string) : "Hold Time" : "1.2" : "The time the text should stay onscreen, after fading in, before it begins to fade out." + fxtime(string) : "Scan time (scan effect only)" : "0.25" : "If the 'Text Effect' is set to Scan Out, this is the time it should take to scan out all the letters in the text." + channel(choices) : "Text Channel" : 1 : "You can have up to four individual game_text messages onscreen at once, stored in channels. Select which channel this text should be placed in, which will overwrite any active message already in that channel." = + [ + 1 : "Channel 1" + 2 : "Channel 2" + 3 : "Channel 3" + 4 : "Channel 4" + ] + master(string) : "Master" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this entity will not activate." + + // Inputs + input Display(void) : "Display the message text." +] + +@PointClass base(Parentname, Angles) size(-2 -2 -2, 2 2 2) = point_enable_motion_fixup : + "An entity used to move a motion-disabled prop when it enables motion. Parent this entity to the prop, and when the prop has its motion enabled, it will immediately teleport to the origin of this entity." +[ +] + +@PointClass base(Targetname, Parentname) size(-8 -8 -8, 8 8 8) = point_message : + "An entity that displays a text message in the world, at its origin." +[ + spawnflags(flags) = + [ + 1: "Start Disabled" : 0 + ] + + message(string) : "Entity Message" + radius(integer) : "Show message radius" : 128 : "Distance the player must be within to see this message." + developeronly(choices) : "Developer Only?" : 0 : "If set, this message will only be visible when developer mode is on." = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Enable(void) : "Start displaying the message text, if the player is within the message radius." + input Disable(void) : "Stop displaying the message text." +] + +@PointClass base(Targetname, Parentname, RenderFields, Angles) studio("models/editor/axis_helper_thick.mdl") = point_spotlight : + "An entity to draw a spotlight. Will draw a beam when the player views it side on, and a halo when it's facing towards the player. "+ + "Unless the 'No Dynamic Light' spawnflag is checked, it will also create a dynamic light wherever the end of the spotlight rests." +[ + spawnflags(Flags) = + [ + 1 : "Start On" : 1 + 2 : "No Dynamic Light" : 0 + ] + + spotlightlength(integer) : "Spotlight Length" : 500 : "Length of the spotlight beam." + spotlightwidth(integer) : "Spotlight Width" : 50 : "Width of the spotlight beam." + rendercolor(color255) : "Color (R G B)" : "255 255 255" + HDRColorScale(float) : "HDR color scale." : "1.0" : "float value to multiply sprite color by when running in HDR mode." + + // Inputs + input LightOn(void) : "Turn the spotlight on." + input LightOff(void) : "Turn the spotlight off" +] + +@PointClass base(Targetname, Parentname) size(-8 -8 -8, 8 8 8) = point_tesla : + "An entity that creates tesla lightning arcs around its origin." +[ + m_SourceEntityName(string) : "Source Entity" : "" : "If specified, tesla lightning will originate from the specified entity. Otherwise, they originate from this entity." + m_SoundName(string) : "Sound Name" : "DoSpark" : "Sound to be played whenever lightning is created." + + texture(sprite) : "Sprite Name" : "sprites/physbeam.vmt" : "Material to use for the tesla lightning beams." + + m_Color(color255) : "Color" : "255 255 255" + + m_flRadius(integer) : "Radius" : 200 : "Radius around the origin to find a point to strike with a tesla lightning beam." + + beamcount_min(integer) : "Min # of Beams" : 6 : "Minimum number of tesla lightning beams to create when creating an arc." + beamcount_max(integer) : "Max # of Beams" : 8 : "Maximum number of tesla lightning beams to create when creating an arc." + + thick_min(string) : "Min Beam Width" : "4" : "Minimum width of the tesla lightning beams." + thick_max(string) : "Max Beam Width" : "5" : "Maximum width of the tesla lightning beams." + + lifetime_min(string) : "Min Time Visible" : "0.3" : "Minimum lifetime of the tesla lightning beams." + lifetime_max(string) : "Max Time Visible" : "0.3" : "Maximum lifetime of the tesla lightning beams." + + interval_min(string) : "Min Time Between Arcs":"0.5" : "Minimum time delay between random arcing." + interval_max(string) : "Max Time Between Arcs":"2" : "Maximum time delay between random arcing." + + // Inputs + input TurnOn(void) : "Turn emitter on." + input TurnOff(void) : "Turn emitter off." + input DoSpark(void) : "Force a single arc." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = point_clientcommand : + "An entity that issues commands to the client console, as if it was typed in by the player (if activator is a player, or the local player in single player)." +[ + // Inputs + input Command(string) : "Command to execute." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = point_servercommand : + "An entity that issues commands to the server console." +[ + // Inputs + input Command(string) : "Command to execute." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = game_ui : + "An entity used to override player input when the player is looking at it." +[ + spawnflags(flags) = + [ + 32 : "Freeze Player" : 1 + 64 : "Hide Weapon" : 1 + 128 : "+Use Deactivates" : 1 + 256 : "Jump Deactivates" : 1 + ] + + FieldOfView(float) : "FieldOfView" : "-1.0" : "The amount of tolerance in the view checking when determining whether the player's input is still under control. 1.0 = straight ahead, 0.0 = +/- 90 degrees, -1.0 = all directions. If the player isn't within the tolerance, the player regains control." + + // Inputs + input Deactivate(void) : "Return Player Control." + input Activate(void) : "Take Player Control." + + // Outputs + output PlayerOn(void) : "Fired whenever this entity starts controlling the player's input." + output PlayerOff(void) : "Fired whenever this entity stops controlling the player's input." + output PressedMoveLeft(void) : "Fired whenever the player presses the moveleft key." + output PressedMoveRight(void) : "Fired whenever the player presses the moveright key." + output PressedForward(void) : "Fired whenever the player presses the forward key." + output PressedBack(void) : "Fired whenever the player presses the backward key." + output PressedAttack(void) : "Fired whenever the player presses the attack key." + output PressedAttack2(void) : "Fired whenever the player presses the secondary attack key." + + output XAxis(string) : "An output that fires whenever the X axis of the player's input changes. i.e. -1 when the player has moveleft key down, 1 when the player has moveright key down, and 0 if neither." + output YAxis(string) : "An output that fires whenever the Y axis of the player's input changes. i.e. -1 when the player has backward key down, 1 when the player has forward key down, and 0 if neither." + output AttackAxis(string) : "An output that fires whenever the state of the player's attack key changes. i.e. 1 when the player has the attack key down, 0 otherwise." + output Attack2Axis(string) : "An output that fires whenever the state of the player's secondary attack key changes. i.e. 1 when the player has the secondary attack key down, 0 otherwise." +] + +@SolidClass base(Targetname, Parentname) = game_zone_player : + "An entity used to count the number of players within a zone." +[ + // Inputs + input CountPlayersInZone(void) : "Count the number of players in the zone, and fire the corresponding outputs." + + // Outputs + output OnPlayerInZone(void) : "Fired whenever a count finds a player inside the zone, with the player as the activator." + output OnPlayerOutZone(void) : "Fired whenever a count finds a player outside the zone, with the player as the activator." + output PlayersInCount(integer) : "Fired after a count, and contains the number of players found inside the zone." + output PlayersOutCount(integer) : "Fired after a count, and contains the number of players found outside the zone." +] + +//------------------------------------------------------------------------- +// +// Info Entities +// +//------------------------------------------------------------------------- + +@PointClass base(Targetname) decal() studio("models/editor/axis_helper_thick.mdl") = infodecal : + "An entity that places a decal on the world. If the decal has no target name, it will immediately apply itself when the level is loaded. "+ + "If it has a name specified, it won't apply until it receives the 'Activate' input." +[ + texture(decal) + + LowPriority(choices) : "Low Priority (can be replaced)" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Activate(void) : "Force the decal to apply itself to the world." +] + +// A decal to be applied to a prop or the world using specified origin and orientation and radius, uses an orientation angle and a radius to determine +// ray to cast for projection +@PointClass base(Angles,Targetname) decal() studio("models/editor/axis_helper_thick.mdl") = info_projecteddecal : + "An entity that projects a decal onto the world (or props). If the decal has no target name, it will immediately apply itself when "+ + "the level is loaded. If it has a name specified, it won't apply until it receives the 'Activate' input." +[ + texture(decal) + Distance(float) : "Distance" : 64 : "Distance from the origin to project the decal." + + // Inputs + input Activate(void) : "Force the decal to apply itself to the world." +] + +@PointClass = info_no_dynamic_shadow : + "Use this entity to mark surfaces that shouldn't receive dynamic shadows. Useful to apply to walls and floors "+ + "where shadows are drawn improperly, giving away the location of enemies." +[ + sides(sidelist) : "Brush faces" +] + +@PointClass base(PlayerClass, Angles) studio("models/editor/playerstart.mdl") = info_player_start : + "This entity indicates the position and facing direction at which the player will spawn. Any number of "+ + "info_player_start entities may be placed in a map for when working in cordoned-off portions of the map. "+ + "When multiple info_player_start entities are present in a map, set the 'Master' spawnflag on one of them "+ + "to indicate which one should be used when running the entire map." +[ + spawnflags(flags) = + [ + 1: "Master (Has priority if multiple info_player_starts exist)" : 0 + ] +] + +@PointClass size(-1 -1 0, 1 1 1) color(80 150 225) studio("models/editor/overlay_helper.mdl") overlay() = info_overlay : + "An entity that places an overlay on the world." +[ + material(material) : "Material" + sides(sidelist) : "Brush faces" + RenderOrder(integer) : "Render Order" : 0 : "Higher values render after lower values. This value can be 0-3." + StartU(float) : "U Start" : "0.0" + EndU(float) : "U End" : "1.0" + StartV(float) : "V Start" : "0.0" + EndV(float) : "V End" : "1.0" + BasisOrigin(Vector) readonly : "Overlay Basis Origin(Read-Only)" + BasisU(Vector) readonly : "Overlay Basis U(Read-Only)" + BasisV(Vector) readonly : "Overlay Basis V(Read-Only)" + BasisNormal(Vector) readonly : "Overlay Basis Normal(Read-Only)" + uv0(vector) readonly : "Overlay Point 1(Read-Only)" + uv1(vector) readonly : "Overlay Point 2(Read-Only)" + uv2(vector) readonly : "Overlay Point 3(Read-Only)" + uv3(vector) readonly : "Overlay Point 4(Read-Only)" +] + +@PointClass size(-8 -8 -8, 8 8 8) sidelist(sides) sidelist(sides2) overlay_transition() = info_overlay_transition : "Overlay Transition" +[ + material(material) : "Material" + sides(sidelist) : "Brush faces" + sides2(sidelist) : "Water faces" + LengthTexcoordStart(float) : "Texcoord Length Start" : "0.0" + LengthTexcoordEnd(float) : "Texcoord Length End" : "1.0" + WidthTexcoordStart(float) : "Texcoord Width Start" : "0.0" + WidthTexcoordEnd(float) : "Texcoord Width End" : "1.0" + Width1(float) : "Width Land" : "25.0" + Width2(float) : "Width Water" : "25.0" + DebugDraw(integer) : "Show Debug" : 0 : "Boolean value (0 or 1)." +] + +@PointClass size(-4 -4 -4, 4 4 4) color(0 180 0) = info_intermission : + "An entity that defines an intermission spot where dead players will float until they respawn." +[ + target(target_destination) : "Entity to look at" : : "Name of entity that dead players will face while in intermission at this spot." +] + +@PointClass base(Targetname) iconsprite("editor/info_landmark") = info_landmark : + "An entity that acts as a landmark for transitions to another level. There should be a corresponding info_landmark entity in the next map. Entities will be transitioned to the next level relative to the info_landmark entities." +[ +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = info_null : + "An entity that's immediately removed on spawning. Useful as a spotlight target." +[ +] + +@PointClass base(Targetname, Parentname, Angles) iconsprite("editor/info_target.vmt") = info_target : + "An entity that does nothing. Very useful as a positioning entity for other entities to refer to (i.e. the endpoint of an env_beam)" +[ + input DispatchEffect(string) : "Dispatch an effect from this point. Unfinished." +] + +@PointClass base(Targetname, EnableDisable, Parentname, Angles) iconsprite("editor/info_target.vmt") sphere(radius) = phys_ragdollmagnet : + "An entity that acts like a magnet for ragdolls. Useful for crafting exaggerated ragdoll behavior (i.e. guys falling over rails on death). If the "+ + "Bar Magnet spawnflag is set, the magnet works like it was a cylindrical magnet i.e. it attracts ragdolls to the nearest point on a line." +[ + axis(vecline) : "Bar Magnet Axis" + radius(float) : "Effective Radius" : "512" : "Radius in which ragdolls are affected around this entity's origin." + force(float) : "Force" : "5000" : "Magnetic force to apply to ragdolls within the radius. Expressed as kilograms per inch per second. So a force of 1000 will add 10 inches/second to a 100kg man. It will add 100 inches per second to a 10kg headcrab." + + target(string) : "Entity to affect" : "" : "If specified, the phys_ragdollmagnet will only affect the target entity." + + spawnflags( Flags ) = + [ + 2 : "Bar Magnet (use axis helper)" : 0 + ] +] + +@PointClass base(Targetname) iconsprite("editor/info_lighting.vmt") = info_lighting : + "An entity that can be used to change the lighting origin of a prop_static. Set the prop_static's Lighting Origin to point at this entity to "+ + "make the prop_static light as if it was at the info_lighting's origin. Good for prop_static entities that are embedded in world geometry (like rocks/windows/etc)." +[ +] + +// This is obsolete, info_target is all you need now. +@PointClass base(Targetname, Parentname, Angles, PlayerClass) studio("models/editor/playerstart.mdl") = info_teleport_destination : + "An entity that does nothing itself, but can be used to specify the destination for a trigger_teleport entity. An info_target can be used instead." +[ +] + + +//------------------------------------------------------------------------- +// +// Nodes and Hints +// +//------------------------------------------------------------------------- + +@PointClass base(Node) studio("models/editor/ground_node.mdl") color(232 219 8) = info_node : + "A navigation node for ground moving NPCs. Navigation nodes are baked into the nodegraph so that NPCs can move " + + "to them. Ground nodes fall to the ground when they spawn." +[ + spawnflags(Flags) = + [ + 1 : "Force human permission" : 0 + 2 : "Force small_centered permission" : 0 + 4 : "Force wide_human permission" : 0 + 8 : "Force tiny permissiont" : 0 + 16 : "Force wide_short permission" : 0 + 32 : "Force medium permission" : 0 + 64 : "Force tiny_centered permission" : 0 + 128 : "Force large permission" : 0 + 256 : "Force large_centered permission" : 0 + 512 : "Keep editor position" : 0 + ] +] + +@PointClass base(Targetname, Angles, HintNode) studio("models/editor/ground_node_hint.mdl") color(232 219 8) = info_node_hint : + "A navigation node for ground moving NPCs that includes some context information for NPCs that are interested in it. The hint might " + + "indicate a window that could be looked out of, or an item of interest that could be commented on. Many hint nodes are NPC-specific, " + + "so it's helpful to use naming conventions like 'Crow: Fly to point' in the hint choices list. The angles of a hint node indicate what direction " + + "the NPC should face to perform the hint behavior.\n\n" + + "It's important to understand the distinction between scripts, such as scripted_sequence and scripted_schedule, and info_hint entities. Scripts summon " + + "NPCs to specific cue points to play their parts, while hints provide context information to the AI that they use to perform their " + + "behaviors. Hints require code support in the NPC, while scripts are generic and may require only animations to play. Use a hint if the behavior is driven " + + "by the AI, use a script if the behavior is driven by the map." + +[ + // Outputs + output OnNPCStartedUsing(string) : "Fired when an NPC has reached this node and started using it. Passes along the NPC." + output OnNPCStoppedUsing(string) : "Fired when an NPC has stopped using this node. Passes along the NPC." +] + +@PointClass base(Node) studio("models/editor/air_node.mdl") color(232 171 8) = info_node_air : + "A navigation node for flying NPCs. Air navigation nodes are baked into the nodegraph so that NPCs can move " + + "to them. Air nodes do not fall to the ground when they spawn." +[ + nodeheight(integer) : "NodeHeight" : 0 +] + +@PointClass base(Angles, Targetname, HintNode) studio("models/editor/air_node_hint.mdl") color(232 171 8) line(255 255 255, nodeid, TargetNode) = info_node_air_hint : + "A navigation node for flying NPCs that includes some context information for NPCs that are interested in it. The hint might " + + "indicate a window that could be looked into, or an item of interest that could be commented on. Many hint nodes are NPC-specific, " + + "so it's helpful to use naming conventions like 'Crow: Fly to point' in the hint choices list. The angles of a hint node indicate what direction " + + "the NPC should face to perform the hint behavior." + +[ + nodeheight(integer) : "NodeHeight" : 0 +] + +@PointClass base(Targetname, Angles, HintNode) studio("models/editor/node_hint.mdl") color(255 255 255) = info_hint : + "A hint that is not used for navigation. They don't go into the nodegraph, nor do they fall to the ground. Use these to provide " + + "some spatial context for NPCs, such as 'look here if you can't find the player' or 'throw rocks at this spot'." +[ +] + +@PointClass base(Targetname) color(220 180 0) size(-8 -8 -8, 8 8 8) line(255 255 255, nodeid, StartNode, nodeid, EndNode) = info_node_link : + "A dynamic connection between two navigation nodes. You specify the node IDs of the start and end nodes, and then you can use entity I/O " + + "to turn on and off the connection. This could be used to create or destroy a connection in the nodegraph because of some event in your map " + + "(a bridge being created/destroyed, etc)." +[ + StartNode(node_dest) : "Start node ID" : : "The node ID of one end of the node connection." + EndNode(node_dest) : "End node ID" : : "The node ID of one end of the node connection." + initialstate(choices) : "Initial State" : 1 = + [ + 0 : "Off" + 1 : "On" + ] + + linktype(choices) : "Type of Connection" : 1 = + [ + 1 : "Ground" + 2 : "Jump" + 4 : "Fly" + 8 : "Climb" + ] + AllowUse(string) : "Allow Pass When Off" : : "Entity or class to allow passage even when node is off" + + spawnflags( Flags ) = + [ + 1 : "Force human connect" : 0 + 2 : "Force small_centered connect" : 0 + 4 : "Force wide_human connect" : 0 + 8 : "Force tiny connect" : 0 + 16 : "Force wide_short connect" : 0 + 32 : "Force medium connect" : 0 + 64 : "Force tiny_centered connect" : 0 + 128 : "Force large connect" : 0 + 256 : "Force large_centered connect" : 0 + ] + + // Inputs + input TurnOn(void) : "Turn the link on." + input TurnOff(void) : "Turn the link off." +] + +@PointClass wirebox(mins, maxs) base(Targetname) = info_node_link_controller : + "An entity that controls all connections between nodes that intersect the controller's volume. "+ + "This allows for mass enabling/disabling of all node connections through a volume." +[ + mins(vector) : "Mins" : "-8 -32 -36" + maxs(vector) : "Maxs" : "8 32 36" + + initialstate(choices) : "Initial State" : 1 = + [ + 0 : "Off" + 1 : "On" + ] + AllowUse(string) : "Allow Pass When Off" : : "Entity or class to allow passage even when node is off" + + // Inputs + input TurnOn(void) : "Turn the link on." + input TurnOff(void) : "Turn the link off." +] + +@PointClass sphere(radius) base(Targetname, Parentname) = info_radial_link_controller : + "This entity automatically severs node connections that pass through its radius. If it moves, it will restore those connections." +[ + radius(float) : "Radius (Use Helper!)" : 120 +] + +@PointClass base(Targetname, Angles, HintNode) studio("models/editor/climb_node.mdl") color(153 215 103) = info_node_climb : + "A climb-node for AI navigation. Only usable by NPCs that can climb." +[ +] + + +//------------------------------------------------------------------------- +// +// Lights +// +//------------------------------------------------------------------------- +@PointClass light() iconsprite("editor/light.vmt") base(Targetname, Light) sphere(_fifty_percent_distance) sphere(_zero_percent_distance) = light : + "An invisible omnidirectional lightsource." +[ + target(target_destination) : "Entity To Point At" : : "The name of an entity in the map that the spotlight will point at. This will override the spotlight's angles." + spawnflags(Flags) = [ 1 : "Initially dark" : 0 ] + _distance(integer) : "Maximum Distance" : 0 : "This is the distance that light is allowed to cast, in inches." +] + +@PointClass base(Angles) iconsprite("editor/light_env.vmt") = light_environment : + "Sets the color and angle of the light from the sun and sky." +[ + pitch(integer) : "Pitch" : 0 : "The downward pitch of the light from the sun. 0 is horizontal, -90 is straight down." + _light(color255) : "Brightness" : "255 255 255 200" + _ambient(color255) : "Ambient" : "255 255 255 20" + _lightHDR(color255) : "BrightnessHDR" : "-1 -1 -1 1" + _ambientHDR(color255) : "AmbientHDR" : "-1 -1 -1 1" +] + +@PointClass base(Targetname, Angles, Light) lightprop("models/editor/spot.mdl") lightcone() sphere(_fifty_percent_distance) sphere(_zero_percent_distance) = light_spot : + "An invisible and directional spotlight." +[ + target(target_destination) : "Entity to point at" : : "The name of an entity in the map that the spotlight will point at. This will override the spotlight's angles." + _inner_cone(integer) : "Inner (bright) angle" : 30 + _cone(integer) : "Outer (fading) angle" : 45 + _exponent(integer) : "Focus" : 1 + _distance(integer) : "Maximum distance" : 0 : "This is the distance that light is allowed to cast, in inches." + pitch(integer) : "Pitch" : -90 + spawnflags(Flags) = [ 1 : "Initially dark" : 0 ] +] + +@PointClass base(Targetname, Parentname, Angles) iconsprite("editor/light.vmt") sphere(distance) lightcone() size(-4 -4 -4, 4 4 4) = light_dynamic : + "An invisible lightsource that changes in some way over time." +[ + target(target_destination) : "Entity to point at" : : "The name of an entity in the map that the dynamic light will point at." + _light(color255) : "Light color" : "255 255 255 200" + brightness(integer) : "Light brightness" : 0 + _inner_cone(integer) : "Inner (bright) angle" : 30 + _cone(integer) : "Outer (fading) angle" : 45 + pitch(integer) : "Pitch" : -90 + distance(float) : "Maximum distance" : 120 : "This is the distance that light is allowed to cast, in inches." + spotlight_radius(float) : "Spotlight end radius" : 80 : "This is the radius of the light, in inches, at the object that it is hitting." + style(Choices) : "Appearance" : 0 = + [ + 0 : "Normal" + 10: "Fluorescent flicker" + 2 : "Slow, strong pulse" + 11: "Slow pulse, noblack" + 5 : "Gentle pulse" + 1 : "Flicker A" + 6 : "Flicker B" + 3 : "Candle A" + 7 : "Candle B" + 8 : "Candle C" + 4 : "Fast strobe" + 9 : "Slow strobe" + ] + spawnflags(Flags) = + [ + 1 : "No world light" : 0 + 2 : "No model light" : 0 + 4 : "Add Displacement Alpha" : 0 + 8 : "Subtract Displacement Alpha" : 0 + ] + + // Inputs + input Color(color255) : "Set the light's render color (R G B)." + input brightness(integer) : "Set the light brightness." + input distance(float) : "Set the maximum light distance." + input _inner_cone(integer) : "Set the inner (bright) angle." + input _cone(integer) : "Set the outer (fading) angle." + input spotlight_radius(float) : "Set the radius of the spotlight at the end point." + input style(integer) : "Change the lightstyle (see Appearance field for possible values)." + + input TurnOn(void) : "Turn the light off." + input TurnOff(void) : "Turn the light on." + input Toggle(void) : "Toggle the light on/off." +] + + +//------------------------------------------------------------------------- +// Shadow control +//------------------------------------------------------------------------- + +@PointClass base(Targetname) iconsprite("editor/shadow_control.vmt") = shadow_control : + "An entity to control the shadows in the map." +[ + angles(string) : "Pitch Yaw Roll (Y Z X)" : "80 30 0" : "This is the shadow direction. Pitch is rotation around the Y axis, yaw is the rotation around the Z axis, and roll is the rotation around the X axis." + + color(color255) : "Shadow Color" : "128 128 128" : "This is the color of the shadows." + distance(float) : "Maximum Distance" : 75 : "This is the maximum distance the shadow is allowed to cast, in inches." + disableallshadows(Choices) : "All Shadows Disabled" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input color(color255) : "Set the shadow color." + input direction(vector) : "Set the shadow direction." + input SetDistance(float) : "Set the maximum shadow cast distance." + input SetAngles(string) : "Set the shadow direction." + input SetShadowsDisabled(integer) : "Set shadows disabled state." +] + + +//------------------------------------------------------------------------- +// Color correction control +//------------------------------------------------------------------------- + +@PointClass base(Targetname, EnableDisable) iconsprite("editor/shadow_control.vmt") = color_correction : + "An entity to control the color correction in the map." +[ + minfalloff(float) : "Lookup Falloff Start Distance" : "0.0" : "This is the distance to the start of the falloff region" + maxfalloff(float) : "Lookup Falloff End Distance" : "200.0" : "This is the distance to the end of the falloff region" + maxweight(float) : "Maximum Weight" : "1.0" : "This is the maximum weight for this lookup" + filename(string) : "Lookup Table Filename" : "" : "This is the lookup table filename" + + // Inputs + input filename(string) : "Set the lookup table filename." +] + + +//------------------------------------------------------------------------- +// Color correction volume control +//------------------------------------------------------------------------- + +@SolidClass base(Targetname, EnableDisable ) iconsprite("editor/shadow_control.vmt") = color_correction_volume : + "An entity to control the color correction in the map." +[ + fadeDuration(float) : "Lookup Fade Duration" : "10.0" : "This is the duration for the lookup to fade in/out on extry/exit" + maxweight(float) : "Maximum Weight" : "1.0" : "This is the maximum weight for this lookup" + filename(string) : "Lookup Table Filename" : "" : "This is the lookup table filename" + + // Inputs + input filename(string) : "Set the lookup table filename." +] + + +//------------------------------------------------------------------------- +// +// Movement and Keyframing Entities +// +//------------------------------------------------------------------------- + +@BaseClass = KeyFrame +[ + NextKey(target_destination) : "Next KeyFrame" : : "Name of the next keyframe along this keyframe path." + +// TimeModifier(choices) : "Time Modifier" : 0 = +// [ +// 0 : "Linear" +// 1 : "Accel" +// 2 : "Deaccel" +// 2 : "Accel/Deaccel (sine)" +// ] + + MoveSpeed(integer) : "Speed (units per second)" : 64 // NEEDHELP +// NextTime(string) : "Time to get to next keyframe" +] + +@BaseClass = Mover +[ + PositionInterpolator(choices) : "Position Interpolator" : 0 = + [ + 0 : "Linear" + 1 : "Catmull-Rom Spline" + ] +] + +@SolidClass base(Targetname, Parentname, Origin, RenderFields) = func_movelinear : + "A brush entity that moves linearly along a given distance, in a given direction." +[ + movedir(angle) : "Move Direction (Pitch Yaw Roll)" : "0 0 0" : "The direction the brushes will move, when told to." + spawnflags(flags) = + [ + 8 : "Not Solid" : 0 + ] + + startposition(float) : "Start Position" : 0 : "Position of brush when spawned. The range is a value between 0.0 and 1.0, where 0 is the starting position and 1 is the starting position + (move direction * move distance)." + speed(integer) : "Speed" : 100 : "The speed that the brush moves, in inches per second." + movedistance(float) : "Move Distance" : 100 : "The distance from the starting point that the brush should move, in inches." + blockdamage(float) : "Block Damage" : 0 : "The amount of damage to do to any entity that blocks the brushes, per frame." + startsound(sound) : "Sound played when the brush starts moving." + stopsound(sound) : "Sound played when the brush stops moving." + + // Inputs + input Open(void) : "Move the brush to the end position (starting position + (move direction * move distance))." + input Close(void) : "Move the brush to the starting position." + input SetPosition(string) : "Move the brush to a specific position between 0.0 and 1.0, where 0 is the starting position and 1 is the starting position + (move direction * move distance)." + + // Outputs + output OnFullyOpen(void) : "Fired when the brush reaches the end position (starting position + (move direction * move distance))." + output OnFullyClosed(void) : "Fired when the brush reaches the starting position." +] + +@SolidClass base(Targetname, Parentname, Origin) = func_water_analog : + "A water brush entity that moves linearly along a given distance, in a given direction" +[ + movedir(angle) : "Move Direction (Pitch Yaw Roll)" : "0 0 0" : "The direction the water will move, when told to 'Open'." + startposition(float) : "Start Position" : 0 : "Position of the water brush when spawned. The range is a value between 0.0 and 1.0, where 0 is the starting position and 1 is the starting position + (move direction * move distance)." + speed(integer) : "Speed" : 100 : "The speed that the water brush moves, in inches per second." + movedistance(float) : "Move Distance" : 100 : "The distance from the starting point that the water brush should move, in inches." + startsound(sound) : "Sound played when the water brush starts moving." + stopsound(sound) : "Sound played when the water brush stops moving." + WaveHeight(string) : "Wave Height" : "3.0" + + // Inputs + input Open(void) : "Move the water brush to the end position (starting position + (move direction * move distance))." + input Close(void) : "Move the water brush to the starting position." + input SetPosition(string) : "Move the water brush to a specific position between 0.0 and 1.0, where 0 is the starting position and 1 is the starting position + (move direction * move distance)." + + // Outputs + output OnFullyOpen(void) : "Fired when the water brush reaches the end position (starting position + (move direction * move distance))." + output OnFullyClosed(void) : "Fired when the water brush reaches the starting position." +] + +@SolidClass base(Targetname, Parentname, Origin, Angles, RenderFields, Shadow) = func_rotating : + "A rotating brush entity." +[ + maxspeed(integer) : "Max Rotation Speed" : 100 : "The maximum rotation speed of the brushes, in degrees per second." + fanfriction(integer) : "Friction (0 - 100%)" : 20 : "The amount of rotational friction. Value must be between 0 and 100 %." + message(sound) : "Rotating sound WAV" : : "Sound to play while rotating." + volume(integer) : "Volume (10 = loudest)" : 10 : "The volume of the rotation sound." + spawnflags(flags) = + [ + 1 : "Start ON" : 0 + 2 : "Reverse Direction" : 0 + 4 : "X Axis" : 0 + 8 : "Y Axis" : 0 + 16: "Acc/Dcc" : 0 + 32: "Fan Pain" : 0 + 64: "Not Solid" : 0 + 128: "Small Sound Radius" : 0 + 256: "Medium Sound Radius" : 0 + 512: "Large Sound Radius" : 1 + ] + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + dmg(integer) : "Blocking Damage" : 0 : "Damage done to any entity that blocks the rotation, per frame." + + solidbsp(choices) : "Solid Type" : 0 = + [ + 0 : "VPhysics" + 1 : "BSP" + ] + + // Inputs + input SetSpeed(integer) : "Set the speed as a ratio of the specified Max Rotation Speed, where 0 is stopped and 1 is the Max Rotation Speed.." + input Start(void) : "Start the rotator rotating." + input Stop(void) : "Stop the rotator from rotating." + input StopAtStartPos(void) : "Stop the rotator from rotating when it gets around to the start position again (on its rotation axis)." + input StartForward(void) : "Start the rotator rotating forward." + input StartBackward(void) : "Start the rotator rotating backward." + input Toggle(void) : "Toggle the rotator between rotating and not rotating." + input Reverse(void) : "Reverse the direction of rotation of the rotator." +] + +@SolidClass base(Targetname, Parentname, Origin, Angles, RenderFields, BasePlat, Shadow) = func_platrot : + "A brush entity that moves vertically, and can rotate while doing so." +[ + spawnflags(Flags) = + [ + 1: "Toggle" : 1 + 64: "X Axis" : 0 + 128: "Y Axis" : 0 + ] + noise1(sound) : "Movement Sound" : : "The sound to play when the brush moves." + noise2(sound) : "Stop Sound" : : "The sound to play when the brush stops moving." + speed(integer) : "Speed of Rotation" : 50 : "Speed at which the brush rotates, in degrees per second." + height(integer) : "Travel Altitude" : 0 : "The vertical distance from the starting position that this platform moves. If negative, the platform will lower." + rotation(integer) : "Spin amount" : 0 : "The amount this platform should rotate as it moves, in degrees." + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." +] + +@KeyFrameClass base(Targetname, Parentname, Angles, KeyFrame) size(-6 -6 -6, 6 6 6) color(255 200 0) keyframe() = keyframe_track : + "Animation KeyFrame" +[ +] + +@MoveClass base(Targetname, Parentname, KeyFrame, Mover) size(-8 -8 -8, 8 8 8) color(255 170 0) animator() = move_keyframed : + "Keyframed Move Behavior" +[ +] + +@MoveClass base(Targetname, Parentname, Mover, KeyFrame) size(-8 -8 -8, 8 8 8) color(255 0 0) animator() = move_track : + "Track Move Behavior" +[ + WheelBaseLength(integer) : "Distance between the wheels" : 50 + Damage(integer) : "Damage done to blocking entities" : 0 + NoRotate(choices) : "Turn to face down path" : 0 = + [ + 0 : "Yes" + 1 : "No" + ] +] + +//------------------------------------------------------------------------- +// +// Ropes and Cables +// +//------------------------------------------------------------------------- +@BaseClass base(DXLevelChoice) = RopeKeyFrame +[ + spawnflags(Flags) = + [ + 1 : "Auto Resize" : 0 + ] + + Slack(integer) : "Slack" : 25 : "How much extra length the rope has (by default it has the length between its two endpoints in the editor)." + + Type(choices) : "Type" : 0 = + [ + 0 : "Rope" + 1 : "Semi-rigid" + 2 : "Rigid" + ] + + Subdiv(integer) : "Subdivision" : 2 : "Number of subdivisions between each rope segment. Maximum value is 8. Higher values make smoother ropes, but are slower to render." + + Barbed(choices) : "Barbed" : 0 : "Test effect that makes the rope look sharper and more barbed." = + [ + 0 : "No" + 1 : "Yes" + ] + + Width(string) : "Width (1-64)" : "2" : "Width of the rope." + + TextureScale(string) : "Texture Scale" : "1" : "This changes the texture resolution. The default resolution is 4 pixels per inch. Larger values stretch the texture and smaller values scrunch it up." + + Collide(choices) : "Collide with world" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + Dangling(choices) : "Start Dangling" : 0 : "When set to Yes, the rope starts out detached from its target endpoint." = + [ + 0 : "No" + 1 : "Yes" + ] + + Breakable(choices) : "Breakable" : 0 : "When set to yes, the rope can be detached from either endpoint when shot." = + [ + 0 : "No" + 1 : "Yes" + ] + + RopeMaterial(material) : "Rope Material" : "cable/cable.vmt" : "The material to use when rendering the rope." + + // Inputs + input SetScrollSpeed(float) : "Set the speed at which the texture scrolls." + input SetForce(string) : "Apply a force instantaneously to the rope. The parameter should be a vector containing the force to be applied (X Y Z)." + input Break(void) : "Break the rope, if it's marked to do so." +] + +@KeyFrameClass base(Targetname, Parentname, KeyFrame, RopeKeyFrame) studio("models/editor/axis_helper_thick.mdl") keyframe() = keyframe_rope : + "A node entity that marks a point in a rope. The first node in the rope should be a move_rope, followed by 1 or more keyframe_ropes." +[ +] + +@MoveClass base(Targetname, Parentname, KeyFrame, RopeKeyFrame) studio("models/editor/axis_helper.mdl") animator() = move_rope : + "The first node in set of nodes that are used to place ropes in the world. It should connect to 1 or more keyframe_rope entities." +[ + PositionInterpolator(choices) : "Position Interpolator" : 2 : "Curve Type. Currently only type 2 (Rope) is fully supported." = + [ + 0 : "Linear" + 1 : "Catmull-Rom Spline" + 2 : "Rope" + ] +] + + +//------------------------------------------------------------------------- +// +// Buttons +// +//------------------------------------------------------------------------- + +@BaseClass = Button +[ + // Inputs + input Lock(void) : "Lock the button, preventing it from functioning." + input Unlock(void) : "Unlock the button, allowing it to function." + input Press(void) : "Activate the button, as if it was pressed." + + // Outputs + output OnDamaged(void) : "Fired when the button is damaged." + output OnPressed(void) : "Fired when the button is pressed." + output OnUseLocked(void) : "Fired when the button is used while locked." + output OnIn(void) : "Fired when the button reaches the in/pressed position." + output OnOut(void) : "Fired when the button reaches the out/released position." +] + +@SolidClass base(Targetname, Parentname, Origin, RenderFields, Button) = func_button : + "A brush entity that's designed to be used for a player-useable button. When used by the player, it moves to a pressed position." +[ + movedir(angle) : "Move Direction (Pitch Yaw Roll)" : "0 0 0" : "Specifies the direction of motion to move when the button is used." + speed(integer) : "Speed" : 5 : "The speed that the button moves, in inches per second." + health(integer) : "Health (Obsolete)" : 0 : "Legacy method of specifying whether or not the button can be shot to activate it. Use the 'Damage Activates' spawnflag instead." + lip(integer) : "Lip" : 0 : "The amount, in inches, of the button to leave sticking out of the wall it recedes into when pressed. Negative values make the button recede even further into the wall." + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this button cannot be pressed." + sounds(choices) : "Sounds" : 0 = + [ + 0: "None (Silent)" + 1: "Big zap & Warmup" + 2: "Access Denied" + 3: "Access Granted" + 4: "Quick Combolock" + 5: "Power Deadbolt 1" + 6: "Power Deadbolt 2" + 7: "Plunger" + 8: "Small zap" + 9: "Keycard Sound" + 10: "Buzz" + 11: "Buzz Off" + 12: "latch locked" + 13: "Latch Unlocked" + 14: "Lightswitch" + 15: "small bleek" + 16: "small deny" + 17: "small doop" + 18: "small tech deny" + 19: "click and combine screen fuzz" + 20: "roomy beep" + 21: "lever or wheel: turn + move sqeek" + 22: "lever or wheel: latch + release gas" + 23: "lever or wheel: ratchet + sqeek" + 24: "lever or wheel: large ratchet" + 25: "lever or wheel: clanky + gas release" + 26: "lever or wheel: latch + large metal thud" + 27: "lever or wheel: smaller ratchet" + 28: "lever or wheel: smaller lever move" + 31: "shock buzz" + 32: "clickbeep" + 33: "tech blip" + 34: "clickbeepbeep open" + 35: "small high blip" + 36: "small tech fuzz blip" + 37: "small click bleep (change to lightswitch)" + 40: "combine door lock - locked" + 41: "combine blip growl" + 42: "combine squick growl" + 43: "combine whine purr" + 44: "combine click talk" + 45: "combine click growl fizz" + 46: "combine click fizz (deny)" + 47: "combine click talker" + ] + wait(integer) : "Delay Before Reset (-1 stay)" : 3 : "Amount of time, in seconds, after the button has been pressed before it returns to the starting position. Once it has returned, it can be used again. If the value is set to -1, the button never returns." + spawnflags(flags) = + [ + 1: "Don't move" : 0 + 32: "Toggle" : 0 + 256: "Touch Activates": 0 + 512: "Damage Activates": 0 + 1024: "Use Activates" : 1 + 2048: "Starts locked" : 0 + 4096: "Sparks" : 0 + ] + locked_sound(choices) : "Locked Sound" : 0 : "Sound played when the player tries to use the button, and fails because it's locked." = + [ + 0: "None" + 2: "Access Denied" + 8: "Small zap" + 10: "Buzz" + 11: "Buzz Off" + 12: "Latch Locked" + ] + unlocked_sound(choices) : "Unlocked Sound" : 0 : "Sound played when the button is unlocked." = + [ + 0: "None" + 1: "Big zap & Warmup" + 3: "Access Granted" + 4: "Quick Combolock" + 5: "Power Deadbolt 1" + 6: "Power Deadbolt 2" + 7: "Plunger" + 8: "Small zap" + 9: "Keycard Sound" + 10: "Buzz" + 13: "Latch Unlocked" + 14: "Lightswitch" + ] + locked_sentence(choices) : "Locked Sentence" : 0 : "A sentence played when the player tries to use the button, and fails because it's locked." = + [ + 0: "None" + 1: "Gen. Access Denied" + 2: "Security Lockout" + 3: "Blast Door" + 4: "Fire Door" + 5: "Chemical Door" + 6: "Radiation Door" + 7: "Gen. Containment" + 8: "Maintenance Door" + 9: "Broken Shut Door" + ] + unlocked_sentence(choices) : "Unlocked Sentence" : 0 : "A sentence played when the button is unlocked." = + [ + 0: "None" + 1: "Gen. Access Granted" + 2: "Security Disengaged" + 3: "Blast Door" + 4: "Fire Door" + 5: "Chemical Door" + 6: "Radiation Door" + 7: "Gen. Containment" + 8: "Maintenance area" + ] + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." +] + +@SolidClass base(Targetname, Parentname, Origin, Angles, Global, Button, EnableDisable) = func_rot_button : + "A brush entity that's designed to be used for a rotating player-useable button. When used by the player, it rotates to a pressed position." +[ + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this button cannot be used." + speed(integer) : "Speed" : 50 : "The speed that the button rotates, in degrees per second." + health(integer) : "Health (Obsolete)" : 0 : "Legacy method of specifying whether or not the button can be shot to activate it. Use the 'Damage Activates' spawnflag instead." + sounds(choices) : "Sounds" : 21 = + [ + 0: "None (Silent)" + 21: "Squeaky" + 22: "Squeaky Pneumatic" + 23: "Ratchet Groan" + 24: "Clean Ratchet" + 25: "Gas Clunk" + ] + wait(integer) : "Delay Before Reset (-1 stay)" : 3 : "Amount of time, in seconds, after the button has been pressed before it returns to the starting position. Once it has returned, it can be used again. If the value is set to -1, the button never returns." + distance(integer) : "Distance (deg)" : 90 : "The amount, in degrees, that the button should rotate when it's pressed." + // TODO: move spawnflags into Button base class? + spawnflags(flags) = + [ + 1 : "Not solid" : 0 + 2 : "Reverse Dir" : 0 + 32: "Toggle" : 0 + 64: "X Axis" : 0 + 128: "Y Axis" : 0 + 256: "Touch Activates": 0 + 512: "Damage Activates": 0 + 1024: "Use Activates": 0 + 2048: "Starts locked" : 0 + ] + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." +] + +@SolidClass base(Targetname, Parentname, Origin, Angles, RenderFields) = momentary_rot_button : + "A brush entity that's designed to be used for rotating wheels, where the player can rotate them to arbitrary positions before stopping." +[ + speed(integer) : "Speed (deg/sec)" : 50 : "The amount, in degrees, that the wheel turns per second." + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this button cannot be used." + sounds(choices) : "Sounds" : 0 = + [ + 0: "None" + 1: "Big zap & Warmup" + 2: "Access Denied" + 3: "Access Granted" + 4: "Quick Combolock" + 5: "Power Deadbolt 1" + 6: "Power Deadbolt 2" + 7: "Plunger" + 8: "Small zap" + 9: "Keycard Sound" + 21: "Squeaky" + 22: "Squeaky Pneumatic" + 23: "Ratchet Groan" + 24: "Clean Ratchet" + 25: "Gas Clunk" + ] + distance(integer) : "Distance" : 90 : "The maximum amount, in degrees, that the wheel is allowed to rotate." + returnspeed(integer) : "Auto-return speed" : 0 : "If the 'Toggle' spawnflag is not set, the speed at which the wheel auto-returns when left alone, in degrees per second." + spawnflags(flags) = + [ + 1: "Not Solid" : 1 + 32: "Toggle (Disable Auto Return)" : 1 + 64: "X Axis" : 0 + 128: "Y Axis" : 0 + 1024: "Use Activates" : 1 + 2048: "Starts locked" : 0 + 8192: "Jiggle when used while locked" : 0 + ] + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + startposition(float) : "Start Position" : 0 : "Postion when spawned. The value is a range between 0.0 and 1.0, where 0 is the unrotated position and 1 is the rotated position + 'Distance'." + startdirection(choices) : "Start Direction" : "Forward" = + [ + -1 : "Forward" // Reverses upon USE, so are + 1 : "Backward" // reversed here. + ] + solidbsp(choices) : "Solid BSP" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Lock(void) : "Lock the button, preventing it from functioning." + input Unlock(void) : "Unlock the button, allowing it to function." + input SetPosition(string) : "Move to a position. The parameter must be a value between 0 and 1, where 0 is the unrotated position and 1 is the rotated position + 'Distance'." + input SetPositionImmediately(string) : "Immediately teleport to a position. The parameter must be a value between 0 and 1, where 0 is the unrotated position and 1 is the rotated position + 'Distance'." + + // Outputs + output Position(integer) : "Fired whenever the button moves. The output is the position of button from 0 to 1, where 0 is the unrotated position and 1 is the rotated position + 'Distance'." + output OnPressed(integer) : "Fired when the button is first pressed." + output OnUnpressed(integer): "Fired when the button is first released from being pressed." + output OnFullyClosed(void) : "Fired when the button has reached position 1, the rotated position + 'Distance'." + output OnFullyOpen(void) : "Fired when the button has reached position 0, the unrotated starting position." + output OnReachedPosition(void) : "Fired whenever the button reaches a goal position: i.e. when it becomes open, becomes closed, or reaches the point specified by a 'SetPosition' input." +] + + +//------------------------------------------------------------------------- +// +// Doors +// +//------------------------------------------------------------------------- + +@BaseClass base(Targetname, Parentname, RenderFields, Global, Shadow) = Door +[ + speed(integer) : "Speed" : 100 : "The speed at which the door moves." + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this button cannot be used." + noise1(sound) : "Start Sound" : : "Sound to play when the door starts moving." + noise2(sound) : "Stop Sound" : : "Sound to play when the door stops moving." + wait(integer) : "Delay Before Reset (-1 stay)" : 4 : "Amount of time, in seconds, after the door has opened before it closes. Once it has closed, it can be used again. If the value is set to -1, the door never closes itself." + lip(integer) : "Lip" : 0 : "The amount, in inches, of the button to leave sticking out of the wall it recedes into when pressed. Negative values make the button recede even further into the wall." + dmg(integer) : "Blocking Damage" : 0 : "Amount of damage done to entities that block the movement of this door, per frame." + forceclosed(choices) : "Force Closed" : 0 : "If set, this door will close no matter what. Useful for doors that have to close even if the player tries to block them with objects." = + [ + 0 : "No" + 1 : "Yes" + ] + ignoredebris(choices) : "Ignore Debris" : 0 : "If set this will change the door's collision group to one that ignore collisions with debris objects (note that this is not compatible with the non-solid-to-player spawnflag)." = + [ + 0 : "No" + 1 : "Yes" + ] + + message(string) : "Message If Triggered" // NEEDHELP: Looks like this was removed + health(integer) : "Health (shoot open)" : 0 // NEEDHELP: Looks like this was removed + + locked_sound(sound) : "Locked Sound" : : "Sound played when the player tries to use the door, and fails because it's locked." + unlocked_sound(sound) : "Unlocked Sound" : : "Sound played when the button is door." + + spawnflags(flags) = + [ + 1 : "Starts Open" : 0 + 4 : "Non-solid to Player" : 0 + 8: "Passable" : 0 + 32: "Toggle" : 0 + 256:"Use Opens" : 0 + 512: "NPCs Can't" : 0 + 1024: "Touch Opens" : 1 + 2048: "Starts locked" : 0 + 4096: "Door Silent" : 0 + ] + locked_sentence(choices) : "Locked Sentence" : 0 : "A sentence played when the player tries to use the door, and fails because it's locked." = + [ + 0: "None" + 1: "Gen. Access Denied" + 2: "Security Lockout" + 3: "Blast Door" + 4: "Fire Door" + 5: "Chemical Door" + 6: "Radiation Door" + 7: "Gen. Containment" + 8: "Maintenance Door" + 9: "Broken Shut Door" + ] + unlocked_sentence(choices) : "Unlocked Sentence" : 0 : "A sentence played when the door is unlocked." = + [ + 0: "None" + 1: "Gen. Access Granted" + 2: "Security Disengaged" + 3: "Blast Door" + 4: "Fire Door" + 5: "Chemical Door" + 6: "Radiation Door" + 7: "Gen. Containment" + 8: "Maintenance area" + ] + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + loopmovesound(choices) : "Loop Moving Sound?" : 0 : "If set to true, the door's 'Start Sound' will be continually looped until the door finishes moving." = + [ + 0: "No" + 1: "Yes" + ] + + // Outputs + output OnClose(void) : "Fired when the door starts closing." + output OnOpen(void) : "Fired when the door starts opening." + output OnFullyOpen(void) : "Fired when the door reaches the fully open position." + output OnFullyClosed(void) : "Fired when the door reaches the fully closed position." + output OnBlockedClosing(void) : "Fired when the door is blocked while closing." + output OnBlockedOpening(void) : "Fired when the door is blocked while opening." + output OnUnblockedClosing(void) : "Fired when the door is unblocked while closing." + output OnUnblockedOpening(void) : "Fired when the door is unblocked while opening." + + // Inputs + input Open(void) : "Open the door, if it is not fully open." + input Close(void) : "Close the door, if it is not fully closed." + input Toggle(void) : "Toggle the door between open and closed." + input Lock(void) : "Lock the door." + input Unlock(void) : "Unlock the door." + input SetSpeed(float) : "Set the door speed." +] + +@SolidClass base(Door, Origin) = func_door : + "A brush entity for use as a player-useable door." +[ + movedir(angle) : "Move Direction (Pitch Yaw Roll)" : "0 0 0" : "The direction the door will move, when it opens." + + filtername(filterclass) : "Block Filter Name" : : "Filter to use to determine entities that block the door. ( Half-Life: Source port only )" +] + +@SolidClass base(Door, Origin, Angles) = func_door_rotating : + "A brush entity for use as a rotating player-useable door." +[ + spawnflags(flags) = + [ + 2 : "Reverse Dir" : 0 + 16: "One-way" : 0 + 64: "X Axis" : 0 + 128: "Y Axis" : 0 + ] + distance(integer) : "Distance" : 90 : "The amount, in degrees, that the button should rotate when it's pressed." + + solidbsp(choices) : "Solid Type" : 0 = + [ + 0 : "VPhysics" + 1 : "BSP" + ] +] + +@PointClass base(Targetname, Parentname, Angles, Global, Studiomodel) studioprop() = prop_door_rotating : + "An entity used to place a door in the world." +[ + slavename(target_destination) : "Slave Name" : : "The name of any doors that should be slaved to this door (i.e. should open when this one opens, and close when this one closes)." + hardware(choices) : "Hardware Type" : 1 = + [ + 0 : "" + 1 : "Lever" + 2 : "Push bar" + 3 : "Keypad" + ] + + ajarangles(angle) : "Ajar Angles (Pitch Yaw Roll)" : "0 0 0" : "If the door 'Spawn Position' is set to Ajar, these are the angles to spawn at, instead of being open or closed." + spawnpos(choices) : "Spawn Position" : 0 = + [ + 0 : "Closed" + 1 : "Open forward" + 2 : "Open back" + 3 : "Ajar (use Ajar Angles)" + ] + + axis(axis) : "Hinge Axis" + distance(float) : "Rotation Distance (deg)" : 90 : "The amount, in degrees, that the door should rotate when opened." + speed(integer) : "Speed" : 100 : "The speed at which the door moves." + soundopenoverride(sound) : "Fully Open Sound" : : "Sound played when the door has finished opening." + soundcloseoverride(sound) : "Fully Closed Sound" : : "Sound played when the door has finished closing." + soundmoveoverride(sound) : "Moving Sound" : : "Sound played when the door starts to move." + returndelay(integer) : "Delay Before close (-1 stay open)" : -1 : "Amount of time, in seconds, after the door has opened before it closes. If the value is set to -1, the door never closes itself." + dmg(integer) : "Damage Inflicted When Blocked" : 0 : "Amount of damage done to entities that block the movement of this door, per frame." + health(integer) : "Health (0 = Unbreakable)" : 0 // NEEDHELP: Doesn't look like this is hooked up anymore? + soundlockedoverride(sound) : "Locked Sound" : : "Sound played when the player tries to open the door, and fails because it's locked." + soundunlockedoverride(sound) : "Unlocked Sound" : : "Sound played when the door is unlocked." + + forceclosed(choices) : "Force Closed" : 0 : "If set, this door will close no matter what. Useful for doors that have to close even if the player tries to block them with objects." = + [ + 0 : "No" + 1 : "Yes" + ] + + spawnflags(flags) = + [ + 1 : "Starts Open" : 0 + //512: "NPCs Can't" : 0 + 2048: "Starts locked" : 0 + 4096: "Door silent (No sound, and does not alert NPCs)" : 0 + 8192: "Use closes" : 1 + 16384 : "Door silent to NPCS (Does not alert NPCs)" : 0 + 32768 : "Ignore player +USE" : 0 + ] + + opendir(choices) : "Open Direction" : 0 : "Force the door to open only forwards or only backwards. Both directions is the standard door behavior." = + [ + 0 : "Open Both Directions" + 1 : "Open Forward Only" + 2 : "Open Backward Only" + ] + + // Outputs + output OnClose(void) : "Fired when the door is told to close." + output OnOpen(void) : "Fired when the door is told to open." + output OnFullyOpen(void) : "Fired when the door reaches the fully open position." + output OnFullyClosed(void) : "Fired when the door reaches the fully closed position." + output OnBlockedClosing(void) : "Fired when the door is blocked while closing." + output OnBlockedOpening(void) : "Fired when the door is blocked while opening." + output OnUnblockedClosing(void) : "Fired when the door is unblocked while closing." + output OnUnblockedOpening(void) : "Fired when the door is unblocked while opening." + + // Inputs + input Open(void) : "Open the door, if it is not fully open." + input OpenAwayFrom(string) : "Open the door away from the specified entity." + input Close(void) : "Close the door, if it is not fully closed." + input Toggle(void) : "Toggle the door between open and closed." + input Lock(void) : "Lock the door." + input Unlock(void) : "Unlock the door." + input SetRotationDistance(float) : "Set the distance (in degrees) between Open and Closed." +] + + +//------------------------------------------------------------------------- +// +// Cube map sample +// +//------------------------------------------------------------------------- + +@PointClass color(0 0 255) sidelist(sides) iconsprite("editor/env_cubemap.vmt") = env_cubemap : + "An entity that creates a sample point for the Cubic Environment Map." +[ + cubemapsize(choices) : "Cubemap Size" : 0 = + [ + 0 : "Default" + 1 : "1x1" + 2 : "2x2" + 3 : "4x4" + 4 : "8x8" + 5 : "16x16" + 6 : "32x32" + 7 : "64x64" + 8 : "128x128" + 9 : "256x256" + ] + sides(sidelist) : "Brush faces": : "(Optional) Brushes faces to directly attach to the env_cubemap. Press Pick then click on faces in the 3D View to select them. Use CTRL while clicking to add or remove from the selection." +] + +@BaseClass = BModelParticleSpawner +[ + StartDisabled(choices) : "Start Disabled" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + Color(color255) : "Particle Color (R G B)" : "255 255 255" + SpawnRate(integer) : "Particle Per Second" : 40 : "Number of particles to spawn, per second." + SpeedMax(string) : "Maximum Particle Speed" : 13 : "Maximum speed that the particles can move after spawning." + LifetimeMin(string) : "Minimum Particle Lifetime" : 3 : "Minimum number of seconds until each particle dies. Particles live for a random duration between this and 'Maximum Particle Lifetime'." + LifetimeMax(string) : "Maximum Particle Lifetime" : 5 : "Maximum number of seconds until each particle dies. Particles live for a random duration between 'Minimum Particle Lifetime' and this." + DistMax(integer) : "Maximum Visible Distance" : 1024 : "Maximum distance at which particles are visible. They fade to translucent at this distance." + + Frozen(choices) : "Frozen" : 0 : "When set, this entity spawns the number of particles in SpawnRate immediately, and then goes inactive." = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input TurnOn(void) : "Turn on." + input TurnOff(void) : "Turn off." +] + +@SolidClass base(Targetname, BModelParticleSpawner) = func_dustmotes : + "A brush entity that spawns sparkling dust motes within its volume." +[ + SizeMin(string) : "Minimum Particle Size" : 10 + SizeMax(string) : "Maximum Particle Size" : 20 + + Alpha(integer) : "Alpha" : 255 +] + +@SolidClass base( Targetname ) = func_smokevolume : + "A brush entity that spawns smoke particles within its volume." +[ + spawnflags(flags) = + [ + 1 : "Emissive" : 0 + ] + + Color1(color255) : "Particle Color1 (R G B)" : "255 255 255" + Color2(color255) : "Particle Color2 (R G B)" : "255 255 255" + material(material) : "Material" : "particle/particle_smokegrenade" : "The material to use for the particles" + ParticleDrawWidth(float) : "Particle Draw Width (units)" : 120 : "The size of the particles, in units/inches." + ParticleSpacingDistance(float) : "Particle Spacing Distance (units)" : 80 : "The distance between the particles inside the volume. The lower the number, the denser the particles, and the more overdraw there will be. It is best to keep it as high as you can without it looking bad." + DensityRampSpeed(float) : "Density Ramp Speed (seconds)" : 1 : "Time to go from density 0 to density 1, in seconds." + + RotationSpeed(float) : "Rotation Speed (degrees/sec)" : 10 : "The speed that the particles should rotate, in degrees per second." + MovementSpeed(float) : "Movement Speed (units/sec)" : 10 : "The speed that the particles should move around, in units/inches per second." + Density(float) : "Density [0..1]" : 1 + + // Inputs + input SetRotationSpeed(float) : "Set the particle rotation speed (in degrees per second)." + input SetMovementSpeed(float) : "Set the particle movement speed (in inches per second)." + input SetDensity(float) : "Set the particle density. It should be a range from 0 to 1." +] + +@SolidClass base( Targetname, BModelParticleSpawner ) = func_dustcloud : + "A brush entity that spawns a translucent dust cloud within its volume." +[ + Alpha(integer) : "Alpha" : 30 + + SizeMin(string) : "Minimum Particle Size" : 100 + SizeMax(string) : "Maximum Particle Size" : 200 +] + +@PointClass base( Targetname, Parentname, Angles ) size( -8 -8 -8, 8 8 8 ) = env_dustpuff : + "An entity that can emit dust puffs." +[ + scale(float) : "Scale" : 8 : "Size of the dust puff." + speed(float) : "Speed" : 16 : "Speed at which the dust particles should move." + + color(color255) : "Dust color" : "128 128 128" + + // Inputs + input SpawnDust(void) : "Spawn a dust puff." +] + +@PointClass base( Targetname, Parentname, Angles ) size( -8 -8 -8, 8 8 8 ) = env_particlescript : + "An entity that has special animation events that can be fired by a model with an animation inside its .qc designed for"+ + "use by this entity." +[ + model(studio) : "Script Model" : "models/Ambient_citadel_paths.mdl" : "Model to use for animation sequences." + + // Inputs + input SetSequence(string) : "Sets the script model's sequence." +] + + +// NEEDHELP +@PointClass base( Targetname, Parentname, Angles ) size( -8 -8 -8, 8 8 8 ) = env_effectscript : + "An entity that allows you to script special visual effects via a script file." +[ + model(studio) : "Script Model" : "models/Effects/teleporttrail.mdl" : "Model to use for animation sequences." + scriptfile(string) : "Script File" : "scripts/effects/testeffect.txt" : "Name of the script to use for this model." + + // Inputs + input SetSequence(string) : "Sets the script model's sequence." +] + + +//------------------------------------------------------------------------- +// +// Logic Entities +// +//------------------------------------------------------------------------- + +@PointClass iconsprite("editor/logic_auto.vmt") = logic_auto : + "Fires outputs when a map spawns. " + + "If 'Remove on fire' flag is set the logic_auto is deleted after firing. " + + "It can be set to check a global state before firing. This allows you to only fire events based on "+ + "what took place in a previous map." +[ + spawnflags(Flags) = + [ + 1 : "Remove on fire" : 1 + ] + + globalstate(choices) : "Global State to Read" : : "If set, this specifies a global state to check before firing. The OnMapSpawn output will only fire if the global state is set." = + [ + "" : "--- None ---" + "gordon_precriminal" : "Gordon pre-criminal" + "antlion_allied" : "Antlions are player allies" +// "player_stealth" : "Player in APC is disguised as combine" + "suit_no_sprint" : "Suit sprint function not yet enabled" + "super_phys_gun" : "Super phys gun is enabled" + "friendly_encounter" : "Friendly encounter sequence (lower weapons, etc.)" +// "citizens_passive" : "Citizens are *not* player allies (cannot be commanded)" + "gordon_invulnerable" : "Gordon is invulnerable" + "no_seagulls_on_jeep" : "Don't spawn seagulls on the jeep" + ] + + // Outputs + output OnMapSpawn(void) : "Fired when the map is loaded for any reason." + output OnNewGame(void) : "Fired when the map is loaded to start a new game." + output OnLoadGame(void) : "Fired when the map is loaded from a saved game." + output OnMapTransition(void) : "Fired when the map is loaded due to a level transition." + output OnBackgroundMap(void) : "Fired when the map is loaded as a background to the main menu." +] + +@PointClass base(Targetname,Angles,Parentname) studioprop("models/editor/camera.mdl") = point_viewcontrol : + "A camera entity that controls the player's view. While it's active, the player will see out of the camera." +[ + target(target_destination) : "Entity to Look At" : : "Name of the entity that the camera should point at and track while active." + targetattachment(string) : "Target Attachment Name" : : "If set, the camera will focus on the specified attachment on the 'Entity to Look At'." + wait(integer) : "Hold Time" : 10 : "The amount of time the camera should control the player's view for, after which it deactivates itself. If the camera should stay active until told to deactive, set the 'Infinite Hold Time' spawnflag." + moveto(target_destination) : "Path Corner" : : "The first path corner in a track that the camera should move along once it's activated. If not specified, the camera won't move." + spawnflags(flags) = + [ + 1: "Start At Player" : 1 + 2: "Follow Player" : 1 + 4: "Freeze Player" : 0 + 8: "Infinite Hold Time" : 0 + 16:"Snap to goal angles" : 0 + 32:"Make Player non-solid" : 0 + 64:"Interruptable by Player" : 0 + ] + speed(string) : "Initial Speed" : "0" : "The starting speed that the camera moves at, if it's on a path track." + acceleration(string) : "Acceleration units/sec^2" : "500" : "The speed at which the camera accelerates to path corner's desired speeds." + deceleration(string) : "Stop Deceleration units/sec^2" : "500" : "The speed at which the camera decelerates to path corner's desired speeds." + + // Inputs + input Enable(void) : "Enable the point_viewcontrol, and start controlling the player's view." + input Disable(void) : "Disable the point_viewcontrol, and stop controlling the player's view." + + // Outputs + output OnEndFollow(void) : "Fired when the point_viewcontrol deactivates, due to the Disable input being received, the Entity to Look At being destroyed, or the Hold Time expiring." +] + +@PointClass base(Targetname) iconsprite("editor/logic_compare.vmt") = logic_compare : + "Compares an input value to another value. " + + "If the input value is less than the compare value, the OnLessThan output is fired with the input value. " + + "If the input value is equal to the compare value, the OnEqualTo output is fired with the input value. " + + "If the input value is greater than the compare value, the OnGreaterThan output is fired with the input value." +[ + // Keys + InitialValue(integer) : "Initial value" : : "Initial value for the input value." + CompareValue(integer) : "Compare value" : : "The value to compare against." + + // Inputs + input SetValue(float) : "Set the value that will be compared against the compare value." + input SetValueCompare(float) : "Set the value that will be compared against the compare value and performs the comparison." + input SetCompareValue(float) : "Set the compare value." + input Compare(void) : "Force a compare of the input value with the compare value." + + // Outputs + output OnLessThan(float) : "Fired when the input value is less than the compare value. Sends the input value as data." + output OnEqualTo(float) : "Fired when the input value is equal to the compare value. Sends the input value as data." + output OnNotEqualTo(float) : "Fired when the input value is different from the compare value. Sends the input value as data." + output OnGreaterThan(float) : "Fired when the input value is greater than the compare value. Sends the input value as data." +] + +@PointClass base(Targetname) iconsprite("editor/logic_branch.vmt") = logic_branch : + "Tests a boolean value and fires an output based on whether the value is true or false. " + + "Use this entity to branch between two potential sets of events." +[ + // Keys + InitialValue(integer) : "Initial value" : : "Initial value for the boolean value (0 or 1)." + + // Inputs + input SetValue(bool) : "Set the boolean value without performing the comparison. Use this to hold a value for a future test." + input SetValueTest(bool) : "Set the boolean value and test it, firing OnTrue or OnFalse based on the new value." + input Toggle(void) : "Toggle the boolean value between true and false." + input ToggleTest(void) : "Toggle the boolean value and tests it, firing OnTrue or OnFalse based on the new value." + input Test(void) : "Test the input value and fire OnTrue or OnFalse based on the value." + + // Outputs + output OnTrue(bool) : "Fired when the input value is true (nonzero)." + output OnFalse(bool) : "Fired when the input value is false (zero)." +] + + +@PointClass base(Targetname) = logic_branch_listener : + "Contains a list of logic_branch entities and fires outputs when the state of any of the logic_branches changes.\n\n"+ + "This entity is used to fire an event when a set of conditions are all satisfied." +[ + Branch01(target_destination) : "Logic Branch 01" : : "The name of one or more logic_branches (wildcards allowed)." + Branch02(target_destination) : "Logic Branch 02" : : "The name of one or more logic_branches (wildcards allowed)." + Branch03(target_destination) : "Logic Branch 03" : : "The name of one or more logic_branches (wildcards allowed)." + Branch04(target_destination) : "Logic Branch 04" : : "The name of one or more logic_branches (wildcards allowed)." + Branch05(target_destination) : "Logic Branch 05" : : "The name of one or more logic_branches (wildcards allowed)." + Branch06(target_destination) : "Logic Branch 06" : : "The name of one or more logic_branches (wildcards allowed)." + Branch07(target_destination) : "Logic Branch 07" : : "The name of one or more logic_branches (wildcards allowed)." + Branch08(target_destination) : "Logic Branch 08" : : "The name of one or more logic_branches (wildcards allowed)." + Branch09(target_destination) : "Logic Branch 09" : : "The name of one or more logic_branches (wildcards allowed)." + Branch10(target_destination) : "Logic Branch 10" : : "The name of one or more logic_branches (wildcards allowed)." + Branch11(target_destination) : "Logic Branch 11" : : "The name of one or more logic_branches (wildcards allowed)." + Branch12(target_destination) : "Logic Branch 12" : : "The name of one or more logic_branches (wildcards allowed)." + Branch13(target_destination) : "Logic Branch 13" : : "The name of one or more logic_branches (wildcards allowed)." + Branch14(target_destination) : "Logic Branch 14" : : "The name of one or more logic_branches (wildcards allowed)." + Branch15(target_destination) : "Logic Branch 15" : : "The name of one or more logic_branches (wildcards allowed)." + Branch16(target_destination) : "Logic Branch 16" : : "The name of one or more logic_branches (wildcards allowed)." + + input Test(void) : "Tests the state of all the logic_branches in the list and fires the appropriate output." + + output OnAllTrue(void) : "Fired when all the logic_branches in the list become true." + output OnAllFalse(void) : "Fired when all the logic_branches in the list become false." + output OnMixed(void) : "Fired when one of the logic branches in the list changes, but some are true and some are false." +] + + +@PointClass base(Targetname) iconsprite("editor/logic_case.vmt") = logic_case : + "Compares an input to up to 16 preset values. If the input value is the same as " + + "any of the preset values, an output corresponding to that value is fired.\n\n" + + "For example: if Case01 is set to 2 and Case02 is set to 5, and the input value is 5, " + + "the OnCase02 output will be fired.\n\n" + + "This entity can also be used to select from a number of random targets via the " + + "PickRandom input. One of the OnCase outputs that is connected to another entity will " + + "be picked at random and fired." +[ + Case01(string) : "Case 01" + Case02(string) : "Case 02" + Case03(string) : "Case 03" + Case04(string) : "Case 04" + Case05(string) : "Case 05" + Case06(string) : "Case 06" + Case07(string) : "Case 07" + Case08(string) : "Case 08" + Case09(string) : "Case 09" + Case10(string) : "Case 10" + Case11(string) : "Case 11" + Case12(string) : "Case 12" + Case13(string) : "Case 13" + Case14(string) : "Case 14" + Case15(string) : "Case 15" + Case16(string) : "Case 16" + + // Inputs + input InValue(string) : "Compares the Input value to the case values, and fires the appropriate output, if any." + input PickRandom(void) : "Fires a random OnCase output with at least one connection." + input PickRandomShuffle(void) : "Fires a random OnCase output with at least one connection, with no repeats until all cases have been picked, at which point the shuffle starts over." + + // Outputs + output OnCase01(void) : "Fired when the input value equals the Case01 value." + output OnCase02(void) : "Fired when the input value equals the Case02 value." + output OnCase03(void) : "Fired when the input value equals the Case03 value." + output OnCase04(void) : "Fired when the input value equals the Case04 value." + output OnCase05(void) : "Fired when the input value equals the Case05 value." + output OnCase06(void) : "Fired when the input value equals the Case06 value." + output OnCase07(void) : "Fired when the input value equals the Case07 value." + output OnCase08(void) : "Fired when the input value equals the Case08 value." + output OnCase09(void) : "Fired when the input value equals the Case09 value." + output OnCase10(void) : "Fired when the input value equals the Case10 value." + output OnCase11(void) : "Fired when the input value equals the Case11 value." + output OnCase12(void) : "Fired when the input value equals the Case12 value." + output OnCase13(void) : "Fired when the input value equals the Case13 value." + output OnCase14(void) : "Fired when the input value equals the Case14 value." + output OnCase15(void) : "Fired when the input value equals the Case15 value." + output OnCase16(void) : "Fired when the input value equals the Case16 value." + output OnDefault(void) : "Fired when the input value does not equal any of the Case values." +] + +// NEEDHELP: Unused in HL2, not clear what it's useful for. +@PointClass base(Targetname) iconsprite("editor/logic_multicompare.vmt") = logic_multicompare : + "Compares a set of inputs to each other. If they are all the same, fires an OnEqual output. " + + "If any are different, fires the OnNotEqual output." +[ + // keys + IntegerValue(integer) : "Integer Value (optional)" + ShouldComparetoValue(choices) : "Should use Integer Value" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input InputValue(integer) : "Input value" + input CompareValues(void) : "Compares the values and fires appropriate outputs" + + // Outputs + output OnEqual(void) : "Fires if the values are equal" + output OnNotEqual(void) : "Fires if the values are not equal" +] + +@PointClass base(Targetname, EnableDisable) iconsprite("editor/logic_relay.vmt") = logic_relay : + "A message forwarder. Fires an OnTrigger output when triggered, and " + + "can be disabled to prevent forwarding outputs.\n\n" + + "Useful as an intermediary between one entity and another for turning " + + "on or off an I/O connection, or as a container for holding a set of " + + "outputs that can be triggered from multiple places." +[ + spawnflags(flags) = + [ + 1: "Only trigger once" : 0 + 2: "Allow fast retrigger" : 0 + ] + + // Inputs + input Trigger(void) : "Trigger the relay, causing its OnTrigger output to fire if it is enabled." + input Toggle(void) : "Toggle the relay between enabled and disabled." + input CancelPending(void) : "Cancel any events fired by this relay that are currently pending in the I/O event queue." + + // Outputs + output OnSpawn(void) : "Fired when the relay is spawned. If the relay is set to only trigger once, it will "+ + "delete itself after firing this output." + output OnTrigger(void) : "Fired when the relay is triggered. If the relay is set to only trigger once, it will "+ + "delete itself after firing this output." +] + +@PointClass base(Targetname, EnableDisable) iconsprite("editor/logic_timer.vmt") = logic_timer : + "An entity that fires a timer event at regular, or random, intervals. It can also be set to oscillate between" + + "a high and low end, in which case it will fire alternating high/low outputs each time it fires." +[ + // Keys + spawnflags(flags) = + [ + 1 : "Oscillator (alternates between OnTimerHigh and OnTimerLow outputs)" : 0 + ] + + UseRandomTime(choices) : "Use Random Time" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + + LowerRandomBound(string) : "Minimum Random Interval" : : "If 'Use Random Time' is set, this is the minimum time between timer fires. The time will be a random number between this and the 'Maximum Random Interval'." + UpperRandomBound(string) : "Maximum Random Interval" : : "If 'Use Random Time' is set, this is the maximum time between timer fires. The time will be a random number between the 'Minimum Random Interval' and this." + RefireTime(string) : "Refire Interval" : : "If 'Use Random Time' isn't set, this is the time between timer fires, in seconds." + + // Inputs + input RefireTime(integer) : "Set a new Refire Interval." + input FireTimer(void) : "Force the timer to fire immediately." + input Enable(void) : "Enable the timer." + input Disable(void) : "Disable the timer." + input Toggle(void) : "Toggle the timer on/off." + input LowerRandomBound(float) : "Set a new Minimum Random Interval." + input UpperRandomBound(float) : "Set a new Maximum Random Interval." + + // Outputs + output OnTimer(void) : "Fired when the timer expires." + output OnTimerHigh(void) : "Fired every other time for an oscillating timer." + output OnTimerLow(void) : "Fired every other time for an oscillating timer." +] + +@PointClass base(Targetname) size(-4 -4 -4, 4 4 4) color(0 255 0) = logic_collision_pair : + "An entity that can be used to enables/disable vphysics collisions between two target entities." +[ + attach1(target_destination) : "Attachment 1" : "" : "The first entity." + attach2(target_destination) : "Attachment 2" : "" : "The second entity." + + startdisabled(choices) : "Start with collisions disabled" : 1 = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input EnableCollisions(void) : "Enable collisions between the first and second entity." + input DisableCollisions(void) : "Disable collisions between the first and second entity." +] + + +@PointClass base(Targetname, Parentname, EnableDisable) iconsprite("editor/env_microphone.vmt") sphere(MaxRange) color(0 0 255) = env_microphone : + "An entity that acts as a microphone. It works in one of two modes. If it has a 'Speaker' set, it picks up all sounds within the specified sound range, " + + "and rebroadcasts them through the Speaker entity. In this Speaker mode, it ignores the Hears X spawnflags and does not fire the SoundLevel output. " + + "If it has no Speaker set, it measures the sound level at a point, and outputs the sound level as a value between 0 and 1. In Measuring mode, it only hears sounds that match the Hear X spawnflags." +[ + target(target_destination) : "Measure target" : : "If the speaker is in Measuring mode, this is the name of the entity where the sound level is to be measured." + SpeakerName(target_destination) : "Speaker" : "" : "The name of a speaker entity through which to play any sounds heard by this microphone. If specified, the microphone will consider itself in Speaker mode." + ListenFilter(filterclass) : "Listen Filter" : "" : "The name of an filter entity which specifies the only entities the microphone can hear. Sounds emitted by other entities will not be heard." + speaker_dsp_preset(choices) : "Speaker DSP Preset" : 0 : "Only useful in Speaker mode. If specified, when the microphone is enabled, it'll set the global dsp_speaker preset to this value. Sounds played back through speakers will then be affected by the selected DSP." = + [ + 0 : "Use Default" + 50 : "1 NO EFFECT" + 51 : "2 (DUPLICATE OF 1)" + 52 : "3 (DUPLICATE OF 1)" + 53 : "4 (DUPLICATE OF 1)" + 54 : "5 (DUPLICATE OF 1)" + 55 : "6 SPEAKER, LOUDER" + 56 : "7 SPEAKER VERY SMALL" + 57 : "8 LOUDSPEAKER, ECHO" + 58 : "9 SPEAKER SMALL" + 59 : "10 SPEAKER TINY" + ] + + spawnflags(flags) = + [ + 1 : "Hears combat sounds" : 1 + 2 : "Hears world sounds" : 1 + 4 : "Hears player sounds" : 1 + 8 : "Hears bullet impacts" : 1 + 16: "Swallows sounds routed through speakers" : 0 + 32: "Hears explosions" : 0 + ] + + Sensitivity(float) : "Sensitivity (0 - 10)" : 1 : "Microphone sensitivity, 0=deaf, 1=default, 10=extremely sensitive). Only applicable in Measuring mode." + SmoothFactor(float) : "Smoothing (0 - 1)" : 0 : "Smoothing factor, 0=no smoothing, 1=maximum smoothing). Only applicable in Measuring mode." + MaxRange(float) : "Maximum hearing range (0=infinite)" : 240 : "Sounds beyond this range won't be heard, irrelevant of attenuation. "+ + "WARNING: setting this to zero (or a value > 1024) when the microphone is in Speaker mode can be very bad for performance!!" + + // Inputs + input SetSpeakerName(string) : "Set the microphone to output through a different speaker entity." + + // Outputs + output SoundLevel(float) : "Fired in Measuring mode whenever the sound level changes." + output OnRoutedSound(void) : "Fired whenever a sound is routed out through the specified speaker (if any)." + output OnHeardSound(void) : "Fired whenever this microphone hears any sound it cares about." +] + +@PointClass base(Targetname, EnableDisable ) = math_remap : + "An entity that remaps a range of input values to a given range of output values." +[ + spawnflags(flags) = + [ + 1 : "Ignore out of range input values" : 1 + ] + + in1(integer) : "Minimum Valid Input Value" : 0 : "Input values below this value will be ignored." + in2(integer) : "Maximum Valid Input Value" : 1 : "Input values above this value will be ignored." + out1(integer) : "Output Value When Input Is Min." : : "When the input value is equal to 'Minimum Valid Input Value', this is the output value." + out2(integer) : "Output Value When Input Is Max." : : "When the input value is equal to 'Maximum Valid Input Value', this is the output value." + + // Inputs + input InValue(float) : "Input value and fire the output with the remapped value." + + // Outputs + output OutValue(float) : "Fired when the InValue input is received, with the remapped input value as the parameter." +] + +@PointClass base(Targetname) = math_colorblend : + "Used to create a blend between two colors for controlling the color of another entity." +[ + spawnflags(flags) = + [ + 1 : "Ignore out of range input values" : 1 + ] + + inmin(integer) : "Minimum Valid Input Value" : 0 : "Input values below this value will be ignored." + inmax(integer) : "Maximum Valid Input Value" : 1 : "Input values above this value will be ignored." + colormin(color255) : "Output RGB color when input is min." : "0 0 0" : "When the input value is equal to 'Minimum Valid Input Value', this is the output RGB color." + colormax(color255) : "Output RGB color when input is max." : "255 255 255" : "When the input value is equal to 'Maximum Valid Input Value', this is the output RGB color." + + // Inputs + input InValue(float) : "Input value and fire the output with the remapped value." + + // Outputs + output OutColor(color255) : "Fired when the InValue input is received, with the remapped RGB color as the parameter." +] + +@PointClass base(Targetname) iconsprite("editor/math_counter.vmt") = math_counter : + "Holds a numeric value and performs arithmetic operations upon it. If either the minimum or maximum " + + "legal value is nonzero, OutValue will be clamped to the legal range, and the OnHitMin/OnHitMax " + + "outputs will be fired at the appropriate times. If both min and max are set to zero, no clamping is " + + "performed and only the OutValue output will be fired." +[ + // Keys + startvalue(integer) : "Initial Value" : 0 : "Starting value for the counter." + min(integer) : "Minimum Legal Value" : 0 : "Minimum legal value for the counter. If min=0 and max=0, no clamping is performed." + max(integer) : "Maximum Legal Value" : 0 : "Maximum legal value for the counter. If min=0 and max=0, no clamping is performed." + + // Inputs + input Add(integer) : "Add an amount to the counter and fire the OutValue output with the result." + input Divide(integer): "Divide the counter by an amount and fire the OutValue output with the result." + input Multiply(integer): "Multiply the counter by an amount and fire the OutValue output with the result." + input SetValue(integer): "Set the counter to a new value and fire the OutValue output with the result." + input SetValueNoFire(integer): "Set the counter to a new value without firing any outputs." + input Subtract(integer): "Subtract an amount from the counter and fire the OutValue output with the result." + input SetHitMax(integer): "Set the upper bound of the counter and fire the OutValue output with the current value." + input SetHitMin(integer): "Set the lower bound of the counter and fire the OutValue output with the current value." + + // Outputs + output OutValue(integer) : "Fired when the counter value changes." + output OnHitMin(void) : "Fired when the counter value meets or goes below the min value. The counter must go back above the min value before the output will fire again." + output OnHitMax(void) : "Fired when the counter value meets or exceeds the max value. The counter must go below the max value before the output will fire again." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = logic_lineto : + "An entity that calculates and outputs a vector from one entity to another." +[ + source(target_destination) : "Start entity" : : "Name of the entity the line should start from." + target(target_destination) : "End entity" : : "Name of the entity that line should end at." + + // Outputs + output Line(vector) : "Fired when the vector, from the start entity to the end entity, changes. Passes along the vector as a parameter." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = logic_navigation : + "An entity that is used to set navigation properties on other entities. Useful to make NPCs ignore physics props in their way that they can easily push." +[ + target(target_destination) : "Navigation Entity" : "Name of the entity to set navigation properties on." + spawnflags(flags) = + [ + 1 : "Start On" : 1 + ] + navprop(choices) : "Nav Property" : "Ignore" = + [ + "Ignore" : "NPCs Ignore this when navigating (they'll bump into it)" + ] + + // Inputs + input TurnOn(void) : "Turn on. The Navigation Entity will have its navigation properties set." + input TurnOff(void) : "Turn off. The Navigation Entity will have its navigation properties returned to the default settings." + input Toggle(void) : "Toggle on/off." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = logic_autosave : + "An entity that is used to force an autosave." +[ + NewLevelUnit(choices) : "Force New Level Unit" : 0 : "If set, the save will discard any savedata from previous levels, for the purpose of keeping savegame filesizes down. Can only be safely used if there is no way for the player to return to previous levels." = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Save(void) : "Force an autosave." + input SaveDangerous(float) : "Force an autosave as autosavedangerous.sav. If the player is alive after the passed number of seconds it replaces the standard auto save." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = point_template : + "Turns an entity, or set of entities, into a single template that can be instanced anywhere, and multiple times. "+ + "If there are interdependencies (entity I/O, hierarchy, or other name references) between the entities "+ + "in the template, the entities in the template will have their names changed and the interdependencies will "+ + "be reconnected to the changes names. The name change format is as follows: '&0000', where the 0000 "+ + "will be replaced with the current global template instance, so wildcard searches for '*' will still find them.\n"+ + "If you don't want the name fixup to happen, because you're only spawning the template once, or you want inputs to "+ + "trigger all instances of the template, check the 'Preserve entity names' spawnflag. \n"+ + "To spawn the template in other places, use an env_entity_maker." +[ + spawnflags(flags) = + [ + 1 : "Don't remove template entities" : 0 + 2 : "Preserve entity names (Don't do name fixup)" : 1 + ] + + Template01(target_destination) : "Template 1" + Template02(target_destination) : "Template 2" + Template03(target_destination) : "Template 3" + Template04(target_destination) : "Template 4" + Template05(target_destination) : "Template 5" + Template06(target_destination) : "Template 6" + Template07(target_destination) : "Template 7" + Template08(target_destination) : "Template 8" + Template09(target_destination) : "Template 9" + Template10(target_destination) : "Template 10" + Template11(target_destination) : "Template 11" + Template12(target_destination) : "Template 12" + Template13(target_destination) : "Template 13" + Template14(target_destination) : "Template 14" + Template15(target_destination) : "Template 15" + Template16(target_destination) : "Template 16" + + // Inputs + input ForceSpawn(void) : "Spawn an instance of the template at the original position." + + // Outputs + output OnEntitySpawned(void) : "Fired after spawning an instance of this template." +] + +@PointClass base(Targetname,Parentname,Angles) = env_entity_maker : + "Spawns the specified entity template at its origin. If set to auto-spawn, it will spawn the template whenever there's room and the player "+ + "is looking elsewhere." +[ + spawnflags(Flags) = + [ + 1 : "Enable AutoSpawn (will spawn whenever there's room)" : 0 + 2 : "AutoSpawn: Wait for entity destruction" : 0 + 4 : "AutoSpawn: Even if the player is looking" : 0 + 8 : "ForceSpawn: Only if there's room" : 0 + 16 : "ForceSpawn: Only if the player isn't looking" : 0 + ] + + EntityTemplate(target_destination) : "Point_template To Spawn" : "" : "Name of the point_template to spawn here." + + PostSpawnSpeed(float) : "PostSpawn Movement Speed" : "0" : "If specified, all the entities created in the template will move this fast in the specified PostSpawn Movement Direction." + PostSpawnDirection(angle) : "PostSpawn Movement Direction" : "0 0 0" : "If a PostSpawn Movement Speed is specified, all the entities created in the template will move in this direction." + PostSpawnDirectionVariance(float) : "PostSpawn Direction Variance" : "0.15" : "This variance is applied to the PostSpawn Movement Direction for each spawned entity in the template. Use it to apply some randomness to the directions." + + // Inputs + input ForceSpawn(void) : "Spawn an instance of the template at this origin and angle." + + // Outputs + output OnEntitySpawned(void) : "Fired when an instance of the entity template has been spawned." + output OnEntityFailedSpawn(void) : "Fired when a ForceSpawn input failed to spawn the template, either due to lack of space or being in player's view, depending on the spawnflags." +] + + +//------------------------------------------------------------------------- +// +// Activator Filters +// +//------------------------------------------------------------------------- + +@BaseClass base(Targetname) = BaseFilter +[ + Negated(choices) : "Filter mode" : "Allow entities that match criteria" : "If set to Allow, only entities who match the criteria will pass the filter. "+ + "If set to Disallow, only entities who do NOT match the criteria will pass the filter." = + [ + 0 : "Allow entities that match criteria" + 1 : "Disallow entities that match criteria" + ] + + // Inputs + input TestActivator(void) : "Test the activator against the filter and fires OnPass or OnFail output." + + // Outputs + output OnPass(void) : "Fired in response to TestActivator input if the activator passes the filter." + output OnFail(void) : "Fired in response to TestActivator input if the activator fails to pass the filter." +] + +@FilterClass base(BaseFilter) iconsprite("editor/filter_multiple.vmt") = filter_multi : + "A filter that tests the activator against multiple filters. This allows you to build more complex filters, such as"+ + "'Allow anyone on Team 1 who is also class engineer', or 'Allow everyone except classes npc_zombie and npc_headcrab'." +[ + filtertype(choices) : "Logic Type" : 0 = + [ + 0 : "AND (all filters must pass)" + 1 : "OR (any filter must pass)" + ] + + Negated(choices) : "Negate Outcome" : 0 : "Whether to negate the result of the subfilters, after combining them using the Logic Type chosen.\n"+ + "Negating the outcome using the AND logic type means that any subfilter must fail for this filter to pass.\n"+ + "Negating the outcome using the OR logic type means that all subfilters must fail for this filter to pass." = + [ + 0 : "No" + 1 : "Yes" + ] + + Filter01(filterclass) : "Filter 1" : : "Activator filter to test." + Filter02(filterclass) : "Filter 2" : : "Activator filter to test." + Filter03(filterclass) : "Filter 3" : : "Activator filter to test." + Filter04(filterclass) : "Filter 4" : : "Activator filter to test." + Filter05(filterclass) : "Filter 5" : : "Activator filter to test." +] + +@FilterClass base(BaseFilter) iconsprite("editor/filter_name.vmt") = filter_activator_name : + "A filter that filters by the name of the activator." +[ + filtername(target_destination) : "Filter Name" : : "The name to filter by. If the filter mode is Allow, only entities whose "+ + "name matches the given string will pass the filter. If the filter mode is Disallow, "+ + "all entities EXCEPT those whose name matches the string will pass the filter." +] + +@FilterClass base(BaseFilter) iconsprite("editor/filter_class.vmt") = filter_activator_class : + "A filter that filters by the class name of the activator." +[ + filterclass(string) : "Filter Classname" : : "The class name to filter by. If the filter mode is Allow, only entities whose "+ + "class name matches the given string will pass the filter. If the filter mode is Disallow, "+ + "all entities EXCEPT those whose class name matches the given string will pass the filter." +] + +@FilterClass base(BaseFilter) = filter_damage_type : + "A damage filter that filters by the type of damage inflicted. This can only be used as a damage filter, not as an activator filter." +[ + damagetype(choices) : "Damage type" : 64 : "The damage type to filter by. If the filter mode is Allow, only damage types that "+ + "match will pass the filter. If the filter mode is Disallow, all damage types EXCEPT those who match will pass the filter." = + [ + 0 : "GENERIC" + 1 : "CRUSH" + 2 : "BULLET" + 4 : "SLASH" + 8 : "BURN" + 16 : "FREEZE" + 32 : "FALL" + 64 : "BLAST" + 128 : "CLUB" + 256 : "SHOCK" + 512 : "SONIC" + 1024 : "ENERGYBEAM" + 16384: "DROWN" + 32768 : "PARALYSE" + 65536 : "NERVEGAS" + 131072 : "POISON" + 262144 : "RADIATION" + 524288 : "DROWNRECOVER" + 1048576 : "CHEMICAL" + 2097152 : "SLOWBURN" + 4194304 : "SLOWFREEZE" + ] +] + + +//------------------------------------------------------------------------- +// +// Point Entities +// +//------------------------------------------------------------------------- + +@PointClass base(Targetname, Parentname, EnableDisable) = point_anglesensor : + "An entity that detects if another entity points in a given direction for a period of time." +[ + target(target_destination) : "Target Entity Name" : : "Name of the entity whose angles will be sensed." + lookatname(target_destination) : "Look At Entity" : : "The entity we want to check to see if the Target Entity is looking at." + duration(float) : "Duration" : : "The amount of time the Target Entity must look at the 'Look at Entity' to trigger this entity, in seconds." + tolerance(integer) : "Tolerance" : : "The tolerance, in degrees, in the checking to determine when the Target Entity is looking at the Look At Entity." + + // Inputs + input Toggle(void) : "Toggle the sensor between enabled and disabled." + input Test(void) : "Check to see if the Target Entity is facing the Look At Entity within the specified tolerance, firing either the OnFacingLookat or OnNotFacingLookat output based on the result." + + // Outputs + output TargetDir(vector) : "Fired when the forward direction of the Target Entity changes. Passes the new forward direction as a parameter." + output OnFacingLookat(void) : "Fired when the Target Entity points at the Look At Entity for more than the specified Duration, or in response to a Test input." + output OnNotFacingLookat(void) : "Fires in response to a Test input when the Target Entity is not pointing at the Look At Entity." +] + +@PointClass base(Targetname) = point_angularvelocitysensor : + "An entity that detects if another entity's angular velocity meets or exceeds a threshold value." +[ + target(target_destination) : "Target Entity Name" : : "Name of the entity whose angular velocity will be sensed." + threshold(float) : "Threshold Velocity" : 0 : "The threshold angular velocity to compare against, in degrees per second." + + axis(vecline) : "Axis" + + usehelper(choices) : "Use Axis Helper" : 0 : "Use axis helper to determine rotation values (clockwise/counter-clockwise)." = + [ + 0 : "No" + 1 : "Yes" + ] + + // Inputs + input Test(void) : "Checks to see if the Target Entity's angular velocity meets or exceeds the Threshold Velocity, " + + "firing either the OnGreaterThanOrEqualTo or OnLessThan output based on the result." + + // Outputs + output AngularVelocity(float) : "Fired when the Target's Angular Velocity changes, passing the new magnitude of the angular velocity." + output OnGreaterThan(void) : "Fired when the Target Entity goes from slower than the threshold angular velocity to faster than the threshold angular velocity." + output OnGreaterThanOrEqualTo(void) : "Fired when the Target Entity goes from slower than the threshold angular velocity to faster than the threshold angular velocity." + output OnLessThan(void) : "Fired when the Target Entity goes from faster than the threshold angular velocity to slower than the threshold angular velocity." + output OnLessThanOrEqualTo(void) : "Fired when the Target Entity goes from faster than the threshold angular velocity to slower than the threshold angular velocity." + output OnEqualTo(void) : "Fired when the Target Entity reaches the threshold angular velocity from a different velocity." +] + +@PointClass base(Targetname, Angles) = point_teleport : + "An entity that teleports a target entity to this position and angles. "+ + "If 'Teleport Home' spawn flag is set, teleports the target entity to its spawn position instead." + + "If object is physically simulated, simulation is turned off when teleported." +[ + target(target_destination) : "Entity To Teleport" : : "Name of the entity that will be teleported." + spawnflags(flags) = + [ + 1 : "Teleport Home" : 0 + ] + + // Inputs + input Teleport(void) : "Teleport the target entity." +] + +@PointClass base(Targetname) sphere(DamageRadius) = point_hurt : + "An entity that does damage to all entities in a radius around itself, with a specified delay." + + "If 'Target Entity' is specified, the damage is only done to that entity." +[ + DamageTarget(string) : "Target Entity" : "" : "If specified, only this entity will take damage. Otherwise, all entities within the Radius will take damage." + + DamageRadius(float) : "Radius" : 256 : "All entities within this radius of this entity will take damage. If a 'Target Entity' is specified, only that entity will take damage." + Damage(integer) : "Damage" : 5 : "Damage done to all affected entities each time this entity fires." + DamageDelay(float) : "Delay" : 1 : "Delay between refires, in seconds." + + DamageType(choices) : "Damage Type" : 0 : "Type of damage to inflict on entities damaged." = + [ + 0 : "GENERIC" + 1 : "CRUSH" + 2 : "BULLET" + 4 : "SLASH" + 8 : "BURN" + 16 : "FREEZE" + 32 : "FALL" + 64 : "BLAST" + 128 : "CLUB" + 256 : "SHOCK" + 512 : "SONIC" + 1024 : "ENERGYBEAM" + 16384: "DROWN" + 32768 : "PARALYSE" + 65536 : "NERVEGAS" + 131072 : "POISON" + 262144 : "RADIATION" + 524288 : "DROWNRECOVER" + 1048576 : "CHEMICAL" + 2097152 : "SLOWBURN" + 4194304 : "SLOWFREEZE" + ] + + // Inputs + input Hurt(void) : "Force a single fire, damaging either the Target Entity or all entities within the radius." + input TurnOn(void) : "Enable this entity. It will start damaging entities everytime it fires, and refire based upon the specified Delay." + input TurnOff(void) : "Disable this entity. It will stop damaging entities." + input Toggle(void) : "Toggle this entity between On/Off state." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = point_playermoveconstraint : + "An entity that constrains players to a radius around itself, slowing them down the closer they get to the edge of the radius." +[ + radius(float) : "Radius" : 256 : "Radius to constrain players to." + width(float) : "Constraint Width" : "75.0" : "Width of the constraint edge. This is the distance in which to start slowing players down as they approach the edge of the radius." + speedfactor(float) : "Speed Factor" : "0.15" : "Factor applied to the player's max speed as they approach the radius edge." + + // Inputs + input TurnOn(void) : "Start constraining any players within the radius." + input TurnOff(void) : "Stop constraining any players previously constrained." + + // Outputs + output OnConstraintBroken(void) : "Fired when a player breaks through the constraint." +] + +//------------------------------------------------------------------------- +// +// Physics entities +// +//------------------------------------------------------------------------- + +@SolidClass base(BreakableBrush,Targetname, Origin, RenderFields, Shadow) = func_physbox : + "A brush entity that's physically simulated." +[ + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + spawnflags(flags) = + [ + 4096 : "Start Asleep" : 0 + 8192 : "Ignore +USE for Pickup" : 0 + 16384 : "Debris - Don't collide with the player or other debris" : 0 + 32768 : "Motion Disabled" : 0 + 65536 : "Use Preferred Carry Angles" : 0 + 131072: "Enable motion on Physcannon grab" : 0 + 262144: "Not affected by rotor wash" : 0 + 524288: "Generate output on +USE " : 1 + 1048576 : "Physgun can ALWAYS pick up. No matter what." : 0 + 2097152 : "Physgun is NOT allowed to pick this up." : 0 + 4194304 : "Physgun is NOT allowed to punt this object." : 0 + ] + + Damagetype(choices) : "Impact Damage Type" : 0 = + [ + 0: "Blunt" + 1: "Sharp" + ] + + massScale(float) : "Mass Scale" : "0" : "A scale multiplier for the object's mass." + overridescript(string) : "Override Parameters" : "" : "A list of physics key/value pairs that are usually in a physics prop .qc file. Format is 'key,value,key,value,etc'." + damagetoenablemotion(integer) : "Health Level to Override Motion" : 0 : "If specified, this object will start motion disabled. Once its health has dropped below this specified amount, it will enable motion." + forcetoenablemotion(float) : "Physics Impact Force to Override Motion" : 0 : "If specified, this object will start motion disabled. Any impact that imparts a force greater than this value on the physbox will enable motion." + health(integer) : "Strength" : 0 : "Number of points of damage to take before breaking. 0 means don't break." + preferredcarryangles(vector) : "Preferred Player-carry Angles" : "0 0 0" : "If the 'Use Preferred Carry Angles' spawnflag is set, this angle is the angle which the object should orient to when the player picks it up, with the physgun or +USE." + notsolid(choices) : "Not solid to world" : 0 = + [ + 0: "Solid to World" + 1: "Passes through World" + ] + + // Inputs + input Wake(void) : "Wake up this physics object, if it is sleeping." + input Sleep(void) : "Put this physics object to sleep. It will wake if given the Wake input, or if force is applied to it. Note that physics objects go to sleep automatically after coming to rest for a while, so you don't really need to use this." + input EnableMotion(void) : "Enable physics motion/collision response." + input DisableMotion(void) : "Disable physics motion/collision response." + input ForceDrop(void) : "If this object is being carried by a player, with the physgun or +USE, force it to be dropped." + + // Outputs + output OnDamaged(void) : "Fired when this entity is damaged." + output OnAwakened(void) : "Fired when this entity becomes awake (collision/force is applied)." + output OnMotionEnabled(void) : "Fired when motion is enabled due to damage/physcannon/force." + output OnPhysGunPickup(void) : "Fired when a player picks this object up, either with the physgun or +USE." + output OnPhysGunOnlyPickup(void) : "Fired when a player picks this object up WITH THE PHYSGUN. +USE pickups do not fire this output." + output OnPhysGunDrop(void) : "Fired when a player drops this object." + output OnPlayerUse(void) : "Fired when the player tries to +USE the physbox. This output will fire only if the Generate output on +USE spawnflag is set." +] + +@BaseClass base(Targetname) = TwoObjectPhysics +[ + spawnflags(flags) = + [ + 1: "No Collision until break" : 0 + // 2 is defined independently by subclasses, do not reuse + 4: "Start inactive" : 0 + 8: "Change mass to keep stable attachment to world" : 0 + ] + attach1(target_destination) : "Entity 1" : "" + attach2(target_destination) : "Entity 2" : "" + constraintsystem(target_destination) : "Constraint System Manager" : "" : "The name of a phys_constraintsystem that this constraint should be a part of. All constraints on a set of entities should be placed in the same system, or they will fight each other during simulation." + + forcelimit(float) : "Force Limit to Break (lbs)" : "0" : "The amount of force an impact must apply to the constraint to break it. A way of calculating this is to set it to the mass of an object that would break this constraint if it were resting on the constrainted objects." + torquelimit(float) : "Torque Limit to Break (lbs * distance)" : "0" : "The amount of torque required to break the constraint. A way of calculating this is to multiply any reference mass by the resting distance (from the center of mass of the object) needed to break the constraint." + breaksound(sound) : "Play Sound on Break" : "" : "A sound played when the constraint is broken." + + // Inputs + input Break(void) : "Force the constraint to break." + input TurnOn(void) : "Enable the constraint. Do this when the objects don't exist when the constraint spawns - or when you have deactivated the constraint. Broken constraints can NOT be turned on. They have been deleted." + input TurnOff(void) : "Disable this constraint." + + // Outputs + output OnBreak(void) : "Fired when the constraint breaks." +] + +@PointClass base(Targetname) = phys_constraintsystem : + "An entity used to manage a group of interacting constraints and keep them stable. " + + "All constraints on a set of entities should be placed in the same system, or they will fight each other during simulation." +[ + additionaliterations(integer) : "Additional System Iterations" : 0 : "Adding iterations makes the interactions among constraints in a system tighter. It will not compensate for errors due to collision, but will help in cases where objects of disparate mass are constrained to each other." +] + +@PointClass base(Targetname,Angles) = phys_keepupright : "A controller that tries to keep an entity facing a particular direction." +[ + spawnflags(flags) = + [ + 1: "Start inactive" : 0 + ] + + attach1(target_destination) : "Target Entity" : "" : "The entity to align to the desired angles." + angularlimit(float) : "Angular Limit" : "15" : "The maximum angular velocity that this controller can compensate for, in degrees per second." + + // Inputs + input TurnOn(void) : "Enable the controller." + input TurnOff(void) : "Disable the controller." +] + +@PointClass base(Targetname, Angles) sphere(expradius) studioprop() = physics_cannister : + "A physically simulated gas cannister that can have its cap shot off, at which point gas will start escaping and cause the cannister to fly around. If it takes enough damage, it will explode." +[ + model(studio) : "World model" : "models/fire_equipment/w_weldtank.mdl" + spawnflags(flags) = + [ + 1 : "Start Asleep" : 0 + 2 : "Explodes" : 1 + ] + + expdamage(string) : "Explosion Damage" : "200.0" : "The amount of damage done by the explosion created when the cannister blows up." + expradius(string) : "Explosion Radius" : "250.0" : "The radius of the explosion to create when the cannister blows up." + health(integer) : "Health" : 25 : "The amount of damage the cannister takes before exploding." + + thrust(string) : "Thrust" : "3000.0" : "When the cap has been blown off, and the escaping gas is thrusting the cannister about, this is the amount of thrust generated." + fuel(string) : "Fuel Seconds" : "12.0" : "The amount of time that gas leaks from the cannister before being considered empty." + rendercolor(color255) : "Smoke Color (R G B)" : "255 255 255" + renderamt(integer) : "Smoke Alpha (0 - 255)" : 128 + gassound(sound) : "Thruster Sound" : "ambient/objects/cannister_loop.wav" : "The sound played when the gas is escaping from the cannister." + + // Inputs + input Activate(string) : "Start gas escaping from the cannister." + input Deactivate(string) : "Stop gas escaping from the cannister." + input Explode(string) : "Force the cannister to explode." + input Wake(void) : "Wakes up the cannister, if it is sleeping." + + // Outputs + output OnActivate(void) : "Fired when gas starts to escape from the cannister." +] + +@PointClass base(Targetname, Parentname) size(-4 -4 -4, 4 4 4) = info_constraint_anchor : + "An entity used to attach constraints to a local position on an entity. Usually constraints will attach to the center of mass of an object. "+ + "Attach the desired constraint to this entity, and then parent this entity to the entity you want the constraint to apply to." +[ + massScale(float) : "Amount to scale the mass of this body in the constraint solver" : "1" +] + +@PointClass size(-4 -4 -4, 4 4 4) = info_mass_center : + "An entity that overrides the mass center of the target physics prop, or func_physbox, by moving it to the info_mass_center's location." +[ + target(target_destination) : "Target object" : "" : "The entity whose mass center will be overridden." +] + +@PointClass halfgridsnap base(Targetname) = phys_spring : + "A physically simulated spring. "+ + "'Length' is what's known as the 'natural spring length'. This is how long the spring would "+ + "be if it was at rest (nothing hanging on it or attached). When you attach something to the "+ + "spring, it will stretch longer than its 'natural length'. The amount of stretch is "+ + "determined by the 'Sprint Constant'. The larger the spring constant the less stretch the spring." +[ + spawnflags(flags) = + [ + 1 : "Force only on stretch" : 0 + ] + + attach1(target_destination) : "Entity 1" : "" + attach2(target_destination) : "Entity 2" : "" + + springaxis(vecline) : "Spring Axis" : "" : "Use the helper. Drag it out to match the virtual spring." + length(string) : "Spring Length" : "0" : "How long the spring would be if it was at rest (nothing hanging on it or attached). 0 means the length of the brush." + constant(string) : "Spring Constant" : "50" : "Stiffness of the spring. The larger the number the less the spring will stretch." + damping(string) : "Damping Constant" : "2.0" : "How much energy the spring loses. The larger the number, the less bouncy the spring." + relativedamping(string) : "Relative Damping Constant" : "0.1" : "The amount of energy the spring loses proportional to the relative velocity of the two objects the spring is attached to." + // UNDONE: add max tension and what event to fire when it breaks + breaklength(string) : "Break on Length" : "0" : "If the spring's length ever exceeds this length, the spring breaks." + + // Inputs + input SetSpringConstant(float) : "Set the Spring Constant." + input SetSpringLength(float) : "Set the Spring Length." + input SetSpringDamping(float) : "Set the Spring Damping." +] + +@PointClass halfgridsnap size(-8 -8 -8, 8 8 8) base(TwoObjectPhysics) = phys_hinge : + "A physically simulated hinge. Use the helper to define the axis of rotation." +[ + hingefriction(float) : "Friction" : "0" : "Resistance/friction in the hinge" + hingeaxis(vecline) : "Hinge Axis" + SystemLoadScale(float) : "Load Scale" : "1" : "Scale of the load connected to this hinge (1=just the objects directly connected)" + + // Inputs + input SetAngularVelocity(float) : "Set angular velocity around the hinge (motor)" +] + +@PointClass base(TwoObjectPhysics) iconsprite("editor/phys_ballsocket.vmt") = phys_ballsocket : + "A constraint that keeps the position of two objects fixed, relative to the constraint's origin. It does not affect rotation." +[ + spawnflags(flags) = + [ + ] +] + +@PointClass base(TwoObjectPhysics) studio("models/editor/axis_helper.mdl") = phys_constraint : + "A constraint that keeps the relative position and orientation of two objects fixed." +[ + spawnflags(flags) = + [ + 1: "No Collision until break" : 1 + ] +] + +@PointClass base(TwoObjectPhysics) studio("models/editor/axis_helper.mdl") = phys_pulleyconstraint : + "A constraint that is essentially two length constraints and two points. Imagine it as a virtual rope connected to two objects, each suspended from a pulley above them."+ + "The constraint keeps the sum of the distances between the pulley points and their suspended objects constant." +[ + addlength(float) : "Additional Length" : "0" : "Add (or subtract) this amount to the rest length of the pulley rope." + gearratio(float) : "Pulley Gear Ratio" : "1" : "Add (or subtract) this amount to the rest length of the pulley rope." + position2(vecline) : "Pulley Position 2" : : "The position of the pulley for Entity 2. The pulley for Entity 1 is the origin of this constraint entity. Entity 1 is always suspended from pulley point 1, and Entity 2 is always suspended from pulley point 2." + spawnflags(flags) = + [ + 1: "No Collision until break" : 1 + 2: "Keep Rigid" : 0 + ] +] + +@PointClass halfgridsnap base(TwoObjectPhysics) studio("models/editor/axis_helper.mdl") = phys_slideconstraint : + "A constraint that constrains an entity along a line segment." +[ + spawnflags(flags) = + [ + 1: "No Collision until break" : 1 + 2: "Limit Endpoints" : 0 + ] + slideaxis(vecline) : "Sliding Axis" + slidefriction(float) : "Friction" : "0" : "Resistance/friction in the constraint" + SystemLoadScale(float) : "Load Scale" : "1" : "Scale of the mass load connected to this constraint (1=just the objects directly connected)" + + // Inputs + input SetVelocity(float) : "Set linear velocity along the constraint" +] + +@PointClass base(TwoObjectPhysics) studio("models/editor/axis_helper.mdl") = phys_lengthconstraint : + "A constraint that preserves the distance between two entities. If the 'Keep Rigid' flag is set, think of it as a rod. If not, think off it as a virtual rope." +[ + addlength(float) : "Additional Length" : "0" : "Add (or subtract) this amount to the rest length of the rope." + minlength(float) : "Minimum Length" : "0" : "If the constraint is not rigid, this is the minimum length it can be." + attachpoint(vecline) : "Attached object 2 point" : "The position the rope attaches to object 2" + spawnflags(flags) = + [ + 1: "No Collision until break" : 1 + 2: "Keep Rigid" : 0 + ] +] + +@PointClass base(TwoObjectPhysics) studio("models/editor/axis_helper.mdl") = phys_ragdollconstraint : + "A constraint that fixes the position of two entities, relative to this constraint's origin. Also allows for limits on the rotation around each axis, in the space of this constraint." +[ + spawnflags(flags) = + [ + 1: "No Collision until break" : 1 + 2: "Only limit rotation (free movement)" : 0 + ] + + xmin(float) : "X axis min limit" : "-90" : "-180 min and 180 max = no constraint on this axis." + xmax(float) : "X axis max limit" : "90" : "-180 min and 180 max = no constraint on this axis." + ymin(float) : "Y axis min limit" : "0" : "-180 min and 180 max = no constraint on this axis." + ymax(float) : "Y axis max limit" : "0" : "-180 min and 180 max = no constraint on this axis." + zmin(float) : "Z axis min limit" : "0" : "-180 min and 180 max = no constraint on this axis." + zmax(float) : "Z axis max limit" : "0" : "-180 min and 180 max = no constraint on this axis." + xfriction(float) : "X axis friction" : "0" + yfriction(float) : "Y axis friction" : "0" + zfriction(float) : "Z axis friction" : "0" +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) color(0 0 255) = phys_convert : + "Turns an arbitrary entity into a physically simulated entity. i.e. brush entities will behave like func_physbox, model entities behave like prop_physics." +[ + spawnflags(flags) = + [ + 1: "Convert Asleep" : 0 + ] + target(target_destination) : "Entity to convert" : : "Name of the entity that will be converted to a physics object when the ConvertTarget input is fired." + swapmodel(string) : "Model Swap Entity" + + // Outputs + output OnConvert(void) : "Fires after the conversion has taken place." + + // Inputs + input ConvertTarget(void) : "Converts this entity's target to a physically simulated object." +] + +@BaseClass base(Targetname) = ForceController +[ + spawnflags(flags) = + [ + // Thrust is on by default (will turn off in forcetime) + 1: "Start On" : 0 + // Apply linear force (if off, torque only) + 2: "Apply Force" : 1 + // Apply rotational force (torque - if off, linear only) + 4: "Apply Torque" : 1 + // Maintain local relationship with the attached object + 8: "Orient Locally" : 1 + // Impulse is independent of object's mass (impulse is acceleration NOT force) + 16: "Ignore Mass" : 0 + ] + attach1(target_destination) : "Attached Object" : "" : "Object to apply the force to." + + forcetime(string) : "Time of Force (0=inf)" : "0" : "Automatic shut-off after this time has passed (0 = stay on forever or until deactivated)" + + input Activate(void) : "Turn the force on" + input Deactivate(void) : "Turn the force off" + input Scale(string) : "Set Force Scale" +] + +@PointClass base(Angles, ForceController) = phys_thruster : + "An entity used to apply constant acceleration to a physics object. "+ + "The force and torque is calculated using the position and direction of the thruster as an impulse. So moving those off the object's center "+ + "will cause torque as well. Torque can be removed by unchecking the 'apply torque' flag. The position of the thruster can be forced to be "+ + "at the object's center by checking to 'ignore pos' flag." +[ + spawnflags(flags) = + [ + // Put the thrust at the object center + 32: "Ignore Pos" : 0 + ] + + force(string) : "Force" : "0" : "Force (will be integrated, units are force kg*in/s^2)" +] + +@PointClass halfgridsnap base(ForceController) = phys_torque : + "An angular thruster. Use it to apply angular force to an entity." +[ + // Angular acceleration (units are degress/s^2) + force(string) : "Angular Acceleration" : "0" + axis(vecline) : "Rotation Axis" : "" +] + +@PointClass base(Targetname) halfgridsnap size(-8 -8 -8, 8 8 8) = phys_motor : + "An entity that tries to spin a target entity at a particular speed." +[ + speed(string) : "Rotation Speed" : "0" : "Angular speed (units are degress/second)" + spinup(string) : "Spin up time" : "1" : "spin up time in seconds (also affects the rate at which speed changes happen)" + inertiafactor(float) : "System Interia Scale" : "1.0" : "Make this larger if the object being driven is constrained to a set of heavier objects." + axis(vecline) : "Rotation Axis" : "" + + spawnflags(flags) = + [ + // starts on by default + 1: "Start On" : 1 + // Disable world collisions on hinges + 2: "No world collision" : 0 + // motor also acts as a hinge constraining the object to this axis + 4: "Hinge Object" : 1 + // Maintain local relationship with the attached object (NOT WORKING YET) +// 8: "Orient Locally" : 1 + ] + attach1(target_destination) : "Attached Object" : "" : "Object to apply the force to" + + // Inputs + input SetSpeed(float) : "Sets target speed" + input TurnOn(void) : "Turns motor on" + input TurnOff(void) : "Turns motor off" +] + +@PointClass base(Targetname, Parentname, Angles, Studiomodel) studio() = phys_magnet : + "An entity that acts like a magnet, attaching metallic physics objects to itself when they touch it." +[ + spawnflags(flags) = + [ + 1 : "Start Asleep" : 0 + 2 : "Motion Disabled" : 0 + 4 : "Suck On Touch" : 0 + 8 : "Allow Attached Rotation" : 0 + 16: "Coast jeep pickup hack" : 0 + ] + + forcelimit(float) : "Force Limit to Break (lbs)" : "0" : "The amount of force necessary to break a stuck object off the magnet. A way of calculating this is to set it to the mass of an object that would break this constraint if it were resting on the magnet." + torquelimit(float) : "Torque Limit to Break (lbs * distance)" : "0" : "The amount of torque necessary to break a stuck object off the magnet. A way of calculating this is to multiply any reference mass by the resting distance (from the center of mass of the object) needed to break the constraint." + + massScale(float) : "Mass Scale" : "0" : "A scale multiplier for the object's mass." + overridescript(string) : "Override parameters" : "" : "A list of physics key/value pairs that are usually in a physics prop .qc file. Format is 'key,value,key,value,etc'." + maxobjects(integer) : "Maximum Attached Objects" : 0 : "The maximum number of physics objects that can be stuck to the magnet at once. 0 = no limit." + + // Inputs + input TurnOn(void) : "Turn the magnet on." + input TurnOff(void) : "The the magnet off. This will detach anything current stuck to the magnet." + + // Outputs + output OnAttach(void) : "Fired when an entity is grabbed by the magnet." + output OnDetach(void) : "Fired when an entity is released by the magnet." +] + + +//------------------------------------------------------------------------- +// +// Props +// +//------------------------------------------------------------------------- + +@BaseClass = prop_detail_base +[ + model(studio) : "World model" +] + +@BaseClass base(Angles, DXLevelChoice) = prop_static_base +[ + model(studio) : "World Model" + skin(integer) : "Skin" : 0 : "Some models have multiple versions of their textures, called skins. Set this to a number other than 0 to use that skin instead of the default." + solid(choices) : "Collisions" : 6 = + [ + 0: "Not Solid" + 2: "Use Bounding Box" + 6: "Use VPhysics" + ] + disableshadows(choices) : "Disable Shadows" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + screenspacefade(choices) : "Screen Space Fade" : 0 : "The method by which the fading distance should be determined. If 'No', the fade distances is the distance from the player's view to the object, in inches. If 'Yes', the fade distance is the size of the object onscreen, in pixels." = + [ + 0 : "No" + 1 : "Yes" + ] + fademindist(float) : "Start Fade Dist/Pixels" : -1 : "Distance at which the prop starts to fade (<0 = use fademaxdist). If 'Screen Space Fade' is selected, this represents the number of pixels wide covered by the prop when it starts to fade." + fademaxdist(float) : "End Fade Dist/Pixels" : 0 : "Maximum distance at which the prop is visible (0 = don't fade out). If 'Screen Space Fade' is selected, this represents the *minimum* number of pixels wide covered by the prop when it fades." + fadescale(float) : "Fade Scale" : 1 : "If you specify a fade in the worldspawn, or if the engine is running under dx7, then the engine will forcibly fade out props even if fademindist/fademaxdist isn't specified." + + " This scale factor gives you some control over the fade. Using 0 here turns off the forcible fades." + + " Numbers smaller than 1 cause the prop to fade out at further distances, and greater than 1 cause it to fade out at closer distances." + lightingorigin(target_destination) : "Lighting Origin" : "" : "Select an info_lighting to specify a location to sample lighting from, instead of using this entity's origin." + disablevertexlighting(choices) : "Disable Vertex lighting" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + disableselfshadowing(choices) : "Disable Self-Shadowing with vertex lighting" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] +] + +@BaseClass base(Parentname, Global, Angles, Studiomodel, BreakableProp, DXLevelChoice) = prop_dynamic_base +[ + solid(choices) : "Collisions" : 6 = + [ + 0: "Not Solid" + 2: "Use Bounding Box" + 6: "Use VPhysics" + ] + + spawnflags(flags) = + [ + 64 : "Use Hitboxes for Renderbox" : 0 + ] + + DefaultAnim(string) : "Default Animation" : "" : "The name of the idle animation that this prop will revert to whenever it finishes a random or forced animation." + + RandomAnimation(choices) : "Randomly Animate" : 0 : "If set, this prop will randomly choose and play animations, based upon the times specified in 'Min/Max Random Anim Time'. Inbetween the random animations, it will revert to playing the 'Default Animation'." = + [ + 0: "No" + 1: "Yes" + ] + MinAnimTime(float) : "Min Random Anim Time" : "5" : "Minimum time between random animations." + MaxAnimTime(float) : "Max Random Anim Time" : "10" : "Maximum time between random animations." + SetBodyGroup(integer) : "Body Group" : 0 // NEEDHELP + + fademindist(float) : "Start Fade Dist" : -1 : "Distance at which the prop starts to fade (<0 = use fademaxdist)." + fademaxdist(float) : "End Fade Dist" : 0 : "Max fade distance at which the prop is visible (0 = don't fade out)" + fadescale(float) : "Fade Scale" : 1 : "If you specify a fade in the worldspawn, or if the engine is running under dx7, then the engine will forcibly fade out props even if fademindist/fademaxdist isn't specified." + + " This scale factor gives you some control over the fade. Using 0 here turns off the forcible fades." + + " Numbers smaller than 1 cause the prop to fade out at further distances, and greater than 1 cause it to fade out at closer distances." + + // Inputs + input SetAnimation(string) : "Force the prop to play an animation. The parameter should be the name of the animation." + input SetDefaultAnimation(string) : "Set the Default Animation to the one specified in the parameter." + input SetBodyGroup(integer) : "Set the visible bodygroup, by index." + input TurnOn(void) : "Make the prop visible." + input TurnOff(void) : "Make the prop invisible." + + // Outputs + output OnAnimationBegun(void) : "Fired whenever a new animation has begun playing." + output OnAnimationDone(void) : "Fired whenever an animation is complete." +] + +@PointClass base(prop_detail_base) studioprop() = prop_detail : + "Detail Prop" +[ + model(studio) : "World model" +] + +@PointClass base(prop_static_base) color(255 255 0) sphere(fademindist) sphere(fademaxdist) studioprop() = prop_static : + "A prop that doesn't move and doesn't animate." +[ +] + +@PointClass base(prop_dynamic_base,EnableDisable) studioprop() = prop_dynamic : + "A prop that can be placed in hierarchy and can play animations. It can also be configured to break when it takes enough damage. "+ + "Note that the health of the object will be overridden by the health inside the model, to ensure consistent health game-wide. "+ + "If the model used by the prop is configured to be used as a prop_physics (i.e. it should be physically simulated) then it CANNOT be "+ + "used as a prop_dynamic. Upon level load it will display a warning in the console and remove itself. Use a prop_physics instead." +[ +] + +@PointClass base(prop_dynamic_base) studioprop() = prop_dynamic_override : + "A prop that can be placed in hierarchy and can play animations. It can also be configured to break when it takes enough damage.\n"+ + "prop_dynamic_override is a prototyping entity only. It will allow the use of models designed to be used as prop_physics." +[ + health(integer) : "Health" : 0 : "Number of points of damage to take before breaking. 0 means don't break." +] + +@BaseClass base(Targetname, Global, Angles, Studiomodel, BreakableProp, DXLevelChoice) = BasePropPhysics +[ + spawnflags(flags) = + [ + 1 : "Start Asleep" : 0 + 2 : "Don't take physics damage" : 0 + 4 : "Debris - Don't collide with the player or other debris" : 0 + 8 : "Motion Disabled" : 0 + 64 : "Enable motion on Physcannon grab" : 0 + 128 : "Not affected by rotor wash" : 0 + 256 : "Generate output on +USE " : 1 + 512 : "Prevent pickup" : 0 + 1024: "Prevent motion enable on player bump" : 0 + 4096: "Debris with trigger interaction" : 0 + 8192: "Force server-side (Multiplayer only)" : 0 + 1048576: "Physgun can ALWAYS pick up. No matter what." : 0 + ] + + minhealthdmg(integer) : "Min Damage to Hurt" : 0 : "The prop will ignore any damage events if the damage is less than this amount." + shadowcastdist(integer) : "Shadow Cast Distance" : 0 : "Use this to override how far this object casts shadows. 0 = default distance." + physdamagescale(float) : "Physics Impact Damage Scale" : "0.1" : "Scales damage energy when this object is hit by a physics object. NOTE: 0 means this feature is disabled for backwards compatibility.\nSet to 1.0 for materials as strong as flesh, smaller numbers indicate stronger materials." + Damagetype(choices) : "Impact damage type" : 0 = + [ + 0: "Blunt" + 1: "Sharp" + ] + + nodamageforces(choices) : "Damaging it Doesn't Push It" : 0 : "Used to determine whether or not damage should cause the brush to move." = + [ + 0: "No" + 1: "Yes" + ] + + inertiaScale(float) : "Scale Factor For Inertia" : "1.0" : "Scales the angular mass of an object. Used to hack angular damage and collision response." + massScale(float) : "Mass Scale" : "0" : "A scale multiplier for the object's mass." + overridescript(string) : "Override Parameters" : "" : "A list of physics key/value pairs that are usually in a physics prop .qc file. Format is 'key,value,key,value,etc'." + damagetoenablemotion(integer) : "Health Level to Override Motion" : 0 : "If specified, this object will start motion disabled. Once its health has dropped below this specified amount, it will enable motion." + forcetoenablemotion(float) : "Physics Impact Force to Override Motion" : 0 : "If specified, this object will start motion disabled. Any impact that imparts a force greater than this value on the physbox will enable motion." + + fademindist(float) : "Start Fade Dist" : -1 : "Distance at which the prop starts to fade (<0 = use fademaxdist)" + fademaxdist(float) : "End Fade Dist" : 0 : "Max fade distance at which the prop is visible (0 = don't fade out)" + fadescale(float) : "fade scale" : 1 : "If you specify a fade in the worldspawn, or if the engine is running under dx7, or the engine will forcibly fade out props even if fademindist/fademaxdist isn't specified." + + " This scale factor gives you some control over the fade. Using 0 here turns off the forcible fades." + + " Numbers smaller than 1 cause the prop to fade out at further distances, and greater than 1 cause it to fade out at closer distances." + puntsound(sound) : "Sound to make when punted" + + // Inputs + input Wake(void) : "Wake up this physics object, if it is sleeping." + input Sleep(void) : "Put this physics object to sleep. It will wake if given the Wake input, or if force is applied to it. Note that physics objects go to sleep automatically after coming to rest for a while, so you don't really need to use this." + input EnableMotion(void) : "Enable physics motion/collision response." + input DisableMotion(void) : "Disable physics motion/collision response." + input DisableFloating(void) : "Disable fluid/floating simulation to reduce cost." + input SetBodyGroup(integer) : "Set this prop's body group (from 0 - n)." + input physdamagescale(float) : "Set the Physics Impact Damage Scale for this character. NOTE: 0 means this feature is disabled for backwards compatibility." + input EnableDamageForces(void) : "Damaging the entity applies physics forces to it." + input DisableDamageForces(void) : "Damaging the entity does *not* apply physics forces to it." + input EnablePuntSound(void) : "Allow this prop to play its own sound when punted" + input DisablePuntSound(void) : "Prevent this prop from playing its own sound when punted" + + // Outputs + output OnMotionEnabled(void) : "Fired when motion is enabled on this prop, either via 'Health Level to Override Motion' or from the EnableMotion input." + output OnAwakened(void) : "Fired when this entity becomes awake (collision/force is applied to it while it's asleep)." + output OnPhysGunPickup(void) : "Fired when the player picks up the prop with the physcannon or +USE." + output OnPhysGunOnlyPickup(void) : "Fired when a player picks this object up WITH THE PHYSGUN. +USE pickups do not fire this output." + output OnPhysGunDrop(void) : "Fired when the player drops the prop with the physcannon or USE." + output OnPlayerUse(void) : "Fired when the player tries to +USE the prop. This output will fire only if the Generate output on +USE spawnflag is set." + output OnPlayerPickup(void) : "Fired whenever the player picks up this prop (with the physcannon or with +USE)." +] + +@PointClass base(BasePropPhysics) studioprop() sphere(fademindist) sphere(fademaxdist) = prop_physics_override : + "A prop that physically simulates as a single rigid body. It can be constrained to other physics objects using hinges "+ + "or other constraints. It can also be configured to break when it takes enough damage. Health can be overridden on this version." +[ + health(integer) : "Health" : 0 : "Number of points of damage to take before breaking. 0 means don't break." + + // Inputs + input Ignite(void) : "Ignite, burst into flames." +] + +@PointClass base(BasePropPhysics, RenderFields) studioprop() sphere(fademindist) sphere(fademaxdist) = prop_physics : + "A prop that physically simulates as a single rigid body. It can be constrained to other physics objects using hinges "+ + "or other constraints. It can also be configured to break when it takes enough damage. "+ + "Note that the health of the object will be overridden by the health inside the model, to ensure consistent health game-wide. "+ + "If the model used by the prop is configured to be used as a prop_dynamic (i.e. it should not be physically simulated) then it CANNOT be "+ + "used as a prop_physics. Upon level load it will display a warning in the console and remove itself. Use a prop_dynamic instead." +[ + // Inputs + input Ignite(void) : "Ignite, burst into flames." +] + +@PointClass base(prop_physics) studioprop() sphere(fademindist) sphere(fademaxdist) = prop_physics_multiplayer : + "This class is the same as prop_physics, except the runtime collisions use a more bouncy method that avoids " + + "the prediction errors normal physics objects get." +[ +] + +@PointClass base(Angles, Targetname, Studiomodel, DXLevelChoice) studioprop() = prop_ragdoll : + "A prop that physically simulates and can be articulated with internal joints. The joint constraints are part of the physics model." +[ + spawnflags(flags) = + [ + 4 : "Debris - Don't collide with the player or other debris" : 1 + 8192 : "Allow Dissolve" : 0 + ] + angleOverride(string) : "Override Animation" : "" : "Filled in by the engine via wc_update_entity, do not edit by hand except to clear." + fademindist(float) : "Start Fade Dist" : -1 : "Distance at which the prop starts to fade (<0 = use fademaxdist)" + fademaxdist(float) : "End Fade Dist" : 0 : "Max fade distance at which the prop is visible (0 = don't fade out)" + fadescale(float) : "fade scale" : 1 : "If you specify a fade in the worldspawn, or if the engine is running under dx7, or the engine will forcibly fade out props even if fademindist/fademaxdist isn't specified." + + " This scale factor gives you some control over the fade. Using 0 here turns off the forcible fades." + + " Numbers smaller than 1 cause the prop to fade out at further distances, and greater than 1 cause it to fade out at closer distances." + + input StartRagdollBoogie(void) : "Begins ragdoll boogie effect. Parameter override = number of seconds to boogie." +] + +@PointClass base(prop_dynamic_base) studioprop() = prop_dynamic_ornament : + "A way to attach one studio model to another as an ornament. It will render in the way that player/NPC weapons render." +[ + solid(choices) : "Collisions" : 0 = + [ + 0: "Not Solid" + ] + + InitialOwner(string) : "Target Entity" : : "Name of the entity that this ornament should attach to, at startup." + + // Inputs + input SetAttached(string) : "Attach the ornament to a different entity. Parameter should be the name of entity to attach to." + input Detach(string) : "Detach from the Target Entity and become invisible. The ornament can be re-attached with the SetAttached input." +] + + +//------------------------------------------------------------------------- +// +// Solid Entities +// +//------------------------------------------------------------------------- + +@SolidClass base(Targetname) color(0 255 255) = func_areaportal : + "A portal brush used to manage visibility in maps. Portals define areas, which are spaces " + + "that are connected in the map. Both sides of a portal cannot touch the same area, for example, a " + + "doughnut shaped map would require at least two portals to divide the map into two areas. A linear map " + + "could be divided into two areas with a single area portal." +[ + target(target_destination) : "Name of Linked Door" : : "(Optional) The name of a door whose open/closed state controls the on/off state of this area portal." + StartOpen(choices) : "Initial State" : 1 = + [ + 0 : "Closed" + 1 : "Open" + ] + + PortalVersion(integer) readonly : "Portal Version" : 1 : "(Don't change). Differentiates between shipping HL2 maps and maps using new engine features." + + // Inputs + input Open(void) : "Open the portal. When the portal is open is can be seen through." + input Close(void) : "Close the portal. When the portal is closed it cannot be seen through." + input Toggle(void) : "Toggle the open/closed state of the portal." +] + +@SolidClass base(Targetname) color(0 255 255) = func_occluder : + "A occluder brush used to manage dynamic visibility in maps. Occluders are used to dynamically " + + "determine what things are behind them, to prevent trying to draw them at all." +[ + StartActive(choices) : "Initial State" : 1 = + [ + 0 : "Inactive" + 1 : "Active" + ] + + // Inputs + input Deactivate(void) : "Deactivate the occluder, When inactive, it can be seen through." + input Activate(void) : "Activate the occluder. When active, it cannot be seen through." + input Toggle(void) : "Toggle the active/inactive state of the occluder." +] + +@SolidClass base(BreakableBrush, Origin, RenderFields, Shadow) = func_breakable : + "A brush entity that can be broken from damage, or an input." +[ + minhealthdmg(integer) : "Min Damage to Hurt" : 0 : "The prop will ignore any damage events if the damage is less than this amount." + + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + physdamagescale(float) : "Physics Impact Damage Scale" : "1.0" : "Scales damage energy when this object is hit by a physics object. NOTE: 0 means this feature is disabled for backwards compatibility.\nSet to 1.0 for materials as strong as flesh, smaller numbers indicate stronger materials." +] + +@SolidClass quadbounds() base(BreakableBrush, RenderFields, Shadow) = func_breakable_surf : + "A breakable surface, for partially breakable glass / tile / etc. All faces but the desired visible one must be marked as NODRAW and that" + + "face must be 4 sided. The material applied to the visible face must be set up to be breakable." +[ + health(integer) : "Health" : 5 : "The amount of damage the surface takes before breaking." + fragility(integer) : "Fragility" : 100 : "If the 'Surface Type' is set to Glass, this value sets how fragile the glass pieces are after the surface has been broken." + surfacetype(choices) : "Surface Type" : 0 = + [ + 0 : "Glass" + 1 : "Tile" + ] + + // Inputs + input Shatter(vector) : "Shatter the window. Input a vector. First two coordinates are the X,Y center of the shattering (as values from from 0-1). The third coordinate is the radius of the shatter, in inches." +] + +@SolidClass base(Targetname, Parentname, RenderFields, Shadow) = func_conveyor : + "Conveyor Belt" // NEEDHELP +[ + movedir(angle) : "Move Direction (Pitch Yaw Roll)" : "0 0 0" : "The direction conveyor moves." + spawnflags(flags) = + [ + 1 : "No Push" : 0 + 2 : "Not Solid" : 0 + ] + speed(string) : "Conveyor Speed" : "100" + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + + // Inputs + input ToggleDirection(void) : "ToggleDirection" + input SetSpeed(integer) : "SetSpeed" +] + +@SolidClass base(DXLevelChoice) color(0 180 0) = func_detail : + "An entity that turns its brushes into detail brushes. Detail brushes do NOT contribute to visibility in the PVS. World geometry "+ + "is not clipped to detail brushes, so if you have a small detail clump attached to a wall, the wall won't be cut up by the detail brush."+ + "func_detail is great for high-frequency brush geometry that's visual detail only. It is also ideal for reducing map VIS time." +[ +] + +@SolidClass base(Targetname, Parentname, Origin, RenderFields, Shadow) = func_illusionary : + "Legacy support. Use func_brush instead." +[ + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." +] + +@SolidClass base(Targetname, Parentname) = func_precipitation : + "A brush entity that creates rain and snow inside its volume." +[ + renderamt(integer) : "Density (0-100%)" : 5 + rendercolor(color255) : "Color (R G B)" : "100 100 100" + preciptype(choices) : "Precipitation Type" : 0 = + [ + 0 : "Rain" + 1 : "Snow" + 2 : "Ash" + 3 : "Snowfall" + ] +] + +@SolidClass base(func_wall) = func_wall_toggle : + "A brush entity that can be toggled on/off. When off, the brush will be non-solid and invisible. Does not cast lightmap shadows." +[ + spawnflags(flags) = + [ + 1 : "Starts Invisible" : 0 + ] + + // Inputs + input Toggle(void) : "Toggle the brush on/off. When off, the brush will be non-solid and invisible." +] + + +//@SolidClass base(Door) = func_water : +// "Liquid" // NEEDHELP +//[ +// spawnflags(flags) = +// [ +// 1 : "Starts Open" : 0 +// 256:"Use Only" : 0 +// ] +// movedir(angle) : "Move Direction (Pitch Yaw Roll)" : "0 0 0" : "The direction the water will move when it is told to 'Open'." +// WaveHeight(string) : "Wave Height" : "3.0" +//] + +@SolidClass base(Targetname, Parentname, RenderFields, Global) = func_guntarget : + "This is a moving target that moves along a path of path_tracks. It can be shot and killed." +[ + speed(integer) : "Speed (units per second)" : 100 : "The speed at which the target moves along its path." + target(target_destination) : "First stop target" : : "The name of the first path_track entity in the path that this target should follow." + health(integer) : "Damage to Take" : 0 : "The amount of damage taken before this target is killed." + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + + // Inputs + input Start(void) : "Start the target moving." + input Stop(void) : "Stop the target from moving." + input Toggle(void) : "Toggle the target between moving and stopped." + + // Outputs + output OnDeath(void) : "Fires when the target is killed." +] + +@PointClass = func_fish_pool : "Creates a school of interactive fish that swim near this entity." +[ + model(studio) : "World model" : "models/Junkola.mdl" + fish_count(integer) : "Fish Count" : 10 : "Number of Fish in this Pool" + max_range(float) : "Max Range" : 150 : "How far away a Fish can wander (max 255)" +] + + +//------------------------------------------------------------------------- +// +// Trains and Tracks +// +//------------------------------------------------------------------------- + +@BaseClass = PlatSounds +[ + movesnd(choices) : "Move Sound" : 0 : "The sound played whenever the platform starts moving." = + [ + 0: "No Sound" + 1: "big elev 1" + 2: "big elev 2" + 3: "tech elev 1" + 4: "tech elev 2" + 5: "tech elev 3" + 6: "freight elev 1" + 7: "freight elev 2" + 8: "heavy elev" + 9: "rack elev" + 10: "rail elev" + 11: "squeek elev" + 12: "odd elev 1" + 13: "odd elev 2" + ] + stopsnd(choices) : "Stop Sound" : 0 : "The sound played when the platform stops moving." = + [ + 0: "No Sound" + 1: "big elev stop1" + 2: "big elev stop2" + 3: "freight elev stop" + 4: "heavy elev stop" + 5: "rack stop" + 6: "rail stop" + 7: "squeek stop" + 8: "quick stop" + ] + volume(string) : "Sound Volume 0.0 - 1.0" : "0.85" +] + +@BaseClass base(Targetname, Parentname, RenderFields, Global, PlatSounds) = Trackchange +[ + height(integer) : "Travel Altitude" : 0 : "The vertical height above the track that the train moves. Negative values moves the train below." + spawnflags(flags) = + [ + 1: "Auto Activate train" : 0 + 2: "Relink track" : 0 + 8: "Start at Bottom" : 0 + 16: "Rotate Only" : 0 + 64: "X Axis" : 0 + 128: "Y Axis" : 0 + ] + rotation(integer) : "Spin amount" : 0 : "The amount this platform should rotate as it moves, in degrees." + train(target_destination) : "Train to Switch" // NEEDHELP + toptrack(target_destination) : "Top Track" // NEEDHELP + bottomtrack(target_destination) : "Bottom Track" // NEEDHELP + speed(integer) : "Move/Rotate Speed" : 0 // NEEDHELP +] + +@BaseClass base(Targetname, Parentname, Origin, RenderFields, Global, Shadow) = BaseTrain +[ + spawnflags(flags) = + [ + 1 : "No Pitch (X-rot)" : 0 + 2 : "No User Control" : 0 + 8 : "Passable" : 0 + 16 : "Fixed Orientation" : 0 + 128 : "HL1 Train" : 0 + 256 : "Use max peed for pitch shifting move sound" : 0 + 512 : "Is unblockable by player" : 0 + ] + + target(target_destination) : "First Stop Target" : "" : "The name of the first path_track in the train's path. The train " + + "will spawn at this path_track. It will also turn to face direction indicated by the 'Orientation Type' setting." + + startspeed(integer) : "Max Speed (units / second)" : 100 : "The maximum speed that this train can move. "+ + "Any speeds applied to this train, such as by path_tracks or SetSpeed inputs, will be clipped to this maximum value." + + speed(integer) : "Initial Speed (units / second)" : 0 : "The speed that the train will move at after it spawns, 0 = stopped." + + velocitytype(choices) : "Change Velocity" : 0 : "The method through which this train changes its velocity as it moves along the path." = + [ + 0 : "Instantaneously" + 1 : "Linear blend" + 2 : "Ease in/ease out" + ] + + orientationtype(choices) : "Change angles" : 1 : "The method through which this train changes its orientation as it moves along the path." = + [ + 0 : "Never (fixed orientation)" + 1 : "Near path_tracks" + 2 : "Linear blend" + 3 : "Ease in/ease out" + ] + + wheels(integer) : "Distance Between the Wheels" : 50 : "Used for turning and stopping." + height(integer) : "Height above track" : 4 : "The height above the track that this train moves." + bank(string) : "Bank Angle on Turns" : "0" // NEEDHELP + + dmg(integer) : "Damage on Crush" : 0 : "The amount of damage this train does to entities that block it." + + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + + MoveSound(sound) : "Move Sound" : "" : "A sound that is played (and looped) while the train is moving." + MovePingSound(sound) : "Move Ping Sound" : "" : "A sound that is played more frequently as the train speeds up." + StartSound(sound) : "Start Sound" : "" : "A sound played when the train starts moving." + StopSound(sound) : "Stop Sound" : "" : "A sound played when the train stops moving." + volume(integer) : "Volume (10 = loudest)" : 10 + MoveSoundMinPitch(integer) : "Min pitch (1-255, > 100 = higher)" : 60 : "The sound pitch value that the train will approach as it comes to a stop." + MoveSoundMaxPitch(integer) : "Max pitch (1-255, > 100 = higher)" : 200 : "The sound pitch value that the train will approach as it approaches its "+ + "max speed (or 1000 inches/second if the 'Use max speed for pitch shifting move sound' flag is not set)." + MoveSoundMinTime(float) : "Min move sound interval" : 0 : "Minimum interval at which to play the move ping sound." + MoveSoundMaxTime(float) : "Max move sound interval" : 0 : "Maximum interval at which to play the move ping sound." + + // Inputs + input SetSpeed(float) : "Set the speed of the train, as a ratio of max speed [0, 1]" + input SetSpeedDir(float) : "Set the speed of the train, as a ratio of max speed. Negative values reverse the direction [-1, 1]" + input SetSpeedReal(float) : "Set the speed of the train. Must be a positive value from 0 to max speed." + input Stop(void) : "Stop the train." + input StartForward(void) : "Start the train moving forward." + input StartBackward(void) : "Start the train moving backward." + input Resume(void) : "Resume the train moving in the current direction after it was stopped via the 'Stop' or 'Toggle' input." + input Reverse(void) : "Reverse the direction of the train." + input Toggle(void) : "Toggle the train between start and stop." +] + +@SolidClass base(Trackchange) = func_trackautochange : + "An entity that works as a rotating/moving platform that will carry a train to a new track. "+ + "It must be larger in X-Y planar area than the train, since it must contain the train within "+ + "these dimensions in order to operate when the train is near it." +[ + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." + + // Inputs + input Trigger(void) : "Trigger the track change." +] + +@SolidClass base(Trackchange) = func_trackchange : + "An entity that works as a rotating/moving platform that will carry a train to a new track. "+ + "It must be larger in X-Y planar area than the train, since it must contain the train within "+ + "these dimensions in order to operate when the train is near it." +[ + _minlight(string) : "Minimum Light Level" : : "The minimum level of ambient light that hits this brush." +] + +@SolidClass base(BaseTrain) = func_tracktrain : + "A moving platform that the player can ride. It follows a path of path_track entities.\n" + + "NOTE: Build your train so that the front of the train is facing down the X axis. " + + "When it spawns it will automatically rotate to face the next path_track on the path." +[ +] + +@SolidClass base(BaseTrain) = func_tanktrain : + "A moving train that follows a path of path_track entities, shoots at the player, and can be killed.\n" + + "NOTE: Build your train so that the front of the train is facing down the X axis. " + + "When it spawns it will automatically rotate to face the next path_track on the path." +[ + health(integer) : "Health" : 100 + + // Outputs + output OnDeath(void) : "Fired when the tank is killed." +] + +@SolidClass base(Parentname,Global) = func_traincontrols : + "When used by the player, this entity overrides the player's controls to let them drive a train." +[ + target(target_destination) : "Train Name" : : "The target train to control when the player uses these controls." +] + +@PointClass base(Targetname) iconsprite("editor/tanktrain_aitarget.vmt") = tanktrain_aitarget : + "An entity that changes the target of a tanktrain_ai entity." +[ + target(target_destination) : "Tank AI Entity" : : "The tanktrain_ai entity to change the target of." + newtarget(target_destination) : "New Target Entity" : : "The entity to tell the tanktrain_ai to target." +] + +@PointClass base(Targetname) iconsprite("editor/tanktrain_ai.vmt") = tanktrain_ai : + "Train chase AI" // NEEDHELP +[ + target(target_destination) : "Train Name" + startsound(sound) : "Start Moving Sound" : "vehicles/diesel_start1.wav" + enginesound(sound) : "Engine Loop Sound" : "vehicles/diesel_turbo_loop1.wav" + movementsound(sound) : "Vehicle Movement Sound" : "vehicles/tank_treads_loop1.wav" +] + +@PointClass base(Targetname, Parentname, Angles) cylinder(255 255 255, targetname, target, radius, targetname, targetname, radius) color(255 192 0) size(16 16 16) = path_track : + "An entity used to build paths for other entities to follow. Each path_track is a node on the path, each holding the name of the next path_track in the path." +[ + spawnflags(Flags) = + [ + 1: "Disabled" : 0 + 2: "Fire once" : 0 + 4: "Branch Reverse" : 0 + 8: "Disable train" : 0 + 16: "Teleport to THIS path track" : 0 + ] + + target(target_destination) : "Next Stop Target" : : "The next path_track in the path." + altpath(target_destination) : "Branch Path" : : "An alternative path_track to be the next node in the path. Useful for making branching paths. Use the ToggleAlternatePath / EnableAlternatePath inputs to make the alternative path active." + speed(float) : "New Train Speed" : 0 : "When the train reaches this path_track, it will set its speed to this speed. "+ + "This speed must be a positive value that is less than the train's max speed. A value of 0 will cause no change in the train's speed." + radius(float) : "Path radius" : 0 : "Used by NPCs who follow track paths (attack chopper/gunship). This tells them the maximum distance they're allowed to be from the path at this node." + + orientationtype(choices) : "Orientation Type" : 1 : "The way that the path follower faces as it moves through this path track." = + [ + 0 : "No change" + 1 : "Face direction of motion" + 2 : "Face this path_track's angles" + ] + + // Inputs + input ToggleAlternatePath(void) : "Cause the track to toggle to/from its alternate path." + input EnableAlternatePath(void) : "Enable the alternate path of the track." + input DisableAlternatePath(void) : "Disable the alternate path of the track." + + input TogglePath(void) : "Cause the track to toggle on/off/" + input EnablePath(void) : "Enable the track." + input DisablePath(void) : "Disable the track." + + // Outputs + output OnPass(void) : "Fired when any entity following this path passes this path_track node." +] + + +//------------------------------------------------------------------------- +// +// Test Entities +// +//------------------------------------------------------------------------- +@PointClass base(Angles) size(-16 -16 -16, 16 16 16) color(255 255 255) = test_traceline : + "A debugging tool for testing tracelines." +[ +] + + +//------------------------------------------------------------------------- +// +// Triggers +// +//------------------------------------------------------------------------- + +@SolidClass base(Targetname) = trigger_autosave : + "A trigger volume that autosaves when the player touches it." +[ + master(string) : "Master" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this entity will not activate." + NewLevelUnit(choices) : "Force New Level Unit" : 0 : "If set, the save will discard any savedata from previous levels, for the purpose of keeping savegame filesizes down. Can only be safely used if there is no way for the player to return to previous levels." = + [ + 0 : "No" + 1 : "Yes" + ] + DangerousTimer(float) : "Dangerous Timer" : 0 : "The number of seconds the player must survive before this autosave takes effect." +] + +@SolidClass = trigger_changelevel : + "An entity that triggers a level change.\n" + + "Place an info_landmark in both maps that marks the 'same' location in each map.\n"+ + "TIPS & TRICKS: To fire events in the next level, use the OnLevelChange output to turn on "+ + "an env_global in the current level. Create a logic_auto in the next level that checks "+ + "for the state set by the env_global.\n\n"+ + "To control which entities go through the level transition, create one or more trigger_transitions and "+ + "give them the same name as the landmark. Any entities within the trigger_transition(s) will go to the next map." +[ + targetname(target_source) : "Name" + map(string) : "New Map Name" + landmark(target_destination) : "Landmark Name" + spawnflags(flags) = + [ + 2: "Disable Touch" : 0 + 4: "To Previous Chapter" : 0 + ] + + // Inputs + input ChangeLevel(void) : "Cause the level change. Use this when triggering the level change with a button, etc." + + // Outputs + output OnChangeLevel(void) : "Fired when the level changes." +] + +@SolidClass base(Trigger) = trigger_gravity : + "A trigger volume that changes the gravity on any entity that touches it." +[ + gravity(integer) : "Gravity (0-1)" : 1 +] + +@SolidClass base(Trigger) = trigger_playermovement : + "An entity that can be used to disable player's automatic ducking/unducking when jumping." +[ + spawnflags(flags) = + [ + // Remove this after maps fixed up: + 16: "(OBSOLETE, Uncheck me)" : 0 + 128: "Disable auto player movement" : 1 + ] +] + + +// NEEDHELP +@SolidClass base(Trigger) = trigger_soundscape : + "Soundscape trigger. " + + "It is not necessary to create outputs for this trigger. It automatically will trigger the " + + "soundscape referred to by its 'Soundscape' property." +[ + soundscape(target_source) : "Soundscape" +] + +@SolidClass base(Trigger, Targetname) = trigger_hurt : + "A trigger volume that damages entities that touch it." +[ + master(string) : "Master (Obsolete)" : : "Legacy support: The name of a master entity. If the master hasn't been activated, this entity will not activate." + damage(integer) : "Damage" : 10 : "The amount of damage done to entities that touch this trigger. The damage is done every half-second. See also 'Damage Model' for extra details on how damage can be dealt." + damagecap(integer) : "Damage Cap" : 20 : "Maximum damage dealt per second. This field is only used if you select the Doubling w/Forgiveness damage model, via the spawnflag." + damagetype(choices) : "Damage Type" : 0 = + [ + 0 : "GENERIC" + 1 : "CRUSH" + 2 : "BULLET" + 4 : "SLASH" + 8 : "BURN" + 16 : "FREEZE" + 32 : "FALL" + 64 : "BLAST" + 128 : "CLUB" + 256 : "SHOCK" + 512 : "SONIC" + 1024 : "ENERGYBEAM" + 16384: "DROWN" + 32768 : "PARALYSE" + 65536 : "NERVEGAS" + 131072 : "POISON" + 262144 : "RADIATION" + 524288 : "DROWNRECOVER" + 1048576 : "CHEMICAL" + 2097152 : "SLOWBURN" + 4194304 : "SLOWFREEZE" + ] + + damagemodel(choices) : "Damage Model" : 0 : "How damage is dealt. Normal always does the specified amount of damage each half second. Doubling starts with the specified amount and doubles it each time it hurts the toucher. Forgiveness means that if the toucher gets out of the trigger the damage will reset to the specified value. Good for making triggers that are deadly over time without having to cause massive damage on each touch." = + [ + 0 : "Normal" + 1 : "Doubling w/forgiveness" + ] + + // Inputs + input SetDamage(float) : "Set a new amount of damage for this trigger." + + // Outputs + output OnHurt(void) : "Fired whenever this trigger hurts something other than a player." + output OnHurtPlayer(void) : "Fired whenever this trigger hurts a player." +] + +@SolidClass base(Trigger, Targetname) = trigger_remove : + "A trigger volume that removes any entities that touch it. Be careful, removing some entities can cause instability. "+ + "This is not the same as killing entities. i.e. NPCs removed in this manner will not fire their OnKilled outputs." +[ + // Outputs + output OnRemove(void) : "Fired whenever an entity is removed." +] + +@SolidClass base(Trigger) = trigger_multiple : + "A trigger volume that can be triggered multiple times." +[ + wait(integer) : "Delay Before Reset" : 1 : "Amount of time, in seconds, after the trigger_multiple has triggered before it can be triggered again. If set to -1, it will never trigger again (in which case you should just use a trigger_once)." + + // Outputs + output OnTrigger(void) : "Fired whenever the trigger is activated." +] + +@SolidClass base(TriggerOnce) = trigger_once : + "A trigger volume that removes itself after it is triggered once." +[ + // Outputs + output OnTrigger(void) : "Fired whenever the trigger is activated." +] + +@SolidClass base(Trigger) = trigger_look : + "An entity used to trigger something when the player looks at something. It fires 'OnTrigger' when the player "+ + "looks at a target entity for the given amount of time, while within the trigger volume. If the player leaves "+ + "the trigger or looks away from the target entity the clock resets. If the 'Use Velocity instead of facing' spawnflag " + + "is checked, the trigger uses the player's velocity instead of the player's view, so it determines whenever the player "+ + "is moving toward the target entity. Useful for triggering when players are driving a vehicle at something."+ + "NOTE: Only designed for single-player game. " +[ + spawnflags(flags) = + [ + 128: "Fire Once" : 1 + 256: "Use Velocity instead of facing" : 0 + ] + + target(target_destination) : "Look Target" : : "The name of the entity to be looked at." + LookTime(string) : "LookTime" : "0.5" : "The time, in seconds, that the player must look the target before firing the output. Resets if player leaves trigger, or looks outside the Field of View threshold." + FieldOfView(string) : "FieldOfView" : "0.9" : "How close the player has to be looking at the target. 1.0 = straight ahead\n 0.0 = +/- 90 degrees\n -1.0 = all directions)." + Timeout(float) : "Timeout" : "0" : "The time, in seconds, to wait after player enters the trigger before firing the OnTimeout output, 0 = never." + + // Output + output OnTrigger(void) : "Fired when the trigger is activated." + output OnTimeout(void) : "Fired after the timeout interval expires if the player never looked at the target." +] + +@SolidClass base(Trigger) = trigger_push : + "A trigger volume that pushes entities that touch it." +[ + pushdir(angle) : "Push Direction (Pitch Yaw Roll)" : "0 0 0" : "Angles indicating the direction to push touched entities." + + spawnflags(flags) = + [ + 128: "Once Only" : 0 + 256: "Affects Ladders (Half-Life 2)" : 0 + ] + + speed(integer) : "Speed of Push" : 40 : "The speed at which to push entities away, in inches / second." +] + +@SolidClass base(Trigger, Angles) = trigger_wind : + "A trigger volume that pushes physics objects that touch it." +[ + Speed(integer) : "Speed" : 200 : "The baseline for how hard the wind blows." + SpeedNoise(integer) : "Speed Noise" : 0 : "Noise added to wind speed +/-" + DirectionNoise(integer) : "Direction Noise" : 10 : "Noise added to wind direction." + HoldTime(integer) : "Hold Time" : 0 : "Baseline for how long to wait before changing wind." + HoldNoise(integer) : "Hold Noise" : 0 : "Noise added to how long to wait before changing wind." + + // Inputs + input SetSpeed(integer) : "Set the baseline for how hard the wind blows." +] + +@SolidClass base(Targetname, Origin, Angles) = trigger_impact : + "A trigger volume that can be told to push all physics objects that are inside of it in the direction specified by this trigger's angles.\n"+ + "Also outputs the force at the time of impact for anyone else that wants to use it." +[ + Magnitude(float) : "Magnitude" : 200 : "The strength of the impact. Negative values reverse the direction." + noise(float) : "Noise" : "0.1" : "The amount of directional noise (0-1). 0 = no noise, 1 = random direction." + viewkick(float) : "Viewkick" : "0.05" : "The amount to kick player's view if the player is in the trigger. Proportional to magnitude (0-1)." + + // Inputs + input Impact(float) : "Fire the impact, pushing all entities within the volume." + input SetMagnitude(float) : "Set the magnitude of the impact." + + // Outputs + output ImpactForce(string) : "Fired after an impact. The parameter passed along is the force of the impact that was generated." +] + +@SolidClass base(Trigger) = trigger_proximity : + "Measures the distance of the player within the trigger volume from a given point (and within " + + "a given radius). The NearestPlayerDistance output will be 0 when the player is at the center point, " + + "and 1 when the player is at the radius." +[ + measuretarget(target_destination) : "Point to Measure From" : : "The name of a target entity who's origin is the point to measure the player's distance from." + radius(string) : "Radius to measure within" : 256 : "The radius to which the distance should be mapped. If the player is outside the radius he will be ignored." + + // Outputs + output NearestEntityDistance(integer) : "Fired continuously when entities are touching the trigger volume. The output parameter is the distance from the "+ + "Point to Measure From to the nearest entity that passed the trigger filters. The distance is mapped to the radius distance, "+ + "so it will be 0 when the entity is on the point, and 1 when the entity is at the edge of the radius." +] + +@SolidClass base(Trigger) = trigger_teleport : + "A trigger volume that teleports entities that touch it. Entities are teleported to the Remote Destination, and have their angles "+ + "set to that of the Remote Destination's. If a Local Destination Landmark is specified, teleported entities are offset from the target "+ + "by their initial offset from the landmark, and their angles are left alone." +[ + target(target_destination) : "Remote Destination" : : "The entity specifying the point to which entities should be teleported." + landmark(target_destination) : "Local Destination Landmark" : : "If specified, then teleported entities are offset from the target by their initial offset from the landmark." + spawnflags(flags) = + [ + 32: "Preserve angles even when a local landmark is not specified" : 0 + ] +] + +@SolidClass base(Targetname) = trigger_transition : + "A volume that's used to control which entities go through the level transition. Create one or more trigger_transitions and "+ + "give them the same name as the changelevel landmark. Any entities within the trigger_transition(s) will go to the next map."+ + "See trigger_changelevel for more info." +[ +] + +@SolidClass base(Targetname) = trigger_serverragdoll : + "A volume that forces any NPC inside it to create a server side ragdoll instead of a client one." +[ +] + + + + + +//------------------------------------------------------------------------- +// +// AI +// +//------------------------------------------------------------------------- + +@PointClass base(Targetname,ResponseContext,EnableDisable) = ai_speechfilter : + "An entity that can be used to control the idle speech patterns of a set of NPCs." +[ + subject(target_destination) : "Subject(s)" : "" : "This is the NPC(s) whose speech we're filtering. May be a targetname or a classname." + + IdleModifier(float) : "Idle modifier." : "1.0" : "Multiplier to the percentage chance that our NPC(s) will idle speak. Set to 0 to prevent all idle speech." + NeverSayHello(choices) : "Greet Player?" : 0 : "If set to Yes, our NPC(s) won't greet the player when they first meet him." = + [ + 0 : "Yes" + 1 : "No" + ] + + input SetIdleModifier(float) : "Allows designers to change the idle modifier at runtime" +] + +//------------------------------------------------------------------------- +// Water LOD control +//------------------------------------------------------------------------- + +@PointClass base(Targetname) iconsprite("editor/waterlodcontrol.vmt") = water_lod_control : + "An entity used to control the LOD behavior of any water in the map. If your map has water, this entity is required." +[ + cheapwaterstartdistance(float) : "Start Transition to Cheap Water" : 1000 : "This is the distance from the camera that water will start transitioning to cheap water, in inches." + cheapwaterenddistance(float) : "End Transition to Cheap Water" : 2000 : "This is the distance from the camera that water will finish transitioning to cheap water, in inches." + + // Inputs + input SetCheapWaterStartDistance(float) : "Set the distance that water starts transitioning to cheap water." + input SetCheapWaterEndDistance(float) : "Set the distance that water finishes transitioning to cheap water." +] + + +//------------------------------------------------------------------------- +// Used to allow entities to use point_cameras for their materials +//------------------------------------------------------------------------- + +@PointClass base(Targetname) = info_camera_link : + "An entity that can use point_cameras to render images for materials used by entities. "+ + "To author the material, use the special identifier _rt_Camera " + + "for the $baseTexture (or whatever texture you want, like envmap, etc.) in the .vmt " + + "then connect the 'target' field to the entity which uses that material, and the 'PointCamera' " + + "field to the point_camera you want to have appear on that entity's material" +[ + target(target_destination) : "Entity Whose Material Uses _rt_camera" + PointCamera(target_destination) : "Camera Name" : : "The name of a point_camera entity in the map that the material should be rendered from." + + // Inputs + input SetCamera(string) : "Set the camera to use. The parameter should be the name of a point_camera entity in the map." +] + + +//------------------------------------------------------------------------- +// Used to allow entities to mimic the motions of other entities +//------------------------------------------------------------------------- + +@PointClass base(Targetname) = logic_measure_movement : + "An entity that can measure the movement of an entity relative to another entity " + + "and apply that movement to a third entity." +[ + MeasureTarget(target_destination) : "Entity to Measure" : "" : "Entity whose movement you want to measure." + MeasureReference(target_destination) : "Measure Reference" : "" : "The movement of Entity to Measure will be measured relative to this entity." + Target(target_destination) : "Entity to Move" : "" : "This entity will be moved to mimic the motions of Entity to Measure." + TargetReference(target_destination) : "Movement Reference" : "" : "The Entity to Move will move relative to this entity." + TargetScale(float) : "Movement scale" : "1" : "A scale to divide the measured movements by, before applying those movements to the Entity to Move. 1 = target entity moves as much as the measured entity, 2 = target entity moves half as far as the measured entity, and 0.5 = target entity moves twice as far as the measured entity." + MeasureType(choices) : "Measurement Type" : 0 = + [ + 0 : "Position" + 1 : "Eye position" + ] + + // Inputs + input SetMeasureTarget(string) : "Set the Entity to Measure, whose movement should be measured." + input SetMeasureReference(string) : "Set the Measure Reference entity." + input Target(string) : "Set the Entity to Move, which will be moved to mimic the measured entity." + input SetTargetReference(string) : "Set the Movement Reference entity." + input SetTargetScale(float) : "Set the scale to divide the measured movements by." + input Enable(void) : "Enable the logic_measure_movement." + input Disable(void) : "Disable the logic_measure_movement." +] + + +//------------------------------------------------------------------------- +// Misc +//------------------------------------------------------------------------- + +@PointClass base(BaseNPC, Parentname) studio() = npc_furniture : + "An entity used for non-NPCs that need to synchronise their animation with an NPC in a scripted_sequence. Usually a piece"+ + "of furniture or door that an NPC needs to manipulate within a scripted_sequence." +[ + model(studio) : "Model" + input DisablePlayerCollision(void) : "Disable collisions against the player." + input EnablePlayerCollision(void) : "Enable collisions against the player." +] + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = env_credits : + "An entity to control the rolling credits." +[ + // Inputs + input RollCredits(void) : "Start the intro credits rolling." + input RollOutroCredits(void) : "Start the outro credits rolling." + input ShowLogo(void) : "Show the HL2 logo." + + // Outputs + output OnCreditsDone(void) : "Fired when the credits having finished rolling." +] + +@PointClass base(Parentname, Targetname) size(-8 -8 -8, 8 8 8 ) = material_modify_control : + "An entity that can be used to directly control material vars. To use it, you need to read the .vmt of the material you "+ + "intend to change. Parent this entity to a brush model entity who's material you want to control." +[ + materialName(string) : "Material to modify." + materialVar(string) : "Material variable to modify." + + // Inputs + input SetMaterialVar(string) : "Fire to modify a material variable. The argument is the value to set the variable to." + input SetMaterialVarToCurrentTime(void) : "This sets the material variable to the current time on the server." + input StartAnimSequence(string) : "Force an animated material with the MaterialModifyAnimated proxy to play a set of animation frames. Format is: \nSetting to -1 uses the last frame of the texture. should be 1 or 0." + input StartFloatLerp(string) : "Force a material with the MaterialModifyAnimated proxy to lerp a material var between two floating point values. Format is: \n should be 1 or 0." +] + +//------------------------------------------------------------------------- +// Devshot camera +// - Used by the -makedevshots system, which automatically takes screenshots +// at the position of every devshot camera in the level. +//------------------------------------------------------------------------- + +@PointClass base(Angles) studioprop("models/editor/camera.mdl") = point_devshot_camera : + "An entity used by the -makedevshots system, which automatically takes screenshots at the position of every devshot camera in the level." +[ + cameraname(string) : "Camera Name" : "" : "Used as the name of the directory to store screenshots from this camera. Must be unique within the level." + FOV(integer) : "Camera FOV" : 75 : "FOV of this camera." +] + + +@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = logic_playerproxy : + "An entity that is used to relay inputs/ouputs to the player and back to the world." +[ + // Outputs + output OnFlashlightOn(float) : "Fired when the player turns on his flashlight. This output has the value of how much energy the player had when this happened [0..1]." + output OnFlashlightOff(float) : "Fired when the player turns off his flashlight. This output has the value of how much energy the player had when this happened [0..1]." + input RequestPlayerHealth(void) : "Requests the current player's health from the proxy. This will fire the PlayerHealth output with the value." + output PlayerHealth(integer) : "The player's current health value." + + input SetFlashlightSlowDrain(void) : "Puts the player's flashlight in slow-power-drain mode (for Episodic darkness)" + input SetFlashlightNormalDrain(void) : "Puts the player's flashlight to default power drain" + + input SetPlayerHealth(integer) : "Sets the player's health to this value." + + input RequestAmmoState(void) : "Request the ammo state of the player. It will fire PlayerHasAmmo or PlayerHasNoAmmo outputs." + output PlayerHasAmmo(void) : "Fired by request if the player has any ammo." + output PlayerHasNoAmmo(void) : "Fired by request if the player doesn't have any ammo." + +] + +@PointClass base(Parentname, Targetname) size(-8 -8 -8, 8 8 8 ) = env_spritetrail : + "A magical trail you can parent to anything you heart desires." +[ + lifetime(float) : "Lifetime" : "0.5" + startwidth(float) : "Start Width" : "8.0" + endwidth(float) : "End Width" : "1.0" + spritename(string) : "Sprite Name" : "sprites/bluelaser1.vmt" + + renderamt(integer) : "FX Amount (0 - 255)" : 255 : "The FX amount is used by the selected Render Mode." + rendercolor(color255) : "FX Color (R G B)" : "255 255 255" : "The FX color is used by the selected Render Mode." + + rendermode(choices) : "Render Mode" : 5 = + [ + 0: "Normal" + 4: "Solid" + 5: "Additive" + ] +] diff --git a/fortressforever.fgd b/fortressforever.fgd new file mode 100644 index 0000000..8fe33e1 --- /dev/null +++ b/fortressforever.fgd @@ -0,0 +1,125 @@ +//------------------------------------------------------------------------- +// +// Game data file for Fortress Forever. +// +//------------------------------------------------------------------------- + +@include "ff_base.fgd" + +@SolidClass = func_ladder : + "Ladder. Players will be able to move freely along this brush, as if it was a ladder." + + "Apply the toolsinvisibleladder material to a func_ladder brush." +[ +] + +//------------------------------------------------------------------------- +// +// Camera/monitor entities +// +//------------------------------------------------------------------------- +@PointClass base(Parentname, Angles) studioprop("models/editor/camera.mdl") = point_camera : "Camera" +[ + spawnflags(Flags) = + [ + 1 : "Start Off" : 0 + ] + + targetname(target_source) : "Name" : : "The name that other entities refer to this entity by." + FOV(float) : "FOV" : 90 : "Field of view in degrees" +// resolution(float) : "resolution" : 256 : "width/height of the render target for the camera" + UseScreenAspectRatio(choices) : "Screen Aspect Ratio" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + fogEnable(choices) : "Fog Enable" : 0 = + [ + 0 : "No" + 1 : "Yes" + ] + fogColor(color255) : "Fog Color" : "0 0 0" + fogStart(float) : "Fog Start" : 2048 : "The near fog plane." + fogEnd(float) : "Fog End" : 4096 : "The far fog/clipping plane." + renderTarget(string) : "Render Target" : "_rt_Camera" : "The render target of the camera." + + // Inputs + input ChangeFOV(string) : "Changes camera's FOV over time" + input SetOnAndTurnOthersOff(void) : "Turn the camera on, and turn all other cameras off." + input SetOn(void) : "Turn the camera on." + input SetOff(void) : "Turn the camera off." +] + +@SolidClass base(func_brush) = func_monitor : + "A monitor that renders the view from a given point_camera entity." +[ + target(target_destination) : "Camera name" + + // Inputs + input Toggle(void) : "Toggle - If on, turn off, if off, turn on." + input Enable(void) : "Enable." + input Disable(void) : "Disable." + input SetCamera(string) : "Sets the camera to use for this monitor. Takes the name of a point_camera entity in the map." +] + +// Do this w/ LUA exclusively +//@SolidClass base(Trigger) = trigger_ff_location : +// "Brush-based location displaying." +//[ +// areaname(string) : "Area Name" : : "The name of the area this brush is describing e.g. flag room." +// team(choices) : "Team" : "The team this area belongs to." = +// [ +// 1 : "No Team" +// 2 : "Blue Team" +// 3 : "Red Team" +// 4 : "Yellow Team" +// 5 : "Green Team" +// ] +//] + +@SolidClass base(Trigger) = trigger_ff_script : + "Brush-based Fortress Forever goal. Interfaced from the lua scripting environment." +[ + output OnOutput(void) : "Output to be fired when activated from the lua scripting environment." +] + +@SolidClass base(Targetname, RenderFields, Global) = trigger_ff_clip : + "Lua clip brush." +[ +] + +@PointClass base(Targetname, Parentname, Angles) studio("models/editor/ff_script_helper.mdl") = info_ff_script : + "Point-based Fortress Forever goal. Interfaced from the lua scripting environment." +[ + output OnOutput(void) : "Output to be fired when activated from the lua scripting environment." +] + +@PointClass base(Targetname, Angles) studio("models/editor/playerstart.mdl") = info_ff_teamspawn : + "Team Spawn. This entity is placed where players will be spawned. The scripting environment in Fortress Forever " + + "controls which players will be able to spawn here. See the documentation for more details." +[ +] + +@PointClass base(Targetname, Angles) studio("models/buildable/respawn_turret/respawn_turret.mdl") = ff_miniturret : + "Respawn turret!" +[ +] + +@PointClass base(Targetname, Angles) studio("models/props/ff_dustbowl/minecart.mdl") = ff_minecart : + "VPhysics Mine Cart" +[ + start_disabled(choices) : "Start Disabled" : "Start the object disabled (unable to move)." = + [ + 0 : "No" + 1 : "Yes" + ] +] + +@PointClass base(Targetname, Parentname, Angles) cylinder(255 255 255, targetname, target, radius, targetname, targetname, radius) color(255 192 0) size(16 16 16) = path_mapguide : + "An entity used to build paths for map guides to follow. Each path_mapguide is a node on the path, each holding the name of the next path_mapguide in the path." +[ + target(target_destination) : "Next MapGuide Target" : : "The next path_mapguide in the path." + wait(float) : "Wait" : 10 : "Seconds spent waiting at this point." + time(float) : "Time" : 10 : "Seconds spent travelling from this point to the next." + curvetowards(target_destination) : "Curve towards target" : : "Curve towards this point." + narration(string) : "Narration" : : "Narration file to play." +] \ No newline at end of file diff --git a/gameinfo.txt b/gameinfo.txt new file mode 100644 index 0000000..0213e31 --- /dev/null +++ b/gameinfo.txt @@ -0,0 +1,49 @@ +"GameInfo" +{ + game "Fortress Forever" + title "Fortress Forever" + name "Fortress Forever" + type multiplayer_only + + developer "Fortress Forever Team" + developer_url "http://www.fortress-forever.com/" + icon "resource/icon_ff" + manual "http://www.fortress-forever.com/wiki/Main_Page" + + hidden_maps + { + "test_speakers" 1 + "test_hardware" 1 + } + + FileSystem + { + SteamAppId 253530 // This will mount all the GCFs we need (240=CS:S, 220=HL2). + ToolsAppId 211 // Tools will load this (ie: source SDK caches) to get things like materials\debug, materials\editor, etc. + + // + // The code that loads this file automatically does a few things here: + // + // 1. For each "Game" search path, it adds a "GameBin" path, in \bin + // 2. For each "Game" search path, it adds another "Game" path in front of it with _ at the end. + // For example: c:\hl2\cstrike on a french machine would get a c:\hl2\cstrike_french path added to it. + // 3. For the first "Game" search path, it adds a search path called "MOD". + // 4. For the first "Game" search path, it adds a search path called "DEFAULT_WRITE_PATH". + // + + // + // Search paths are relative to the base directory, which is where hl2.exe is found. + // + // |gameinfo_path| points at the directory where gameinfo.txt is. + // We always want to mount that directory relative to gameinfo.txt, so + // people can mount stuff in c:\mymod, and the main game resources are in + // someplace like c:\program files\valve\steam\steamapps\\half-life 2. + // + SearchPaths + { + Game |gameinfo_path|. + Game hl2 + Game FortressForever + } + } +} diff --git a/maplist.txt b/maplist.txt new file mode 100644 index 0000000..12e47ec --- /dev/null +++ b/maplist.txt @@ -0,0 +1,11 @@ +ff_destroy +ff_openfire +ff_napoli +ff_ksour +ff_palermo +ff_monkey +ff_schtop +ff_shutdown2 +ff_aardvark +ff_warpath +ff_dustbowl \ No newline at end of file diff --git a/maps/default.lua b/maps/default.lua new file mode 100644 index 0000000..44a12bd --- /dev/null +++ b/maps/default.lua @@ -0,0 +1,18 @@ +-- if no lua scripts are found for the map (ff_xxx.bsp) then this file will be loaded +IncludeScript("base_ctf"); + +function startup() + enabled_teams = { Team.kBlue, Team.kRed } + SetPlayerLimit(Team.kBlue, 0) + SetPlayerLimit(Team.kRed, 0) + SetPlayerLimit(Team.kYellow, -1) + SetPlayerLimit(Team.kGreen, -1) + + -- disable civilians + for index, iteam in ipairs( enabled_teams ) do + local team = GetTeam(iteam) + team:SetClassLimit(Player.kCivilian, -1) + end + + ConsoleToAll("No map lua found! Loaded default") +end \ No newline at end of file diff --git a/maps/ff_2fort.lua b/maps/ff_2fort.lua new file mode 100644 index 0000000..021a941 --- /dev/null +++ b/maps/ff_2fort.lua @@ -0,0 +1,181 @@ +IncludeScript("base_ctf"); +IncludeScript("base_location"); +IncludeScript("base_respawnturret"); + +----------------------------------------------------------------------------------------------------------------------------- +-- LOCATIONS +-- Q: wow clover, there sure are alot of them! +-- A: hell yes there are. +----------------------------------------------------------------------------------------------------------------------------- +blue_location_ulobby = location_info:new({ text = "Upper Lobby", team = Team.kBlue }) +blue_location_llobby = location_info:new({ text = "Lower Lobby", team = Team.kBlue }) +blue_location_ch = location_info:new({ text = "Covered Hallway", team = Team.kBlue }) +blue_location_bspawn = location_info:new({ text = "Battlements Spawn", team = Team.kBlue }) +blue_location_lspawn = location_info:new({ text = "Lobby Spawn", team = Team.kBlue }) +blue_location_rr = location_info:new({ text = "#FF_LOCATION_RAMPROOM", team = Team.kBlue }) +blue_location_crates = location_info:new({ text = "Crate Tunnel", team = Team.kBlue }) +blue_location_ulift = location_info:new({ text = "Upper Elevator Room", team = Team.kBlue }) +blue_location_llift = location_info:new({ text = "Lower Elevator Room", team = Team.kBlue }) +blue_location_cod = location_info:new({ text = "Corner of Eternal Despair", team = Team.kBlue }) +blue_location_fd = location_info:new({ text = "#FF_LOCATION_FRONTDOOR", team = Team.kBlue }) +blue_location_grate = location_info:new({ text = "Grate Room", team = Team.kBlue }) +blue_location_uspiral = location_info:new({ text = "Upper Spiral", team = Team.kBlue }) +blue_location_mspiral = location_info:new({ text = "Mid Spiral", team = Team.kBlue }) +blue_location_lspiral = location_info:new({ text = "Lower Spiral", team = Team.kBlue }) +blue_location_waccess = location_info:new({ text = "Water Access", team = Team.kBlue }) +blue_location_wtunnel = location_info:new({ text = "Water Tunnel", team = Team.kBlue }) +blue_location_bfr = location_info:new({ text = "Basement - Flagroom", team = Team.kBlue }) +blue_location_bsteam = location_info:new({ text = "Basement - Steam Corridor", team = Team.kBlue }) +blue_location_bmf = location_info:new({ text = "Basement - Mainframe", team = Team.kBlue }) +blue_location_blobby = location_info:new({ text = "Basement - Lobby", team = Team.kBlue }) +blue_location_blift = location_info:new({ text = "Basement - Elevator Side", team = Team.kBlue }) +blue_location_bresup = location_info:new({ text = "Basement - Resupply", team = Team.kBlue }) +blue_location_batts = location_info:new({ text = "#FF_LOCATION_BATTLEMENTS", team = Team.kBlue }) + +neutral_location_yard = location_info:new({ text = "#FF_LOCATION_YARD", team = Team.kUnassigned }) +neutral_location_ywater = location_info:new({ text = "Yard - Water", team = Team.kUnassigned }) + +red_location_ulobby = location_info:new({ text = "Upper Lobby", team = Team.kRed }) +red_location_llobby = location_info:new({ text = "Lower Lobby", team = Team.kRed }) +red_location_ch = location_info:new({ text = "Covered Hallway", team = Team.kRed }) +red_location_bspawn = location_info:new({ text = "Battlements Spawn", team = Team.kRed }) +red_location_lspawn = location_info:new({ text = "Lobby Spawn", team = Team.kRed }) +red_location_rr = location_info:new({ text = "#FF_LOCATION_RAMPROOM", team = Team.kRed }) +red_location_crates = location_info:new({ text = "Crate Tunnel", team = Team.kRed }) +red_location_ulift = location_info:new({ text = "Upper Elevator Room", team = Team.kRed }) +red_location_llift = location_info:new({ text = "Lower Elevator Room", team = Team.kRed }) +red_location_cod = location_info:new({ text = "Corner of Eternal Despair", team = Team.kRed }) +red_location_fd = location_info:new({ text = "#FF_LOCATION_FRONTDOOR", team = Team.kRed }) +red_location_grate = location_info:new({ text = "Grate Room", team = Team.kRed }) +red_location_uspiral = location_info:new({ text = "Upper Spiral", team = Team.kRed }) +red_location_mspiral = location_info:new({ text = "Mid Spiral", team = Team.kRed }) +red_location_lspiral = location_info:new({ text = "Lower Spiral", team = Team.kRed }) +red_location_waccess = location_info:new({ text = "Water Access", team = Team.kRed }) +red_location_wtunnel = location_info:new({ text = "Water Tunnel", team = Team.kRed }) +red_location_bfr = location_info:new({ text = "Basement - Flagroom", team = Team.kRed }) +red_location_bsteam = location_info:new({ text = "Basement - Steam Corridor", team = Team.kRed }) +red_location_bmf = location_info:new({ text = "Basement - Mainframe", team = Team.kRed }) +red_location_blobby = location_info:new({ text = "Basement - Lobby", team = Team.kRed }) +red_location_blift = location_info:new({ text = "Basement - Elevator Side", team = Team.kRed }) +red_location_bresup = location_info:new({ text = "Basement - Resupply", team = Team.kRed }) +red_location_batts = location_info:new({ text = "#FF_LOCATION_BATTLEMENTS", team = Team.kRed }) + +----------------------------------------------------------------------------------------------------------------------------- +-- bag for respawns +----------------------------------------------------------------------------------------------------------------------------- +ff_2fort_genericpack = genericbackpack:new({ + health = 400, + armor = 400, + + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 400, + + gren1 = 0, + gren2 = 0, + + respawntime = 2, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) +function ff_2fort_genericpack:dropatspawn() return false end +blue_2fort_genericpack = ff_2fort_genericpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue } }) +red_2fort_genericpack = ff_2fort_genericpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kRed } }) + +----------------------------------------------------------------------------------------------------------------------------- +-- grenpack +----------------------------------------------------------------------------------------------------------------------------- +ff_2fort_grenpack = genericbackpack:new({ + health = 0, + armor = 0, + + grenades = 0, + nails = 0, + shells = 0, + rockets = 0, + cells = 0, + + gren1 = 2, + gren2 = 2, + + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) +function ff_2fort_grenpack:dropatspawn() return false end +blue_2fort_grenpack = ff_2fort_grenpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue } }) +red_2fort_grenpack = ff_2fort_grenpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kRed } }) + +----------------------------------------------------------------------------------------------------------------------------- +-- bag by water exit that anyone can use +----------------------------------------------------------------------------------------------------------------------------- +ff_2fort_waterpack = genericbackpack:new({ + health = 50, + armor = 50, + + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 80, + + gren1 = 0, + gren2 = 0, + + respawntime = 30, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) +function ff_2fort_waterpack:dropatspawn() return false end +blue_2fort_waterpack = ff_2fort_waterpack:new({}) +red_2fort_waterpack = ff_2fort_waterpack:new({}) + +----------------------------------------------------------------------------------------------------------------------------- +-- bag used in mid spiral and bottom lift resupply to stagger resources +-- tweak the respawntime of this bag to control offence/defence balance +----------------------------------------------------------------------------------------------------------------------------- +ff_2fort_spiralpack = genericbackpack:new({ + health = 50, + armor = 50, + + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 130, + + gren1 = 0, + gren2 = 0, + + respawntime = 20, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) +function ff_2fort_spiralpack:dropatspawn() return false end +blue_2fort_spiralpack = ff_2fort_spiralpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue } }) +red_2fort_spiralpack = ff_2fort_spiralpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kRed } }) + +----------------------------------------------------------------------------- +-- SPAWNS +----------------------------------------------------------------------------- +red_spiral = function(self,player) return ((player:GetTeamId() == Team.kRed) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSniper) or (player:GetClass() == Player.kSpy))) end +red_balc = function(self,player) return ((player:GetTeamId() == Team.kRed) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSniper) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kSoldier) or (player:GetClass() == Player.kHwguy) or (player:GetClass() == Player.kDemoman) or (player:GetClass() == Player.kPyro) or (player:GetClass() == Player.kEngineer))) end + +red_spiralspawn = { validspawn = red_spiral } +red_balcspawn = { validspawn = red_balc } + +blue_spiral = function(self,player) return ((player:GetTeamId() == Team.kBlue) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSniper) or (player:GetClass() == Player.kSpy))) end +blue_balc = function(self,player) return ((player:GetTeamId() == Team.kBlue) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSniper) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kSoldier) or (player:GetClass() == Player.kHwguy) or (player:GetClass() == Player.kDemoman) or (player:GetClass() == Player.kPyro) or (player:GetClass() == Player.kEngineer))) end + +blue_spiralspawn = { validspawn = blue_spiral } +blue_balcspawn = { validspawn = blue_balc } diff --git a/maps/ff_2fort.txt b/maps/ff_2fort.txt new file mode 100644 index 0000000..3328ddc --- /dev/null +++ b/maps/ff_2fort.txt @@ -0,0 +1,9 @@ +ff_2fort +Industrial sector CTF (capture the flag). + +Use stealth or sheer force to reach basement of the enemy base. +Once inside, steal their precious flag and capture it at your battlements. +Make them pay for their insolence! + +Each capture nets your team 10 points. +The team with the most points at the end of the round wins. \ No newline at end of file diff --git a/maps/ff_2fort_soundscapes.txt b/maps/ff_2fort_soundscapes.txt new file mode 100644 index 0000000..8b74fe2 --- /dev/null +++ b/maps/ff_2fort_soundscapes.txt @@ -0,0 +1,267 @@ +//////////////////////////////////////////////// +// FF_2FORT SOUNDSCAPES +// +// INDOORS +// OUTDOORS +// INDOORS_OUTDOORSAUDIBLE +// BASEMENT +// WATER +// +//////////////////////////////////////////////// + + +//////////////////////////////////////////////// +// INDOORS +// Basic ambience with metal scratching sounds. +//////////////////////////////////////////////// + +"ff_2fort.indoors" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/atmosphere/ambience5.wav" + "volume" "1.0" + "pitch" "100" + } + + "playrandom" + { + "time" "3, 10" + "volume" "0.05,0.15" + "pitch" "95,105" + "position" "random" + "rndwave" + { + "wave" "ambient/materials/metal_rattle1.wav" + "wave" "ambient/materials/metal_rattle2.wav" + "wave" "ambient/materials/metal_rattle3.wav" + } + } +} + + +//////////////////////////////////////////////// +// OUTDOORS +// Outdoor wind ambience with random gusts. +// Also has random low-volume train sounds and +// some slightly louder wildlife sound effects. +//////////////////////////////////////////////// + + +"ff_2fort.outdoors" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/wind/ff_wasteland_wind.wav" + "volume" "0.8" + "pitch" "100" + } + + "playsoundscape" + { + "name" "d1_canals.util_windgusts" + "volume" "1.0" + } + + "playrandom" + { + "time" "45, 90" + "volume" "0.1, 0.3" + "pitch" "50, 120" + "position" "random" + "rndwave" + { + "wave" "ambient/machines/train_rumble.wav" + "wave" "ambient/alarms/train_horn_distant1.wav" + } + } + + "playrandom" + { + "time" "10, 30" + "volume" "0.3, 0.6" + "pitch" "80, 120" + "position" "random" + "rndwave" + { + "wave" "ambient/levels/coast/coastbird1.wav" + "wave" "ambient/levels/coast/coastbird2.wav" + "wave" "ambient/levels/coast/coastbird3.wav" + "wave" "ambient/levels/coast/coastbird4.wav" + "wave" "ambient/levels/coast/coastbird5.wav" + "wave" "ambient/levels/coast/coastbird6.wav" + "wave" "ambient/levels/canals/critter2.wav" + "wave" "ambient/levels/canals/critter6.wav" + "wave" "ambient/levels/canals/critter7.wav" + } + } +} + +//////////////////////////////////////////////// +// INDOORS OUTDOORSAUDIBLE +// Indoor soundscape with a quieter outdoor +// soundscape playing in the background. +//////////////////////////////////////////////// + +"ff_2fort.indoors_outdoorsaudible" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/atmosphere/ambience5.wav" + "volume" "0.9" + "pitch" "100" + } + + "playrandom" + { + "time" "3, 10" + "volume" "0.05,0.15" + "pitch" "95,105" + "position" "random" + "rndwave" + { + "wave" "ambient/materials/metal_rattle1.wav" + "wave" "ambient/materials/metal_rattle2.wav" + "wave" "ambient/materials/metal_rattle3.wav" + } + } + + "playlooping" + { + "wave" "ambient/wind/ff_wasteland_wind.wav" + "volume" "0.5" + "pitch" "100" + } + + "playsoundscape" + { + "name" "d1_canals.util_windgusts" + "volume" "0.4" + } + + "playrandom" + { + "time" "45, 90" + "volume" "0.1, 0.3" + "pitch" "50, 120" + "position" "random" + "rndwave" + { + "wave" "ambient/machines/train_rumble.wav" + "wave" "ambient/alarms/train_horn_distant1.wav" + } + } + + "playrandom" + { + "time" "10, 30" + "volume" "0.1, 0.4" + "pitch" "80, 120" + "position" "random" + "rndwave" + { + "wave" "ambient/levels/coast/coastbird1.wav" + "wave" "ambient/levels/coast/coastbird2.wav" + "wave" "ambient/levels/coast/coastbird3.wav" + "wave" "ambient/levels/coast/coastbird4.wav" + "wave" "ambient/levels/coast/coastbird5.wav" + "wave" "ambient/levels/coast/coastbird6.wav" + "wave" "ambient/levels/canals/critter2.wav" + "wave" "ambient/levels/canals/critter6.wav" + "wave" "ambient/levels/canals/critter7.wav" + } + } +} + +//////////////////////////////////////////////// +// BASEMENT +// Underground background sounds and metal stresses. +//////////////////////////////////////////////// + +"ff_2fort.basement" +{ + "dsp" "1" + "playlooping" + { + "volume" "0.6" + "pitch" "100" + "wave" "ambient/atmosphere/corridor.wav" + } + + "playlooping" + { + "volume" "0.4" + "pitch" "100" + "wave" "ambient/atmosphere/drone2lp.wav" + "position" "0" + } + + "playsoundscape" + { + "name" "coast.util_metalstress" + "volume" "0.4" + } + + "playsoundscape" + { + "name" "coast.util_shackmetal" + "volume" "0.3" + } + + "playrandom" + { + "time" "30, 60" + "volume" "0.25, 0.50" + "pitch" "50, 120" + "position" "random" + "rndwave" + { + "wave" "ambient/materials/rustypipes1.wav" + "wave" "ambient/materials/rustypipes2.wav" + "wave" "ambient/materials/rustypipes3.wav" + "wave" "ambient/materials/shuffle1.wav" + } + } +} + +//////////////////////////////////////////////// +// WATER +// Some runnign water sounds and random dripping. +//////////////////////////////////////////////// + +"ff_2fort.water" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/water/corridor_water.wav" + "volume" "0.8" + "pitch" "100" + } + + "playlooping" + { + "wave" "ambient/levels/canals/waterleak_loop1.wav" + "volume" "0.3" + "pitch" "100" + } + + "playsoundscape" + { + "name" "d1_canals.util_drip" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "d1_canals.util_fardrips" + "volume" "1.0" + } +} \ No newline at end of file diff --git a/maps/ff_aardvark.lua b/maps/ff_aardvark.lua new file mode 100644 index 0000000..4ab9420 --- /dev/null +++ b/maps/ff_aardvark.lua @@ -0,0 +1,301 @@ +-- ff_aardvark.lua + +----------------------------------------------------------------------------- +-- number of snipers allowed per team +----------------------------------------------------------------------------- +SNIPER_LIMIT = 1; + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base"); +IncludeScript("base_ctf"); +IncludeScript("base_location"); +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- +POINTS_PER_CAPTURE = 10; +FLAG_RETURN_TIME = 60; + +----------------------------------------------------------------------------- +-- unique aardvark locations +----------------------------------------------------------------------------- +location_redspawn = location_info:new({ text = "Respawn", team = Team.kRed }) +location_redsec = location_info:new({ text = "Laser Control", team = Team.kRed }) +location_redfr = location_info:new({ text = "Flag Room", team = Team.kRed }) +location_redgen = location_info:new({ text = "Generator Room", team = Team.kRed }) +location_redbasement = location_info:new({ text = "Basement", team = Team.kRed }) +location_redwater = location_info:new({ text = "Perilous Passage", team = Team.kRed }) +location_redcor = location_info:new({ text = "Utility Corridors", team = Team.kRed }) +location_redlift = location_info:new({ text = "Lift", team = Team.kRed }) +location_redfd = location_info:new({ text = "Front Door", team = Team.kRed }) +location_redramp = location_info:new({ text = "Top Main Ramp", team = Team.kRed }) +location_redrampon = location_info:new({ text = "Main Ramp", team = Team.kRed }) +location_redhallspawn = location_info:new({ text = "Respawn-Side Hallway", team = Team.kRed }) +location_redhallwater = location_info:new({ text = "Lift-Side Hallway", team = Team.kRed }) +location_redtoilet = location_info:new({ text = "Toilet", team = Team.kRed }) +location_redshame = location_info:new({ text = "Tunnel of Shame", team = Team.kRed }) +location_redoven = location_info:new({ text = "OVEN", team = Team.kRed }) + +location_bluespawn = location_info:new({ text = "Respawn", team = Team.kBlue }) +location_bluesec = location_info:new({ text = "Laser Control", team = Team.kBlue }) +location_bluefr = location_info:new({ text = "Flag Room", team = Team.kBlue }) +location_bluegen = location_info:new({ text = "Generator Room", team = Team.kBlue }) +location_bluebasement = location_info:new({ text = "Basement", team = Team.kBlue }) +location_bluewater = location_info:new({ text = "Perilous Passage", team = Team.kBlue }) +location_bluecor = location_info:new({ text = "Utility Corridors", team = Team.kBlue }) +location_bluelift = location_info:new({ text = "Lift", team = Team.kBlue }) +location_bluefd = location_info:new({ text = "Front Door", team = Team.kBlue }) +location_blueramp = location_info:new({ text = "Top Main Ramp", team = Team.kBlue }) +location_bluerampon = location_info:new({ text = "Main Ramp", team = Team.kBlue }) +location_bluehallspawn = location_info:new({ text = "Respawn-Side Hallway", team = Team.kBlue }) +location_bluehallwater = location_info:new({ text = "Lift-Side Hallway", team = Team.kBlue }) +location_bluetoilet = location_info:new({ text = "Toilet", team = Team.kBlue }) +location_blueshame = location_info:new({ text = "Tunnel of Shame", team = Team.kBlue }) +location_blueoven = location_info:new({ text = "OVEN", team = Team.kBlue }) + +location_midmap = location_info:new({ text = "Outside", team = NO_TEAM }) + +----------------------------------------------------------------------------- +-- set class limits +----------------------------------------------------------------------------- +function startup() + SetGameDescription("Capture the Flag") + + -- set up team limits on each team + SetPlayerLimit(Team.kBlue, 0) + SetPlayerLimit(Team.kRed, 0) + SetPlayerLimit(Team.kYellow, -1) + SetPlayerLimit(Team.kGreen, -1) + + -- CTF maps generally don't have civilians, + -- so override in map LUA file if you want 'em + local team = GetTeam(Team.kBlue) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kSniper, SNIPER_LIMIT) + + team = GetTeam(Team.kRed) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kSniper, SNIPER_LIMIT) +end + +----------------------------------------------------------------------------- +-- custom aardvark packs +----------------------------------------------------------------------------- +aardvarkpack = genericbackpack:new({ + health = 60, + armor = 60, + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 0, + gren1 = 1, + gren2 = 1, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +aardvarkpack_metal = genericbackpack:new({ + health = 0, + armor = 0, + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 130, + respawntime = 6, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +function aardvarkpack:dropatspawn() return false end +function aardvarkpack_metal:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- backpack entity setup (modified for aardvarkpack) +----------------------------------------------------------------------------- +function build_backpacks(tf) + return healthkit:new({touchflags = tf}), + armorkit:new({touchflags = tf}), + ammobackpack:new({touchflags = tf}), + bigpack:new({touchflags = tf}), + grenadebackpack:new({touchflags = tf}), + aardvarkpack:new({touchflags = tf}), + aardvarkpack_metal:new({touchflags = tf}) +end + +blue_healthkit, blue_armorkit, blue_ammobackpack, blue_bigpack, blue_grenadebackpack, blue_aardvarkpack, blue_aardvarkpack_metal = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kBlue}) +red_healthkit, red_armorkit, red_ammobackpack, red_bigpack ,red_grenadebackpack, red_aardvarkpack, red_aardvarkpack_metal = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kRed}) +yellow_healthkit, yellow_armorkit, yellow_ammobackpack, yellow_bigpack, yellow_grenadebackpack, yellow_aardvarkpack, yellow_aardvarkpack_metal = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kYellow}) +green_healthkit, green_armorkit, green_ammobackpack, green_bigpack, green_grenadebackpack, green_aardvarkpack, green_aardvarkpack_metal = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kGreen}) + +----------------------------------------------------------------------------- +-- aardvark resupply (bagless) +----------------------------------------------------------------------------- +aardvarkresup = trigger_ff_script:new({ team = Team.kUnassigned }) + +function aardvarkresup:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == self.team then + player:AddHealth( 400 ) + player:AddArmor( 400 ) + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + end + end +end + +blue_aardvarkresup = aardvarkresup:new({ team = Team.kBlue }) +red_aardvarkresup = aardvarkresup:new({ team = Team.kRed }) + +----------------------------------------------------------------------------- +-- aardvark security +----------------------------------------------------------------------------- +red_aardvarksec = trigger_ff_script:new() +blue_aardvarksec = trigger_ff_script:new() +bluesecstatus = 1 +redsecstatus = 1 + +sec_iconx = 60 +sec_icony = 30 +sec_iconw = 16 +sec_iconh = 16 + +function red_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kBlue then + if redsecstatus == 1 then + redsecstatus = 0 + AddSchedule("aardvarksecup10red",20,aardvarksecup10red) + AddSchedule("aardvarksecupred",30,aardvarksecupred) + OpenDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_30") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_REDDOWN" ) + RemoveHudItemFromAll( "red-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end + end + end +end + +function blue_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kRed then + if bluesecstatus == 1 then + bluesecstatus = 0 + AddSchedule("aardvarksecup10blue",20,aardvarksecup10blue) + AddSchedule("aardvarksecupblue",30,aardvarksecupblue) + OpenDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_30") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_BLUEDOWN" ) + RemoveHudItemFromAll( "blue-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + end + end +end + +function aardvarksecupred() + redsecstatus = 1 + CloseDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_ON") + SpeakAll( "SD_REDUP" ) + RemoveHudItemFromAll( "red-sec-down" ) + AddHudIconToAll( "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) +end + +function aardvarksecupblue() + bluesecstatus = 1 + CloseDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_ON") + SpeakAll( "SD_BLUEUP" ) + RemoveHudItemFromAll( "blue-sec-down" ) + AddHudIconToAll( "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) +end + +function aardvarksecup10red() + BroadCastMessage("#FF_RED_SEC_10") +end + +function aardvarksecup10blue() + BroadCastMessage("#FF_BLUE_SEC_10") +end + +----------------------------------------------------------------------------- +-- aardvark lasers and respawn shields +----------------------------------------------------------------------------- +KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) +lasers_KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) + +function KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +function lasers_KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + if self.team == Team.kBlue then + if redsecstatus == 1 then + return EVENT_ALLOWED + end + end + if self.team == Team.kRed then + if bluesecstatus == 1 then + return EVENT_ALLOWED + end + end + end + end + return EVENT_DISALLOWED +end + +blue_slayer = KILL_KILL_KILL:new({ team = Team.kBlue }) +red_slayer = KILL_KILL_KILL:new({ team = Team.kRed }) +sec_blue_slayer = lasers_KILL_KILL_KILL:new({ team = Team.kBlue }) +sec_red_slayer = lasers_KILL_KILL_KILL:new({ team = Team.kRed }) + +------------------------- +-- flaginfo +------------------------- +function flaginfo( player_entity ) + local player = CastToPlayer( player_entity ) + + flaginfo_base(player_entity) --basic CTF HUD items + + RemoveHudItem( player, "red-sec-down" ) + RemoveHudItem( player, "blue-sec-down" ) + RemoveHudItem( player, "red-sec-up" ) + RemoveHudItem( player, "blue-sec-up" ) + + if bluesecstatus == 1 then + AddHudIcon( player, "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + else + AddHudIcon( player, "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + + if redsecstatus == 1 then + AddHudIcon( player, "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + else + AddHudIcon( player, "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end +end diff --git a/maps/ff_aardvark.txt b/maps/ff_aardvark.txt new file mode 100644 index 0000000..287dac1 --- /dev/null +++ b/maps/ff_aardvark.txt @@ -0,0 +1,6 @@ +Steal the enemy flag while protecting your own +[1] Take enemy flag +[2] Bring to capture point in your base +Deactivate enemy security to open up additional routes to the enemy flag +SCORING: 10 points per flag capture +Team with most points at end of round wins \ No newline at end of file diff --git a/maps/ff_aardvark_soundscapes.txt b/maps/ff_aardvark_soundscapes.txt new file mode 100644 index 0000000..cafff23 --- /dev/null +++ b/maps/ff_aardvark_soundscapes.txt @@ -0,0 +1,38 @@ +"aardvark_inside" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "volume" "1" + "pitch" "100" + "wave" "ambient/push/inside_amb1.wav" + } +} + +"aardvark_basement" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "volume" "1" + "pitch" "100" + "wave" "ambient/water/drip_loop1.wav" + } +} + +"aardvark_outside" +{ + "dsp" "1" + "dsp_volume" "0.4" + + "playlooping" + { + "volume" "1" + "pitch" "100" + "wave" "ff_aardvark/exo_birds.wav" + } +} diff --git a/maps/ff_bases.lua b/maps/ff_bases.lua new file mode 100644 index 0000000..a994f70 --- /dev/null +++ b/maps/ff_bases.lua @@ -0,0 +1,276 @@ +-- ff_bases.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base") +IncludeScript("base_ctf") +IncludeScript("base_location") +IncludeScript("base_respawnturret") +----------------------------------------------------------------------------- + +function precache() + PrecacheSound( "Backpack.Touch" ) + PrecacheSound( "misc.thunder" ) +end + +----------------------------------------------------------------------------- +-- Doors +----------------------------------------------------------------------------- +blue_only = bluerespawndoor +red_only = redrespawndoor + + +----------------------------------------------------------------------------- +-- Computer Explodeded +----------------------------------------------------------------------------- +fr_computer = trigger_ff_script:new({ team = Team.kUnassigned }) +function fr_computer:onexplode( explosion_entity ) + if IsDetpack( explosion_entity ) then + local detpack = CastToDetpack(explosion_entity) + if detpack:GetTeamId() ~= self.team then + local points = 5 + local team = detpack:GetTeam() + team:AddScore(points) + + local player = detpack:GetOwner() + player:AddFortPoints(points * 100, "Destroyed Computer" ) + + SmartSound(player, "misc.thunder", "misc.thunder", "misc.thunder") + SmartMessage(player, "You Destroyed the Enemy Command Centre!", "Your Team Destroyed the Enemy Command Centre!", "Your Command Centre has been Destroyed!") + + if team:GetTeamId() == Team.kBlue then + SpeakAll( "CZ_RCC_DET" ) + elseif team:GetTeamId() == Team.kRed then + SpeakAll( "CZ_BCC_DET" ) + end + end + end + + return EVENT_ALLOWED +end + +blue_computer = fr_computer:new({ team = Team.kBlue }) +red_computer = fr_computer:new({ team = Team.kRed }) + +----------------------------------------------------------------------------- +-- Backpacks +----------------------------------------------------------------------------- +blue_gen_pack = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 0, + nails = 300, + shells = 300, + rockets = 300, + gren1 = 1, + gren2 = 0, + cells = 130, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue}}) + +blue_fr_gen_pack = genericbackpack:new({ + health = 30, + armor = 30, + grenades = 0, + nails = 300, + shells = 300, + rockets = 300, + gren1 = 0, + gren2 = 0, + cells = 130, + respawntime = 20, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue}}) + +red_gen_pack = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 0, + nails = 300, + shells = 300, + rockets = 300, + gren1 = 1, + gren2 = 0, + cells = 130, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kRed}}) + +red_fr_gen_pack = genericbackpack:new({ + health = 30, + armor = 30, + grenades = 0, + nails = 300, + shells = 300, + rockets = 300, + gren1 = 0, + gren2 = 0, + cells = 130, + respawntime = 20, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kRed}}) + +----------------------------------------------------------------------------- +-- Locations +-- Switched all "Left"/"Right" so that it's from defenders pov so it makes sense to say "INCOMING RIGHT RAMP"/etc (caesium) +----------------------------------------------------------------------------- + +location_midmap = location_info:new({ text = "Midmap", team = Team.kUnassigned }) +location_water = location_info:new({ text = "Water", team = Team.kUnassigned }) + +location_blue_bments = location_info:new({ text = "Battlements", team = Team.kBlue }) +location_red_bments = location_info:new({ text = "Battlements", team = Team.kRed }) + +location_blue_balcony = location_info:new({ text = "Balcony", team = Team.kBlue }) +location_red_balcony = location_info:new({ text = "Balcony", team = Team.kRed }) + +location_blue_frontdoor = location_info:new({ text = "Front Door", team = Team.kBlue }) +location_red_frontdoor = location_info:new({ text = "Front Door", team = Team.kRed }) + +location_blue_frontdoor_ramp = location_info:new({ text = "Front Door Ramp", team = Team.kBlue }) +location_red_frontdoor_ramp = location_info:new({ text = "Front Door Ramp", team = Team.kRed }) + +location_blue_midramps = location_info:new({ text = "Mid Ramps", team = Team.kBlue }) +location_red_midramps = location_info:new({ text = "Mid Ramps", team = Team.kRed }) + +location_blue_midramps_left = location_info:new({ text = "Right Ramp", team = Team.kBlue }) +location_red_midramps_left = location_info:new({ text = "Right Ramp", team = Team.kRed }) + +location_blue_midramps_right = location_info:new({ text = "Left Ramp", team = Team.kBlue }) +location_red_midramps_right = location_info:new({ text = "Left Ramp", team = Team.kRed }) + +location_blue_flagroom = location_info:new({ text = "Flag Room", team = Team.kBlue }) +location_red_flagroom = location_info:new({ text = "Flag Room", team = Team.kRed }) + +location_blue_sniperdeck = location_info:new({ text = "Sniper Deck", team = Team.kBlue }) +location_red_sniperdeck = location_info:new({ text = "Sniper Deck", team = Team.kRed }) + +location_blue_ramproom = location_info:new({ text = "Main Room", team = Team.kBlue }) +location_red_ramproom = location_info:new({ text = "Main Room", team = Team.kRed }) + +location_blue_lower = location_info:new({ text = "Lower Level", team = Team.kBlue }) +location_red_lower = location_info:new({ text = "Lower Level", team = Team.kRed }) + +location_blue_upper = location_info:new({ text = "Upper Level", team = Team.kBlue }) +location_red_upper = location_info:new({ text = "Upper Level", team = Team.kRed }) + +location_blue_airlift = location_info:new({ text = "Air Lift", team = Team.kBlue }) +location_red_airlift = location_info:new({ text = "Air Lift", team = Team.kRed }) + +location_blue_lowerladder = location_info:new({ text = "Lower Ladder to Ramp Room", team = Team.kBlue }) +location_red_lowerladder = location_info:new({ text = "Lower Ladder to Ramp Room", team = Team.kRed }) + +location_blue_rightcorridoor = location_info:new({ text = "Left Corridor", team = Team.kBlue }) +location_red_rightcorridoor = location_info:new({ text = "Left Corridor", team = Team.kRed }) + +location_blue_leftcorridoor = location_info:new({ text = "Right Corridor", team = Team.kBlue }) +location_red_leftcorridoor = location_info:new({ text = "Right Corridor", team = Team.kRed }) + +location_blue_rightresupply = location_info:new({ text = "Left Respawn", team = Team.kBlue }) +location_red_rightresupply = location_info:new({ text = "Left Respawn", team = Team.kRed }) + +location_blue_leftresupply = location_info:new({ text = "Right Respawn", team = Team.kBlue }) +location_red_leftresupply = location_info:new({ text = "Right Respawn", team = Team.kRed }) + +location_blue_leftspawn = location_info:new({ text = "Left Respawn", team = Team.kBlue }) +location_red_leftspawn = location_info:new({ text = "Left Respawn", team = Team.kRed }) + +location_blue_secret = location_info:new({ text = "Secret Passage", team = Team.kBlue }) +location_red_secret = location_info:new({ text = "Secret Passage", team = Team.kRed }) + +location_blue_flagroom_passage = location_info:new({ text = "Flagroom Hole Access Passage", team = Team.kBlue }) +location_red_flagroom_passage = location_info:new({ text = "Flagroom Hole Access Passage", team = Team.kRed }) + +location_blue_flagroom_ramp = location_info:new({ text = "Flag Room Ramp", team = Team.kBlue }) +location_red_flagroom_ramp = location_info:new({ text = "Flag Room Ramp", team = Team.kRed }) + +location_blue_water_entry = location_info:new({ text = "Water Entrance", team = Team.kBlue }) +location_red_water_entry = location_info:new({ text = "Water Entrance", team = Team.kRed }) + +location_blue_water_exit = location_info:new({ text = "Water Exit", team = Team.kBlue }) +location_red_water_exit = location_info:new({ text = "Water Exit", team = Team.kRed }) + +location_blue_water_access = location_info:new({ text = "Water Access", team = Team.kBlue }) +location_red_water_access = location_info:new({ text = "Water Access", team = Team.kRed }) + +----------------------------------------------------------------------------- +-- spawn +----------------------------------------------------------------------------- + +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 400 ) + player:AddArmor( 400 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + + -- end of default player_spawn + player:RemoveAmmo( Ammo.kManCannon, 1 ) +end + +----------------------------------------------------------------------------- +-- Respawns +----------------------------------------------------------------------------- + +spawn_red_offence = function(self,player) + return ((player:GetTeamId() == Team.kRed) + and ((player:GetClass() == Player.kScout) + or (player:GetClass() == Player.kMedic) + or (player:GetClass() == Player.kSpy))) +end + +spawn_red_defence = function(self,player) + return ((player:GetTeamId() == Team.kRed) + and (((player:GetClass() == Player.kScout) == false) + and ((player:GetClass() == Player.kMedic) == false) + and ((player:GetClass() == Player.kSpy) == false))) +end + + +spawn_blue_offence = function(self,player) + return ((player:GetTeamId() == Team.kBlue) + and ((player:GetClass() == Player.kScout) + or (player:GetClass() == Player.kMedic) + or (player:GetClass() == Player.kSpy))) +end + +spawn_blue_defence = function(self,player) + return ((player:GetTeamId() == Team.kBlue) + and (((player:GetClass() == Player.kScout) == false) + and ((player:GetClass() == Player.kMedic) == false) + and ((player:GetClass() == Player.kSpy) == false))) +end + +bluespawn_offence = { validspawn = spawn_blue_offence } +bluespawn_defence = { validspawn = spawn_blue_defence } +redspawn_offence = { validspawn = spawn_red_offence } +redspawn_defence = { validspawn = spawn_red_defence } + +----------------------------------------------------------------------------- +-- Basecap (no mancannon) +----------------------------------------------------------------------------- +bases_cap = basecap:new({ + mancannons = 0, +}) + +-- red cap point +red_cap = bases_cap:new({team = Team.kRed, + item = {"blue_flag","yellow_flag","green_flag"}}) + +-- blue cap point +blue_cap = bases_cap:new({team = Team.kBlue, + item = {"red_flag","yellow_flag","green_flag"}}) diff --git a/maps/ff_bases.txt b/maps/ff_bases.txt new file mode 100644 index 0000000..9ab6e0d --- /dev/null +++ b/maps/ff_bases.txt @@ -0,0 +1,7 @@ +CAPTURE THE FLAG + +Get the enemy flag and take it back to your capture point to score. + +Alternately: Detpack the enemy computer to score. + +Visit http://www.fortress-forever.com for more information. diff --git a/maps/ff_bases_soundscapes.txt b/maps/ff_bases_soundscapes.txt new file mode 100644 index 0000000..129d387 --- /dev/null +++ b/maps/ff_bases_soundscapes.txt @@ -0,0 +1,229 @@ +-------------------------------------------------------------- +FF_BASES SOUNDSCAPES +-------------------------------------------------------------- + +"ff_bases.midmap" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "wave" "ambient/wind/ff_wasteland_wind.wav" + "volume" "0.5" + "pitch" "100" + } + "playsoundscape" + { + "name" "d1_canals.util_windgusts" + "volume" "1.0" + } +} + + +"ff_bases.water" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "wave" "ambient/atmosphere/ambience5.wav" + "volume" "0.1" + "pitch" "100" + } + + "playlooping" + { + "wave" "ambient/water/drip_loop1.wav" + "volume" "0.3" + "pitch" "100" + } + + "playsoundscape" + { + "name" "d1_canals.util_drip" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "d1_canals.util_fardrips" + "volume" "1.0" + } +} + +"ff_bases.ramproom" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "name" "ambient/atmosphere/ambience_base.wav" + "volume" "0.3" + "pitch" "100" + } + "playlooping" + { + "name" "ambient/push/inside_amb1.wav" + "volume" "0.5" + "pitch" "100" + } +} + +"ff_bases.corridor1" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "name" "ambient/atmosphere/ambience_base.wav" + "volume" "0.5" + "pitch" "100" + } + "playlooping" + { + "name" "ambient/push/inside_amb1.wav" + "volume" "0.5" + "pitch" "100" + } +} + +"ff_bases.bments" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "name" "ambient/levels/canals/tunnel_wind_loop1.wav" + "volume" "0.7" + "pitch" "100" + } + "playlooping" + { + "name" "ambient/push/inside_amb1.wav" + "volume" "0.4" + "pitch" "100" + } +} + +"ff_bases.out" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "name" "ambient/wind/ff_wasteland_wind.wav" + "volume" "0.7" + "pitch" "100" + } + + "playsoundscape" + { + "name" "d1_canals.util_windgusts" + "volume" "1.0" + } +} + +"ff_bases.secret" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "name" "ambient/atmosphere/ambience_base.wav" + "volume" "0.6" + "pitch" "100" + } + "playlooping" + { + "name" "ambient/push/inside_amb1.wav" + "volume" "0.3" + "pitch" "100" + } +} + +"ff_bases.computer" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "wave" "ambient/wind/ff_wasteland_wind.wav" + "volume" "0.3" + "pitch" "100" + } + "playlooping" + { + "wave" "ambient/machines/lab_loop1.wav" + "volume" "0.4" + "pitch" "100" + } + "playsoundscape" + { + "name" "d1_canals.util_windgusts" + "volume" "0.3" + } +} + +"ff_bases.flagroom" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "wave" "ambient/wind/ff_wasteland_wind.wav" + "volume" "0.4" + "pitch" "100" + } + "playsoundscape" + { + "name" "d1_canals.util_windgusts" + "volume" "0.3" + } +} + +"ff_bases.lower" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "wave" "ambient/atmosphere/ambience_base.wav" + "volume" "0.3" + "pitch" "100" + } + "playlooping" + { + "name" "ambient/push/inside_amb1.wav" + "volume" "0.6" + "pitch" "100" + } +} + +"ff_bases.water2" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playlooping" + { + "wave" "ambient/atmosphere/ambience_base.wav" + "volume" "0.1" + "pitch" "100" + } + "playlooping" + { + "name" "ambient/push/inside_amb1.wav" + "volume" "0.6" + "pitch" "100" + } +} \ No newline at end of file diff --git a/maps/ff_cz2.lua b/maps/ff_cz2.lua new file mode 100644 index 0000000..47c8d5e --- /dev/null +++ b/maps/ff_cz2.lua @@ -0,0 +1,21 @@ +-- ff_cz2.lua + + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_cp_default") +IncludeScript("base_cp") + + +----------------------------------------------------------------------------- +-- overrides +----------------------------------------------------------------------------- +function healthkit:dropatspawn() return false end + + +----------------------------------------------------------------------------- +-- locations +----------------------------------------------------------------------------- + + diff --git a/maps/ff_cz2.txt b/maps/ff_cz2.txt new file mode 100644 index 0000000..c8b9bd4 --- /dev/null +++ b/maps/ff_cz2.txt @@ -0,0 +1,22 @@ +ff_cz2 + + +GAME MODE: Command Point (CP) +Capture and control each command point. + +TEAMS: Red vs Blue + +OBJECTIVES: +- Capture command points by standing on them. +- Defend points from enemy captures. + +SCORING: +- Command points farthest from your + base are worth more points, which + are rewarded every 15-30 seconds. +- All Cap: 100 points are given for + capturing all command points, which + also resets players, flags, and CPs. + +Visit www.fortress-forever.com for +additional information. \ No newline at end of file diff --git a/maps/ff_destroy.lua b/maps/ff_destroy.lua new file mode 100644 index 0000000..a68c35e --- /dev/null +++ b/maps/ff_destroy.lua @@ -0,0 +1,316 @@ +-- ff_destroy.lua +-- caesium 01/2009 + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base"); +IncludeScript("base_ctf"); +IncludeScript("base_location"); + +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- +POINTS_PER_CAPTURE = 10; +FLAG_RETURN_TIME = 60; + +----------------------------------------------------------------------------- +-- locations +----------------------------------------------------------------------------- +location_redfd = location_info:new({ text = "Foyer", team = Team.kRed }) +location_redramp = location_info:new({ text = "Main Ramps", team = Team.kRed }) +location_redspawn = location_info:new({ text = "Respawn", team = Team.kRed }) +location_redtopramp = location_info:new({ text = "Top Main Ramps", team = Team.kRed }) +location_redbalc = location_info:new({ text = "Balcony", team = Team.kRed }) +location_redsec = location_info:new({ text = "Security Control", team = Team.kRed }) +location_redfr = location_info:new({ text = "Flag Room", team = Team.kRed }) +location_redresup = location_info:new({ text = "Resupply", team = Team.kRed }) + +location_bluefd = location_info:new({ text = "Foyer", team = Team.kBlue }) +location_blueramp = location_info:new({ text = "Main Ramps", team = Team.kBlue }) +location_bluespawn = location_info:new({ text = "Respawn", team = Team.kBlue }) +location_bluetopramp = location_info:new({ text = "Top Main Ramps", team = Team.kBlue }) +location_bluebalc = location_info:new({ text = "Balcony", team = Team.kBlue }) +location_bluesec = location_info:new({ text = "Security Control", team = Team.kBlue }) +location_bluefr = location_info:new({ text = "Flag Room", team = Team.kBlue }) +location_blueresup = location_info:new({ text = "Resupply", team = Team.kBlue }) + +location_midmap = location_info:new({ text = "Outside", team = NO_TEAM }) + +----------------------------------------------------------------------------- +-- remove mirvs (?) and give full resup on spawn +----------------------------------------------------------------------------- +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) +-- if player:GetClass() == Player.kHwguy then +-- player:RemoveAmmo(Ammo.kGren2, 4) +-- end +-- if player:GetClass() == Player.kDemoman then +-- player:RemoveAmmo(Ammo.kGren2, 4) +-- end + player:AddHealth( 400 ) + player:AddArmor( 400 ) + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) +end + +----------------------------------------------------------------------------- +-- bagless resupply +----------------------------------------------------------------------------- +aardvarkresup = trigger_ff_script:new({ team = Team.kUnassigned }) + +function aardvarkresup:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == self.team then + player:AddHealth( 400 ) + player:AddArmor( 400 ) + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + end + end +end + +blue_aardvarkresup = aardvarkresup:new({ team = Team.kBlue }) +red_aardvarkresup = aardvarkresup:new({ team = Team.kRed }) + +----------------------------------------------------------------------------- +-- aardvark security +----------------------------------------------------------------------------- +red_aardvarksec = trigger_ff_script:new() +blue_aardvarksec = trigger_ff_script:new() +bluesecstatus = 1 +redsecstatus = 1 + +sec_iconx = 60 +sec_icony = 30 +sec_iconw = 16 +sec_iconh = 16 + +function red_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kBlue then + if redsecstatus == 1 then + redsecstatus = 0 + AddSchedule("aardvarksecup10red",20,aardvarksecup10red) + AddSchedule("aardvarksecupred",30,aardvarksecupred) + OpenDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_30") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_REDDOWN" ) + RemoveHudItemFromAll( "red-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end + end + end +end + +function blue_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kRed then + if bluesecstatus == 1 then + bluesecstatus = 0 + AddSchedule("aardvarksecup10blue",20,aardvarksecup10blue) + AddSchedule("aardvarksecupblue",30,aardvarksecupblue) + OpenDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_30") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_BLUEDOWN" ) + RemoveHudItemFromAll( "blue-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + end + end +end + +function aardvarksecupred() + redsecstatus = 1 + CloseDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_ON") + SpeakAll( "SD_REDUP" ) + RemoveHudItemFromAll( "red-sec-down" ) + AddHudIconToAll( "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) +end + +function aardvarksecupblue() + bluesecstatus = 1 + CloseDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_ON") + SpeakAll( "SD_BLUEUP" ) + RemoveHudItemFromAll( "blue-sec-down" ) + AddHudIconToAll( "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) +end + +function aardvarksecup10red() + BroadCastMessage("#FF_RED_SEC_10") +end + +function aardvarksecup10blue() + BroadCastMessage("#FF_BLUE_SEC_10") +end + +----------------------------------------------------------------------------- +-- aardvark lasers and respawn shields +----------------------------------------------------------------------------- +KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) +lasers_KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) + +function KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +function lasers_KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + if self.team == Team.kBlue then + if redsecstatus == 1 then + return EVENT_ALLOWED + end + end + if self.team == Team.kRed then + if bluesecstatus == 1 then + return EVENT_ALLOWED + end + end + end + end + return EVENT_DISALLOWED +end + +blue_slayer = KILL_KILL_KILL:new({ team = Team.kBlue }) +red_slayer = KILL_KILL_KILL:new({ team = Team.kRed }) +sec_blue_slayer = lasers_KILL_KILL_KILL:new({ team = Team.kBlue }) +sec_red_slayer = lasers_KILL_KILL_KILL:new({ team = Team.kRed }) + +------------------------- +-- flaginfo +------------------------- +function flaginfo( player_entity ) + local player = CastToPlayer( player_entity ) + + flaginfo_base(player_entity) --basic CTF HUD items + + RemoveHudItem( player, "red-sec-down" ) + RemoveHudItem( player, "blue-sec-down" ) + RemoveHudItem( player, "red-sec-up" ) + RemoveHudItem( player, "blue-sec-up" ) + + if bluesecstatus == 1 then + AddHudIcon( player, "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + else + AddHudIcon( player, "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + + if redsecstatus == 1 then + AddHudIcon( player, "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + else + AddHudIcon( player, "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end +end + +----------------------------------------------------------------------------- +-- custom packs +----------------------------------------------------------------------------- +aardvarkpack_fr = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 130, + gren1 = 0, + gren2 = 0, + respawntime = 20, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +aardvarkpack_ramp = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 0, + gren1 = 0, + gren2 = 0, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +aardvarkpack_sec = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 0, + gren1 = 1, + gren2 = 1, + respawntime = 20, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +function aardvarkpack_fr:dropatspawn() return false end +function aardvarkpack_ramp:dropatspawn() return false end +function aardvarkpack_sec:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- backpack entity setup (modified for aardvarkpacks) +----------------------------------------------------------------------------- +function build_backpacks(tf) + return healthkit:new({touchflags = tf}), + armorkit:new({touchflags = tf}), + ammobackpack:new({touchflags = tf}), + bigpack:new({touchflags = tf}), + grenadebackpack:new({touchflags = tf}), + aardvarkpack_fr:new({touchflags = tf}), + aardvarkpack_ramp:new({touchflags = tf}), + aardvarkpack_sec:new({touchflags = tf}) +end + +blue_healthkit, blue_armorkit, blue_ammobackpack, blue_bigpack, blue_grenadebackpack, blue_aardvarkpack_fr, blue_aardvarkpack_ramp, blue_aardvarkpack_sec = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kBlue}) +red_healthkit, red_armorkit, red_ammobackpack, red_bigpack, red_grenadebackpack, red_aardvarkpack_fr, red_aardvarkpack_ramp, red_aardvarkpack_sec = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kRed}) +yellow_healthkit, yellow_armorkit, yellow_ammobackpack, yellow_bigpack, yellow_grenadebackpack, yellow_aardvarkpack_fr, yellow_aardvarkpack_ramp, yellow_aardvarkpack_sec = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kYellow}) +green_healthkit, green_armorkit, green_ammobackpack, green_bigpack, green_grenadebackpack, green_aardvarkpack_fr, green_aardvarkpack_ramp, green_aardvarkpack_sec = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kGreen}) + +----------------------------------------------------------------------------- +-- bouncepads for lifts +----------------------------------------------------------------------------- +base_jump = trigger_ff_script:new({ pushz = 0 }) + +function base_jump:ontouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + local playerVel = player:GetVelocity() + playerVel.z = self.pushz + player:SetVelocity( playerVel ) + end +end + +lift_red = base_jump:new({ pushz = 600 }) +lift_blue = base_jump:new({ pushz = 600 }) diff --git a/maps/ff_destroy.txt b/maps/ff_destroy.txt new file mode 100644 index 0000000..002570b --- /dev/null +++ b/maps/ff_destroy.txt @@ -0,0 +1,6 @@ +Steal the enemy flag while protecting your own: +[1] Deactivate enemy security system +[2] Take enemy flag +[3] Bring to capture point in your base +SCORING: 10 points per flag capture +Based on original TFC map by Koochy ;D \ No newline at end of file diff --git a/maps/ff_dm.lua b/maps/ff_dm.lua new file mode 100644 index 0000000..e83b30f --- /dev/null +++ b/maps/ff_dm.lua @@ -0,0 +1,172 @@ + +-- ff_dm.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +-- IncludeScript("base_soldierarena"); +IncludeScript("base_teamplay"); + +function startup() + -- set up team limits (only red & blue) + SetPlayerLimit( Team.kBlue, 0 ) + SetPlayerLimit( Team.kRed, 0 ) + SetPlayerLimit( Team.kYellow, -1 ) + SetPlayerLimit( Team.kGreen, -1 ) + + SetTeamName( Team.kRed, "Destroyers" ) +end + +function precache() + PrecacheSound( "Backpack.Touch" ) +end + +--function player_onconc( player_entity, concer_entity ) +-- -- player_entity is always a player +-- local player = CastToPlayer( player_entity ) +-- local concer = CastToPlayer( concer_entity ) +-- +-- ConsoleToAll( "Running player_onconc! Player: " .. player:GetName() .. " Concer: " .. concer:GetName() ) +-- ConsoleToAll( "conc_duration = " .. conc_duration .. " conc_iconduration = " .. conc_iconduration ) +-- +-- if player:GetTeamId() == Team.kRed then +-- return EVENT_DISALLOWED +-- end +-- +-- conc_duration = -1 +-- conc_iconduration = -1 +-- +-- ConsoleToAll( "conc_duration = " .. conc_duration .. " conc_iconduration = " .. conc_iconduration ) +-- +-- return EVENT_ALLOWED +--end + +--function player_ontranq( player_entity, tranqer_entity ) +-- local player = CastToPlayer( player_entity ) +-- local tranqer = CastToPlayer( tranqer_entity ) +-- +-- ConsoleToAll( "Running player_ontranq! Player: " .. player:GetName() .. " Tranqer: " .. tranqer:GetName() ) +-- ConsoleToAll( "tranq_duration = " .. tranq_duration .. " tranq_iconduration = " .. tranq_iconduration .. " tranq_speed = " .. tranq_speed ) +-- +-- if player:GetTeamId() == Team.kRed then +-- return EVENT_DISALLOWED +-- end +-- +-- tranq_duration = -1 +-- tranq_iconduration = -1 +-- tranq_speed = 0.2 +-- +-- return EVENT_ALLOWED +--end + +-- Everyone to spawns with everything +function player_spawn( player_entity ) + -- 400 for overkill. of course the values + -- get clamped in game code + --local player = GetPlayer(player_id) + local player = CastToPlayer( player_entity ) + player:AddHealth( 400 ) + player:AddArmor( 400 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + player:AddAmmo( Ammo.kManCannon, 1 ) + player:AddAmmo( Ammo.kGren1, 4 ) + player:AddAmmo( Ammo.kGren2, 4 ) +end + +function player_onkill( player ) + -- Test, Don't let blue team suicide. +-- if player:GetTeamId() == Team.kBlue then +-- return false +-- end + return true +end + +-- Get team points for killing a player +function player_killed( player_entity, damageinfo ) + -- suicides have no damageinfo + if damageinfo ~= nil then + local killer = damageinfo:GetAttacker() + + local player = CastToPlayer( player_entity ) + if IsPlayer(killer) then + killer = CastToPlayer(killer) + --local victim = GetPlayer(player_id) + + if not (player:GetTeamId() == killer:GetTeamId()) then + local killersTeam = killer:GetTeam() + killersTeam:AddScore(1) + end + end + end +end + +-- Just here because +function player_ondamage( player_entity, damageinfo ) +end + +-- Infinite bag +infini_bag = trigger_ff_script:new({ touchsound = "Backpack.Touch" }) + +-- Infinite bag :: ontouch +function infini_bag:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + -- 400 for overkill. of course the values + -- get clamped in game code + player:AddHealth( 400 ) + player:AddArmor( 400 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + player:AddAmmo( Ammo.kManCannon, 1 ) + player:AddAmmo( Ammo.kGren1, 4 ) + player:AddAmmo( Ammo.kGren2, 4 ) + + -- Play the touch sound + player:EmitSound( self.touchsound ) + end +end + +function infini_bag:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team then + return true + end + end + + return false +end + +-- Red infinite bag +red_infini_bag = infini_bag:new({ team = Team.kRed }) + +-- Blue infinite bag +blue_infini_bag = infini_bag:new({ team = Team.kBlue }) + +-- Spawn doors +spawn_door_trigger = trigger_ff_script:new({ team = Team.kUnassigned, doorname = "" }) + +function spawn_door_trigger:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == self.team then + if self.doorname then + OpenDoor( self.doorname ) + end + end + end +end + +red_spawn_door1_trigger = spawn_door_trigger:new({ team = Team.kRed, doorname = "red_spawn_door1" }) +red_spawn_door2_trigger = spawn_door_trigger:new({ team = Team.kRed, doorname = "red_spawn_door2" }) +blue_spawn_door1_trigger = spawn_door_trigger:new({ team = Team.kBlue, doorname = "blue_spawn_door1" }) +blue_spawn_door2_trigger = spawn_door_trigger:new({ team = Team.kBlue, doorname = "blue_spawn_door2" }) diff --git a/maps/ff_dustbowl.lua b/maps/ff_dustbowl.lua new file mode 100644 index 0000000..6183207 --- /dev/null +++ b/maps/ff_dustbowl.lua @@ -0,0 +1,295 @@ + +-- ff_dustbowl.lua + +-- includes +IncludeScript("base_ad"); +IncludeScript("base_location"); + +-- set teams +ATTACKERS = Team.kBlue +DEFENDERS = Team.kRed + +dbhealthkit = genericbackpack:new({ + health = 50, + model = "models/items/healthkit.mdl", + materializesound = "Item.Materialize", + touchsound = "HealthKit.Touch" +}) +dbarmorkit = genericbackpack:new({ + armor = 200, + model = "models/items/armour/armour.mdl", + materializesound = "Item.Materialize", + touchsound = "ArmorKit.Touch" +}) +dbammopack = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 100, + rockets = 15, + cells = 130, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammopack:dropatspawn() return false end + +dbgrenadepackone = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + mancannons = 1, + gren1 = 2, + gren2 = 2, + armor = 100, + health = 300, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbgrenadepackone:dropatspawn() return false end + +dbgrenadepacktwo = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + mancannons = 1, + gren1 = 2, + gren2 = 2, + armor = 100, + health = 100, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbgrenadepacktwo:dropatspawn() return false end + +dbammotypeone = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 130, + armor = 50, + health = 40, + respawntime = 5, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypeone:dropatspawn() return false end + +dbammotypetwo = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 25, + health = 50, + respawntime = 6, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypetwo:dropatspawn() return false end + +dbammotypethree = genericbackpack:new({ + grenades = 30, + nails = 150, + shells = 50, + rockets = 30, + cells = 200, + armor = 100, + health = 75, + respawntime = 3, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypethree:dropatspawn() return false end + +dbammotypefour = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 100, + health = 100, + respawntime = 5, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypefour:dropatspawn() return false end + +dbammotypefive = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 100, + health = 100, + respawntime = 5, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypefive:dropatspawn() return false end + +dbammotypesix = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 130, + armor = 50, + health = 50, + respawntime = 5, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypesix:dropatspawn() return false end + +dbammotypeseven = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 75, + health = 75, + respawntime = 5, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypeseven:dropatspawn() return false end + +dbammotypeeight = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 300, + health = 100, + respawntime = 3, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypeeight:dropatspawn() return false end + +dbammotypenine = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 30, + health = 30, + respawntime = 6, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypenine:dropatspawn() return false end + +dbammotypeten = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 150, + armor = 10, + health = 20, + respawntime = 3, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypeten:dropatspawn() return false end + +dbammotypeeleven = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 0, + health = 20, + respawntime = 4, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypeeleven:dropatspawn() return false end + +dbammotypetwelve = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 100, + rockets = 20, + cells = 130, + armor = 100, + health = 0, + respawntime = 3, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypetwelve:dropatspawn() return false end + +dbammotypethirteen = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 100, + armor = 25, + health = 25, + respawntime = 5, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypethirteen:dropatspawn() return false end + +dbammotypefourteen = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 200, + armor = 0, + health = 0, + respawntime = 4, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function dbammotypefourteen:dropatspawn() return false end diff --git a/maps/ff_dustbowl.txt b/maps/ff_dustbowl.txt new file mode 100644 index 0000000..91f8313 --- /dev/null +++ b/maps/ff_dustbowl.txt @@ -0,0 +1,10 @@ +ATTACK OR DEFEND + +Objective: Blue team must take their flag to +Red team's Headquarters to win the game. +There are two command points on the way +which must be secured in order. + +Other Notes: When a capture point is secured, +spawn points are revised and a new flag +appears. Rounds last 25 minutes. \ No newline at end of file diff --git a/maps/ff_fusion.lua b/maps/ff_fusion.lua new file mode 100644 index 0000000..1268e4c --- /dev/null +++ b/maps/ff_fusion.lua @@ -0,0 +1,377 @@ +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- + +IncludeScript("base_idzone") +IncludeScript("base_location") +IncludeScript("base_respawnturret") + +----------------------------------------------------------------------------- +-- global overrides that you can do what you want with +----------------------------------------------------------------------------- + +FORT_POINTS_PER_INITIAL_TOUCH = 200 +FORT_POINTS_PER_PERIOD = 50 +FORT_POINTS_PER_DEFEND = 100 + +POINTS_PER_INITIAL_TOUCH = 1 +POINTS_PER_PERIOD = 1 + +DELAY_BEFORE_PERIOD_POINTS = 2 +PERIOD_TIME = 1 +INITIAL_ROUND_PERIOD = 60 +ROUND_SETUP_PERIOD = 17 + +DEFENSE_PERIOD_TIME = 60 +POINTS_PER_DEFENSE_PERIOD = 1 + +DEFAULT_POINTS_TO_CAP = 10 +NUMBER_OF_CAP_POINTS = 3 +DELAY_BEFORE_TEAMSWITCH = 3 +DELAY_AFTER_CAP = 3 + +ZONE_COLOR = "purple" + +----------------------------------------------------------------------------- +-- Zone-controlling outputs +----------------------------------------------------------------------------- + +function oncap_outputs() + + OutputEvent( "shake"..phase, "StartShake" ) + OutputEvent( "shakebreak"..phase, "Playsound" ) + AddSchedule( "Partition_On", 4, OutputEvent,"cp"..phase.."_partition", "TurnOn") + AddSchedule( "Partition_Enabled", 4, OutputEvent,"cp"..phase.."_partition", "Enable") + AddSchedule( "Partition_Door_On", 4, OutputEvent, "cp"..phase.."_partition_door", "TurnOff") + AddSchedule( "Partition_Door_Enable", 4, OutputEvent, "cp"..phase.."_partition_door", "Disable") + AddSchedule( "Areaportal_On", 4, OutputEvent, "cp"..phase.."_areaportal_door", "Open") + AddSchedule( "Areaportal_Partition_On", 4, OutputEvent, "cp"..phase.."_areaportal", "Close") + AddSchedule( "alarm_voice", 2, OutputEvent, "voice1", "PlaySound") + AddSchedule( "alarm_text", 2, schedulemessagetoall, "Zone Captured!") + AddSchedule( "stop_voice", 2.5, OutputEvent, "voice1", "StopSound") + AddSchedule( "alarm_voices", 2.5, OutputEvent, "voice2", "PlaySound") + AddSchedule( "stop_voices", 2.975, OutputEvent, "voice2", "StopSound") + AddSchedule( "35 second warning", 7, schedulemessagetoall, "Gate Opens in 35 seconds!") + AddSchedule( "35 second warning_sound" , 7 , schedulesound, "misc.bloop" ) + AddSchedule( "dooropen5sec_sound", 37, schedulecountdown, "5") + AddSchedule( "dooropen4sec_sound", 38, schedulecountdown, "4") + AddSchedule( "dooropen3sec_sound", 39, schedulecountdown, "3") + AddSchedule( "dooropen2sec_sound", 40, schedulecountdown, "2") + AddSchedule( "dooropen1sec_sound", 41, schedulecountdown, "1") + AddSchedule("alarm_events", 42, OutputEvent, "breakglass"..phase, "Break") + AddSchedule("alarm_sounds", 42, OutputEvent, "breakalarm"..phase, "PlaySound") + + + if phase == 1 then + defender_door_trigger1 = id_door:new({ team = attackers, door = "defender_door1" }) + defender_door_trigger2 = id_door:new({ team = attackers, door = "defender_door2" }) + end + if phase == 2 then + defender_door_trigger3 = id_door:new({ team = attackers, door = "defender_door3" }) + defender_door_trigger4 = id_door:new({ team = attackers, door = "defender_door4" }) + end +end +function oncap_outputs_nextphase() + RespawnAllPlayers() + +end +function onreset_outputs() + OutputEvent( "breakalarm"..phase, "Playsound" ) + OutputEvent( "shake"..phase, "StartShake" ) + OutputEvent( "shakebreak"..phase, "Playsound" ) + AddSchedule( "alarm_voice", 2, OutputEvent, "voice1", "PlaySound") + AddSchedule( "alarm_text", 2, schedulemessagetoall, "Zone Captured!") + AddSchedule( "stop_voice", 2.5, OutputEvent, "voice1", "StopSound") + AddSchedule( "alarm_voices", 2.5, OutputEvent, "voice2", "PlaySound") + AddSchedule( "stop_voices", 2.97, OutputEvent, "voice2", "StopSound") +end + +function zone_on_outputs() + + -- use for entities that have two copies per zone (e.g. rotate1 and rotate2) + two1 = phase * 2 - 1 + two2 = phase * 2 + -- use for entities that have three copies per zone (e.g. rotate1, rotate2, and rotate3) + three1 = phase * 3 - 2 + three2 = phase * 3 - 1 + three3 = phase * 3 + -- use for entities that have three copies per zone (e.g. rotate1, rotate2, rotate3 and rotate4) + four1 = phase * 4 - 3 + four2 = phase * 4 - 2 + four3 = phase * 4 - 1 + four4 = phase * 4 + + -- outputs + OutputEvent( "alarm"..phase, "PlaySound" ) + OutputEvent( "light"..phase, "TurnOn" ) + OutputEvent( "spot"..phase, "LightOn" ) + OutputEvent( "rotate"..two1, "Start" ) + OutputEvent( "rotate"..two2, "Start" ) + OutputEvent( "Tesla"..phase, "DoSpark" ) +end + +function zone_off_outputs() + + -- use for entities that have two copies per zone (e.g. rotate1 and rotate2) + two1 = phase * 2 - 1 + two2 = phase * 2 + -- use for entities that have three copies per zone (e.g. rotate1, rotate2, and rotate3) + three1 = phase * 3 - 2 + three2 = phase * 3 - 1 + three3 = phase * 3 + -- use for entities that have three copies per zone (e.g. rotate1, rotate2, rotate3 and rotate4) + four1 = phase * 4 - 3 + four2 = phase * 4 - 2 + four3 = phase * 4 - 1 + four4 = phase * 4 + + -- outputs + OutputEvent( "alarm"..phase, "StopSound" ) + OutputEvent( "light"..phase, "TurnOff" ) + OutputEvent( "spot"..phase, "LightOff" ) + OutputEvent( "rotate"..two1, "Stop" ) + OutputEvent( "rotate"..two2, "Stop" ) +end + +function openstartdoor() + -- unlock them doors + attacker_door_trigger1 = id_door:new({ team = attackers, door = "attacker_door1" }) + attacker_door_trigger2 = id_door:new({ team = attackers, door = "attacker_door2" }) + + -- open the first door + OutputEvent( "attacker_door1", "Open" ) + OutputEvent( "attacker_door2", "Open" ) +end + +function onswitch() + -- reset doors to open for the right team + defender_door_trigger1 = id_door:new({ team = defenders, door = "defender_door1" }) + defender_door_trigger2 = id_door:new({ team = defenders, door = "defender_door2" }) + defender_door_trigger3 = id_door:new({ team = defenders, door = "defender_door3" }) + defender_door_trigger4 = id_door:new({ team = defenders, door = "defender_door4" }) + defender_door_trigger5 = id_door:new({ team = defenders, door = "defender_door5" }) + defender_door_trigger6 = id_door:new({ team = defenders, door = "defender_door6" }) + defender_door_trigger7 = id_door:new({ team = defenders, door = "defender_door7" }) + defender_door_trigger8 = id_door:new({ team = defenders, door = "defender_door8" }) + + -- lock them doors + attacker_door_trigger1 = id_door:new({ team = Team.kUnassigned, door = "attacker_door1" }) + attacker_door_trigger2 = id_door:new({ team = Team.kUnassigned, door = "attacker_door2" }) + + OutputEvent( "point_template", "ForceSpawn" ) +end + +function onswitch_bluetodef() + -- switch the lights + OutputEvent( "defender_light1", "TurnOff" ) + OutputEvent( "defender_spotlight1", "LightOff" ) + + OutputEvent( "defender_light2", "TurnOn" ) + OutputEvent( "defender_spotlight2", "LightOn" ) + + OutputEvent( "cp1_partition", "TurnOff" ) + OutputEvent( "cp1_partition", "Disable" ) + OutputEvent( "cp2_partition", "TurnOff" ) + OutputEvent( "cp2_partition", "Disable" ) + + OutputEvent( "cp1_areaportal", "Open" ) + OutputEvent( "cp1_areaportal_door", "Close" ) + OutputEvent( "cp2_areaportal", "Open" ) + OutputEvent( "cp2_areaportal_door", "Close" ) + + OutputEvent( "cp1_partition_door", "TurnOn") + OutputEvent( "cp1_partition_door", "Enable") + OutputEvent( "cp2_partition_door", "TurnOn") + OutputEvent( "cp2_partition_door", "Enable") + + -- switch them packs, for real this time; this is a workaround due to how the touchflags are set in base.lua + local num_packs = 9 + for i=1,num_packs do + entity = GetEntityByName( "gen_pack_defender"..i ) + local info = CastToInfoScript( entity ) + info:SetTouchFlags({ AllowFlags.kBlue}) + end +end + +function onswitch_redtodef() + -- switch the lights + OutputEvent( "defender_light1", "TurnOn" ) + OutputEvent( "defender_spotlight1", "LightOn" ) + + OutputEvent( "defender_light2", "TurnOff" ) + OutputEvent( "defender_spotlight2", "LightOff" ) + + OutputEvent( "cp1_partition", "TurnOff" ) + OutputEvent( "cp1_partition", "Disable" ) + OutputEvent( "cp2_partition", "TurnOff" ) + OutputEvent( "cp2_partition", "Disable" ) + + OutputEvent( "cp1_areaportal", "Open" ) + OutputEvent( "cp1_areaportal_door", "Close" ) + OutputEvent( "cp2_areaportal", "Open" ) + OutputEvent( "cp2_areaportal_door", "Close" ) + + OutputEvent( "cp1_partition_door", "TurnOn") + OutputEvent( "cp1_partition_door", "Enable") + OutputEvent( "cp2_partition_door", "TurnOn") + OutputEvent( "cp2_partition_door", "Enable") + + + -- switch them packs, for real this time; this is a workaround due to how the touchflags are set in base.lua + local num_packs = 9 + for i=1,num_packs do + entity = GetEntityByName( "gen_pack_defender"..i ) + local info = CastToInfoScript( entity ) + info:SetTouchFlags({ AllowFlags.kRed}) + end +end + +----------------------------------------------------------------------------- +-- backpacks, doors, etc. etc. +----------------------------------------------------------------------------- + +gen_pack = genericbackpack:new({ + health = 30, + armor = 25, + grenades = 20, + nails = 50, + shells = 300, + rockets = 15, + gren1 = 1, + gren2 = 0, + cells = 120, + respawntime = 10, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function gen_pack:dropatspawn() return false +end + +gen_pack_defender1 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender2 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender3 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender4 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender5 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender6 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender7 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender8 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) +gen_pack_defender9 = gen_pack:new({ touchflags = {AllowFlags.kRed} }) + +----------------------------------------------------------------------------- +-- No Fucking Annoyances +----------------------------------------------------------------------------- +noannoyances = trigger_ff_script:new({}) + +function noannoyances:onbuild( build_entity ) + return EVENT_DISALLOWED +end + +function noannoyances:onexplode( explode_entity ) + if IsGrenade( explode_entity ) then + return EVENT_DISALLOWED + end + return EVENT_ALLOWED +end + +function noannoyances:oninfect( infect_entity ) + return EVENT_DISALLOWED +end + +no_annoyances = noannoyances +spawn_protection = noannoyances + +------------------------------------------------------------------ +--Resup Doors +------------------------------------------------------------------ +neutral_door_trigger1 = trigger_ff_script:new({}) + +function neutral_door_trigger1:ontouch( trigger_entity ) + OutputEvent( "neutral_door1", "Open" ) +end + +id_door = trigger_ff_script:new({ team = Team.kUnassigned, door = nil }) + +function id_door:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return player:GetTeamId() == self.team + end + + return EVENT_DISALLOWED +end + +function id_door:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + OutputEvent(self.door, "Open") + end +end + +attacker_door_trigger1 = id_door:new({ team = Team.kUnassigned, door = "attacker_door1" }) +attacker_door_trigger2 = id_door:new({ team = Team.kUnassigned, door = "attacker_door2" }) +defender_door_trigger1 = id_door:new({ team = defenders, door = "defender_door1" }) +defender_door_trigger2 = id_door:new({ team = defenders, door = "defender_door2" }) +defender_door_trigger3 = id_door:new({ team = defenders, door = "defender_door3" }) +defender_door_trigger4 = id_door:new({ team = defenders, door = "defender_door4" }) +defender_door_trigger5 = id_door:new({ team = defenders, door = "defender_door5" }) +defender_door_trigger6 = id_door:new({ team = defenders, door = "defender_door6" }) + +defender_spawn = base_defender_spawn:new({phase=1}) +defender_spawn2 = base_defender_spawn:new({phase=2}) +defender_spawn3 = base_defender_spawn:new({phase=3}) +attacker_spawn = base_attacker_spawn:new({phase=1}) +attacker_spawn2 = base_attacker_spawn:new({phase=2}) +attacker_spawn3 = base_attacker_spawn:new({phase=3}) + +------------------------------------------------------------------ +--Elevator +------------------------------------------------------------------ + +-- keeps track of elevator goings on +local elev_collection = Collection() + +elev_trigger_add = trigger_ff_script:new({ }) + +-- registers attackers as they hit the top +function elev_trigger_add:ontouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + elev_collection:AddItem( player ) + end +end + +elev_trigger_remove = trigger_ff_script:new({ }) + +function elev_trigger_remove:onendtouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + elev_collection:RemoveItem( player ) + end +end + +function elev_trigger_remove:oninactive( trigger_entity ) + elev_collection:RemoveAllItems() +end + +elev_trigger = trigger_ff_script:new({ }) + +function elev_trigger:allowed( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + for playerx in elev_collection.items do + playerx = CastToPlayer(playerx) + if playerx:GetId() == player:GetId() then + return EVENT_DISALLOWED + end + end + end + return EVENT_ALLOWED +end + +function elev_trigger:ontouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + --local player = CastToPlayer( trigger_entity ) + OutputEvent( "elev2", "Open" ) + end +end diff --git a/maps/ff_genesis.lua b/maps/ff_genesis.lua new file mode 100644 index 0000000..281493d --- /dev/null +++ b/maps/ff_genesis.lua @@ -0,0 +1,141 @@ +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- + +IncludeScript("base_adzone") +IncludeScript("base_location") +IncludeScript("base_respawnturret") + +----------------------------------------------------------------------------- +-- global overrides that you can do what you want with +----------------------------------------------------------------------------- + +ZONE_COLOR = "green" +USE_ZONE_AREA = true +NUM_DEFENDER_ONLY_PACKS = 3 + +----------------------------------------------------------------------------- +-- Zone-controlling outputs +----------------------------------------------------------------------------- + +function zone_on_outputs() + -- outputs + OutputEvent( "alarm1", "PlaySound" ) + OutputEvent( "light1", "TurnOn" ) + OutputEvent( "spot1", "LightOn" ) + OutputEvent( "rotate1", "Start" ) + OutputEvent( "rotate2", "Start" ) + OutputEvent( "Tesla1", "DoSpark" ) +end + +function zone_off_outputs() + OutputEvent( "alarm1", "StopSound" ) + OutputEvent( "light1", "TurnOff" ) + OutputEvent( "spot1", "LightOff" ) + OutputEvent( "rotate1", "Stop" ) + OutputEvent( "rotate2", "Stop" ) +end + +function openstartdoor() + -- unlock them doors + attacker_door_trigger2 = id_door:new({ team = attackers, door = "attacker_door2" }) + attacker_door_trigger3 = id_door:new({ team = attackers, door = "attacker_door3" }) + + -- open the first door + OutputEvent( "attacker_door2", "Open" ) + OutputEvent( "attacker_door3", "Open" ) +end + +function onswitch() + -- reset doors to open for the right team + attacker_door_trigger1 = id_door:new({ team = attackers, door = "attacker_door1" }) + attacker_door_trigger4 = id_door:new({ team = attackers, door = "attacker_door4" }) + attacker_door_trigger5 = id_door:new({ team = attackers, door = "attacker_door5" }) + attacker_door_trigger6 = id_door:new({ team = attackers, door = "attacker_door6" }) + defender_door_trigger1 = id_door:new({ team = defenders, door = "defender_door1" }) + defender_door_trigger2 = id_door:new({ team = defenders, door = "defender_door2" }) + + -- lock them doors + attacker_door_trigger2 = id_door:new({ team = Team.kUnassigned, door = "attacker_door2" }) + attacker_door_trigger3 = id_door:new({ team = Team.kUnassigned, door = "attacker_door3" }) +end + +function onswitch_bluetodef() + -- switch the lights + OutputEvent( "defender_light1", "TurnOff" ) + OutputEvent( "defender_spotlight1", "LightOff" ) + + OutputEvent( "defender_light2", "TurnOn" ) + OutputEvent( "defender_spotlight2", "LightOn" ) +end + +function onswitch_redtodef() + -- switch the lights + OutputEvent( "defender_light1", "TurnOn" ) + OutputEvent( "defender_spotlight1", "LightOn" ) + + OutputEvent( "defender_light2", "TurnOff" ) + OutputEvent( "defender_spotlight2", "LightOff" ) +end + +------------------------------------------------------------------ +--Resup Doors +------------------------------------------------------------------ +neutral_door_trigger1 = trigger_ff_script:new({}) + +function neutral_door_trigger1:ontouch( trigger_entity ) + OutputEvent( "neutral_door1", "Open" ) +end + +id_door = trigger_ff_script:new({ team = Team.kUnassigned, door = nil }) + +function id_door:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return player:GetTeamId() == self.team + end + + return EVENT_DISALLOWED +end + +function id_door:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + OutputEvent(self.door, "Open") + end +end + +attacker_door_trigger1 = id_door:new({ team = attackers, door = "attacker_door1" }) +attacker_door_trigger2 = id_door:new({ team = Team.kUnassigned, door = "attacker_door2" }) +attacker_door_trigger3 = id_door:new({ team = Team.kUnassigned, door = "attacker_door3" }) +attacker_door_trigger4 = id_door:new({ team = attackers, door = "attacker_door4" }) +attacker_door_trigger5 = id_door:new({ team = attackers, door = "attacker_door5" }) +attacker_door_trigger6 = id_door:new({ team = attackers, door = "attacker_door6" }) +defender_door_trigger1 = id_door:new({ team = defenders, door = "defender_door1" }) +defender_door_trigger2 = id_door:new({ team = defenders, door = "defender_door2" }) + +----------------------------------------------------------------------------- +-- Locations +----------------------------------------------------------------------------- + +location_a_spawn = location_info:new({ text = "Attacker's Spawn"}) +location_a_spawn2 = location_info:new({ text = "Attacker's Spawn"}) +location_a_spawn3 = location_info:new({ text = "Attacker's Gate Room"}) + +location_a_bottom = location_info:new({ text = "Secondary Attacker Route"}) +location_a_bottom2 = location_info:new({ text = "Secondary Attacker Route"}) + +location_gate = location_info:new({ text = "Attacker's Gate"}) +location_lower = location_info:new({ text = "Lower Hallway"}) +location_gate_balcony = location_info:new({ text = "Overhanging Defensive Balcony"}) +location_side_balcony = location_info:new({ text = "Side Defensive Balcony"}) + +location_elevator = location_info:new({ text = "Elevator Shaft"}) + +location_lab = location_info:new({ text = "Center Laboratory"}) + +location_building = location_info:new({ text = "Defense Building"}) +location_main = location_info:new({ text = "Main Area"}) +location_main_top = location_info:new({ text = "Top Balcony"}) + +location_cap = location_info:new({ text = "Capture Area"}) +location_d_spawn = location_info:new({ text = "Defense Spawn"}) \ No newline at end of file diff --git a/maps/ff_hunted.lua b/maps/ff_hunted.lua new file mode 100644 index 0000000..0d86038 --- /dev/null +++ b/maps/ff_hunted.lua @@ -0,0 +1,145 @@ + +-- ff_hunted.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_hunted") + +----------------------------------------------------------------------------- +-- entities +----------------------------------------------------------------------------- + +escape_door_top = base_escape_door + +yellow_door = yellowrespawndoor +yellow_door_Sewers_1 = yellowrespawndoor +yellow_door_BuildingOneNook_2 = yellowrespawndoor +yellow_door_BuildingOneBreakRoom = yellowrespawndoor +yellow_door_Sewers_2 = yellowrespawndoor +yellow_door_BuildingOneNook_1 = yellowrespawndoor +yellow_door_Warehouse_1 = yellowrespawndoor +yellow_door_RuinsAttic = yellowrespawndoor +yellow_door_ShaftRoom = yellowrespawndoor +yellow_door_RuinsBathroom_1 = yellowrespawndoor +yellow_door_RuinsBathroom_2 = yellowrespawndoor +yellow_door_OrgyTower = yellowrespawndoor +yellow_door_MainRoadBuilding_1 = yellowrespawndoor + +----------------------------------------------------------------------------- +-- locations +----------------------------------------------------------------------------- + +location_green_hallway = location_info:new({ text = "Green Hallway", team = Team.kGreen }) +location_main_tunnel_elevator = location_info:new({ text = "Main Tunnel Elevator", team = Team.kBlue }) +location_main_tunnel_section1 = location_info:new({ text = "Main Tunnel Section 1", team = Team.kRed }) +location_main_tunnel_section2 = location_info:new({ text = "Main Tunnel Section 2", team = Team.kRed }) +location_main_tunnel_section3 = location_info:new({ text = "Main Tunnel Section 3", team = Team.kRed }) +location_main_tunnel_sewer_ladder = location_info:new({ text = "Main Tunnel Sewer Ladder", team = Team.kRed }) +location_main_tunnel_t = location_info:new({ text = "Main Tunnel T", team = Team.kRed }) +location_main_tunnel_turn1 = location_info:new({ text = "Main Tunnel Turn 1", team = Team.kRed }) +location_main_tunnel_turn2 = location_info:new({ text = "Main Tunnel Turn 2", team = Team.kRed }) + +location_beside_robotery = location_info:new({ text = "Beside Robotery", team = NO_TEAM }) +location_behind_robotery = location_info:new({ text = "Behind Robotery", team = NO_TEAM }) +location_main_ramp = location_info:new({ text = "Main Ramp", team = NO_TEAM }) +location_main_ramp_opening = location_info:new({ text = "Main Ramp Opening", team = NO_TEAM }) +location_main_ramp_overhang = location_info:new({ text = "Main Ramp Overhang", team = NO_TEAM }) +location_main_road = location_info:new({ text = "Main Road", team = NO_TEAM }) +location_main_road_hill = location_info:new({ text = "Main Road Hill", team = NO_TEAM }) +location_main_road_lookout = location_info:new({ text = "Main Road Lookout", team = NO_TEAM }) +location_main_road_stairs = location_info:new({ text = "Main Road Stairs", team = NO_TEAM }) +location_mountain_tunnel = location_info:new({ text = "Mountain Tunnel", team = NO_TEAM }) +location_robotery = location_info:new({ text = "Robotery", team = NO_TEAM }) +location_robotery_crevice = location_info:new({ text = "Robotery Crevice", team = NO_TEAM }) +location_robotery_front_roof = location_info:new({ text = "Robotery Front Roof", team = NO_TEAM }) +location_robotery_loading_bay = location_info:new({ text = "Robotery Loading Bay", team = NO_TEAM }) +location_robotery_side_doors = location_info:new({ text = "Robotery Side Doors", team = NO_TEAM }) + +location_lower_vent_room = location_info:new({ text = "Lower Vent Room", team = NO_TEAM }) +location_upper_vent_room = location_info:new({ text = "Upper Vent Room", team = NO_TEAM }) +location_vent = location_info:new({ text = "Vent", team = NO_TEAM }) +location_vent_stairwell_room = location_info:new({ text = "Vent-Stairwell Room", team = NO_TEAM }) + +location_break_room = location_info:new({ text = "Break Room", team = Team.kYellow }) +location_break_room_nook = location_info:new({ text = "Break Room Nook", team = Team.kYellow }) +location_building_1_alley_lookout = location_info:new({ text = "Building 1 Alley Lookout", team = Team.kYellow }) +location_building_1_entrance = location_info:new({ text = "Building 1 Entrance", team = NO_TEAM }) +location_building_1_exit = location_info:new({ text = "Building 1 Exit", team = NO_TEAM }) +location_building_1_lockers = location_info:new({ text = "Building 1 Lockers", team = NO_TEAM }) +location_building_1_lockers_nook = location_info:new({ text = "Building 1 Lockers Nook", team = NO_TEAM }) +location_building_1_lookout = location_info:new({ text = "Building 1 Lookout", team = Team.kYellow }) +location_building_1_lookout_room = location_info:new({ text = "Building 1 Lookout Room", team = Team.kYellow }) +location_building_1_lookout_room_exit = location_info:new({ text = "Building 1 Lookout Room Exit", team = Team.kYellow }) +location_building_1_rooftop = location_info:new({ text = "Building 1 Rooftop", team = NO_TEAM }) +location_utility_room = location_info:new({ text = "Utility Room", team = Team.kYellow }) +location_utility_room_boxes = location_info:new({ text = "Utility Room Boxes", team = NO_TEAM }) +location_utility_room_lower_stairs = location_info:new({ text = "Utility Room Lower Stairs", team = Team.kYellow }) +location_utility_room_other_boxes = location_info:new({ text = "Utility Room Other Boxes", team = NO_TEAM }) +location_utility_room_upper_nook = location_info:new({ text = "Utility Room Upper Nook", team = NO_TEAM }) +location_utility_room_upper_stairs = location_info:new({ text = "Utility Room Upper Stairs", team = Team.kYellow }) + +location_sewers_alley = location_info:new({ text = "Sewer Alley Ladder", team = NO_TEAM }) +location_sewers_dead_end = location_info:new({ text = "Sewer Dead End", team = NO_TEAM }) +location_sewers_main_road = location_info:new({ text = "Sewer Main Road Ladder", team = NO_TEAM }) +location_sewers_main_tunnel = location_info:new({ text = "Sewer Main Tunnel Ladder", team = NO_TEAM }) +location_sewers_mountain_tunnel = location_info:new({ text = "Sewer Mountain Tunnel Ladder", team = NO_TEAM }) +location_sewers_section1 = location_info:new({ text = "Sewer Section 1", team = NO_TEAM }) +location_sewers_section2 = location_info:new({ text = "Sewer Section 2", team = NO_TEAM }) +location_sewers_section3 = location_info:new({ text = "Sewer Section 3", team = NO_TEAM }) +location_sewers_section4 = location_info:new({ text = "Sewer Section 4", team = NO_TEAM }) +location_sewers_turn1 = location_info:new({ text = "Sewer Turn 1", team = NO_TEAM }) +location_sewers_turn2 = location_info:new({ text = "Sewer Turn 2", team = NO_TEAM }) +location_sewers_turn3 = location_info:new({ text = "Sewer Turn 3", team = NO_TEAM }) +location_sewers_turn4 = location_info:new({ text = "Sewer Turn 4", team = NO_TEAM }) +location_sewers_turn5 = location_info:new({ text = "Sewer Turn 5", team = NO_TEAM }) + +location_alley = location_info:new({ text = "Alley", team = NO_TEAM }) +location_alley_entrance = location_info:new({ text = "Alley Entrance", team = NO_TEAM }) +location_alley_lookouts = location_info:new({ text = "Alley Lookouts", team = Team.kYellow }) + +location_above_t_hallway = location_info:new({ text = "Above T Hallway", team = NO_TEAM }) +location_t_hallway = location_info:new({ text = "T Hallway", team = NO_TEAM }) +location_t_hallway_exit = location_info:new({ text = "T Hallway Exit", team = NO_TEAM }) + +location_stairwell_building_floor2 = location_info:new({ text = "Stairwell Building Floor 2", team = NO_TEAM }) +location_stairwell_building_floor3 = location_info:new({ text = "Stairwell Building Floor 3", team = NO_TEAM }) +location_stairwell_building_floor4 = location_info:new({ text = "Stairwell Building Floor 4", team = Team.kYellow }) +location_stairwell_floor1 = location_info:new({ text = "Stairwell Floor 1", team = NO_TEAM }) +location_stairwell_floor2 = location_info:new({ text = "Stairwell Floor 2", team = NO_TEAM }) +location_stairwell_floor3 = location_info:new({ text = "Stairwell Floor 3", team = Team.kYellow }) +location_stairwell_floor4 = location_info:new({ text = "Stairwell Floor 4", team = Team.kYellow }) + +location_ruins = location_info:new({ text = "Ruins", team = Team.kYellow }) +location_ruins_attic = location_info:new({ text = "Ruins Attic", team = Team.kYellow }) +location_ruins_attic_door = location_info:new({ text = "Ruins Attic Door", team = Team.kYellow }) +location_ruins_bathroom = location_info:new({ text = "Ruins Bathroom", team = Team.kYellow }) +location_ruins_crate_room = location_info:new({ text = "Ruins Crate Room", team = NO_TEAM }) +location_ruins_crate_room_exit = location_info:new({ text = "Ruins Crate Room Exit", team = NO_TEAM }) +location_ruins_dark_side = location_info:new({ text = "Ruins Dark Side", team = NO_TEAM }) +location_ruins_exit = location_info:new({ text = "Ruins Exit", team = NO_TEAM }) +location_ruins_field_holes = location_info:new({ text = "Ruins Field Holes", team = Team.kYellow }) +location_ruins_lower_ladder_room = location_info:new({ text = "Ruins Lower Ladder Room", team = Team.kYellow }) +location_ruins_middle_floor = location_info:new({ text = "Ruins Middle Floor", team = Team.kYellow }) +location_ruins_storage = location_info:new({ text = "Ruins Storage", team = NO_TEAM }) +location_ruins_tower_base = location_info:new({ text = "Ruins Tower Base", team = NO_TEAM }) +location_ruins_tower_rooftop = location_info:new({ text = "Ruins Tower Rooftop", team = NO_TEAM }) +location_ruins_tower_window = location_info:new({ text = "Ruins Tower Window", team = NO_TEAM }) +location_ruins_upper_ladder_room = location_info:new({ text = "Ruins Upper Ladder Room", team = Team.kYellow }) + +location_warehouse = location_info:new({ text = "Warehouse", team = Team.kYellow }) +location_warehouse_alley = location_info:new({ text = "Warehouse Alley", team = NO_TEAM }) +location_warehouse_entrance = location_info:new({ text = "Warehouse Entrance", team = NO_TEAM }) +location_warehouse_ramp = location_info:new({ text = "Warehouse Ramp", team = NO_TEAM }) +location_warehouse_ramp_nook = location_info:new({ text = "Warehouse Ramp Nook", team = NO_TEAM }) + +location_between_towers = location_info:new({ text = "Between Towers", team = NO_TEAM }) +location_billy_dons_property = location_info:new({ text = "Billy Don's Property", team = Team.kYellow }) +location_escape_tunnel = location_info:new({ text = "Escape Tunnel", team = Team.kBlue }) +location_field = location_info:new({ text = "Field", team = NO_TEAM }) +location_field_bridge = location_info:new({ text = "Field Bridge", team = NO_TEAM }) +location_fuel_room = location_info:new({ text = "Fuel Room", team = NO_TEAM }) +location_fuel_room_rooftop = location_info:new({ text = "Fuel Room Rooftop", team = NO_TEAM }) +location_tower1 = location_info:new({ text = "Tower 1", team = Team.kRed }) +location_tower2 = location_info:new({ text = "Tower 2", team = Team.kRed }) +location_under_the_bridge = location_info:new({ text = "Under Field Bridge", team = NO_TEAM }) diff --git a/maps/ff_hunted.txt b/maps/ff_hunted.txt new file mode 100644 index 0000000..82d0a15 --- /dev/null +++ b/maps/ff_hunted.txt @@ -0,0 +1,17 @@ +GAME MODE: Hunted + +Teams: +Blue Civilian escorted by Red Bodyguards vs Yellow Assassins + +Objectives: +Bodyguards open garage from the towers and escort civilian to the escape area + +Scoring: +Bodyguard: 10 points per escape +Assassin: 5 points per assassination + +Notes: + - The Hunted only takes damage +from sniper rifle, crowbar, knife, +tranq, and sabotaged SGs and +dispensers \ No newline at end of file diff --git a/maps/ff_hunted__classic__.lua b/maps/ff_hunted__classic__.lua new file mode 100644 index 0000000..6a876ad --- /dev/null +++ b/maps/ff_hunted__classic__.lua @@ -0,0 +1,71 @@ + +-- ff_hunted__classic__.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("ff_hunted") + +----------------------------------------------------------------------------- +-- Basic hunted-style gameplay. Respawns all players when the VIP is killed +----------------------------------------------------------------------------- +POINTS_PER_HUNTED_DEATH = 25 +POINTS_PER_HUNTED_ESCAPE = 50 + +function startup() + SetGameDescription("Hunted Classic") + + -- set up team names + SetTeamName( Team.kBlue, "The Hunted" ) + SetTeamName( Team.kRed, "Bodyguards" ) + SetTeamName( Team.kYellow, "Assassins" ) + SetTeamName( Team.kGreen, "Green Kid Touchers" ) + + -- set up team limits + SetPlayerLimit( Team.kBlue, 1 ) -- There can be only one Highlander! + SetPlayerLimit( Team.kRed, 0 ) -- Unlimited bodyguards. + SetPlayerLimit( Team.kYellow, 5 ) -- Only 5 assassins, but can we dynamically change this based on maxplayers and/or the current playercount? + SetPlayerLimit( Team.kGreen, -1 ) -- Fuck green. + + local team = GetTeam( Team.kBlue ) + team:SetAllies( Team.kRed ) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, -1 ) + team:SetClassLimit( Player.kSoldier, -1 ) + team:SetClassLimit( Player.kDemoman, -1 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, 0 ) + + team = GetTeam( Team.kRed ) + team:SetAllies( Team.kBlue ) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, -1 ) + team:SetClassLimit( Player.kSoldier, 0 ) + team:SetClassLimit( Player.kDemoman, -1 ) + team:SetClassLimit( Player.kMedic, 0 ) + team:SetClassLimit( Player.kHwguy, 0 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + team = GetTeam( Team.kYellow ) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, 0 ) + team:SetClassLimit( Player.kSoldier, -1 ) + team:SetClassLimit( Player.kDemoman, -1 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + RemoveSchedule( "hunted_location_timer" ) + AddScheduleRepeating( "hunted_location_timer" , 1.0, hunted_location_timer ) + +end diff --git a/maps/ff_hunted_level_sounds.txt b/maps/ff_hunted_level_sounds.txt new file mode 100644 index 0000000..5340596 --- /dev/null +++ b/maps/ff_hunted_level_sounds.txt @@ -0,0 +1,106 @@ +//-------------------------------- +// begin game sounds for ff_hunted +//-------------------------------- + +"ff_hunted.thunder" +{ + "channel" "CHAN_STATIC" + "volume" "0.3" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ambient/levels/labs/teleport_postblast_thunder1.wav" +} + +"ff_hunted.cheer" +{ + "channel" "CHAN_STATIC" + "volume" "0.6" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ff_hunted/CrowdCheer.wav" +} + +"ff_hunted.dying_bird" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "rndwave" + { + "wave" "@ff_hunted\dying_bird_1.wav" + "wave" "@ff_hunted\dying_bird_2.wav" + "wave" "@ff_hunted\dying_bird_3.wav" + } +} + +"ff_hunted.dying_bird_full" +{ + "channel" "CHAN_STATIC" + "volume" "0.6" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ff_hunted\dying_bird_full.wav" +} + +"ff_hunted.i_am_the_werewolf" +{ + "channel" "CHAN_STATIC" + "volume" "0.6" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ff_hunted\i_am_the_werewolf.wav" +} + +"ff_hunted.i_fight_vampires" +{ + "channel" "CHAN_STATIC" + "volume" "0.6" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ff_hunted\i_fight_vampires.wav" +} + +"ff_hunted.werewolf_howling" +{ + "channel" "CHAN_STATIC" + "volume" "0.6" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ff_hunted\werewolf_howling.wav" +} + +"ff_hunted.werewolf_movies" +{ + "channel" "CHAN_STATIC" + "volume" "0.6" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ff_hunted\werewolf_movies.wav" +} + +"ff_hunted.werewolves_howling" +{ + "channel" "CHAN_STATIC" + "volume" "0.6" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@ff_hunted\werewolves_howling.wav" +} + +//-------------------- +// UNAGI POWER, UNAGI! +//-------------------- + +"ff_hunted.unagi" +{ + "channel" "CHAN_STATIC" + "volume" "0.8" + "soundlevel" "SNDLVL_NONE" + "pitch" "95,105" + "wave" "@misc/unagi.wav" +} + +//------------------------------ +// end game sounds for ff_hunted +//------------------------------ \ No newline at end of file diff --git a/maps/ff_hunted_soundscapes.txt b/maps/ff_hunted_soundscapes.txt new file mode 100644 index 0000000..b99e9db --- /dev/null +++ b/maps/ff_hunted_soundscapes.txt @@ -0,0 +1,64 @@ +"ff_hunted.FrontRoad" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.75" + "pitch" "100" + "wave" "ambient/atmosphere/town_ambience.wav" + } + "playrandom" + { + "time" "0.0,15.0" + "volume" "0.1" + "pitch" "50,100" + "rndwave" + { + "wave" "ambient/materials/metal4.wav" + "wave" "ambient/atmosphere/metallic1.wav" + } + } +} + +"ff_hunted.BodyguardTunnelTop" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.05" + "pitch" "100" + "wave" "ambient/atmosphere/indoor2.wav" + } + "playlooping" + { + "volume" "0.1" + "pitch" "50" + "wave" "ambient/atmosphere/undercity_loop1.wav" + } + + "playsoundscape" + { + "name" "ff_hunted.FrontRoad" + "volume" ".5" + } +} + +"ff_hunted.BodyguardTunnel" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.1" + "pitch" "100" + "wave" "ambient/atmosphere/indoor2.wav" + } + "playlooping" + { + "volume" "0.2" + "pitch" "50" + "wave" "ambient/atmosphere/undercity_loop1.wav" + } +} \ No newline at end of file diff --git a/maps/ff_ksour.lua b/maps/ff_ksour.lua new file mode 100644 index 0000000..65ad1db --- /dev/null +++ b/maps/ff_ksour.lua @@ -0,0 +1,404 @@ +IncludeScript("base_id"); +IncludeScript("base_respawnturret"); +----------------------------------------------------------------------------- +-- globals +FLAG_RETURN_TIME = 60; +INITIAL_ROUND_DELAY = 45; +TEAM_SWITCH_DELAY = 4 +NUM_PHASES = 4 +----------------------------------------------------------------------------- + +-- sounds, right? +function precache() + PrecacheSound("otherteam.flagstolen") + PrecacheSound("misc.bloop") +end + +-- startup +function startup() + SetGameDescription("Invade Defend") + + -- set up team limits + local team = GetTeam( Team.kBlue ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kRed ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kYellow ) + team:SetPlayerLimit( -1 ) + + team = GetTeam( Team.kGreen ) + team:SetPlayerLimit( -1 ) + + -- CTF maps generally don't have civilians, + -- so override in map LUA file if you want 'em + local team = GetTeam(attackers) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kSniper, 1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) + + + team = GetTeam(defenders) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, -1) + team:SetClassLimit(Player.kMedic, -1) + team:SetClassLimit(Player.kSniper, 1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) + + -- set team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- start the timer for the points + AddScheduleRepeating("addpoints", PERIOD_TIME, addpoints) + + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_DELAY - 30 , schedulemessagetoall, "Gates open in 30 seconds!" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_DELAY - 10 , schedulemessagetoall, "Gates open in 10 seconds!" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5sec" , INITIAL_ROUND_DELAY - 5 , schedulemessagetoall, "5" ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4sec" , INITIAL_ROUND_DELAY - 4 , schedulemessagetoall, "4" ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3sec" , INITIAL_ROUND_DELAY - 3, schedulemessagetoall, "3" ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2sec" , INITIAL_ROUND_DELAY - 2, schedulemessagetoall, "2" ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1sec" , INITIAL_ROUND_DELAY - 1, schedulemessagetoall, "1" ) end + + -- sounds + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_DELAY - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_DELAY - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_DELAY - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_DELAY - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_DELAY - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_DELAY - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_DELAY - 1 , schedulecountdown, 1 ) end + + cp1_flag.enabled = true + for i,v in ipairs({"cp1_flag", "cp2_flag", "cp3_flag", "cp4_flag", "cp5_flag", "cp6_flag", "cp7_flag", "cp8_flag"}) do + local flag = GetInfoScriptByName(v) + if flag then + flag:SetModel(_G[v].model) + flag:SetSkin(teamskins[attackers]) + if i == 1 then + flag:Restore() + else + flag:Remove() + end + end + end + + flags_set_team( attackers ) + + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) +end + +-- overwriting these functions so that there aren't repeat messages +function round_30secwarn() end +function round_10secwarn() end + +function base_id_cap:oncapture(player, item) + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") +--SmartSound(player, "vox.yourcap", "vox.yourcap", "vox.enemycap") + SmartSpeak(player, "CTF_YOUCAP", "CTF_TEAMCAP", "CTF_THEYCAP") + SmartMessage(player, "#FF_YOUCAP", "#FF_TEAMCAP", "#FF_OTHERTEAMCAP", Color.kGreen, Color.kGreen, Color.kRed) + + local flag_item = GetInfoScriptByName( item ) + RemoveHudItem( player, flag_item:GetName() ) + + -- turn off this flag + for i,v in ipairs(self.item) do + _G[v].enabled = nil + local flag = GetInfoScriptByName(v) + if flag then + flag:Remove() + end + end + + if phase == NUM_PHASES then + -- it's the last round. end and stuff + phase = 1 + + AddSchedule("switch_teams", TEAM_SWITCH_DELAY, switch_teams) + else + phase = phase + 1 + + -- enable the next flag after a time + AddSchedule("flag_start", ROUND_DELAY, flag_start, self.next) + if ROUND_DELAY > 30 then AddSchedule("flag_30secwarn", ROUND_DELAY-30, flag_30secwarn) end + if ROUND_DELAY > 10 then AddSchedule("flag_10secwarn", ROUND_DELAY-10, flag_10secwarn) end + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = nil + if DEFENDERS_OBJECTIVE_ONFLAG or DEFENDERS_OBJECTIVE_ONCARRIER then DEFENDERS_OBJECTIVE_ENTITY = nil + else DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_tobase_timer() + update_hud() + end + +end + +function switch_teams() + if attackers == Team.kBlue then + attackers = Team.kRed + defenders = Team.kBlue + else + attackers = Team.kBlue + defenders = Team.kRed + end + + local team = GetTeam(attackers) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kDemoman, 0) + team:SetClassLimit(Player.kEngineer, 0) + team:SetClassLimit(Player.kScout, 0) + team:SetClassLimit(Player.kMedic, 0) + + team = GetTeam(defenders) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kScout, -1) + team:SetClassLimit(Player.kMedic, -1) + + -- set all flag teams to new attackers + flags_set_team( attackers ) + + -- switch them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- enable the first flag + cp1_flag.enabled = true + cp1_flag.status = 0 + local flag = GetInfoScriptByName("cp1_flag") + if flag then + flag:Restore() + flag:SetSkin(teamskins[attackers]) + end + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + -- reset the timer on points + AddScheduleRepeating("addpoints", PERIOD_TIME, addpoints) + + -- respawn the players + RespawnAllPlayers() + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + + -- run custom round reset stuff + onroundreset() + update_hud() +end + +-- Give everyone a full resupply, but strip secondary grenades and defender detpacks +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + + player:RemoveAmmo( Ammo.kGren2, 4 ) + + -- wtf, scout or med on d? are you mental? + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + local classt = "Scout" + if player:GetClass() == Player.kMedic then classt = "Medic" end + local id = player:GetId() + AddSchedule("force_changemessage"..id, 2, schedulechangemessage, player, "No "..classt.."s on defense. Autoswitching to Soldier." ) + AddSchedule("force_change"..id, 2.5, forcechange, player) + end + + if player:GetTeamId() == attackers then + UpdateObjectiveIcon( player, ATTACKERS_OBJECTIVE_ENTITY ) + elseif player:GetTeamId() == defenders then + UpdateObjectiveIcon( player, DEFENDERS_OBJECTIVE_ENTITY ) + player:RemoveAmmo( Ammo.kDetpack, 1 ) + end +end + +----------------------------------------------------------------------------- +-- Scheduled functions that do stuff +----------------------------------------------------------------------------- + +-- Sends a message to all after the determined time +function schedulechangemessage( player, message ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + BroadCastMessageToPlayer( player, message ) + end +end + +-- force a scout/med to switch to soli if they haven't +function forcechange( player ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + ApplyToPlayer( player, { AT.kChangeClassSoldier, AT.kRespawnPlayers } ) + end +end + +--------------------------------------------------------------------------- +--Turrets +------------------------------------------------------------ + +respawnturret_attackers = base_respawnturret:new({ team = attackers }) +respawnturret_defenders = base_respawnturret:new({ team = defenders }) + +--------------------- +--Backpacks +--------------------- +genpack = genericbackpack:new({ + health = 35, + armor = 50, + grenades = 20, + nails = 50, + shells = 300, + rockets = 15, + cells = 120, + mancannons = 1, + gren1 = 1, + gren2 = 0, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function genpack:dropatspawn() return false +end + +genpack_grenpack = genericbackpack:new({ + health = 35, + armor = 50, + grenades = 20, + nails = 50, + shells = 300, + rockets = 15, + cells = 120, + mancannons = 1, + gren1 = 2, + gren2 = 1, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function genpack_grenpack:dropatspawn() return false +end + +---------------------------------------------------- +--Toggle Cap points +--------------------------------------------------- +function cp1_cap:ontouch( trigger_entity ) + OutputEvent( "cp1_door", "Toggle" ) + +end +function cp2_cap:ontouch( trigger_entity ) + OutputEvent( "cp2_door", "Toggle" ) + +end +function cp3_cap:ontouch( trigger_entity ) + OutputEvent( "cp3_door", "Toggle" ) + +end +function cp4_cap:ontouch( trigger_entity ) + OutputEvent( "cp4_door", "Toggle" ) + +end + +---------------------------------------------------- +--Random schedule functions +--------------------------------------------------- +-- Sends a message to all after the determined time +function schedulemessagetoall( message ) + BroadCastMessage( message ) +end + +-- Plays a sound to all after the determined time +function schedulesound( sound ) + BroadCastSound( sound ) +end + + +function schedulecountdown( time ) + BroadCastMessage( ""..time.."" ) + SpeakAll( "AD_" .. time .. "SEC" ) +end + +function round_start(doorname) + BroadCastMessage("Gates are now open!") + OpenDoor(doorname) + + BroadCastSound( "otherteam.flagstolen" ) + SpeakAll( "AD_GATESOPEN" ) +end + +--------------------------------------- +--Resetting round +------------------------------------ +detpack_wall_open = nil + +function onroundreset() + -- close the door + if detpack_wall_open then + -- there's no "close".. wtf + OutputEvent("detpack_hole", "Toggle") + detpack_wall_open = nil + end + -- Reset The Turrets + respawnturret_attackers = base_respawnturret:new({ team = attackers }) + respawnturret_defenders = base_respawnturret:new({ team = defenders }) + + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_DELAY - 30 , schedulemessagetoall, "Gates open in 30 seconds!" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_DELAY - 10 , schedulemessagetoall, "Gates open in 10 seconds!" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5sec" , INITIAL_ROUND_DELAY - 5 , schedulemessagetoall, "5" ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4sec" , INITIAL_ROUND_DELAY - 4 , schedulemessagetoall, "4" ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3sec" , INITIAL_ROUND_DELAY - 3, schedulemessagetoall, "3" ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2sec" , INITIAL_ROUND_DELAY - 2, schedulemessagetoall, "2" ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1sec" , INITIAL_ROUND_DELAY - 1, schedulemessagetoall, "1" ) end + + -- sounds + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_DELAY - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_DELAY - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_DELAY - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_DELAY - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_DELAY - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_DELAY - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_DELAY - 1 , schedulecountdown, 1 ) end +end + +detpack_trigger = trigger_ff_script:new({}) +function detpack_trigger:onexplode( trigger_entity ) + if IsDetpack( trigger_entity ) then + BroadCastMessage("The detpack wall has been blown open!") + BroadCastSound( "otherteam.flagstolen" ) + OutputEvent("detpack_hole", "Toggle") + OutputEvent("break1", "PlaySound") + detpack_wall_open = true + end + return EVENT_ALLOWED +end + +-- Don't want any body touching/triggering it except the detpack +function trigger_detpackable_door:allowed( trigger_entity ) return EVENT_DISALLOWED +end + + diff --git a/maps/ff_monkey.lua b/maps/ff_monkey.lua new file mode 100644 index 0000000..4a03389 --- /dev/null +++ b/maps/ff_monkey.lua @@ -0,0 +1,233 @@ +-- ff_monkey.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- + +IncludeScript("base_ctf") +IncludeScript("base_location") +IncludeScript("base_respawnturret") + +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- + +POINTS_PER_CAPTURE = 10 +FLAG_RETURN_TIME = 60 + +function startup() + SetGameDescription("Capture the Flag") + + -- set up team limits on each team + SetPlayerLimit(Team.kBlue, 0) + SetPlayerLimit(Team.kRed, 0) + SetPlayerLimit(Team.kYellow, -1) + SetPlayerLimit(Team.kGreen, -1) + + -- CTF maps generally don't have civilians, + -- so override in map LUA file if you want 'em + local team = GetTeam(Team.kBlue) + team:SetClassLimit(Player.kCivilian, -1) + + team = GetTeam(Team.kRed) + team:SetClassLimit(Player.kCivilian, -1) +end + +----------------------------------------------------------------------------- +-- Pickups +----------------------------------------------------------------------------- + +monkeypackgeneric = genericbackpack:new({ + health = 20, + armor = 15, + grenades = 60, + nails = 60, + shells = 60, + rockets = 60, + cells = 60, + mancannons = 1, + gren1 = 1, + gren2 = 1, + respawntime = 35, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +function monkeypackgeneric:dropatspawn() return false end + +redmonkeypack = genericbackpack:new({ + health = 200, + armor = 200, + grenades = 200, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + respawntime = 2, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kRed}, + botgoaltype = Bot.kBackPack_Ammo +}) + +function redmonkeypack:dropatspawn() return false end + +redmonkeypacktoo = genericbackpack:new({ + health = 20, + armor = 15, + grenades = 10, + nails = 30, + shells = 30, + rockets = 10, + cells = 30, + respawntime = 20, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kRed}, + botgoaltype = Bot.kBackPack_Ammo +}) + +function redmonkeypacktoo:dropatspawn() return false end + +bluemonkeypack = genericbackpack:new({ + health = 200, + armor = 200, + grenades = 200, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + respawntime = 2, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kBlue}, + botgoaltype = Bot.kBackPack_Ammo +}) + +function bluemonkeypack:dropatspawn() return false end + +bluemonkeypacktoo = genericbackpack:new({ + health = 20, + armor = 15, + grenades = 10, + nails = 30, + shells = 30, + rockets = 10, + cells = 30, + respawntime = 20, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kBlue}, + botgoaltype = Bot.kBackPack_Ammo +}) + +function bluemonkeypacktoo:dropatspawn() return false end + +redmonkeygrenades = genericbackpack:new({ + detpacks = 1, + mancannons = 1, + gren1 = 4, + gren2 = 4, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kRed}, + respawntime = 15, + botgoaltype = Bot.kBackPack_Ammo +}) + +function redmonkeygrenades:dropatspawn() return false end + +bluemonkeygrenades = genericbackpack:new({ + detpacks = 1, + mancannons = 1, + gren1 = 4, + gren2 = 4, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kBlue}, + respawntime = 15, + botgoaltype = Bot.kBackPack_Ammo +}) + +function bluemonkeygrenades:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- Locations +----------------------------------------------------------------------------- + +location_blue_front_door = location_info:new({ text = "Front Door", team = Team.kBlue }) +location_blue_right_front_door = location_info:new({ text = "Right Front Door", team = Team.kBlue }) +location_blue_left_front_door = location_info:new({ text = "Left Front Door", team = Team.kBlue }) +location_blue_ramp_room = location_info:new({ text = "Great Hall", team = Team.kBlue }) +location_blue_T_route = location_info:new({ text = "'T' Route", team = Team.kBlue }) +location_blue_upper_spawn = location_info:new({ text = "Upper Spawn", team = Team.kBlue }) +location_blue_lower_spawn = location_info:new({ text = "Lower Spawn", team = Team.kBlue }) +location_blue_lower_route = location_info:new({ text = "Lower Route", team = Team.kBlue }) +location_blue_water_route = location_info:new({ text = "Water Route", team = Team.kBlue }) +location_blue_flag_room = location_info:new({ text = "Flag Room", team = Team.kBlue }) +location_blue_pit = location_info:new({ text = "Flag Room Pit", team = Team.kBlue }) +location_blue_flag_room_catwalk = location_info:new({ text = "Flag Room Catwalks", team = Team.kBlue }) +location_blue_water_tunnel = location_info:new({ text = "Water Tunnel", team = Team.kBlue }) +location_blue_yard = location_info:new({ text = "Yard", team = Team.kBlue }) + +location_red_front_door = location_info:new({ text = "Front Door", team = Team.kRed }) +location_red_right_front_door = location_info:new({ text = "Right Front Door", team = Team.kRed }) +location_red_left_front_door = location_info:new({ text = "Left Front Door", team = Team.kRed }) +location_red_ramp_room = location_info:new({ text = "Great Hall", team = Team.kRed }) +location_red_T_route = location_info:new({ text = "'T' Route", team = Team.kRed }) +location_red_upper_spawn = location_info:new({ text = "Upper Spawn", team = Team.kRed }) +location_red_lower_spawn = location_info:new({ text = "Lower Spawn", team = Team.kRed }) +location_red_lower_route = location_info:new({ text = "Lower Route", team = Team.kRed }) +location_red_water_route = location_info:new({ text = "Water Route", team = Team.kRed }) +location_red_flag_room = location_info:new({ text = "Flag Room", team = Team.kRed }) +location_red_pit = location_info:new({ text = "Flag Room Pit", team = Team.kRed }) +location_red_flag_room_catwalk = location_info:new({ text = "Flag Room Catwalks", team = Team.kRed }) +location_red_water_tunnel = location_info:new({ text = "Water Tunnel", team = Team.kRed }) +location_red_yard = location_info:new({ text = "Yard", team = Team.kRed }) + +location_river = location_info:new({ text = "River", team = Team.kUnassigned }) +location_midmap = location_info:new({ text = "Midmap", team = Team.kUnassigned }) +location_bridge = location_info:new({ text = "Bridge", team = Team.kUnassigned }) + +----------------------------------------------------------------------------- +-- OFFENSIVE AND DEFENSIVE SPAWNS +----------------------------------------------------------------------------- + +red_o_only = function(self,player) return ((player:GetTeamId() == Team.kRed) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kDemoman))) end +red_d_only = function(self,player) return ((player:GetTeamId() == Team.kRed) and (((player:GetClass() == Player.kScout) == false) and ((player:GetClass() == Player.kMedic) == false) and ((player:GetClass() == Player.kSpy) == false))) end + +red_ospawn = { validspawn = red_o_only } +red_dspawn = { validspawn = red_d_only } + +blue_o_only = function(self,player) return ((player:GetTeamId() == Team.kBlue) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kDemoman))) end +blue_d_only = function(self,player) return ((player:GetTeamId() == Team.kBlue) and (((player:GetClass() == Player.kScout) == false) and ((player:GetClass() == Player.kMedic) == false) and ((player:GetClass() == Player.kSpy) == false))) end + +blue_ospawn = { validspawn = blue_o_only } +blue_dspawn = { validspawn = blue_d_only } + +----------------------------------------------------------------------------- +-- respawn shields +----------------------------------------------------------------------------- + +KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) + +function KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +blue_slayer = KILL_KILL_KILL:new({ team = Team.kBlue }) +red_slayer = KILL_KILL_KILL:new({ team = Team.kRed }) diff --git a/maps/ff_monkey.txt b/maps/ff_monkey.txt new file mode 100644 index 0000000..48abf2f --- /dev/null +++ b/maps/ff_monkey.txt @@ -0,0 +1,7 @@ +CAPTURE THE FLAG + +Grab the enemy flag and take it to your capture point to score. + +Original map designed by The Cheese + +Note: Not all Monkeys eat Bananas \ No newline at end of file diff --git a/maps/ff_napoli.lua b/maps/ff_napoli.lua new file mode 100644 index 0000000..f3b31c4 --- /dev/null +++ b/maps/ff_napoli.lua @@ -0,0 +1,425 @@ +IncludeScript("base_id"); +IncludeScript("base_respawnturret"); +----------------------------------------------------------------------------- +-- globals +FLAG_RETURN_TIME = 60; +INITIAL_ROUND_DELAY = 45; +TEAM_SWITCH_DELAY = 4 +NUM_PHASES = 3 +NONINITIAL_ROUND_DELAY = 45; +RESPAWN_AFTER_CAP = false +----------------------------------------------------------------------------- +function respawnall() + BroadCastMessage( "Area Captured. Respawning..." ) + ApplyToAll( { AT.kRespawnPlayers, AT.kRemoveBuildables } ) +end + +-- sounds, right? +function precache() + PrecacheSound("otherteam.flagstolen") + PrecacheSound("misc.bloop") +end + +-- startup +function startup() + SetGameDescription("Invade Defend") + + -- set up team limits + local team = GetTeam( Team.kBlue ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kRed ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kYellow ) + team:SetPlayerLimit( -1 ) + + team = GetTeam( Team.kGreen ) + team:SetPlayerLimit( -1 ) + + + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + + local team = GetTeam(attackers) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kSniper, -1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) + + + team = GetTeam(defenders) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, -1) + team:SetClassLimit(Player.kMedic, -1) + team:SetClassLimit(Player.kSniper, -1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) + + -- start the timer for the points + AddScheduleRepeating("addpoints", PERIOD_TIME, addpoints) + + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_DELAY - 30 , schedulemessagetoall, "Gates open in 30 seconds!" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_DELAY - 10 , schedulemessagetoall, "Gates open in 10 seconds!" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5sec" , INITIAL_ROUND_DELAY - 5 , schedulemessagetoall, "5" ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4sec" , INITIAL_ROUND_DELAY - 4 , schedulemessagetoall, "4" ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3sec" , INITIAL_ROUND_DELAY - 3, schedulemessagetoall, "3" ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2sec" , INITIAL_ROUND_DELAY - 2, schedulemessagetoall, "2" ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1sec" , INITIAL_ROUND_DELAY - 1, schedulemessagetoall, "1" ) end + + -- sounds + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_DELAY - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_DELAY - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_DELAY - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_DELAY - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_DELAY - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_DELAY - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_DELAY - 1 , schedulecountdown, 1 ) end + + cp1_flag.enabled = true + for i,v in ipairs({"cp1_flag", "cp2_flag", "cp3_flag", "cp4_flag", "cp5_flag", "cp6_flag", "cp7_flag", "cp8_flag"}) do + local flag = GetInfoScriptByName(v) + if flag then + flag:SetModel(_G[v].model) + flag:SetSkin(teamskins[attackers]) + if i == 1 then + flag:Restore() + else + flag:Remove() + end + end + end + + flags_set_team( attackers ) + + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) +end + +-- overwriting these functions so that there aren't repeat messages +function round_30secwarn() end +function round_10secwarn() end + +-- Give everyone a full resupply, but strip secondary grenades and defender detpacks +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + + player:RemoveAmmo( Ammo.kGren2, 4 ) + + -- wtf, scout or med on d? are you mental? + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + local classt = "Scout" + if player:GetClass() == Player.kMedic then classt = "Medic" end + local id = player:GetId() + AddSchedule("force_changemessage"..id, 2, schedulechangemessage, player, "No "..classt.."s on defense. Autoswitching to Soldier." ) + AddSchedule("force_change"..id, 2.5, forcechange, player) + end + + if player:GetTeamId() == attackers then + UpdateObjectiveIcon( player, ATTACKERS_OBJECTIVE_ENTITY ) + --player:RemoveAmmo( Ammo.kManCannon, 1 ) + elseif player:GetTeamId() == defenders then + UpdateObjectiveIcon( player, DEFENDERS_OBJECTIVE_ENTITY ) + --player:RemoveAmmo( Ammo.kDetpack, 1 ) + end +end + +function base_id_cap:oncapture(player, item) + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") +--SmartSound(player, "vox.yourcap", "vox.yourcap", "vox.enemycap") + SmartSpeak(player, "CTF_YOUCAP", "CTF_TEAMCAP", "CTF_THEYCAP") + SmartMessage(player, "#FF_YOUCAP", "#FF_TEAMCAP", "#FF_OTHERTEAMCAP", Color.kGreen, Color.kGreen, Color.kRed) + + local flag_item = GetInfoScriptByName( item ) + RemoveHudItem( player, flag_item:GetName() ) + + -- turn off this flag + for i,v in ipairs(self.item) do + _G[v].enabled = nil + local flag = GetInfoScriptByName(v) + if flag then + flag:Remove() + end + end + + if phase == NUM_PHASES then + -- it's the last round. end and stuff + phase = 1 + + OutputEvent( "start_gate", "Close" ) + + AddSchedule("switch_teams", TEAM_SWITCH_DELAY, switch_teams) + else + if phase == 1 then + AddSchedule( "cp2partition", 5, OutputEvent, "cp2_partition", "Disable" ) + AddSchedule( "cp3partition", 5, OutputEvent, "cp3_partition", "Enable" ) + end + if phase == 2 then + AddSchedule( "cp2partition", 5, OutputEvent, "cp2_partition", "Enable" ) + AddSchedule( "cp3partition", 5, OutputEvent, "cp3_partition", "Disable" ) + AddSchedule( "cp3areaportal", 5, OutputEvent, "cp3_areaportal", "Toggle" ) + end + AddSchedule("respawnall", 5, respawnall) + phase = phase + 1 + + -- enable the next flag after a time + AddSchedule("flag_start", ROUND_DELAY, flag_start, self.next) + if ROUND_DELAY > 30 then AddSchedule("flag_30secwarn", ROUND_DELAY-30, flag_30secwarn) end + if ROUND_DELAY > 10 then AddSchedule("flag_10secwarn", ROUND_DELAY-10, flag_10secwarn) end + + OutputEvent( "start_gate", "Close" ) + setup_door_timer("start_gate", NONINITIAL_ROUND_DELAY) + + -- clear objective icon + ATTACKERS_OBJECTIVE_ENTITY = nil + if DEFENDERS_OBJECTIVE_ONFLAG or DEFENDERS_OBJECTIVE_ONCARRIER then DEFENDERS_OBJECTIVE_ENTITY = nil + else DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_tobase_timer() + update_hud() + end + +end + +function switch_teams() + if attackers == Team.kBlue then + attackers = Team.kRed + defenders = Team.kBlue + else + attackers = Team.kBlue + defenders = Team.kRed + end + + -- set all flag teams to new attackers + flags_set_team( attackers ) + + -- enable the first flag + cp1_flag.enabled = true + cp1_flag.status = 0 + local flag = GetInfoScriptByName("cp1_flag") + if flag then + flag:Restore() + flag:SetSkin(teamskins[attackers]) + end + + -- switch them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + -- reset the timer on points + AddScheduleRepeating("addpoints", PERIOD_TIME, addpoints) + + -- respawn the players + RespawnAllPlayers() + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + + -- run custom round reset stuff + onroundreset() + update_hud() + + OutputEvent( "point_template", "ForceSpawn" ) + OutputEvent( "cp3_areaportal", "Toggle" ) +end + +----------------------------------------------------------------------------- +-- Scheduled functions that do stuff +----------------------------------------------------------------------------- + +-- Sends a message to all after the determined time +function schedulechangemessage( player, message ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + BroadCastMessageToPlayer( player, message ) + end +end + +-- force a scout/med to switch to soli if they haven't +function forcechange( player ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + ApplyToPlayer( player, { AT.kChangeClassSoldier, AT.kRespawnPlayers } ) + end +end + +--------------------------------------------------------------------------- +--Turrets +------------------------------------------------------------ + +respawnturret_attackers = base_respawnturret:new({ team = attackers }) +respawnturret_defenders = base_respawnturret:new({ team = defenders }) + +--------------------- +--Backpacks +--------------------- +genpack = genericbackpack:new({ + health = 35, + armor = 50, + grenades = 20, + nails = 50, + shells = 300, + rockets = 15, + cells = 120, + mancannons = 1, + gren1 = 0, + gren2 = 0, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function genpack:dropatspawn() return false +end + +genpack_grenpack = genericbackpack:new({ + health = 35, + armor = 50, + grenades = 20, + nails = 50, + shells = 300, + rockets = 15, + cells = 120, + mancannons = 1, + gren1 = 2, + gren2 = 1, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +function genpack_grenpack:dropatspawn() return false +end + +---------------------------------------------------- +--Toggle Cap points +--------------------------------------------------- +function cp1_cap:ontouch( trigger_entity ) + OutputEvent( "cp1_door", "Toggle" ) + +end +function cp2_cap:ontouch( trigger_entity ) + OutputEvent( "cp2_door", "Toggle" ) + +end +function cp3_cap:ontouch( trigger_entity ) + OutputEvent( "cp3_door", "Toggle" ) + +end +function cp4_cap:ontouch( trigger_entity ) + OutputEvent( "cp4_door", "Toggle" ) + +end + +---------------------------------------------------- +--Random schedule functions +--------------------------------------------------- +-- Sends a message to all after the determined time +function schedulemessagetoall( message ) + BroadCastMessage( message ) +end + +-- Plays a sound to all after the determined time +function schedulesound( sound ) + BroadCastSound( sound ) +end + + +function schedulecountdown( time ) + BroadCastMessage( ""..time.."" ) + SpeakAll( "AD_" .. time .. "SEC" ) +end + +function round_start(doorname) + BroadCastMessage("Gates are now open!") + OpenDoor(doorname) + + BroadCastSound( "otherteam.flagstolen" ) + SpeakAll( "AD_GATESOPEN" ) +end + +--------------------------------------- +--Resetting round +------------------------------------ +detpack_wall_open = nil + +function onroundreset() + -- close the door + if detpack_wall_open then + -- there's no "close".. wtf + OutputEvent("detpack_hole", "Toggle") + detpack_wall_open = nil + end + -- Reset The Turrets + respawnturret_attackers = base_respawnturret:new({ team = attackers }) + respawnturret_defenders = base_respawnturret:new({ team = defenders }) + + -- reset them limits + team = GetTeam(defenders) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, -1) + team:SetClassLimit(Player.kMedic, -1) + + team = GetTeam(attackers) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, 0) + team:SetClassLimit(Player.kMedic, 0) + + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_DELAY - 30 , schedulemessagetoall, "Gates open in 30 seconds!" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_DELAY - 10 , schedulemessagetoall, "Gates open in 10 seconds!" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5sec" , INITIAL_ROUND_DELAY - 5 , schedulemessagetoall, "5" ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4sec" , INITIAL_ROUND_DELAY - 4 , schedulemessagetoall, "4" ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3sec" , INITIAL_ROUND_DELAY - 3, schedulemessagetoall, "3" ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2sec" , INITIAL_ROUND_DELAY - 2, schedulemessagetoall, "2" ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1sec" , INITIAL_ROUND_DELAY - 1, schedulemessagetoall, "1" ) end + + -- sounds + if INITIAL_ROUND_DELAY > 30 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_DELAY - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_DELAY - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_DELAY > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_DELAY - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_DELAY > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_DELAY - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_DELAY > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_DELAY - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_DELAY > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_DELAY - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_DELAY > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_DELAY - 1 , schedulecountdown, 1 ) end +end + +detpack_trigger = trigger_ff_script:new({}) +function detpack_trigger:onexplode( trigger_entity ) + if IsDetpack( trigger_entity ) then + BroadCastMessage("The detpack wall has been blown open!") + BroadCastSound( "otherteam.flagstolen" ) + OutputEvent("detpack_hole", "Toggle") + OutputEvent("break1", "PlaySound") + detpack_wall_open = true + end + return EVENT_ALLOWED +end + +-- Don't want any body touching/triggering it except the detpack +function trigger_detpackable_door:allowed( trigger_entity ) return EVENT_DISALLOWED +end + + diff --git a/maps/ff_openfire.lua b/maps/ff_openfire.lua new file mode 100644 index 0000000..3e31b4e --- /dev/null +++ b/maps/ff_openfire.lua @@ -0,0 +1,251 @@ +-- ff_openfire.lua +-- based on aardvark 15/09/07 + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base"); +IncludeScript("base_ctf"); +IncludeScript("base_location"); + +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- +POINTS_PER_CAPTURE = 10; +FLAG_RETURN_TIME = 60; + +----------------------------------------------------------------------------- +-- unique openfire locations +----------------------------------------------------------------------------- +location_redspawn = location_info:new({ text = "Respawn", team = Team.kRed }) +location_redsec = location_info:new({ text = "Fire Control", team = Team.kRed }) +location_redfr = location_info:new({ text = "Flag Room", team = Team.kRed }) +location_redwater = location_info:new({ text = "Perilous Passage", team = Team.kRed }) +location_redfrontdoor = location_info:new({ text = "Front Door Corridor", team = Team.kRed }) +location_redbalcony = location_info:new({ text = "Balcony", team = Team.kRed }) + +location_bluespawn = location_info:new({ text = "Respawn", team = Team.kBlue }) +location_bluesec = location_info:new({ text = "Fire Control", team = Team.kBlue }) +location_bluefr = location_info:new({ text = "Flag Room", team = Team.kBlue }) +location_bluewater = location_info:new({ text = "Perilous Passage", team = Team.kBlue }) +location_bluefrontdoor = location_info:new({ text = "Front Door Corridor", team = Team.kBlue }) +location_bluebalcony = location_info:new({ text = "Balcony", team = Team.kBlue }) + +location_midmap = location_info:new({ text = "Outside", team = NO_TEAM }) + +----------------------------------------------------------------------------- +-- bagless resupply +----------------------------------------------------------------------------- +aardvarkresup = trigger_ff_script:new({ team = Team.kUnassigned }) + +function aardvarkresup:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == self.team then + player:AddHealth( 400 ) + player:AddArmor( 400 ) + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + end + end +end + +blue_aardvarkresup = aardvarkresup:new({ team = Team.kBlue }) +red_aardvarkresup = aardvarkresup:new({ team = Team.kRed }) + +----------------------------------------------------------------------------- +-- aardvark security +----------------------------------------------------------------------------- +red_aardvarksec = trigger_ff_script:new() +blue_aardvarksec = trigger_ff_script:new() +bluesecstatus = 1 +redsecstatus = 1 + +sec_iconx = 60 +sec_icony = 30 +sec_iconw = 16 +sec_iconh = 16 + +function red_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kBlue then + if redsecstatus == 1 then + redsecstatus = 0 + AddSchedule("aardvarksecup10red",20,aardvarksecup10red) + AddSchedule("aardvarksecupred",30,aardvarksecupred) + OpenDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_30") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_REDDOWN" ) + RemoveHudItemFromAll( "red-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end + end + end +end + +function blue_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kRed then + if bluesecstatus == 1 then + bluesecstatus = 0 + AddSchedule("aardvarksecup10blue",20,aardvarksecup10blue) + AddSchedule("aardvarksecupblue",30,aardvarksecupblue) + OpenDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_30") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_BLUEDOWN" ) + RemoveHudItemFromAll( "blue-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + end + end +end + +function aardvarksecupred() + redsecstatus = 1 + CloseDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_ON") + SpeakAll( "SD_REDUP" ) + RemoveHudItemFromAll( "red-sec-down" ) + AddHudIconToAll( "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) +end + +function aardvarksecupblue() + bluesecstatus = 1 + CloseDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_ON") + SpeakAll( "SD_BLUEUP" ) + RemoveHudItemFromAll( "blue-sec-down" ) + AddHudIconToAll( "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) +end + +function aardvarksecup10red() + BroadCastMessage("#FF_RED_SEC_10") +end + +function aardvarksecup10blue() + BroadCastMessage("#FF_BLUE_SEC_10") +end + +----------------------------------------------------------------------------- +-- aardvark lasers and respawn shields +----------------------------------------------------------------------------- +KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) +lasers_KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) + +function KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +function lasers_KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + if self.team == Team.kBlue then + if redsecstatus == 1 then + return EVENT_ALLOWED + end + end + if self.team == Team.kRed then + if bluesecstatus == 1 then + return EVENT_ALLOWED + end + end + end + end + return EVENT_DISALLOWED +end + +blue_slayer = KILL_KILL_KILL:new({ team = Team.kBlue }) +red_slayer = KILL_KILL_KILL:new({ team = Team.kRed }) +sec_blue_slayer = lasers_KILL_KILL_KILL:new({ team = Team.kBlue }) +sec_red_slayer = lasers_KILL_KILL_KILL:new({ team = Team.kRed }) + +------------------------- +-- flaginfo +------------------------- +function flaginfo( player_entity ) + local player = CastToPlayer( player_entity ) + + flaginfo_base(player_entity) --basic CTF HUD items + + RemoveHudItem( player, "red-sec-down" ) + RemoveHudItem( player, "blue-sec-down" ) + RemoveHudItem( player, "red-sec-up" ) + RemoveHudItem( player, "blue-sec-up" ) + + if bluesecstatus == 1 then + AddHudIcon( player, "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + else + AddHudIcon( player, "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + + if redsecstatus == 1 then + AddHudIcon( player, "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + else + AddHudIcon( player, "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end +end + +----------------------------------------------------------------------------- +-- custom openfire pack +----------------------------------------------------------------------------- +aardvarkpack = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 400, + nails = 400, + shells = 400, + rockets = 400, + cells = 130, + respawntime = 8, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +function aardvarkpack:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- backpack entity setup (modified for aardvarkpack) +----------------------------------------------------------------------------- +function build_backpacks(tf) + return healthkit:new({touchflags = tf}), + armorkit:new({touchflags = tf}), + ammobackpack:new({touchflags = tf}), + bigpack:new({touchflags = tf}), + grenadebackpack:new({touchflags = tf}), + aardvarkpack:new({touchflags = tf}) +end + +blue_healthkit, blue_armorkit, blue_ammobackpack, blue_bigpack, blue_grenadebackpack, blue_aardvarkpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kBlue}) +red_healthkit, red_armorkit, red_ammobackpack, red_bigpack ,red_grenadebackpack, red_aardvarkpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kRed}) +yellow_healthkit, yellow_armorkit, yellow_ammobackpack, yellow_bigpack, yellow_grenadebackpack, yellow_aardvarkpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kYellow}) +green_healthkit, green_armorkit, green_ammobackpack, green_bigpack, green_grenadebackpack, green_aardvarkpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kGreen}) + +----------------------------------------------------------------------------- +-- SPAWNS +----------------------------------------------------------------------------- +red_o_only = function(self,player) return ((player:GetTeamId() == Team.kRed) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kSniper))) end +red_d_only = function(self,player) return ((player:GetTeamId() == Team.kRed) and (((player:GetClass() == Player.kScout) == false) and ((player:GetClass() == Player.kMedic) == false) and ((player:GetClass() == Player.kSpy) == false) and ((player:GetClass() == Player.kSniper) == false))) end + +redspawn_balc = { validspawn = red_o_only } +redspawn_fr = { validspawn = red_d_only } + +blue_o_only = function(self,player) return ((player:GetTeamId() == Team.kBlue) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kSniper))) end +blue_d_only = function(self,player) return ((player:GetTeamId() == Team.kBlue) and (((player:GetClass() == Player.kScout) == false) and ((player:GetClass() == Player.kMedic) == false) and ((player:GetClass() == Player.kSpy) == false) and ((player:GetClass() == Player.kSniper) == false))) end + +bluespawn_balc = { validspawn = blue_o_only } +bluespawn_fr = { validspawn = blue_d_only } diff --git a/maps/ff_palermo.lua b/maps/ff_palermo.lua new file mode 100644 index 0000000..7be1338 --- /dev/null +++ b/maps/ff_palermo.lua @@ -0,0 +1,189 @@ + +-- ff_palermo.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- + +IncludeScript("base_id_new"); +IncludeScript("base_respawnturret"); +IncludeScript("base_location"); + +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- + +function startup() + id_startup() + + -- lower trigger_hurt damage in water + OutputEvent( "trigger_hurt", "SetDamage", "42" ) +end + +palammopack = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 100, + rockets = 15, + cells = 70, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) +palgrenadepackone = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + mancannons = 1, + gren1 = 2, + gren2 = 1, + armor = 50, + health = 25, + respawntime = 30, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) +attackers_palgrenadepackone = idbackpack:new({ + team = attackers, + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + mancannons = 1, + gren1 = 2, + gren2 = 1, + armor = 50, + health = 25, + respawntime = 30, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) +palammotypeone = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 75, + armor = 50, + health = 25, + respawntime = 7, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) +attackers_palammotypeone = idbackpack:new({ + team = attackers, + grenades = 20, + nails = 50, + shells = 50, + rockets = 20, + cells = 75, + armor = 50, + health = 25, + respawntime = 7, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch" +}) + +--This is called from base_id to do map-specific stuff +function onroundreset() + -- close the holes + OutputEvent("cp1_detpack_hole", "Enable") + OutputEvent("cp4_detpack_hole", "Enable") + --re-enable detpack relays + OutputEvent("cp1_detpack_relay", "Enable") + OutputEvent("cp4_detpack_relay", "Enable") + -- Reset The Turrets(?) and Bags + respawnturret_attackers = base_respawnturret:new({ team = attackers }) + respawnturret_defenders = base_respawnturret:new({ team = defenders }) + + attackers_palammotypeone.team = attackers + attackers_palgrenadepackone.team = attackers + + +end + +bellbutton = func_button:new({}) +function bellbutton:ondamage() return true end + +--------------------------- +--Detpack shit +--------------------------- + +detpack_trigger = trigger_ff_script:new({ prefix = "" }) + +function detpack_trigger:onexplode( trigger_entity ) + if IsDetpack( trigger_entity ) then + local detpack = CastToDetpack( trigger_entity ) + if detpack:GetTeamId() == attackers then + --This triggers a logic_relay in the map, which opens the hole and can trigger any other effect. + OutputEvent( self.prefix .. "_detpack_relay", "Trigger" ) + end + end + return EVENT_ALLOWED +end + +--The detpack trigger names. Only attakers can activate them. +--Prefix is used so each detpack area can have a different effect. +cp1_detpack_trigger = detpack_trigger:new({ prefix = "cp1" }) +cp4_detpack_trigger = detpack_trigger:new({ prefix = "cp4" }) + +--------------------------------------------------- +--Respawn the player if they go too far out to sea. +--------------------------------------------------- +out_of_bounds = trigger_ff_script:new({}) + +function out_of_bounds:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return EVENT_ALLOWED + end + return EVENT_DISALLOWED +end + +function out_of_bounds:ontrigger( triggering_entity ) + if IsPlayer( triggering_entity ) then + local player = CastToPlayer( triggering_entity ) + ApplyToPlayer( player, { AT.kRespawnPlayers } ) + end +end + +cp1_detpack_trigger_hint = trigger_ff_script:new({}) + +function cp1_detpack_trigger_hint:ontrigger( triggering_entity ) + if IsPlayer( triggering_entity ) then + local player = CastToPlayer( triggering_entity ) + DisplayMessage( player, "A demoman on the attacking team can open this passage by laying a detpack here." ) + end +end + +cp4_detpack_trigger_hint = cp1_detpack_trigger_hint +------------------------------------------ +--return the flag if it goes in the water. +------------------------------------------ +--hijacking this base_id function to add in the last line +function setup_return_timer() + RemoveSchedule( "timer_tobase_schedule" ) + current_timer = FLAG_RETURN_TIME + + AddScheduleRepeatingNotInfinitely( "timer_return_schedule", 1, timer_schedule, current_timer) + + --five seconds should be enough time to check. + AddSchedule( "water_check", 5, check_flag_position) +end + + +function check_flag_position() + local flag = GetInfoScriptByName(current_flag) + local o = flag:GetOrigin() + + -- -256 is Palermo's sea level + if o.z < -256 then + flag:Return() + BroadCastMessage("The flag was lost at sea and has returned.") + end +end \ No newline at end of file diff --git a/maps/ff_palermo.txt b/maps/ff_palermo.txt new file mode 100644 index 0000000..a91a943 --- /dev/null +++ b/maps/ff_palermo.txt @@ -0,0 +1,21 @@ +INVADE AND DEFEND + +Objective: + +Blue team starts as the attacker. Red team +starts as the defender. + +The attacking team must take control of the +town by pushing through and capping the four +Command Points sequentially. The defending +team simply tries to hold out as long as they +can. Once the attackers succeed, teams swap, +and play begins again. + +Command Points are captured by taking the flag +from the previous point and carrying it to the +next. When a Command Point is secured, the flag +required to capture the next Command Point +appears on top of it. For example, the flag +needed to capture Command Point 3 will always +spawn at Command Point 2. \ No newline at end of file diff --git a/maps/ff_push.lua b/maps/ff_push.lua new file mode 100644 index 0000000..f564e83 --- /dev/null +++ b/maps/ff_push.lua @@ -0,0 +1,48 @@ +-- ff_push.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_push"); + +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- + +local orig_startup = startup + +function startup() + -- set up team names. Localisation? + SetTeamName( Team.kBlue, "Ball Locks" ) + SetTeamName( Team.kRed, "Rocket Expediting" ) + + orig_startup() +end + +----------------------------------------------------------------------------- +-- triggers for doors +----------------------------------------------------------------------------- +red_respawn_triggerA = respawndoor:new({ team = Team.kRed }) +red_respawn_triggerB = respawndoor:new({ team = Team.kRed }) + +blue_respawn_triggerA = respawndoor:new({ team = Team.kBlue }) +blue_respawn_triggerB = respawndoor:new({ team = Team.kBlue }) + + +----------------------------------------------------------------------------- +-- unique push locations +----------------------------------------------------------------------------- +location_blue_corridor = location_info:new({ text = "Corridor", team = Team.kBlue }) +location_red_corridor = location_info:new({ text = "Corridor", team = Team.kRed }) + +location_blue_lasers = location_info:new({ text = "Lasers", team = Team.kBlue }) +location_red_lasers = location_info:new({ text = "Lasers", team = Team.kRed }) + +location_blue_side_warehouse = location_info:new({ text = "Side Warehouse", team = Team.kBlue }) +location_red_side_warehouse = location_info:new({ text = "Side Warehouse", team = Team.kRed }) + +location_blue_loading_bay = location_info:new({ text = "Loading Bay", team = Team.kBlue }) +location_red_loading_bay = location_info:new({ text = "Loading Bay", team = Team.kRed }) + +location_middle_warehouse = location_info:new({ text = "Middle Warehouse", team = Team.kUnassigned }) + diff --git a/maps/ff_push.txt b/maps/ff_push.txt new file mode 100644 index 0000000..f2975b4 --- /dev/null +++ b/maps/ff_push.txt @@ -0,0 +1,4 @@ +PUSH SCORING + +Objective: Grab the ball from the centre warehouse and then run it to the enemy company's loading zone! Capture it on the raised platform. +The team with the most captures at the end of the game wins! \ No newline at end of file diff --git a/maps/ff_push_soundscapes.txt b/maps/ff_push_soundscapes.txt new file mode 100644 index 0000000..a9a6660 --- /dev/null +++ b/maps/ff_push_soundscapes.txt @@ -0,0 +1,211 @@ +// Push soundscape file +// Author: Defrag +// Some sections based on existing valve soundscapes but modified + +// generic outside sound +"ff.outside" +{ + // constant wind base + "playlooping" + { + "volume" "0.2" + "pitch" "100" + "wave" "ambient/wind/ff_wasteland_wind.wav" + } + + // Wind gusts (based on cliffe's cs_assault settings) + "playrandom" + { + "time" "20,30" + "volume" "0.3,0.4" + "pitch" "90,110" + + "rndwave" + { + "wave" "ambient/wind/wind_snippet1.wav" + "wave" "ambient/wind/wind_snippet2.wav" + "wave" "ambient/wind/wind_snippet3.wav" + "wave" "ambient/wind/wind_snippet4.wav" + "wave" "ambient/wind/wind_snippet5.wav" + } + } +} + // Rats. Ach, gash! +"push.rats" +{ + "playrandom" + { + "time" "20,30" + "volume" "0.3,0.5" + "pitch" "90,100" + "position" "random" + "soundlevel" "SNDLVL_140db" + + "rndwave" + { + "wave" "ambient/creatures/rats1.wav" + "wave" "ambient/creatures/rats2.wav" + "wave" "ambient/creatures/rats3.wav" + "wave" "ambient/creatures/rats4.wav" + } + } +} + + // workshop noises +"push.workshop" +{ + "playrandom" + { + "time" "30,60" + "volume" "0.1,0.2" + "pitch" "90,110" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/push/airhose.wav" + "wave" "ambient/push/airwrench1.wav" + "wave" "ambient/push/airwrench2.wav" + } + } +} +// outside area between the central warehouse and the base corridor +"push.outside" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playsoundscape" + { + "name" "ff.outside" + "volume" "1.0" + } +} + +// capture point area +"push.capturepoint" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playsoundscape" + { + "name" "ff.outside" + "volume" "1.0" + } + + // train going past + "playrandom" + { + "time" "120,180" + "volume" "0.3" + "pitch" "100" + + "rndwave" + { + "wave" "ambient/machines/train_rumble.wav" + } + } +} + + +// side warehouse with no roof +"push.sidewarehouse" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playsoundscape" + { + "name" "ff.outside" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "push.rats" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "push.workshop" + "volume" "1.0" + } +} + +// respawn +"push.respawn" +{ + "dsp" "1" + "dsp_volume" "0.5" + + // General ambient noise + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/push/inside_amb1.wav" + } + + "playrandom" + { + "time" "30,60" + "volume" "0.3,0.5" + "pitch" "90,100" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/materials/metal4.wav" + "wave" "ambient/materials/rustypipes1.wav" + "wave" "ambient/materials/rustypipes2.wav" + } + } +} + +// main warehouse in centre +"push.centralwarehouse" +{ + "dsp" "1" + "dsp_volume" "0.5" + + // General ambient noise + "playlooping" + { + "volume" "0.5" + "pitch" "100" + "wave" "ambient/push/inside_amb1.wav" + } + + "playsoundscape" + { + "name" "push.workshop" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "ff.outside" + "volume" "0.6" + } +} + +// doughnut shaped hallway that connects the respawn, cap point, side warehouse etc. +"push.doughnut" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playsoundscape" + { + "name" "push.respawn" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "ff.outside" + "volume" "0.6" + } +} \ No newline at end of file diff --git a/maps/ff_schtop.lua b/maps/ff_schtop.lua new file mode 100644 index 0000000..9447cbf --- /dev/null +++ b/maps/ff_schtop.lua @@ -0,0 +1,250 @@ +----------------------------------------------------------------------------------------------------------------------------- +-- INCLUDES +----------------------------------------------------------------------------------------------------------------------------- + +IncludeScript("base_shutdown"); +IncludeScript("base_location"); + +----------------------------------------------------------------------------------------------------------------------------- +-- CONSTANT! +-- I don't recommend changing this, as the in-game timer (above the FR door) will not change along with it. +-- Behaviour is undefined for values <= 10 +----------------------------------------------------------------------------------------------------------------------------- + +SECURITY_LENGTH = 40 + +----------------------------------------------------------------------------------------------------------------------------- +-- LOCATIONS +----------------------------------------------------------------------------------------------------------------------------- + +location_blue_flagroom = location_info:new({ text = "Flag Room", team = Team.kBlue }) +location_blue_window = location_info:new({ text = "Security Window", team = Team.kBlue }) +location_blue_security = location_info:new({ text = "Security Area", team = Team.kBlue }) +location_blue_courtyard = location_info:new({ text = "Main Courtyard", team = Team.kBlue }) +location_blue_rampside = location_info:new({ text = "Ramp Side", team = Team.kBlue }) +location_blue_secside = location_info:new({ text = "Security Side", team = Team.kBlue }) +location_blue_frontdoor = location_info:new({ text = "Front Door", team = Team.kBlue }) +location_blue_water = location_info:new({ text = "Water Area", team = Team.kBlue }) +location_blue_spawn = location_info:new({ text = "Team Respawn", team = Team.kBlue }) + +location_red_flagroom = location_info:new({ text = "Flag Room", team = Team.kRed }) +location_red_window = location_info:new({ text = "Security Window", team = Team.kRed }) +location_red_security = location_info:new({ text = "Security Area", team = Team.kRed }) +location_red_courtyard = location_info:new({ text = "Main Courtyard", team = Team.kRed }) +location_red_rampside = location_info:new({ text = "Ramp Side", team = Team.kRed }) +location_red_secside = location_info:new({ text = "Security Side", team = Team.kRed }) +location_red_frontdoor = location_info:new({ text = "Front Door", team = Team.kRed }) +location_red_water = location_info:new({ text = "Water Area", team = Team.kRed }) +location_red_spawn = location_info:new({ text = "Team Respawn", team = Team.kRed }) + +location_yard = location_info:new({ text = "Yard", team = Team.kUnassigned }) + + +----------------------------------------------------------------------------- +-- TOUCH RESUP +-- Brush volume which gives players health, ammo, etc... +-- Pretty much taken from ff_.lua +----------------------------------------------------------------------------- + +touch_resup = trigger_ff_script:new({ team = Team.kUnassigned }) + +function touch_resup:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == self.team then + player:AddHealth( 400 ) + player:AddArmor( 400 ) + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + end + end +end + +blue_touch_resup = touch_resup:new({ team = Team.kBlue }) +red_touch_resup = touch_resup:new({ team = Team.kRed }) + +----------------------------------------------------------------------------------------------------------------------------- +-- WINDOWPACK +-- Team-specific packs which are located near the window where players can throw the flag out. +----------------------------------------------------------------------------------------------------------------------------- + +windowpack = genericbackpack:new({ + health = 50, + armor = 50, + + grenades = 200, + nails = 200, + shells = 200, + rockets = 200, + cells = 130, + + gren1 = 0, + gren2 = 0, + + respawntime = 8, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) +function windowpack:dropatspawn() return false end + +blue_windowpack = windowpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue } }) +red_windowpack = windowpack:new({ touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kRed } }) + +----------------------------------------------------------------------------- +-- SPAWN PROTECTION +-- kills those who wander into the enemy spawn +----------------------------------------------------------------------------- + +spawn_protection = trigger_ff_script:new({ team = Team.kUnassigned }) + +function spawn_protection:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +red_spawn_protection = spawn_protection:new({ team = Team.kBlue }) +blue_spawn_protection = spawn_protection:new({ team = Team.kRed }) + +----------------------------------------------------------------------------- +-- OFFENSIVE AND DEFENSIVE SPAWNS +-- Medic, Spy, and Scout spawn in the offensive spawns, other classes spawn in the defensive spawn, +-- Copied from ff_session.lua +----------------------------------------------------------------------------- + +red_o_only = function(self,player) return ((player:GetTeamId() == Team.kRed) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kEngineer))) end +red_d_only = function(self,player) return ((player:GetTeamId() == Team.kRed) and (((player:GetClass() == Player.kScout) == false) and ((player:GetClass() == Player.kMedic) == false) and ((player:GetClass() == Player.kSpy) == false) and ((player:GetClass() == Player.kEngineer) == false))) end + +red_ospawn = { validspawn = red_o_only } +red_dspawn = { validspawn = red_d_only } + +blue_o_only = function(self,player) return ((player:GetTeamId() == Team.kBlue) and ((player:GetClass() == Player.kScout) or (player:GetClass() == Player.kMedic) or (player:GetClass() == Player.kSpy) or (player:GetClass() == Player.kEngineer))) end +blue_d_only = function(self,player) return ((player:GetTeamId() == Team.kBlue) and (((player:GetClass() == Player.kScout) == false) and ((player:GetClass() == Player.kMedic) == false) and ((player:GetClass() == Player.kSpy) == false) and ((player:GetClass() == Player.kEngineer) == false))) end + +blue_ospawn = { validspawn = blue_o_only } +blue_dspawn = { validspawn = blue_d_only } + +----------------------------------------------------------------------------- +-- AND THEN, SOME MORE STUFF... +----------------------------------------------------------------------------- + +red_sec = trigger_ff_script:new() +blue_sec = trigger_ff_script:new() +bluesecstatus = 1 +redsecstatus = 1 + +sec_iconx = 60 +sec_icony = 30 +sec_iconw = 16 +sec_iconh = 16 + +function red_sec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kBlue then + if redsecstatus == 1 then + redsecstatus = 0 + AddSchedule("secup10red", SECURITY_LENGTH - 10, secup10red) + AddSchedule("beginclosered", SECURITY_LENGTH - 6, beginclosered) + AddSchedule("secupred",SECURITY_LENGTH,secupred) + OpenDoor("red_secdoor") + BroadCastMessage("#FF_RED_SEC_40") + SpeakAll( "SD_REDDOWN" ) + RemoveHudItemFromAll( "red-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end + end + end +end + +function blue_sec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kRed then + if bluesecstatus == 1 then + bluesecstatus = 0 + AddSchedule("secup10blue", SECURITY_LENGTH - 10, secup10blue) + AddSchedule("begincloseblue", SECURITY_LENGTH - 6, begincloseblue) + AddSchedule("secupblue",SECURITY_LENGTH,secupblue) + OpenDoor("blue_secdoor") + BroadCastMessage("#FF_BLUE_SEC_40") + SpeakAll( "SD_BLUEDOWN" ) + RemoveHudItemFromAll( "blue-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + end + end +end + +function secupred() + redsecstatus = 1 + BroadCastMessage("#FF_RED_SEC_ON") + SpeakAll( "SD_REDUP" ) + RemoveHudItemFromAll( "red-sec-down" ) + AddHudIconToAll( "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) +end + +function begincloseblue() + CloseDoor("blue_secdoor") +end + +function beginclosered() + CloseDoor("red_secdoor") +end + +function secupblue() + bluesecstatus = 1 + BroadCastMessage("#FF_BLUE_SEC_ON") + SpeakAll( "SD_BLUEUP" ) + RemoveHudItemFromAll( "blue-sec-down" ) + AddHudIconToAll( "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) +end + +function secup10red() + BroadCastMessage("#FF_RED_SEC_10") +end + +function secup10blue() + BroadCastMessage("#FF_BLUE_SEC_10") +end + +grp = bigpack:new({ +materializesound="Item.Materialize", +gren1=4,gren2=4,model= +"models/items/backpack/backpack.mdl", +respawntime=1,touchsound="Backpack.Touch"}) +function grp:dropatspawn() return false end + +------------------------- +-- flaginfo +------------------------- +function flaginfo( player_entity ) + local player = CastToPlayer( player_entity ) + + flaginfo_base(player_entity) --basic CTF HUD items + + RemoveHudItem( player, "red-sec-down" ) + RemoveHudItem( player, "blue-sec-down" ) + RemoveHudItem( player, "red-sec-up" ) + RemoveHudItem( player, "blue-sec-up" ) + + if bluesecstatus == 1 then + AddHudIcon( player, "hud_secup_blue.vtf", "blue-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + else + AddHudIcon( player, "hud_secdown.vtf", "blue-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 2 ) + end + + if redsecstatus == 1 then + AddHudIcon( player, "hud_secup_red.vtf", "red-sec-up", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + else + AddHudIcon( player, "hud_secdown.vtf", "red-sec-down", sec_iconx, sec_icony, sec_iconw, sec_iconh, 3 ) + end +end diff --git a/maps/ff_schtop.txt b/maps/ff_schtop.txt new file mode 100644 index 0000000..97ce269 --- /dev/null +++ b/maps/ff_schtop.txt @@ -0,0 +1,7 @@ +ff_schtop + +Shut off the security devices protecting the enemy flag and +steal it from their base. Capture it in your own base. + +Each capture is worth 10 points for your team. +The team with the most points at the end of the round wins. \ No newline at end of file diff --git a/maps/ff_schtop_soundscapes.txt b/maps/ff_schtop_soundscapes.txt new file mode 100644 index 0000000..2941bb6 --- /dev/null +++ b/maps/ff_schtop_soundscapes.txt @@ -0,0 +1,200 @@ +//////////////////////////////////////////////// +// FF_SCHTOP SOUNDSCAPES +// Modified ff_session soundscape file. +// +// GENERIC +// WATER +// YARD +// +//////////////////////////////////////////////// + +//////////////////////////////////////////////// +// STRANGE AMBIENCE +// Utility soundscape for some digital-sounding ambience. +//////////////////////////////////////////////// + +"ff_schtop.strange_ambience" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/levels/citadel/field_loop3.wav" + "volume" "0.25" + "pitch" "100" + } + + "playlooping" + { + "wave" "hl1/ambience/techamb2.wav" + "volume" "0.25" + "pitch" "100" + } + + "playlooping" + { + "wave" "hl1/ambience/alien_blipper.wav" + "volume" "0.25" + "pitch" "100" + } + + "playlooping" + { + "wave" "hl1/ambience/alien_cycletone.wav" + "volume" "0.25" + "pitch" "100" + } + + "playrandom" + { + "volume" "0.25,0.40" + "time" "5.0,15.0" + "pitch" "80,120" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/levels/prison/radio_random3.wav" + "wave" "ambient/levels/prison/radio_random7.wav" + "wave" "ambient/levels/canals/headcrab_canister_ambient3.wav" + "wave" "ambient/levels/citadel/portal_beam_shoot6.wav" + "wave" "ambient/machines/machine1_hit2.wav" + } + } + +} + +//////////////////////////////////////////////// +// GENERIC +// Some digital-sounding ambience and random wierd noises. +// Default soundscape. +//////////////////////////////////////////////// + + +"ff_schtop.generic" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/atmosphere/ff_ambience.wav" + "volume" "0.66" + "pitch" "100" + } + + "playlooping" + { + "wave" "ambient/push/inside_amb1.wav" + "volume" "0.33" + "pitch" "100" + } + + "playsoundscape" + { + "name" "ff_schtop.strange_ambience" + "volume" "0.66" + } + + "playrandom" + { + "volume" "0.15,0.30" + "time" "10.0,20.0" + "pitch" "50,150" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "weapons/physcannon/energy_sing_flyby1.wav" + "wave" "weapons/physcannon/energy_sing_flyby2.wav" + } + } +} + + +//////////////////////////////////////////////// +// YARD +// Outdoor wind ambience with random gusts. +//////////////////////////////////////////////// + + +"ff_schtop.yard" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/wind/ff_wasteland_wind.wav" + "volume" "0.8" + "pitch" "100" + } + + "playsoundscape" + { + "name" "d1_canals.util_windgusts" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "ff_schtop.strange_ambience" + "volume" "0.15" + } + + "playrandom" + { + "volume" "0.15,0.30" + "time" "7.0,14.0" + "pitch" "80,120" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/levels/citadel/strange_talk6.wav" + "wave" "ambient/levels/citadel/strange_talk7.wav" + "wave" "ambient/levels/citadel/strange_talk8.wav" + "wave" "ambient/levels/citadel/strange_talk9.wav" + "wave" "ambient/levels/citadel/strange_talk10.wav" + } + } + +} + + +//////////////////////////////////////////////// +// WATER +// Water running and random dripping ambience. +//////////////////////////////////////////////// + + +"ff_schtop.water" +{ + "dsp" "1" + + "playlooping" + { + "wave" "ambient/atmosphere/ambience5.wav" + "volume" "0.2" + "pitch" "100" + } + + "playlooping" + { + "wave" "ambient/levels/canals/waterleak_loop1.wav" + "volume" "0.3" + "pitch" "100" + } + + "playsoundscape" + { + "name" "d1_canals.util_drip" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "d1_canals.util_fardrips" + "volume" "1.0" + } +} + +//////////////////////////////////////////////// \ No newline at end of file diff --git a/maps/ff_shutdown2.lua b/maps/ff_shutdown2.lua new file mode 100644 index 0000000..7398138 --- /dev/null +++ b/maps/ff_shutdown2.lua @@ -0,0 +1,126 @@ +-- ff_shutdown2.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_shutdown"); + +----------------------------------------------------------------------------- +-- unique shutdown2 locations +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- aardvark security +----------------------------------------------------------------------------- +red_aardvarksec = trigger_ff_script:new() +blue_aardvarksec = trigger_ff_script:new() +bluesecstatus = 1 +redsecstatus = 1 + +function red_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kBlue then + if redsecstatus == 1 then + redsecstatus = 0 + AddSchedule("aardvarksecup10red",50,aardvarksecup10red) + AddSchedule("aardvarksecupred",60,aardvarksecupred) + OpenDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_60") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_REDDOWN" ) + RemoveHudItemFromAll( "red-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "red-sec-down", button_red.iconx, button_red.icony, button_red.iconw, button_red.iconh, 3 ) + end + end + end +end + +function blue_aardvarksec:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kRed then + if bluesecstatus == 1 then + bluesecstatus = 0 + AddSchedule("aardvarksecup10blue",50,aardvarksecup10blue) + AddSchedule("aardvarksecupblue",60,aardvarksecupblue) + OpenDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_60") + --BroadCastSound( "otherteam.flagstolen") + SpeakAll( "SD_BLUEDOWN" ) + RemoveHudItemFromAll( "blue-sec-up" ) + AddHudIconToAll( "hud_secdown.vtf", "blue-sec-down", button_blue.iconx, button_blue.icony, button_blue.iconw, button_blue.iconh, 2 ) + end + end + end +end + +function aardvarksecupred() + redsecstatus = 1 + CloseDoor("red_aardvarkdoorhack") + BroadCastMessage("#FF_RED_SEC_ON") + SpeakAll( "SD_REDUP" ) + RemoveHudItemFromAll( "red-sec-down" ) + AddHudIconToAll( "hud_secup_red.vtf", "red-sec-up", button_red.iconx, button_red.icony, button_red.iconw, button_red.iconh, 3 ) +end + +function aardvarksecupblue() + bluesecstatus = 1 + CloseDoor("blue_aardvarkdoorhack") + BroadCastMessage("#FF_BLUE_SEC_ON") + SpeakAll( "SD_BLUEUP" ) + RemoveHudItemFromAll( "blue-sec-down" ) + AddHudIconToAll( "hud_secup_blue.vtf", "blue-sec-up", button_blue.iconx, button_blue.icony, button_blue.iconw, button_blue.iconh, 2 ) +end + +function aardvarksecup10red() + BroadCastMessage("#FF_RED_SEC_10") +end + +function aardvarksecup10blue() + BroadCastMessage("#FF_BLUE_SEC_10") +end + +------------------------- +-- flaginfo +------------------------- +function flaginfo( player_entity ) + local player = CastToPlayer( player_entity ) + + flaginfo_base(player_entity) --basic CTF HUD items + + RemoveHudItem( player, "red-sec-down" ) + RemoveHudItem( player, "blue-sec-down" ) + RemoveHudItem( player, "red-sec-up" ) + RemoveHudItem( player, "blue-sec-up" ) + + if bluesecstatus == 1 then + AddHudIcon( player, "hud_secup_blue.vtf", "blue-sec-up", button_blue.iconx, button_blue.icony, button_blue.iconw, button_blue.iconh, 2 ) + else + AddHudIcon( player, "hud_secdown.vtf", "blue-sec-down", button_blue.iconx, button_blue.icony, button_blue.iconw, button_blue.iconh, 2 ) + end + + if redsecstatus == 1 then + AddHudIcon( player, "hud_secup_red.vtf", "red-sec-up", button_red.iconx, button_red.icony, button_red.iconw, button_red.iconh, 3 ) + else + AddHudIcon( player, "hud_secdown.vtf", "red-sec-down", button_red.iconx, button_red.icony, button_red.iconw, button_red.iconh, 3 ) + end +end + +----------------------------------------------------------------------------- +-- respawn shields +----------------------------------------------------------------------------- +KILL_KILL_KILL = trigger_ff_script:new({ team = Team.kUnassigned }) + +function KILL_KILL_KILL:allowed( activator ) + local player = CastToPlayer( activator ) + if player then + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +blue_slayer = KILL_KILL_KILL:new({ team = Team.kBlue }) +red_slayer = KILL_KILL_KILL:new({ team = Team.kRed }) diff --git a/maps/ff_shutdown2.txt b/maps/ff_shutdown2.txt new file mode 100644 index 0000000..9f9c4a0 --- /dev/null +++ b/maps/ff_shutdown2.txt @@ -0,0 +1,5 @@ +SHUTDOWN CAPTURE THE FLAG + +Objectives: +# Temporarily de-activate the enemy team's security systems by making your way to the security generator room and touching the switch. +# Once the lasers are de-activated, enter the flag room and steal the enemy flag! Return the enemy flag to your base to capture. The capture point is in the middle of the battlements. \ No newline at end of file diff --git a/maps/ff_shutdown2_level_sounds.txt b/maps/ff_shutdown2_level_sounds.txt new file mode 100644 index 0000000..72b85ac --- /dev/null +++ b/maps/ff_shutdown2_level_sounds.txt @@ -0,0 +1,32 @@ +"shutdown2.generatordown" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "pitch" "PITCH_NORM" + "CompatibilityAttenuation" "0.5" + "wave" "ambient/shutdown/generator_down.wav" +} +"shutdown2.generatorup" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "pitch" "PITCH_NORM" + "CompatibilityAttenuation" "0.5" + "wave" "ambient/shutdown/generator_up.wav" +} +"shutdown2.generatorhumloop1" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "pitch" "PITCH_NORM" + "CompatibilityAttenuation" "0.5" + "wave" "ambient/shutdown/generator_hum_low.wav" +} +"shutdown2.generatorhumloop2" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "pitch" "PITCH_NORM" + "CompatibilityAttenuation" "0.5" + "wave" "ambient/shutdown/generator_hum_high.wav" +} \ No newline at end of file diff --git a/maps/ff_shutdown2_soundscapes.txt b/maps/ff_shutdown2_soundscapes.txt new file mode 100644 index 0000000..be856ad --- /dev/null +++ b/maps/ff_shutdown2_soundscapes.txt @@ -0,0 +1,240 @@ +// Shutdown2 soundscape file +// Author: Defrag +// Some sections based on existing valve soundscapes but modified + +// Flag Room +"shutdown2.flagroom" +{ + "dsp" "1" + "dsp_volume" "0.6" + + // General ambient noise + "playlooping" + { + "volume" "0.1" + "pitch" "100" + "wave" "ambient/atmosphere/ff_ambience.wav" + } + + "playrandom" + { + "time" "30,60" + "volume" "0.3,0.5" + "pitch" "90,100" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/materials/metal4.wav" + "wave" "ambient/materials/rustypipes1.wav" + "wave" "ambient/materials/rustypipes2.wav" + } + } + +} + +// Front door +"shutdown2.frontdoor" +{ + "dsp" "1" + "dsp_volume" "0.5" + "playsoundscape" + { + "name" "shutdown2.ramproom" + "volume" "0.7" + } + "playsoundscape" + { + "name" "shutdown2.yard" + "volume" "0.3" + } +} + +// Lift / Elevator +"shutdown2.lift" +{ + "dsp" "1" + "dsp_volume" "0.4" + + "playsoundscape" + { + "name" "shutdown2.topramp" + "volume" "0.5" + } + "playsoundscape" + { + "name" "shutdown2.flagroom" + "volume" "0.5" + } +} + +// Plank +"shutdown2.plank" +{ + "dsp" "1" + "dsp_volume" "0.4" + + "playsoundscape" + { + "name" "shutdown2.ramproom" + "volume" "0.2" + } + + "playsoundscape" + { + "name" "shutdown2.flagroom" + "volume" "0.6" + } + + "playrandom" + { + "time" "20,30" + "volume" "0.5, 0.8" + "pitch" "100" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/materials/rock1.wav" + "wave" "ambient/materials/rock2.wav" + "wave" "ambient/materials/rock3.wav" + "wave" "ambient/materials/rock4.wav" + "wave" "ambient/materials/rock5.wav" + } + } +} + +// Ramp Room +"shutdown2.ramproom" +{ + "dsp" "1" + "dsp_volume" "0.6" + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/atmosphere/tone_alley.wav" + } +} + +// Respawn Lower +"shutdown2.respawnlower" +{ + "dsp" "1" + "dsp_volume" "0.4" + "playsoundscape" + { + "name" "shutdown2.ramproom" + "volume" "0.6" + } +} +// Respawn Upper +"shutdown2.respawnupper" +{ + "dsp" "1" + "dsp_volume" "0.4" + + "playsoundscape" + { + "name" "shutdown2.topramp" + "volume" "0.6" + } +} + +// Switch Room +"shutdown2.switchroom" +{ + "playsoundscape" + { + "name" "shutdown2.topramp" + "volume" "1.0" + } + +} + +// Top Ramp +"shutdown2.topramp" +{ + "dsp" "1" + "dsp_volume" "0.4" + + "playsoundscape" + { + "name" "shutdown2.ramproom" + "volume" "0.2" + } + + "playsoundscape" + { + "name" "shutdown2.flagroom" + "volume" "0.6" + } +} + +// Train Tunnel +"shutdown2.traintunnel" +{ + "dsp" "1" + "dsp_volume" "0.8" + + + "playsoundscape" + { + "name" "shutdown2.ramproom" + "volume" "0.2" + } + + "playlooping" + { + "volume" "0.05" + "pitch" "100" + "wave" "ambient/atmosphere/undercity_loop1.wav" + } + + "playlooping" + { + "volume" "0.1" + "pitch" "100" + "wave" "ambient/atmosphere/ff_ambience.wav" + } + + "playlooping" + { + "volume" "0.5" + "pitch" "100" + "wave" "ambient/water/drip_loop1.wav" + } + +} + +// Yard between two bases +"shutdown2.yard" +{ + "dsp" "1" + "dsp_volume" "0.4" + + // constant wind base + "playlooping" + { + "volume" "0.2" + "pitch" "100" + "wave" "ambient/wind/ff_wasteland_wind.wav" + } + + // Wind gusts (based on cliffe's cs_assault settings) + "playrandom" + { + "time" "20,30" + "volume" "0.3,0.4" + "pitch" "90,110" + + "rndwave" + { + "wave" "ambient/wind/wind_snippet1.wav" + "wave" "ambient/wind/wind_snippet2.wav" + "wave" "ambient/wind/wind_snippet3.wav" + "wave" "ambient/wind/wind_snippet4.wav" + "wave" "ambient/wind/wind_snippet5.wav" + } + } +} diff --git a/maps/ff_training.lua b/maps/ff_training.lua new file mode 100644 index 0000000..0e2d03b --- /dev/null +++ b/maps/ff_training.lua @@ -0,0 +1,1934 @@ +--------------------------------------------- +-- FF_Training +--------------------------------------------- + +IncludeScript("base_ctf") + +JUMP_TECHNIQUES = 1 +MOVEMENT = 2 +ALL_TOGETHER = 3 + +-- stage types +VERTICAL_JUMP = 1 +HORIZONTAL_JUMP = 2 +MISC_JUMP = 3 +MOVEMENT_STAGE = 4 +MOVEMENT_STAGE_START = 5 +MOVEMENT_STAGE_OTHER = 6 +ALL_TOGETHER_STAGE = 7 + +TIME_FOR_GOLD = 15 +TIME_FOR_SILVER = 20 +TIME_FOR_BRONZE = 25 + +stage_info = { + + [JUMP_TECHNIQUES] = { + technique_name = "Jump Techniques", + stages = { + [1] = { + stage_type = VERTICAL_JUMP, + stage_name = "Drop Concussion Jump", + stage_specific = "Vertical", + stage_checklist = "Vertical Drop Conc Jump", + stage_code = "v_conc", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Prime concussion gren:", + stage_key = "%+gren2% or %toggletwo%", + stage_limits = { + force_hhconc = false, + force_dropconc = true, + force_waterconc = true, + force_1pipe = false, + force_2pipe = false + } + }, + [2] = { + stage_type = HORIZONTAL_JUMP, + stage_name = "Drop Concussion Jump", + stage_specific = "Application", + stage_checklist = "Drop Conc Jump Application", + stage_code = "a_conc", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Prime concussion gren:", + stage_key = "%+gren2% or %toggletwo%", + stage_limits = { + force_hhconc = false, + force_dropconc = true, + force_waterconc = false, + force_1pipe = false, + force_2pipe = false + } + }, + [3] = { + stage_type = MISC_JUMP, + stage_name = "Concussion Jump", + stage_specific = "Water", + stage_checklist = "Water Conc Jump", + stage_code = "m_waterconc", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Prime concussion gren:", + stage_key = "%+gren2% or %toggletwo%", + stage_limits = { + force_hhconc = false, + force_dropconc = false, + force_waterconc = true, + force_1pipe = false, + force_2pipe = false + } + }, + [4] = { + stage_type = VERTICAL_JUMP, + stage_name = "Hand-Held Concussion Jump", + stage_specific = "Vertical", + stage_checklist = "Vertical HH Conc Jump", + stage_code = "v_hhconc", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Prime concussion gren:", + stage_key = "%+gren2% or %toggletwo%", + stage_limits = { + force_hhconc = true, + force_dropconc = false, + force_waterconc = false, + force_1pipe = false, + force_2pipe = false + } + }, + [5] = { + stage_type = HORIZONTAL_JUMP, + stage_name = "Hand-Held Concussion Jump", + stage_specific = "Application", + stage_checklist = "HH Conc Jump Application", + stage_code = "a_hhconc", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Prime concussion gren:", + stage_key = "%+gren2% or %toggletwo%", + stage_limits = { + force_hhconc = true, + force_dropconc = false, + force_waterconc = false, + force_1pipe = false, + force_2pipe = false + } + }, + [6] = { + stage_type = VERTICAL_JUMP, + stage_name = "Rocket Jump", + stage_specific = "Vertical", + stage_checklist = "Vertical Rocket Jump", + stage_code = "v_rj", + stage_complete = false, + stage_class = Player.kSoldier, + stage_key_text = "Shoot rocket:", + stage_key = "%+attack%", + stage_limits = { + force_hhconc = false, + force_dropconc = false, + force_waterconc = false, + force_1pipe = false, + force_2pipe = false + } + }, + [7] = { + stage_type = HORIZONTAL_JUMP, + stage_name = "Rocket Jump", + stage_specific = "Application", + stage_checklist = "Rocket Jump Application", + stage_code = "a_rj", + stage_complete = false, + stage_class = Player.kSoldier, + stage_key_text = "Shoot rocket:", + stage_key = "%+attack%", + stage_limits = { + force_hhconc = false, + force_dropconc = false, + force_waterconc = false, + force_1pipe = false, + force_2pipe = false + } + }, + [8] = { + stage_type = VERTICAL_JUMP, + stage_name = "Pipe Jump", + stage_specific = "Vertical", + stage_checklist = "Vertical Pipe Jump", + stage_code = "v_pipe", + stage_complete = false, + stage_class = Player.kDemoman, + stage_key_text = "Det pipes:", + stage_key = "%+attack2%", + stage_limits = { + force_hhconc = false, + force_dropconc = false, + force_waterconc = false, + force_1pipe = false, + force_2pipe = true + } + }, + [9] = { + stage_type = HORIZONTAL_JUMP, + stage_name = "Pipe Jump", + stage_specific = "Application", + stage_checklist = "Pipe Jump Application", + stage_code = "a_pipe", + stage_complete = false, + stage_class = Player.kDemoman, + stage_key_text = "Det pipes:", + stage_key = "%+attack2%", + stage_limits = { + force_hhconc = false, + force_dropconc = false, + force_waterconc = false, + force_1pipe = true, + force_2pipe = false + } + }, + [10] = { + stage_type = HORIZONTAL_JUMP, + stage_name = "Flamethrower", + stage_specific = "Application", + stage_checklist = "Flamethrower", + stage_code = "a_ft", + stage_complete = false, + stage_class = Player.kPyro, + stage_key_text = "Shoot flamethrower:", + stage_key = "%+attack%", + stage_limits = { + force_hhconc = false, + force_dropconc = false, + force_waterconc = false, + force_1pipe = false, + force_2pipe = false + } + } + } + }, + + [MOVEMENT] = { + technique_name = "Movement Techniques", + stages = { + [1] = { + stage_type = MOVEMENT_STAGE, + stage_name = "Double Jump", + stage_specific = "Basics", + stage_checklist = "Double Jump", + stage_code = "move_doublejump", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Jump:", + stage_key = "%+jump%" + }, + [2] = { + stage_type = MOVEMENT_STAGE_START, + stage_name = "Air Control", + stage_specific = "Basics", + stage_checklist = "Air Control Basics", + stage_code = "move_aircontrol", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Strafe: %+moveleft% and %+moveright%", + stage_key = "Reset stage: %+use%" + }, + [3] = { + stage_type = MOVEMENT_STAGE, + stage_name = "Air Control", + stage_specific = "Jump", + stage_checklist = "Air Control Jump", + stage_code = "move_aircontrolpush", + stage_complete = false, + stage_class = Player.kScout, + stage_key = "" + }, + [4] = { + stage_type = MOVEMENT_STAGE_START, + stage_name = "Air Control", + stage_specific = "Gaining Speed", + stage_checklist = "Gaining Speed with Strafe", + stage_code = "move_aircontrolspeed", + stage_complete = false, + stage_class = Player.kScout, + stage_key = "" + }, + [5] = { + stage_type = MOVEMENT_STAGE_START, + stage_name = "Air Control", + stage_specific = "Bunnyhop Primer", + stage_checklist = "Bunnyhop Air Control", + stage_code = "move_aircontrolbhop", + stage_complete = false, + stage_class = Player.kScout, + stage_key = "" + }, + [6] = { + stage_type = MOVEMENT_STAGE_MULTIPLE, + stage_name = "Bunnyhop", + stage_specific = "Stepping Stones", + stage_checklist = "Bunnyhop", + stage_num_steps = 3, + stage_code = "move_bhop", + stage_complete = false, + stage_class = Player.kScout, + stage_key = "" + }, + [7] = { + stage_type = MOVEMENT_STAGE_START, + stage_name = "Rampslide", + stage_specific = "", + stage_checklist = "Rampslide", + stage_code = "move_rampslide", + stage_complete = false, + stage_class = Player.kScout, + stage_key = "" + }, + [8] = { + stage_type = MOVEMENT_STAGE_START, + stage_name = "Trimp", + stage_specific = "", + stage_checklist = "Trimp", + stage_code = "move_trimp", + stage_complete = false, + stage_class = Player.kScout, + stage_key_text = "Jump:", + stage_key = "%+jump%" + } + } + }, + + [ALL_TOGETHER] = { + technique_name = "Putting it All Together", + stages = { + [1] = { + stage_type = ALL_TOGETHER_STAGE, + stage_name = "Scout", + stage_specific = "Speed Run", + stage_checklist = "Scout Speed Run", + stage_code = "all_scout", + stage_complete = false, + stage_medal = 0, + stage_class = Player.kScout, + stage_key_text = "Reset:", + stage_key = "%+use%" + } + } + } +} + + +VERTICAL_JUMP_TOUCHED = 0 +VERTICAL_JUMP_BROADCASTED = 0 +VERTICAL_JUMP_MESSAGE = "What?" + +NUM_JUMP_QUEUES_NEEDED = 10 + +GIVE_GREN2 = false +GIVE_PIPES = false +GIVE_RPG = false + +TIMEOUT_REPLAY_TIME = 45 + +current_technique = JUMP_TECHNIQUES +current_stage = 1 +failed_attempts = 0 +best_run = nil +show_timer = false + + +-- startup +function startup() + SetGameDescription( "Training" ) + + SetTeamName( Team.kBlue, "Trainee" ) + + SetPlayerLimit( Team.kBlue, 1 ) + SetPlayerLimit( Team.kRed, -1 ) + SetPlayerLimit( Team.kYellow, -1 ) + SetPlayerLimit( Team.kGreen, -1 ) + + team = GetTeam( Team.kBlue ) + team:SetClassLimit( Player.kCivilian, 0 ) + + setup() + +end + +function setup() + + for i,v in ipairs(stage_info) do + for i2,v2 in ipairs(v.stages) do + _G[v2.stage_code.."_tele"] = base_tele:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_replay_btn"] = base_replay_btn:new({ technique_id = i, stage_number = i2 }) + if v2.stage_type == VERTICAL_JUMP then + _G[v2.stage_code] = v_jump:new({ technique_id = i, stage_number = i2 }) + elseif v2.stage_type == HORIZONTAL_JUMP then + _G[v2.stage_code] = a_jump:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_finish"] = a_finish:new({ technique_id = i, stage_number = i2 }) + elseif v2.stage_type == MISC_JUMP then + _G[v2.stage_code.."_start"] = m_jump_start:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code] = m_jump:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_finish"] = a_finish:new({ technique_id = i, stage_number = i2 }) + elseif v2.stage_type == MOVEMENT_STAGE then + _G[v2.stage_code] = move_room:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_init"] = move_init:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_finish"] = a_finish:new({ technique_id = i, stage_number = i2 }) + elseif v2.stage_type == MOVEMENT_STAGE_START then + _G[v2.stage_code] = move_area:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_start"] = move_start:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_init"] = move_init:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_finish"] = a_finish:new({ technique_id = i, stage_number = i2 }) + elseif v2.stage_type == MOVEMENT_STAGE_MULTIPLE then + for i3=1,v2.stage_num_steps do + _G[v2.stage_code..""..i3.."_replay_btn"] = base_replay_btn:new({ technique_id = i, stage_number = i2, step = i3 }) + _G[v2.stage_code..""..i3.."_tele"] = base_tele:new({ technique_id = i, stage_number = i2, step = i3 }) + _G[v2.stage_code..""..i3] = move_bhop_area:new({ technique_id = i, stage_number = i2, step = i3 }) + _G[v2.stage_code..""..i3.."_start"] = move_bhop_start:new({ technique_id = i, stage_number = i2, step = i3 }) + _G[v2.stage_code..""..i3.."_init"] = move_bhop_init:new({ technique_id = i, stage_number = i2, step = i3 }) + _G[v2.stage_code..""..i3.."_finish"] = move_bhop_finish:new({ technique_id = i, stage_number = i2, step = i3 }) + end + elseif v2.stage_type == ALL_TOGETHER_STAGE then + _G[v2.stage_code] = all_together_room:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_init"] = all_together_init:new({ technique_id = i, stage_number = i2 }) + _G[v2.stage_code.."_start"] = all_together_start:new({ technique_id = i, stage_number = i2 }) + else + --ChatToAll( "[SCRIPT] ERROR: no stage type defined for "..v2.stage_checklist ) + end + end + end + +end + +-- precache sounds +function precache() + for i,v in ipairs(stage_info) do + for i2,v2 in ipairs(v.stages) do + PrecacheSound("training."..v2.stage_code.."_start") + PrecacheSound("training."..v2.stage_code.."01") + PrecacheSound("training."..v2.stage_code.."02") + PrecacheSound("training."..v2.stage_code.."03") + PrecacheSound("training."..v2.stage_code.."04") + PrecacheSound("training."..v2.stage_code.."_timeout") + if v2.stage_num_steps ~= nil then + for i3=1,v2.stage_num_steps do + PrecacheSound("training."..v2.stage_code..i3.."_start") + end + end + if v2.stage_medal ~= nil then + PrecacheSound("training."..v2.stage_code.."_bronze") + PrecacheSound("training."..v2.stage_code.."_silver") + PrecacheSound("training."..v2.stage_code.."_gold") + end + end + end + + PrecacheSound("training.stage_complete") + PrecacheSound("training.all_complete") + PrecacheSound("training.intro") + + PrecacheSound("misc.bizwarn") + PrecacheSound("misc.bloop") + PrecacheSound("misc.buzwarn") + PrecacheSound("misc.dadeda") + PrecacheSound("misc.deeoo") + PrecacheSound("misc.doop") + PrecacheSound("misc.woop") + PrecacheSound("otherteam.flagstolen") +end + +function set_ammo( player_entity, ammo_type, amount ) + if IsPlayer( player_entity ) then + local player = CastToPlayer( player_entity ) + player:RemoveAmmo( ammo_type, 300 ) + player:AddAmmo( ammo_type, amount ) + end +end + +function reset_stock( player ) + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:RemoveAmmo( Ammo.kNails, 400 ) + player:RemoveAmmo( Ammo.kShells, 400 ) + player:RemoveAmmo( Ammo.kRockets, 400 ) + player:RemoveAmmo( Ammo.kCells, 400 ) + + player:RemoveAmmo( Ammo.kGren1, 4 ) + player:RemoveAmmo( Ammo.kGren2, 4 ) +end + +function removeprimed( player_entity ) + if IsPlayer( player_entity ) then + local player = CastToPlayer( player_entity ) + + ApplyToPlayer( player, {AT.kStopPrimedGrens} ) + + BroadCastMessage( "You must drop the grenade!" ) + GIVE_GREN2 = true + end +end + +function add_timeout() + --ChatToAll( "[script] adding timeout schedule (time: "..TIMEOUT_REPLAY_TIME..")" ) + AddSchedule( "timeout", TIMEOUT_REPLAY_TIME, play_timeout ) +end + +function reset_timeout() + --ChatToAll( "[script] resetting timeout schedule (time: "..TIMEOUT_REPLAY_TIME..")" ) + RemoveSchedule( "timeout" ) + AddSchedule( "timeout", TIMEOUT_REPLAY_TIME, play_timeout ) +end + +function remove_timeout() + --ChatToAll( "[script] removing timeout schedule" ) + RemoveSchedule( "timeout" ) +end + +function play_timeout() + --ChatToAll( "[script] playing timeout sound" ) + BroadCastSound( "training."..stage_info[current_technique].stages[current_stage].stage_code.."_timeout" ) + reset_timeout() +end + +function increment_failed( player, inc ) + failed_attempts = failed_attempts + inc + --ChatToAll( "[script] failed attempts: "..failed_attempts ) + + if failed_attempts >= 3 then + --ChatToAll( "[script] broadcasting failed sound" ) + BroadCastSound( "training."..stage_info[current_technique].stages[current_stage].stage_code.."02" ) + reset_failed() + end +end + +function reset_failed() + failed_attempts = 0 + --ChatToAll( "[script] reset failed attempts: "..failed_attempts ) +end + +function complete_stage( player ) + --ChatToAll( "[script] technique #"..current_technique.." stage #"..current_stage.." complete" ) + stage_info[current_technique].stages[current_stage].stage_complete = true + + show_complete( player, stage_info[current_technique].stages[current_stage].stage_checklist ) + + if current_stage + 1 <= # stage_info[current_technique].stages then + current_stage = current_stage + 1 + else + current_technique = current_technique + 1 + current_stage = 1 + end + + flaginfo( player ) + + reset_failed() + + hide_current( player ) + AddSchedule( "hide_complete", 4, hide_complete, player ) + AddSchedule( "show_current", 4, show_current, player ) + + hide_key( player ) + hide_progressbar( player ) +end + +function award_medal( player, medal ) + local medal_name = "" + local sound_delay = 0 + if medal == 1 then medal_name = "Gold"; sound_delay = 6 + elseif medal == 2 then medal_name = "Silver"; sound_delay = 5 + elseif medal == 3 then medal_name = "Bronze"; sound_delay = 4 end + BroadCastSound( "training."..stage_info[current_technique].stages[current_stage].stage_code.."_"..string.lower(medal_name) ) + + hide_medal( player ) + show_medal_won( player, medal ) + AddSchedule( "hide_medal_won", 4, hide_medal_won, player ) + AddSchedule( "show_medal", 4, show_medal, player, medal ) + AddSchedule( "play_all_complete", sound_delay, play_all_complete, player ) + + stage_info[current_technique].stages[current_stage].stage_complete = true + stage_info[current_technique].stages[current_stage].stage_medal = medal +end + +function show_medal( player, medal ) + hide_medal(player) + if medal == 1 then + AddHudIcon( player, "ff_training_medal_gold.vtf", "Medal", 16, 64, 64, 64, 0 ) + elseif medal == 2 then + AddHudIcon( player, "ff_training_medal_silver.vtf", "Medal", 16, 64, 64, 64, 0 ) + elseif medal == 3 then + AddHudIcon( player, "ff_training_medal_bronze.vtf", "Medal", 16, 64, 64, 64, 0 ) + end +end + +function hide_medal( player ) + RemoveHudItem( player, "Medal" ) +end + +function show_medal_won( player, medal ) + local medal_name = "" + if medal == 1 then medal_name = "Gold" + elseif medal == 2 then medal_name = "Silver" + elseif medal == 3 then medal_name = "Bronze" end + hide_medal_won(player) + AddHudIcon( player, "hud_statusbar_256.vtf", "Medal_won_BG", -128, 180, 256, 16, 3 ) + AddHudIcon( player, "ff_training_medal_"..string.lower(medal_name)..".vtf", "Medal_won", -112, 170, 32, 32, 3 ) + AddHudText( player, "Medal_won_text", "You won the "..medal_name.." medal!", 0, 184, 4 ) +end + +function hide_medal_won( player ) + RemoveHudItem( player, "Medal_won" ) + RemoveHudItem( player, "Medal_won_text" ) + RemoveHudItem( player, "Medal_won_BG" ) +end + +function play_all_complete( player ) + BroadCastSound( "training.all_complete" ) +end + +function show_complete( player, technique ) + RemoveHudItem( player, "Completed_BG" ) + RemoveHudItem( player, "Completed_check" ) + RemoveHudItem( player, "Completed_text" ) + AddHudIcon( player, "hud_statusbar_256.vtf", "Completed_BG", -128, 180, 256, 16, 3 ) + AddHudIcon( player, "hud_checkmark.vtf", "Completed_check", -112, 170, 32, 32, 3 ) + AddHudText( player, "Completed_text", technique, 0, 184, 4 ) +end + +function hide_complete( player ) + RemoveHudItem( player, "Completed_BG" ) + RemoveHudItem( player, "Completed_check" ) + RemoveHudItem( player, "Completed_text" ) +end + +function show_current( player ) + RemoveHudItem( player, "Current_BG" ) + RemoveHudItem( player, "Current_BG2" ) + RemoveHudItem( player, "Current_arrow" ) + RemoveHudItem( player, "Current_arrow_l" ) + RemoveHudItem( player, "Current_text" ) + RemoveHudItem( player, "Current_text2" ) + AddHudIcon( player, "hud_statusbar_256.vtf", "Current_BG", -64, 40, 128, 16, 3 ) + AddHudIcon( player, "hud_statusbar_256.vtf", "Current_BG2", -64, 58, 128, 16, 3 ) + AddHudIcon( player, "hud_current_arrow.vtf", "Current_arrow", -90, 32, 32, 32, 3 ) + AddHudIcon( player, "hud_current_arrow_l.vtf", "Current_arrow_l", 58, 32, 32, 32, 3 ) + if current_technique == ALL_TOGETHER then + if show_timer then + AddHudTimer( player, "Current_text", "speedrun_timer", 0, 42, 4 ) + else + AddHudText( player, "Current_text", "Timer not started", 0, 44, 4 ) + end + if best_run ~= nil then + AddHudTextToAll( "Current_text2", string.format("Best Time: %.3f seconds", best_run), 0, 62, 4 ) + else + AddHudTextToAll( "Current_text2", "No best time yet", 0, 62, 4 ) + end + else + AddHudText( player, "Current_text", stage_info[current_technique].stages[current_stage].stage_name, 0, 44, 4 ) + AddHudText( player, "Current_text2", stage_info[current_technique].stages[current_stage].stage_specific, 0, 62, 4 ) + end + +end + +function hide_current( player ) + RemoveHudItem( player, "Current_BG" ) + RemoveHudItem( player, "Current_BG2" ) + RemoveHudItem( player, "Current_arrow" ) + RemoveHudItem( player, "Current_arrow_l" ) + RemoveHudItem( player, "Current_text" ) + RemoveHudItem( player, "Current_text2" ) +end + +function show_key( player ) + if stage_info[current_technique].stages[current_stage].stage_key ~= "" then + RemoveHudItem( player, "Key_BG" ) + RemoveHudItem( player, "Key_text" ) + RemoveHudItem( player, "Key_text2" ) + AddHudIcon( player, "hud_statusbar_256_128.vtf", "Key_BG", -64, 80, 128, 32, 3 ) + AddHudText( player, "Key_text", stage_info[current_technique].stages[current_stage].stage_key_text, 0, 88, 4 ) + AddHudText( player, "Key_text2", stage_info[current_technique].stages[current_stage].stage_key, 0, 96, 4 ) + end + +end + +function hide_key( player ) + RemoveHudItem( player, "Key_BG" ) + RemoveHudItem( player, "Key_text" ) + RemoveHudItem( player, "Key_text2" ) +end + +function show_progressbar( player ) + if stage_info[current_technique].stages[current_stage].stage_code == "move_aircontrolspeed" then + hide_progressbar( player ) + local bar_width = 1 + AddHudIcon( player, "hud_statusbar_256.vtf", "Progress_BG", -64, 80, 128, 16, 3 ) + AddHudIcon( player, "hud_statusbar_blue.vtf", "Progress_bar", -62, 80, bar_width, 16, 3 ) + end +end + +function update_progressbar( player, percent ) + RemoveHudItem( player, "Progress_bar" ) + RemoveHudItem( player, "Progress_text" ) + local max_width = 124 + local bar_width = percent * max_width + AddHudIcon( player, "hud_statusbar_blue_active.vtf", "Progress_bar", -62, 80, bar_width, 16, 3 ) + AddHudText( player, "Progress_text", tostring(math.floor(percent * 100 + 0.5)).."% of target speed", 0, 84, 4 ) +end + +function hide_progressbar( player ) + RemoveHudItem( player, "Progress_BG" ) + RemoveHudItem( player, "Progress_bar" ) + RemoveHudItem( player, "Progress_text" ) +end + +------------------------------------- +-- Teleports +------------------------------------- +base_tele = trigger_ff_script:new({ technique_id = 0, stage_number = 0, step = 0 }) + +function base_tele:ontouch( touch_entity ) + if IsPlayer(touch_entity) then + local player = CastToPlayer( touch_entity ) + player:SetVelocity(Vector(0,0,0)) + + OutputEvent("steppingstone_*", "Enable") + + increment_failed(player, 1) + reset_timeout() + end +end + +------------------------------------- +-- Teleports +------------------------------------- +base_replay_btn = trigger_ff_script:new({ technique_id = 0, stage_number = 0, step = 0 }) + +function base_replay_btn:ontrigger( touch_entity ) + if IsPlayer(touch_entity) then + local player = CastToPlayer( touch_entity ) + if player:IsInUse() then + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."_timeout" ) + end + end +end + +------------------------------------- +-- Vertical Jump Rooms +------------------------------------- +v_jump = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function v_jump:ontouch( touch_entity ) + if VERTICAL_JUMP_TOUCHED == 10 then + BroadCastSound( "training.stage_complete" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_door", "Open" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_door_trigger", "Enable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_light", "TurnOn" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_sprite", "ShowSprite" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_model", "Skin", "6" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_next", "Enable" ) + + remove_timeout() + end + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + --ChatToAll( "[script] technique: "..self.technique_id.." stage num: "..self.stage_number ) + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if (VERTICAL_JUMP_TOUCHED > 0) then + ------------------ + ----ChatToAll( "[training] "..VERTICAL_JUMP_TOUCHED.." marker touched") + ------------------ + -- first touch + else + if self.stage_number > 1 then + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_finish_door", "Close" ) + else + OutputEvent( "start_door", "Close" ) + end + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."01" ) + add_timeout() + end + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + GIVE_GREN2 = true + end + if p:GetClass() ~= stage_info[self.technique_id].stages[self.stage_number].stage_class then + + show_key( p ) + + ------------------ + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + ApplyToPlayer( p, {AT.kChangeClassScout} ) + p:RemoveAllWeapons() + reset_stock( p ) + --ChatToAll( "[training] give the concs!" ) + set_ammo( p, Ammo.kGren2, 1 ) + --DisplayMessage( p, "Use {gren2} or {toggletwo} to throw a concussion grenade" ) + elseif stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kSoldier then + ApplyToPlayer( p, {AT.kChangeClassSoldier} ) + p:RemoveAllWeapons() + reset_stock( p ) + p:GiveWeapon( "ff_weapon_rpg", true ) + p:SetAmmoInClip(1) + GIVE_GREN2 = false + elseif stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kDemoman then + ApplyToPlayer( p, {AT.kChangeClassDemoman} ) + p:RemoveAllWeapons() + reset_stock( p ) + p:GiveWeapon( "ff_weapon_pipelauncher", true ) + if stage_info[self.technique_id].stages[self.stage_number].stage_code == "v_pipe" then + p:SetAmmoInClip(2) + else + p:SetAmmoInClip(1) + end + GIVE_GREN2 = false + GIVE_PIPES = false + end + ------------------ + end + end + end + end + + VERTICAL_JUMP_TOUCHED = 0 + VERTICAL_JUMP_BROADCASTED = 0 + +end + +function v_jump:ontrigger( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if p:IsOnGround() and GIVE_GREN2 then + ------------------ + set_ammo( p, Ammo.kGren2, 1 ) + GIVE_GREN2 = false + ------------------ + end + if p:IsOnGround() and p:GetClass() == Player.kSoldier then + ------------------ + p:GiveWeapon( "ff_weapon_rpg", true ) + set_ammo( p, Ammo.kRockets, 0 ) + ApplyToPlayer( p, {AT.kReloadClips} ) + p:SetAmmoInClip(1) + ------------------ + end + if p:IsOnGround() and p:GetClass() == Player.kDemoman and GIVE_PIPES then + ------------------ + p:GiveWeapon( "ff_weapon_pipelauncher", true ) + set_ammo( p, Ammo.kRockets, 0 ) + ApplyToPlayer( p, {AT.kReloadClips} ) + p:SetAmmoInClip(2) + GIVE_PIPES = false + ------------------ + end + end + end + end +end + +function v_jump:onexplode( explode_entity ) + return EVENT_ALLOWED +end + +function v_jump:onendtouch() + +end + + +------------------------------------- +-- Jump Application Rooms +------------------------------------- +a_jump = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function a_jump:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if self.stage_number > 1 then + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_finish_door", "Close" ) + end + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."01" ) + reset_timeout() + + show_current( p ) + + if p:GetClass() ~= stage_info[self.technique_id].stages[self.stage_number].stage_class then + + show_key( p ) + + ------------------ + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + ApplyToPlayer( p, {AT.kChangeClassScout} ) + p:RemoveAllWeapons() + reset_stock( p ) + set_ammo( p, Ammo.kGren2, 1 ) + elseif stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kSoldier then + ApplyToPlayer( p, {AT.kChangeClassSoldier} ) + p:RemoveAllWeapons() + reset_stock( p ) + p:GiveWeapon( "ff_weapon_rpg", true ) + GIVE_GREN2 = false + elseif stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kDemoman then + ApplyToPlayer( p, {AT.kChangeClassDemoman} ) + p:RemoveAllWeapons() + reset_stock( p ) + p:GiveWeapon( "ff_weapon_pipelauncher", true ) + GIVE_GREN2 = false + elseif stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kPyro then + ApplyToPlayer( p, {AT.kChangeClassPyro} ) + p:RemoveAllWeapons() + reset_stock( p ) + p:GiveWeapon( "ff_weapon_flamethrower", true ) + set_ammo( p, Ammo.kCells, 200 ) + GIVE_GREN2 = false + end + end + end + end + end +end + +function a_jump:ontrigger( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if p:IsOnGround() and GIVE_GREN2 then + ------------------ + set_ammo( p, Ammo.kGren2, 1 ) + GIVE_GREN2 = false + ------------------ + end + if p:IsOnGround() and p:GetClass() == Player.kSoldier then + ------------------ + p:GiveWeapon( "ff_weapon_rpg", true ) + set_ammo( p, Ammo.kRockets, 0 ) + ApplyToPlayer( p, {AT.kReloadClips} ) + p:SetAmmoInClip(1) + ------------------ + end + if p:IsOnGround() and p:GetClass() == Player.kDemoman and GIVE_PIPES then + ------------------ + p:GiveWeapon( "ff_weapon_pipelauncher", true ) + set_ammo( p, Ammo.kRockets, 0 ) + ApplyToPlayer( p, {AT.kReloadClips} ) + p:SetAmmoInClip(1) + GIVE_PIPES = false + ------------------ + end + if p:IsOnGround() and p:GetClass() == Player.kPyro then + ------------------ + set_ammo( p, Ammo.kCells, 200 ) + ------------------ + end + end + end + end +end + +function a_jump:onexplode( explode_entity ) + return EVENT_ALLOWED +end + +function a_jump:onendtouch() + +end + + +------------------------------------- +-- Misc Jump Start +------------------------------------- +m_jump_start = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function m_jump_start:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if self.stage_number > 1 then + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_finish_door", "Close" ) + end + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."_start" ) + + reset_timeout() + + show_current( p ) + + if p:GetClass() ~= stage_info[self.technique_id].stages[self.stage_number].stage_class then + + show_key( p ) + + ------------------ + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + ApplyToPlayer( p, {AT.kChangeClassScout} ) + p:RemoveAllWeapons() + reset_stock( p ) + GIVE_GREN2 = true + end + end + end + end + end +end + +function m_jump_start:onexplode( explode_entity ) + return EVENT_ALLOWED +end + +function m_jump_start:onendtouch() + +end + +------------------------------------- +-- Misc Jump Rooms +------------------------------------- +m_jump = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function m_jump:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."01" ) + reset_timeout() + end + end +end + +function m_jump:ontrigger( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if (p:IsOnGround() or p:IsUnderWater()) and p:GetClass() == Player.kScout and GIVE_GREN2 then + ------------------ + set_ammo( p, Ammo.kGren2, 1 ) + GIVE_GREN2 = false + ------------------ + end + end + end + end +end + +function m_jump:onexplode( explode_entity ) + return EVENT_ALLOWED +end + +function m_jump:onendtouch() + +end + +------------------------------------- +-- Movement Room +------------------------------------- +move_room = trigger_ff_script:new({ technique_id = 0, stage_number = 0, played_sound = false }) + +function move_room:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if not self.played_sound then + + self.played_sound = true + + if self.stage_number > 1 then + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_finish_door", "Close" ) + elseif self.technique_id > 1 then + local num_stages_previous_technique = # stage_info[self.technique_id - 1].stages + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_finish_door", "Close" ) + end + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."01" ) + + reset_timeout() + + show_current( p ) + end + + if p:GetClass() ~= stage_info[self.technique_id].stages[self.stage_number].stage_class then + + show_key( p ) + + ------------------ + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + ApplyToPlayer( p, {AT.kChangeClassScout} ) + p:RemoveAllWeapons() + reset_stock( p ) + end + end + + end + end + end +end + + +------------------------------------- +-- Movement Start +------------------------------------- +move_start = trigger_ff_script:new({ technique_id = 0, stage_number = 0, played_sound = false }) + +function move_start:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if not self.played_sound then + + self.played_sound = true + + if self.stage_number > 1 then + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_finish_door", "Close" ) + elseif self.technique_id > 1 then + local num_stages_previous_technique = # stage_info[self.technique_id - 1].stages + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_finish_door", "Close" ) + end + + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."_start" ) + + reset_timeout() + + show_current( p ) + end + + if p:GetClass() ~= stage_info[self.technique_id].stages[self.stage_number].stage_class then + + show_key( p ) + show_progressbar( p ) + + ------------------ + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + ApplyToPlayer( p, {AT.kChangeClassScout} ) + p:RemoveAllWeapons() + reset_stock( p ) + end + end + end + end + end +end + + +------------------------------------- +-- Movement Area +------------------------------------- +move_area = trigger_ff_script:new({ technique_id = 0, stage_number = 0, disabled = false }) + +function move_area:ontrigger( touch_entity ) + if self.disabled then return end + + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + local l_stage_code = stage_info[self.technique_id].stages[self.stage_number].stage_code + + if l_stage_code == "move_aircontrol" or l_stage_code == "move_aircontrolbhop" then + if p:IsInUse() then + local neworigin = GetEntityByName( l_stage_code.."_tele_dest" ):GetOrigin() + neworigin = Vector(neworigin.x,neworigin.y,neworigin.z+36) + local newangles = GetEntityByName( l_stage_code.."_tele_dest" ):GetAngles() + local newvelocity = Vector(0,0,0) + p:Teleport( neworigin, newangles, newvelocity ) + p:SetGravity( 1 ) + p:SpeedMod( 1 ) + increment_failed(p, 1) + self:adddisable() + reset_timeout() + elseif p:IsInForward() then + BroadCastMessage( "Do not press forward while air controlling" ) + else + local speed = p:GetSpeed() + if speed < 50 then + BroadCastMessage( "You seem to be stuck. Press your USE button to retry" ) + end + end + end + + if l_stage_code == "move_rampslide" then + + local speed = p:GetSpeed() + + if speed < 800 then + local neworigin = GetEntityByName( l_stage_code.."_tele_dest" ):GetOrigin() + neworigin = Vector(neworigin.x,neworigin.y,neworigin.z+36) + local newangles = GetEntityByName( l_stage_code.."_tele_dest" ):GetAngles() + local newvelocity = Vector(0,0,0) + p:Teleport( neworigin, newangles, newvelocity ) + p:SetGravity( 1 ) + p:SpeedMod( 1 ) + increment_failed(p, 1) + self:adddisable() + reset_timeout() + end + end + + if l_stage_code == "move_trimp" then + + local speed = p:GetSpeed() + + if speed <= 500 then + local neworigin = GetEntityByName( l_stage_code.."_tele_dest" ):GetOrigin() + neworigin = Vector(neworigin.x,neworigin.y,neworigin.z+36) + local newangles = GetEntityByName( l_stage_code.."_tele_dest" ):GetAngles() + local newvelocity = Vector(0,0,0) + p:Teleport( neworigin, newangles, newvelocity ) + p:SetGravity( 1 ) + p:SpeedMod( 1 ) + increment_failed(p, 1) + self:adddisable() + reset_timeout() + end + end + + if l_stage_code == "move_aircontrolspeed" then + --if p:IsInUse() then + -- local origin = GetEntityByName( l_stage_code.."_tele_dest" ):GetOrigin() + -- p:SetOrigin( Vector( origin.x, origin.y, origin.z + 64 ) ) + -- p:SetVelocity( Vector( 0,0,0 ) ) + -- p:SetGravity( 1 ) + -- p:SpeedMod( 1 ) + if p:IsInForward() then + BroadCastMessage( "Do not press forward while air controlling" ) + else + local speed = p:GetSpeed() + update_progressbar( p, speed / 700 ) + if speed > 700 then + update_progressbar( p, 1.0 ) + BroadCastSound( "misc.doop" ) + remove_timeout() + OutputEvent("move_aircontrolspeed_showfinishblock", "Enable") + OutputEvent("move_aircontrolspeed", "Disable") + end + end + end + + end + end + end +end + +function move_area:adddisable() + self.disabled = true + AddSchedule(stage_info[self.technique_id].stages[self.stage_number].stage_code .. "-removedisable", 1, self.removedisable, self) +end + +function move_area.removedisable(self) + self.disabled = false +end + +------------------------------------- +-- Movement Room +------------------------------------- +move_init = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function move_init:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + + local l_stage_code = stage_info[self.technique_id].stages[self.stage_number].stage_code + + if l_stage_code == "move_aircontrol" then + p:SetVelocity( Vector( 500, 0, 600 ) ) + p:SetGravity( 0.000000001 ) + elseif l_stage_code == "move_aircontrolpush" then + p:SetVelocity( Vector( -800, 0, 600 ) ) + elseif l_stage_code == "move_aircontrolspeed" then + p:SetVelocity( Vector( 0, -300, 600 ) ) + p:SetGravity( 0.000000001 ) + elseif l_stage_code == "move_aircontrolbhop" then + p:SetVelocity( Vector( 0, -400, 600 ) ) + p:SetGravity( 0.000000001 ) + elseif l_stage_code == "move_rampslide" then + p:SetVelocity( Vector( 2000, 0, 0 ) ) + elseif l_stage_code == "move_trimp" then + p:SetVelocity( Vector( 1500, 0, 0 ) ) + end + end + end + end +end + +------------------------------------- +-- Application finish +------------------------------------- +a_finish = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function a_finish:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + + BroadCastSound( "misc.doop" ) + BroadCastSound( "training.stage_complete" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_door", "Open" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_door_trigger", "Enable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_light", "TurnOn" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_sprite", "ShowSprite" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_model", "Skin", "6" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_next", "Enable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_block", "Enable" ) + + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_tesla", "DoSpark" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_beam", "TurnOff" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_arrow", "Disable" ) + complete_stage( p ) + p:RemoveAllWeapons() + p:SetGravity( 1.0 ) + p:SpeedMod( 1.0 ) + + remove_timeout() + + end + end + end +end + +------------------------------------- +-- Aircontrolspeed +------------------------------------- + +move_aircontrolspeed_hidestartarrows = trigger_ff_script:new({ }) + +function move_aircontrolspeed_hidestartarrows:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + + OutputEvent("move_aircontrolspeed_starthideblock", "Disable") + OutputEvent("move_aircontrolspeed_arrow_starthide", "TurnOff") + OutputEvent("move_aircontrolspeed_arrow_startshow", "TurnOn") + OutputEvent("move_aircontrolspeed_startblock", "Enable") + + end + end +end + +move_aircontrolspeed_showfinishblock = trigger_ff_script:new({ touched=false }) + +function move_aircontrolspeed_showfinishblock:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + + if not self.touched then + OutputEvent("move_aircontrolspeed_finishshowblock", "Enable") + OutputEvent("move_aircontrolspeed_arrow_finishhide", "TurnOff") + OutputEvent("move_aircontrolspeed_arrow_finishshow", "TurnOn") + OutputEvent("move_aircontrolspeed_finishblock", "Disable") + self.touched = true + end + + end + end +end + + +------------------------------------- +-- Bhop +------------------------------------- + +move_bhop_init = trigger_ff_script:new({ technique_id = 0, stage_number = 0, step = 0 }) + +move_bhop_area = trigger_ff_script:new({ technique_id = 0, stage_number = 0, step = 0 }) + +move_bhop_start = trigger_ff_script:new({ technique_id = 0, stage_number = 0, step = 0, played_sound = false }) + +function move_bhop_start:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if not self.played_sound then + + self.played_sound = true + + if self.stage_number > 1 then + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_finish_door", "Close" ) + elseif self.technique_id > 1 then + local num_stages_previous_technique = # stage_info[self.technique_id - 1].stages + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_finish_door", "Close" ) + end + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code..self.step.."_start" ) + + OutputEvent("steppingstone_*", "Enable") + + reset_timeout() + + show_current( p ) + end + + if p:GetClass() ~= stage_info[self.technique_id].stages[self.stage_number].stage_class then + ------------------ + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + ApplyToPlayer( p, {AT.kChangeClassScout} ) + p:RemoveAllWeapons() + reset_stock( p ) + end + end + + if self.step == 1 then + p:SpeedMod( .5 ) + elseif self.step == 2 then + p:SpeedMod( .75 ) + else + p:SpeedMod( 1.0 ) + end + + end + end + end +end + + +move_bhop_finish = trigger_ff_script:new({ technique_id = 0, stage_number = 0, step = 0 }) + +function move_bhop_finish:ontouch( touch_entity ) + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + + BroadCastSound( "misc.doop" ) + + p:RemoveAllWeapons() + p:SetGravity( 1.0 ) + p:SpeedMod( 1.0 ) + + reset_timeout() + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code..self.step.."_block", "Enable" ) + + if self.step == stage_info[self.technique_id].stages[self.stage_number].stage_num_steps then + BroadCastSound( "training.stage_complete" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_door", "Open" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_door_trigger", "Enable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_light", "TurnOn" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_sprite", "ShowSprite" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_finish_model", "Skin", "6" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_next", "Enable" ) + + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_tesla", "DoSpark" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_beam", "TurnOff" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_arrow", "Disable" ) + complete_stage( p ) + + remove_timeout() + end + + end + end + end +end + +------------------------------------- +-- freeze +------------------------------------- + +function player_freeze( p, bF ) + p:Freeze( bF ) +end + +------------------------------------- +-- Multipurpose remove +------------------------------------- + +remove_all = trigger_ff_script:new({}) + +function remove_all:allowed( allowed_entity ) + if not stage_info[current_technique].stages[current_stage].stage_complete and current_technique == JUMP_TECHNIQUES then + if stage_info[current_technique].stages[current_stage].stage_limits.force_hhconc then + ----ChatToAll( "[training] trigger_remove force_hhconc" ) + if IsGrenade( allowed_entity ) then + GIVE_GREN2 = true + return EVENT_ALLOWED + end + end + if stage_info[current_technique].stages[current_stage].stage_limits.force_waterconc then + ----ChatToAll( "[training] trigger_remove force_waterconc" ) + if IsGrenade( allowed_entity ) then + GIVE_GREN2 = true + BroadCastMessage( "Throw the conc in the water!" ) + --ApplyToPlayer( player, {AT.kStopPrimedGrens} ) + return EVENT_ALLOWED + end + end + end + return EVENT_DISALLOWED +end + +--- TEMPORARY +v_hhconc_remove = remove_all:new({}) +a_hhconc_remove = remove_all:new({}) +m_waterconc_remove = remove_all:new({}) +a_pipe_remove = remove_all:new({}) +v_pipe_remove = remove_all:new({}) + +------------------------------------- +-- Multipurpose catch +------------------------------------- + +catch_all = trigger_ff_script:new({}) + +function catch_all:ontouch( touch_entity ) + if IsPlayer(touch_entity) then return end +end + +function catch_all:ontrigger( touch_entity ) + return +end + +function catch_all:onexplode( explode_entity ) + if explode_entity:GetClassName() == "ff_projectile_pl" then + GIVE_PIPES = true + elseif explode_entity:GetClassName() == "ff_grenade_concussion" then + GIVE_GREN2 = true + end + return EVENT_ALLOWED +end + +------------------------------------- +-- speedrun +------------------------------------- +all_together_start = trigger_ff_script:new({ technique_id = 0, stage_number = 0, sound_played = false }) + +function all_together_start:ontouch( touch_entity ) + if show_timer then return end + if not stage_info[self.technique_id].stages[self.stage_number].stage_complete then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if not self.sound_played then + + self.sound_played = true + + if self.stage_number > 1 then + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id].stages[self.stage_number - 1].stage_code.."_finish_door", "Close" ) + elseif self.technique_id > 1 then + local num_stages_previous_technique = # stage_info[self.technique_id - 1].stages + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_next", "Disable" ) + OutputEvent( stage_info[self.technique_id - 1].stages[num_stages_previous_technique].stage_code.."_finish_door", "Close" ) + end + BroadCastSound( "training."..stage_info[self.technique_id].stages[self.stage_number].stage_code.."_start" ) + + reset_timeout() + + show_current( p ) + end + + if p:GetClass() ~= stage_info[self.technique_id].stages[self.stage_number].stage_class then + + show_key( p ) + + ------------------ + if stage_info[self.technique_id].stages[self.stage_number].stage_class == Player.kScout then + ApplyToPlayer( p, {AT.kChangeClassScout} ) + p:RemoveAllWeapons() + reset_stock( p ) + end + end + end + end + end +end + +all_together_init = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function all_together_init:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + RemoveTimer( "speedrun_timer" ) + AddTimer( "speedrun_timer", 0, 1 ) + show_timer = true + OutputEvent( stage_info[self.technique_id].stages[self.stage_number].stage_code.."_init", "Disable" ) + + player:GiveWeapon( "ff_weapon_crowbar", true ) + player:AddAmmo( Ammo.kGren1, 4 ) + player:AddAmmo( Ammo.kGren2, 4 ) + + show_current( player ) + + UpdateObjectiveIcon( player, GetEntityByName( "red_flag" ) ) + end +end + +all_together_room = trigger_ff_script:new({ technique_id = 0, stage_number = 0 }) + +function all_together_room:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + end +end + +function all_together_room:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if show_timer and player:IsInUse() then + RemoveTimer( "speedrun_timer" ) + OutputEvent( "all_scout_init", "Enable" ) + + show_timer = false + + player:RemoveAllWeapons() + player:RemoveAmmo( Ammo.kGren1, 4 ) + player:RemoveAmmo( Ammo.kGren2, 4 ) + + show_current( player ) + + local stage_code = stage_info[current_technique].stages[current_stage].stage_code + TeleportToEntity( player, stage_code.."_tele_dest" ) + player:SetGravity( 1 ) + player:SpeedMod( 1 ) + ApplyToPlayer( player, { AT.kStopPrimedGrens } ) + ApplyToAll({AT.kRemoveProjectiles}) + local flag = CastToInfoScript(GetEntityByName("red_flag")) + RemoveHudItem( player, flag:GetName() ) + flag:Return() + UpdateObjectiveIcon( player, nil ) + end + end +end + +function OutputTime( timername ) + local timerval = GetTimerTime( timername ) + --ChatToAll("["..timername.."] "..timerval.."s") + BroadCastMessage( string.format("Time: %.3f seconds", timerval), 10, Color.kBlue ) + return timerval +end + +function blue_cap:oncapture(player, item) + + local timerval = OutputTime( "speedrun_timer" ) + + RemoveTimer( "speedrun_timer" ) + OutputEvent( "all_scout_init", "Enable" ) + + show_timer = false + + player:RemoveAllWeapons() + player:RemoveAmmo( Ammo.kGren1, 4 ) + player:RemoveAmmo( Ammo.kGren2, 4 ) + + if timerval > 0 then + if best_run == nil then + best_run = timerval + else + if timerval < best_run then + best_run = timerval + end + end + end + + local medal_won = nil + if timerval <= TIME_FOR_GOLD then + medal_won = 1 + elseif timerval <= TIME_FOR_SILVER then + medal_won = 2 + elseif timerval <= TIME_FOR_BRONZE then + medal_won = 3 + else + -- only play the capture sound if no medal was won + SmartSpeak(player, "CTF_YOUCAP", "CTF_TEAMCAP", "CTF_THEYCAP") + end + + if medal_won ~= nil then + if stage_info[current_technique].stages[current_stage].stage_medal == 0 or stage_info[current_technique].stages[current_stage].stage_medal > medal_won then + award_medal( player, medal_won ) + end + end + + show_current( player ) + + local stage_code = stage_info[current_technique].stages[current_stage].stage_code + TeleportToEntity( player, stage_code.."_tele_dest" ) + player:SetGravity( 1 ) + player:SpeedMod( 1 ) + ApplyToPlayer( player, { AT.kStopPrimedGrens } ) + + -- let the teams know that a capture occured + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") +end + +function TeleportToEntity( player, entity_name ) + if GetEntityByName( entity_name ) ~= nil then + local neworigin = GetEntityByName( entity_name ):GetOrigin() + neworigin = Vector(neworigin.x,neworigin.y,neworigin.z+36+16) + local newangles = GetEntityByName( entity_name ):GetAngles() + local newvelocity = Vector(0,0,0) + player:Teleport( neworigin, newangles, newvelocity ) + return true + else + return false + end +end + +------------------------------------- +-- Change class triggers +------------------------------------- +ChangeClass = trigger_ff_script:new({ class=Player.kScout, changeclass=AT.kChangeClassScout }) + +function ChangeClass:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + ------------------ + ApplyToPlayer( p, {self.changeclass} ) + p:RemoveAllWeapons() + reset_stock( p ) + ------------------ + end + end +end + +ChangeClass_Scout = ChangeClass:new({ class=Player.kScout, changeclass=AT.kChangeClassScout }) +ChangeClass_Medic = ChangeClass:new({ class=Player.kMedic, changeclass=AT.kChangeClassMedic }) +ChangeClass_Civilian = ChangeClass:new({ class=Player.kCivilian, changeclass=AT.kChangeClassCivilian }) + +------------------------------------- +-- OnPrime +------------------------------------- + +function player_spawn( player ) + if IsPlayer( player ) then + BroadCastSound( "training.intro" ) + end +end + +function player_onprimegren1( player_id ) + ----ChatToAll( "[training] gren1 primed" ) + local player = GetPlayer(player_id) + if stage_info[current_technique].stages[current_stage].stage_code == "v_frag" then + AddSchedule("gren2prime3", .85, message, "3") + AddSchedule("gren2prime2", 1.85, message, "2") + AddSchedule("gren2prime1", 2.85, message, "1") + AddSchedule("gren2prime", 3.85, message, "Jump!") + end +end + +function player_onprimegren2( player_id ) + ----ChatToAll( "[training] gren2 primed" ) + local player = GetPlayer(player_id) + + if stage_info[current_technique].stages[current_stage].stage_type == VERTICAL_JUMP or stage_info[current_technique].stages[current_stage].stage_type == MISC_JUMP then + increment_failed(player, 1) + reset_timeout() + end + + if stage_info[current_technique].stages[current_stage].stage_code == "v_conc" then + AddSchedule("gren2prime3", .5, message, "3") + AddSchedule("gren2prime2", 1.5, message, "2") + AddSchedule("gren2prime1", 2.5, message, "1") + AddSchedule("gren2prime", 3.5, message, "Jump!") + AddSchedule("gren2primeremove", 3.6, removeprimed, player) + elseif stage_info[current_technique].stages[current_stage].stage_code == "a_conc" then + AddSchedule("gren2prime3", .5, message, "3") + AddSchedule("gren2prime2", 1.5, message, "2") + AddSchedule("gren2prime1", 2.5, message, "1") + AddSchedule("gren2prime", 3.5, message, "Jump!") + AddSchedule("gren2primeremove", 3.6, removeprimed, player) + elseif stage_info[current_technique].stages[current_stage].stage_code == "v_hhconc" then + AddSchedule("gren2prime3", .85, message, "3") + AddSchedule("gren2prime2", 1.85, message, "2") + AddSchedule("gren2prime1", 2.85, message, "1") + AddSchedule("gren2prime", 3.85, message, "Jump!") + elseif stage_info[current_technique].stages[current_stage].stage_code == "a_hhconc" then + AddSchedule("gren2prime3", .5, message, "3") + AddSchedule("gren2prime2", 1.5, message, "2") + AddSchedule("gren2prime1", 2.5, message, "1") + AddSchedule("gren2prime", 3.5, message, "Jump!") + end +end + +function player_onthrowgren1( player, primed ) + ----ChatToAll( "[training] gren1 thrown" ) + return EVENT_ALLOWED +end + +function player_onthrowgren2( player, primed ) + ----ChatToAll( "[training] gren2 thrown" ) + if stage_info[current_technique].stages[current_stage].stage_code == "v_hhconc" or stage_info[current_technique].stages[current_stage].stage_code == "a_hhconc" then + BroadCastMessage( "Do not throw the conc when Hand-Held Conc Jumping!" ) + GIVE_GREN2 = true + RemoveSchedule("gren2prime3") + RemoveSchedule("gren2prime2") + RemoveSchedule("gren2prime1") + RemoveSchedule("gren2prime") + --ApplyToPlayer( player, {AT.kStopPrimedGrens} ) + return EVENT_DISALLOWED + end + + if stage_info[current_technique].stages[current_stage].stage_code == "v_conc" or stage_info[current_technique].stages[current_stage].stage_code == "a_conc" then + RemoveSchedule("gren2primeremove") + return EVENT_ALLOWED + end + + return EVENT_ALLOWED +end + +----------------------------------------------------------------------------- +-- On damage +----------------------------------------------------------------------------- +function player_ondamage( player, damageinfo ) + ----ChatToAll( "[training] player ondamage" ) + if not damageinfo then + return + end + + damageinfo:SetDamage(0) + + local weapon = damageinfo:GetInflictor():GetClassName() + + if weapon == "ff_projectile_rocket" then + player:RemoveAllWeapons() + if stage_info[current_technique].stages[current_stage].stage_type == VERTICAL_JUMP then + increment_failed(player, 1) + reset_timeout() + end + end + + if weapon == "ff_projectile_pl" then + player:RemoveAllWeapons() + if stage_info[current_technique].stages[current_stage].stage_type == VERTICAL_JUMP then + increment_failed(player, .5) + reset_timeout() + end + end + +end + +------------------------------------- +-- Vertical Jump Markers +------------------------------------- +VerticalJumpMarker = trigger_ff_script:new({ message = "Touched", number = 0 }) + +function VerticalJumpMarker:ontouch( touch_entity ) + if VERTICAL_JUMP_BROADCASTED == 0 then + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + if self.number > VERTICAL_JUMP_TOUCHED then + ------------- + ----ChatToAll( "[training] Upped to: " .. self.number ) + -------------- + VERTICAL_JUMP_TOUCHED = self.number + VERTICAL_JUMP_MESSAGE = self.message + if self.number == 10 then + BroadCastSound ( "misc.doop" ) + OutputEvent( stage_info[current_technique].stages[current_stage].stage_code.."_tesla", "DoSpark" ) + OutputEvent( stage_info[current_technique].stages[current_stage].stage_code.."_beam", "TurnOff" ) + OutputEvent( stage_info[current_technique].stages[current_stage].stage_code.."_arrow", "Disable" ) + complete_stage( p ) + end + else + BroadCastMessage( VERTICAL_JUMP_MESSAGE ) + VERTICAL_JUMP_BROADCASTED = 1 + reset_timeout() + end + end + end + end +end + +function VerticalJumpMarker:onendtouch() + +end + +------------------------------------- +-- Declare Veritical Jump Markers +------------------------------------- +Jump1 = VerticalJumpMarker:new({ message="Not Quite", number=1 }) +Jump2 = VerticalJumpMarker:new({ message="Nice Try", number=2 }) +Jump3 = VerticalJumpMarker:new({ message="Keep it up", number=3 }) +Jump4 = VerticalJumpMarker:new({ message="Good Effort", number=4 }) +Jump5 = VerticalJumpMarker:new({ message="You're Getting It", number=5 }) +Jump6 = VerticalJumpMarker:new({ message="Good, but still a ways to go", number=6 }) +Jump7 = VerticalJumpMarker:new({ message="Great, but not quite", number=7 }) +Jump8 = VerticalJumpMarker:new({ message="Almost There", number=8 }) +Jump9 = VerticalJumpMarker:new({ message="So Close...", number=9 }) +Jump10 = VerticalJumpMarker:new({ message="Complete!", number=10 }) + + +function flaginfo( player_entity ) + local player = CastToPlayer( player_entity ) + + current_y = 0 + + for i,v in ipairs(stage_info) do + + heading_complete = true + for i2,v2 in ipairs(v.stages) do + if not v2.stage_complete then + heading_complete = false + break + end + end + + RemoveHudItem( player, "Checklist_Header"..i ) + RemoveHudItem( player, "Checklist_Header_text"..i ) + RemoveHudItem( player, "Checklist_Header"..i.."_check" ) + + AddHudIcon( player, "hud_statusbar_256.vtf", "Checklist_Header"..i, 10, current_y + 10, 136, 16, 1 ) + if heading_complete then + AddHudText( player, "Checklist_Header_text"..i, v.technique_name, 127, current_y + 14, 5 ) + AddHudIcon( player, "hud_checkmark.vtf", "Checklist_Header"..i.."_check", 124, current_y + 6, 20, 20, 1 ) + else + AddHudText( player, "Checklist_Header_text"..i, v.technique_name, 140, current_y + 14, 5 ) + end + + RemoveHudItem( player, "Checklist_BG"..i ) + + if i == current_technique then + if # v.stages > 2 then + AddHudIcon( player, "hud_statusbar_256_128.vtf", "Checklist_BG"..i, 10, current_y + 28, 136, 10 + # v.stages * 10, 1 ) + else + AddHudIcon( player, "hud_statusbar_256.vtf", "Checklist_BG"..i, 10, current_y + 28, 136, 10 + # v.stages * 10, 1 ) + end + end + for i2,v2 in ipairs(v.stages) do + RemoveHudItem( player, "Checklist_Item"..i.."-"..i2 ) + RemoveHudItem( player, "Checklist_Item"..i.."-"..i2.."_check" ) + + if i == current_technique then + if v2.stage_complete then + AddHudIcon( player, "hud_checkmark.vtf", "Checklist_Item"..i.."-"..i2.."_check", 132, current_y + 22 + i2 * 10, 10, 10, 1 ) + elseif i2 == current_stage and i == current_technique then + AddHudIcon( player, "hud_current_arrow.vtf", "Checklist_Item"..i.."-"..i2.."_check", 132, current_y + 23 + i2 * 10, 10, 10, 1 ) + end + AddHudText( player, "Checklist_Item"..i.."-"..i2, v2.stage_checklist, 130, current_y + 24 + i2 * 10, 5 ) + end + end + + if i == current_technique then + current_y = current_y + 32 + # v.stages * 10 + else + current_y = current_y + 20 + end + + end + + show_current( player ) +end + + +function message( text ) + BroadCastMessage( text ) +end + +function disable( entity ) + ConsoleToAll( entity.." you are nuts" ) + OutputEvent( entity, "Disable" ) +end \ No newline at end of file diff --git a/maps/ff_warpath.lua b/maps/ff_warpath.lua new file mode 100644 index 0000000..bb7edb1 --- /dev/null +++ b/maps/ff_warpath.lua @@ -0,0 +1,592 @@ +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_cp_default") +IncludeScript("base_cp_sequential") +IncludeScript("base_chatcommands") + +----------------------------------------------------------------------------- +--Globals +----------------------------------------------------------------------------- + +POINTS_FOR_COMPLETE_CONTROL = 25 +ENABLE_COMPLETE_CONTROL_RESET = true +ENABLE_COMPLETE_CONTROL_RESPAWN = true +COMPLETE_CONTROL_RESPAWN_DELAY = 5 +INITIAL_ROUND_DELAY = 20 +RETOUCH_DELAY = 10.0 --CP3 +RETOUCH_DELAY_CP2RED_CP4BLUE = 20 +RETOUCH_DELAY_CP2BLUE_CP4RED = 10 + +CAP_REQ_CP1_CP5 = 750 +CAP_REQ_CP3 = 1000 +CAP_REQ_CP2RED_CP4BLUE = 1000 +CAP_REQ_CP2BLUE_CP4RED = 1250 + +cp_blue = 1 +cp_red = 5 +RED_TUNNEL_WALL_BLOWN = false +BLUE_TUNNEL_WALL_BLOWN = false + +----------------------------------------------------------------------------- +-- Chat commands and settings +----------------------------------------------------------------------------- + +-- teamcapsound +chatbase_addcommand( "teamcapsound", "Determines if a sound is played when the other team starts capping a point", "teamcapsound 0/1" ) +function chat_teamcapsound( player, setting ) + setting = tonumber(setting) + if setting == "" or setting == nil then + -- no parameter, just echo back their current setting + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Current team capture sound setting: "..tostring(chatbase_getplayersetting(player, "startcapsound"))) + elseif setting == 0 or not setting then + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Turned your team capture sound off") + chatbase_setplayersetting(player, "teamcapsound", 0) + else + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Turned your team capture sound on") + chatbase_setplayersetting(player, "teamcapsound", 1) + end +end +chatbase_addplayersetting( "teamcapsound", 1, "Determines if a sound is played when the other team starts capping a point" ) + +-- startcapsound +chatbase_addcommand( "startcapsound", "Determines if a sound is played when you start to capture a point", "startcapsound 0/1" ) +function chat_startcapsound( player, setting ) + setting = tonumber(setting) + if setting == "" or setting == nil then + -- no parameter, just echo back their current setting + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Current start capture sound setting: "..tostring(chatbase_getplayersetting(player, "startcapsound"))) + elseif setting == 0 or not setting then + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Turned your start capture sound off") + chatbase_setplayersetting(player, "startcapsound", 0) + else + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Turned your start capture sound on") + chatbase_setplayersetting(player, "startcapsound", 1) + end +end + +chatbase_addplayersetting( "startcapsound", 1, "Determines if a sound is played when the opposite team starts to capture a point" ) + +----------------------------------------------------------------------------- +-- event outputs +----------------------------------------------------------------------------- + +function startup() + SetGameDescription("Sequential Control Points") + + -- disable certain teams + for i,v in pairs(disabled_teams) do + SetPlayerLimit( v, -1 ) + end + + -- set up team limits + for i1,v1 in pairs(teams) do + local team = GetTeam(v1) + for i2,v2 in ipairs(team_info[team:GetTeamId()].class_limits) do + team:SetClassLimit( i2, v2 ) + end + end + + RemoveAllCPAmmoAndArmor() + + for i,v in ipairs(command_points) do + RemoveSchedule( "cp" .. v.cp_number .. "_cap_timer" ) + ResetCPCapping( v ) + AddScheduleRepeating( "cp" .. v.cp_number .. "_cap_zone_timer", CAP_ZONE_TIMER_INTERVAL, cap_zone_timer, v ) + end + + reset_map_items(true) +end + +function complete_control_notification ( team_number ) + local team = GetTeam(team_number) + SmartTeamSound(team, "yourteam.flagcap", "otherteam.flagcap") + SmartTeamSpeak(team, "CZ_GOTALL", "CZ_THEYGOTALL") + SmartTeamMessage(team, "#FF_CZ2_YOURTEAM_COMPLETE", "#FF_CZ2_OTHERTEAM_COMPLETE") + + AddSchedule("reset_map_items", COMPLETE_CONTROL_RESPAWN_DELAY, reset_map_items, false) +end + +function reset_map_items (firstRound) + BLUE_TUNNEL_WALL_BLOWN = false + RED_TUNNEL_WALL_BLOWN = false + OutputEvent( "blue_detwall_template", "ForceSpawn" ) + OutputEvent( "red_detwall_template", "ForceSpawn" ) + + OBJECTIVE_TEAM1 = "cp2_zone" + OBJECTIVE_TEAM2 = "cp4_zone" + UpdateTeamObjectiveIcon( GetTeam(TEAM1), GetEntityByName( OBJECTIVE_TEAM1 ) ) + UpdateTeamObjectiveIcon( GetTeam(TEAM2), GetEntityByName( OBJECTIVE_TEAM2 ) ) + + if firstRound then + for i,v in ipairs(command_points) do + ChangeCPDefendingTeam(v.cp_number, Team.kUnassigned) + ResetCPCapping( v ) + end + + ChangeCPDefendingTeam( 1, TEAM1 ) + ChangeCPDefendingTeam( CP_COUNT, TEAM2 ) + + setup_door_timer("startgate_blue", INITIAL_ROUND_DELAY) + setup_door_timer("startgate_red", INITIAL_ROUND_DELAY) + else + setup_door_timer("startgate_blue", 12) + setup_door_timer("startgate_red", 12) + end +end + +function event_StopTouchingCP( entity, cp ) + return +end + +function event_StartTouchingCP( entity, cp ) + if IsPlayer( entity ) then + local player = CastToPlayer( entity ) + if chatbase_getplayersetting(player, "startcapsound") ~= 0 then + BroadCastSoundToPlayer( player, "misc.woop" ) + end + end + return +end + +function event_StartTouchingCC( entity, cc_team_number ) + return +end + +function event_StopTouchingCC( entity, cc_team_number ) + return +end + +function event_ChangeCPDefendingTeam( cp_number, new_defending_team ) + -- Change the skybeam and groundbeam color + OutputEvent( "cp" .. cp_number .. "_actiondoor_" .. team_info[command_points[cp_number].defending_team].team_name, "Close") + OutputEvent( "cp" .. cp_number .. "_actiondoor_" .. team_info[new_defending_team].team_name, "Open") + + -- update valid spawns + if new_defending_team == Team.kBlue then + cp_blue = cp_number + if command_points[cp_number].defending_team == Team.kRed then + cp_red = cp_number + 1 + end + elseif new_defending_team == Team.kRed then + cp_red = cp_number + if command_points[cp_number].defending_team == Team.kBlue then + cp_blue = cp_number - 1 + end + end +end + +function event_ResetTeamCPCapping( cp, team_number ) + OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[team_number].team_name .. "_beam", "TurnOff" ) +end + +function event_StartTeamCPCapping( cp, team_number ) + OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[team_number].team_name .. "_beam", "TurnOn" ) + local team = GetTeam(team_number) + for i,v in pairs(chatbase_players) do + local player = CastToPlayer(v.player) + if IsPlayer(player) then + if player:GetTeamId() ~= team_number then + if chatbase_getplayersetting(player, "teamcapsound") then + BroadCastSoundToPlayer( player, "misc.bloop" ) + end + end + end + end +end + + +team_info = { + + [Team.kUnassigned] = { + team_name = "neutral", + enemy_team = Team.kUnassigned, + objective_icon = nil, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen }, + skybeam_color = "128 128 128", + respawnbeam_color = { [0] = 100, [1] = 100, [2] = 100 }, + color_index = 1, + skin = "0", + flag_visibility = "TurnOff", + cc_touch_count = 0, + ccalarmicon = "hud_secdown.vtf", ccalarmiconx = 0, ccalarmicony = 0, ccalarmiconwidth = 16, ccalarmiconheight = 16, ccalarmiconalign = 2, + detcc_sentence = "HTD_DOORS", + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = 0, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = -1, + } + }, + + [TEAM1] = { + team_name = "blue", + enemy_team = TEAM2, + objective_icon = nil, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue }, + skybeam_color = "64 64 255", + respawnbeam_color = { [0] = 100, [1] = 100, [2] = 100 }, + color_index = 2, + skin = "2", + flag_visibility = "TurnOn", + cc_touch_count = 0, + ccalarmicon = "hud_secup_blue.vtf", ccalarmiconx = 60, ccalarmicony = 5, ccalarmiconwidth = 16, ccalarmiconheight = 16, ccalarmiconalign = 2, + detcc_sentence = "CZ_BCC_DET", + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = 0, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = -1, + } + }, + + [TEAM2] = { + team_name = "red", + enemy_team = TEAM1, + objective_icon = nil, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kRed }, + skybeam_color = "255 64 64", + respawnbeam_color = { [0] = 100, [1] = 100, [2] = 100 }, + color_index = 0, + skin = "1", + flag_visibility = "TurnOn", + cc_touch_count = 0, + ccalarmicon = "hud_secup_red.vtf", ccalarmiconx = 60, ccalarmicony = 5, ccalarmiconwidth = 16, ccalarmiconheight = 16, ccalarmiconalign = 3, + detcc_sentence = "CZ_RCC_DET", + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = 0, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = -1, + } + } +} + + +------------------------------------------- +-- Round start functions +------------------------------------------- + +function setup_door_timer(doorname, duration) + CloseDoor(doorname) + AddSchedule("round_opendoor_" .. doorname, duration, round_start, doorname) + + if duration > 10 then AddSchedule( "dooropen5sec" , duration - 10 , schedulemessagetoall, "Gates open in 10 seconds!" ) end + if duration > 5 then AddSchedule( "dooropen5sec" , duration - 5 , schedulemessagetoall, "5" ) end + if duration > 4 then AddSchedule( "dooropen4sec" , duration - 4 , schedulemessagetoall, "4" ) end + if duration > 3 then AddSchedule( "dooropen3sec" , duration - 3, schedulemessagetoall, "3" ) end + if duration > 2 then AddSchedule( "dooropen2sec" , duration - 2, schedulemessagetoall, "2" ) end + if duration > 1 then AddSchedule( "dooropen1sec" , duration - 1, schedulemessagetoall, "1" ) end + + if duration > 5 then AddSchedule( "dooropen5seccount" , duration - 5 , schedulecountdown, 5 ) end + if duration > 4 then AddSchedule( "dooropen4seccount" , duration - 4 , schedulecountdown, 4 ) end + if duration > 3 then AddSchedule( "dooropen3seccount" , duration - 3 , schedulecountdown, 3 ) end + if duration > 2 then AddSchedule( "dooropen2seccount" , duration - 2 , schedulecountdown, 2 ) end + if duration > 1 then AddSchedule( "dooropen1seccount" , duration - 1 , schedulecountdown, 1 ) end +end + +function round_start(doorname) + BroadCastMessage("Gates are now open!") + BroadCastSound( "otherteam.flagstolen" ) + SpeakAll( "AD_GATESOPEN" ) + + OpenDoor(doorname) +end + +function schedulemessagetoall( message ) + BroadCastMessage( message ) +end + +function schedulecountdown( time ) + BroadCastMessage( ""..time.."" ) + SpeakAll( "AD_" .. time .. "SEC" ) +end + +----------------------------------------------------------------------------- +-- bags +----------------------------------------------------------------------------- + +gen_pack = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 0, + nails = 300, + shells = 300, + rockets = 300, + gren1 = 0, + gren2 = 0, + cells = 130, + respawntime = 10, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch"}) + +blue_gen_pack = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 0, + nails = 300, + shells = 300, + rockets = 300, + gren1 = 1, + gren2 = 0, + cells = 130, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue}}) + +red_gen_pack = genericbackpack:new({ + health = 50, + armor = 50, + grenades = 0, + nails = 300, + shells = 300, + rockets = 300, + gren1 = 1, + gren2 = 0, + cells = 130, + respawntime = 15, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kRed}}) + +----------------------------------------------------------------------------- +-- overrides +----------------------------------------------------------------------------- + +-- teleporting +ENABLE_CC_TELEPORTERS = false +ENABLE_CP_TELEPORTERS = false + +-- command center +ENABLE_CC = false + +-- command points +CP_COUNT = 5 + +command_points = { + [1] = { + cp_number = 1, + defending_team = Team.kBlue, + cap_requirement = { [TEAM1] = CAP_REQ_CP1_CP5, [TEAM2] = CAP_REQ_CP1_CP5 }, + cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, + cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, + next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, + delay_before_retouch = { [TEAM1] = RETOUCH_DELAY, [TEAM2] = RETOUCH_DELAY }, + touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + point_value = { [TEAM1] = 1, [TEAM2] = 5 }, + score_timer_interval = { [TEAM1] = 30.00, [TEAM2] = 15.00 }, + hudstatusicon = "hud_cp_1.vtf", hudposx = -40, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + + [2] = { + cp_number = 2, + defending_team = Team.kUnassigned, + cap_requirement = { [TEAM1] = CAP_REQ_CP2RED_CP4BLUE, [TEAM2] = CAP_REQ_CP2BLUE_CP4RED }, + cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, + cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, + next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, + delay_before_retouch = { [TEAM1] = RETOUCH_DELAY_CP2BLUE_CP4RED, [TEAM2] = RETOUCH_DELAY_CP2RED_CP4BLUE }, + touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + point_value = { [TEAM1] = 2, [TEAM2] = 4 }, + score_timer_interval = { [TEAM1] = 22.50, [TEAM2] = 22.50 }, + hudstatusicon = "hud_cp_2.vtf", hudposx = -20, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + [3] = { + cp_number = 3, + defending_team = Team.kUnassigned, + cap_requirement = { [TEAM1] = CAP_REQ_CP3, [TEAM2] = CAP_REQ_CP3 }, + cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, + cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, + next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, + delay_before_retouch = { [TEAM1] = RETOUCH_DELAY, [TEAM2] = RETOUCH_DELAY }, + touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + point_value = { [TEAM1] = 3, [TEAM2] = 3 }, + score_timer_interval = { [TEAM1] = 30.00, [TEAM2] = 30.00 }, + hudstatusicon = "hud_cp_3.vtf", hudposx = 0, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + [4] = { + cp_number = 4, + defending_team = Team.kUnassigned, + cap_requirement = { [TEAM1] = CAP_REQ_CP2BLUE_CP4RED, [TEAM2] = CAP_REQ_CP2RED_CP4BLUE }, + cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, + cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, + next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, + delay_before_retouch = { [TEAM1] = RETOUCH_DELAY_CP2RED_CP4BLUE, [TEAM2] = RETOUCH_DELAY_CP2BLUE_CP4RED }, + touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + point_value = { [TEAM1] = 4, [TEAM2] = 2 }, + score_timer_interval = { [TEAM1] = 22.50, [TEAM2] = 22.50 }, + hudstatusicon = "hud_cp_4.vtf", hudposx = 20, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + [CP_COUNT] = { + cp_number = 5, + defending_team = Team.kRed, + cap_requirement = { [TEAM1] = CAP_REQ_CP1_CP5, [TEAM2] = CAP_REQ_CP1_CP5 }, + cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, + cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, + next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, + delay_before_retouch = { [TEAM1] = RETOUCH_DELAY, [TEAM2] = RETOUCH_DELAY }, + touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, + point_value = { [TEAM1] = 5, [TEAM2] = 1 }, + score_timer_interval = { [TEAM1] = 15.00, [TEAM2] = 30.00 }, + hudstatusicon = "hud_cp_5.vtf", hudposx = 40, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 } +} + +cap_resupply = { + health = 100, + armor = 300, + nails = 400, + shells = 400, + cells = 400, + grenades = 100, + rockets = 50, + detpacks = 0, + mancannons = 1, + gren1 = 2, + gren2 = 1 +} + +---------------------------------------------------------------------------- +-- Spawnpoints +---------------------------------------------------------------------------- + +-- Spawn Points +base_blue_spawn = info_ff_teamspawn:new({ cp_number = 0, validspawn = function(self,player) + return player:GetTeamId() == Team.kBlue and self.cp_number == cp_blue +end }) +base_red_spawn = info_ff_teamspawn:new({ cp_number = 0, validspawn = function(self,player) + return player:GetTeamId() == Team.kRed and self.cp_number == cp_red +end }) +bluespawn_cp1 = base_blue_spawn:new({cp_number=1}) +bluespawn_cp2 = base_blue_spawn:new({cp_number=2}) +bluespawn_cp3 = base_blue_spawn:new({cp_number=3}) +bluespawn_cp4 = base_blue_spawn:new({cp_number=4}) +redspawn_cp5 = base_red_spawn:new({cp_number=5}) +redspawn_cp4 = base_red_spawn:new({cp_number=4}) +redspawn_cp3 = base_red_spawn:new({cp_number=3}) +redspawn_cp2 = base_red_spawn:new({cp_number=2}) + +-- Spawn Doors (base entity) +blue_respawn_door = trigger_ff_script:new({cp_number = 0}) +red_respawn_door = trigger_ff_script:new({cp_number = 0}) + +-- Spawn Doors (validity checks) +function blue_respawn_door:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == Team.kBlue then --and self.cp_number <= cp_blue then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +function red_respawn_door:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == Team.kRed then --and self.cp_number >= cp_red then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +--Spawn Doors (Validity checks failure) +function blue_respawn_door:onfailtouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + --if player:GetTeamId() == Team.kBlue then + -- BroadCastMessageToPlayer( player, "You need to capture Command Point ".. self.cp_number .. " before you can use this respawn!" ) + --else + BroadCastMessageToPlayer( player, "Your team cannot use this respawn." ) + --end + end +end + +function red_respawn_door:onfailtouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + --if player:GetTeamId() == Team.kRed then + -- BroadCastMessageToPlayer( player, "You need to capture Command Point ".. self.cp_number .." before you can use this respawn!" ) + --else + BroadCastMessageToPlayer( player, "Your team cannot use this respawn." ) + --end + end +end + + +-- Spawn Doors (actual entities with command point condition attached) +bluerespawn_cp2 = blue_respawn_door:new({cp_number=2}) +bluerespawn_cp3 = blue_respawn_door:new({cp_number=3}) +bluerespawn_cp4 = blue_respawn_door:new({cp_number=4}) +redrespawn_cp2 = red_respawn_door:new({cp_number=2}) +redrespawn_cp3 = red_respawn_door:new({cp_number=3}) +redrespawn_cp4 = red_respawn_door:new({cp_number=4}) + +----------------------------------------------------------------------------- +-- Grates +----------------------------------------------------------------------------- + +detwall_trigger = trigger_ff_script:new({ team = Team.kUnassigned, team_name = "neutral" }) + +function detwall_trigger:onexplode( explosion_entity ) + if team == Team.kUnassigned then + return + end + + if IsDetpack( explosion_entity ) then + local detpack = CastToDetpack( explosion_entity ) + -- GetTemId() might not exist for buildables, they have their own seperate shit and it might be named differently + -- if detpack:GetTeamId() ~= self.team then -- both teams can destroy while commented out + + BroadCastSound( "misc.thunder" ) + + if self.team == Team.kRed then + if not RED_TUNNEL_WALL_BLOWN then + OutputEvent( self.team_name .. "_detwall", "Kill" ) + BroadCastMessage("Red's tunnel has been blown!" ) + RED_TUNNEL_WALL_BLOWN = true + else + OutputEvent( self.team_name .. "_detwall_template", "ForceSpawn" ) + BroadCastMessage("Red's tunnel has been sealed!" ) + RED_TUNNEL_WALL_BLOWN = false + end + elseif self.team == Team.kBlue then + if not BLUE_TUNNEL_WALL_BLOWN then + OutputEvent( self.team_name .. "_detwall", "Kill" ) + BroadCastMessage("Blue's tunnel has been blown!" ) + BLUE_TUNNEL_WALL_BLOWN = true + else + OutputEvent( self.team_name .. "_detwall_template", "ForceSpawn" ) + BroadCastMessage("Blue's tunnel has been sealed!" ) + BLUE_TUNNEL_WALL_BLOWN = false + end + end + -- end + end +end + +red_detwall_trigger = detwall_trigger:new({ team = Team.kRed, team_name = "red" }) +blue_detwall_trigger = detwall_trigger:new({ team = Team.kBlue, team_name = "blue" }) \ No newline at end of file diff --git a/maps/ff_waterpolo.lua b/maps/ff_waterpolo.lua new file mode 100644 index 0000000..048894a --- /dev/null +++ b/maps/ff_waterpolo.lua @@ -0,0 +1,20 @@ +-- ff_waterpolo.lua + + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_fortball_default") +IncludeScript("base_fortball") + + +----------------------------------------------------------------------------- +-- overrides +----------------------------------------------------------------------------- + + +----------------------------------------------------------------------------- +-- locations +----------------------------------------------------------------------------- + + diff --git a/maps/ff_waterpolo.txt b/maps/ff_waterpolo.txt new file mode 100644 index 0000000..45104b0 --- /dev/null +++ b/maps/ff_waterpolo.txt @@ -0,0 +1,30 @@ +FF_Waterpolo + +GAME MODE: Push Variant +Teams vie for control of the soccer ball. +The ball carrier must enter the enemy's goal + +Teams: Red VS Blue + +Objectives: + - Take the enemy flag + - Bring it to the enemy's goal + +Scoring: + - 10 points per goal + - 10 points given to the enemy team per own goal + - Team with most points at end of round wins + +Goalies: + - Each team can have 1 super-fast civialian goalie + - Goalies are invincible inside their own team's zone, but +take 3 times normal damage outside of their zone + - Goalies cannot go out-of-bounds or into the enemy's +zone + - Goalies return the ball if they touch it + +Notes: + - Landing out-of-bounds returns the ball + +Optional Objectives: + - Grenade packs can be found on the sides of the map \ No newline at end of file diff --git a/maps/ff_waterpolo_level_sounds.txt b/maps/ff_waterpolo_level_sounds.txt new file mode 100644 index 0000000..35ad1a3 --- /dev/null +++ b/maps/ff_waterpolo_level_sounds.txt @@ -0,0 +1,58 @@ +// game sounds for the ff_waterpolo map + +"ff_waterpolo.bizwarn" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_100dB" + "wave" "*misc/bizwarn.wav" +} + +"ff_waterpolo.bloop" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_100dB" + "wave" "*misc/bloop.wav" +} + +"ff_waterpolo.buzwarn" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_100dB" + "wave" "*misc/buzwarn.wav" +} + +"ff_waterpolo.dadeda" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_100dB" + "wave" "*misc/dadeda.wav" +} + +"ff_waterpolo.deeoo" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_100dB" + "wave" "*misc/deeoo.wav" +} + +"ff_waterpolo.doop" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_100dB" + "wave" "*misc/doop.wav" +} + +"ff_waterpolo.woop" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_100dB" + "wave" "*misc/woop.wav" +} + diff --git a/maps/ff_waterpolo_soundscapes.txt b/maps/ff_waterpolo_soundscapes.txt new file mode 100644 index 0000000..9164407 --- /dev/null +++ b/maps/ff_waterpolo_soundscapes.txt @@ -0,0 +1,55 @@ +// Ramp Room, Front Door, and Resups +"waterpolo.center" +{ + "dsp" "1" + "dsp_volume" "0.4" + + "playlooping" + { + "volume" "0.2" + "pitch" "100" + "wave" "ambient/water/rumble_rain_nowind.wav" + } + + "playlooping" + { + "volume" "0.5" + "wave" "ambient/water/lake_water.wav" + "pitch" "100" + } + + // Wind gusts (based on cliffe's cs_assault settings) + "playrandom" + { + "time" "20,30" + "volume" "0.3,0.4" + "pitch" "90,110" + + "rndwave" + { + "wave" "ambient/wind/wind_snippet1.wav" + "wave" "ambient/wind/wind_snippet2.wav" + "wave" "ambient/wind/wind_snippet3.wav" + "wave" "ambient/wind/wind_snippet4.wav" + "wave" "ambient/wind/wind_snippet5.wav" + } + } + + "playrandom" + { + "time" "30,60" + "volume" "0.4,0.6" + "pitch" "90,110" + "position" "random" + + "rndwave" + { + "wave" "ambient/weather/thunder1.wav" + "wave" "ambient/weather/thunder2.wav" + "wave" "ambient/weather/thunder3.wav" + "wave" "ambient/weather/thunder4.wav" + "wave" "ambient/weather/thunder5.wav" + } + } + +} \ No newline at end of file diff --git a/maps/ff_well.lua b/maps/ff_well.lua new file mode 100644 index 0000000..a3a1e12 --- /dev/null +++ b/maps/ff_well.lua @@ -0,0 +1,193 @@ + +-- ff_well.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_ctf") +IncludeScript("base_teamplay") +IncludeScript("base_location") +IncludeScript("base_respawnturret") + +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- +POINTS_PER_CAPTURE = 10 +FLAG_RETURN_TIME = 60 +----------------------------------------------------------------------------- +-- Locations +----------------------------------------------------------------------------- +location_blue_frupper = location_info:new({ text = "Flag Room Catwalks", team = Team.kBlue }) +location_red_frupper = location_info:new({ text = "Flag Room Catwalks", team = Team.kRed }) + +location_blue_frlower = location_info:new({ text = "Lower Flag Room", team = Team.kBlue }) +location_red_frlower = location_info:new({ text = "Lower Flag Room", team = Team.kRed }) + +location_blue_frwater = location_info:new({ text = "Flag Room Water", team = Team.kBlue }) +location_red_frwater = location_info:new({ text = "Flag Room Water", team = Team.kRed }) + +location_blue_ladder = location_info:new({ text = "Battlements Ladder", team = Team.kBlue }) +location_red_ladder = location_info:new({ text = "Battlements Ladder", team = Team.kRed }) + +location_blue_concexit = location_info:new({ text = "Conc Route Exit", team = Team.kBlue }) +location_red_concexit = location_info:new({ text = "Conc Route Exit", team = Team.kRed }) + +location_blue_canal = location_info:new({ text = "Yard Canal", team = Team.kBlue }) +location_red_canal = location_info:new({ text = "Yard Canal", team = Team.kRed }) + + +----------------------------------------------------------------------------- +-- Doors +----------------------------------------------------------------------------- + + +blue_door1_trigger = trigger_ff_script:new({ team = Team.kBlue }) + +function blue_door1_trigger:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return player:GetTeamId() == self.team + end + + return EVENT_DISALLOWED +end + +function blue_door1_trigger:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + OutputEvent("blue_door1_left", "Open") + OutputEvent("blue_door1_right", "Open") + end +end + + +blue_door2_trigger = trigger_ff_script:new({ team = Team.kBlue }) + +function blue_door2_trigger:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return player:GetTeamId() == self.team + end + + return EVENT_DISALLOWED +end + +function blue_door2_trigger:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + OutputEvent("blue_door2_left", "Open") + OutputEvent("blue_door2_right", "Open") + end +end + +red_door1_trigger = trigger_ff_script:new({ team = Team.kRed }) + +function red_door1_trigger:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return player:GetTeamId() == self.team + end + + return EVENT_DISALLOWED +end + +function red_door1_trigger:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + OutputEvent("red_door1_left", "Open") + OutputEvent("red_door1_right", "Open") + end +end + + +red_door2_trigger = trigger_ff_script:new({ team = Team.kRed }) + +function red_door2_trigger:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return player:GetTeamId() == self.team + end + + return EVENT_DISALLOWED +end + +function red_door2_trigger:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + OutputEvent("red_door2_left", "Open") + OutputEvent("red_door2_right", "Open") + end +end + + +----------------------------------------------------------------------------- +-- backpacks +----------------------------------------------------------------------------- + +wellpackgeneric = genericbackpack:new({ + health = 20, + armor = 15, + grenades = 60, + nails = 60, + shells = 60, + rockets = 60, + cells = 60, + mancannons = 1, + gren1 = 1, + gren2 = 1, + respawntime = 35, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +function wellpackgeneric:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- Grates +----------------------------------------------------------------------------- + +base_grate_trigger = trigger_ff_script:new({ team = Team.kUnassigned, team_name = "neutral" }) + +function base_grate_trigger:onexplode( explosion_entity ) + if IsDetpack( explosion_entity ) then + local detpack = CastToDetpack( explosion_entity ) + + -- GetTemId() might not exist for buildables, they have their own seperate shit and it might be named differently + if detpack:GetTeamId() ~= self.team then + OutputEvent( self.team_name .. "_grate", "Kill" ) + OutputEvent( self.team_name .. "_grate_wall", "Kill" ) + if self.team_name == "red" then BroadCastMessage("#FF_RED_GRATEBLOWN") end + if self.team_name == "blue" then BroadCastMessage("#FF_BLUE_GRATEBLOWN") end + end + end + + -- I think this is needed so grenades and other shit can blow up here. They won't fire the events, though. + return EVENT_ALLOWED +end + +red_grate_trigger = base_grate_trigger:new({ team = Team.kRed, team_name = "red" }) +blue_grate_trigger = base_grate_trigger:new({ team = Team.kBlue, team_name = "blue" }) + + +----------------------------------------------------------------------------- +-- Buttons +----------------------------------------------------------------------------- + +blue_fr_button = func_button:new({}) +function blue_fr_button:ondamage() OutputEvent( "blue_fr_grate_r", "Open" ) end +function blue_fr_button:ondamage() OutputEvent( "blue_fr_grate_l", "Open" ) end +function blue_fr_button:ontouch() OutputEvent( "blue_fr_grate_r", "Open" ) end +function blue_fr_button:ontouch() OutputEvent( "blue_fr_grate_l", "Open" ) end + +red_fr_button = func_button:new({}) +function red_fr_button:ondamage() OutputEvent( "red_fr_grate_r", "Open" ) end +function red_fr_button:ondamage() OutputEvent( "red_fr_grate_l", "Open" ) end +function red_fr_button:ontouch() OutputEvent( "red_fr_grate_r", "Open" ) end +function red_fr_button:ontouch() OutputEvent( "red_fr_grate_l", "Open" ) end + +blue_fd_button = func_button:new({}) +function blue_fd_button:ondamage() OutputEvent( "blue_door0", "Open" ) end +function blue_fd_button:ontouch() OutputEvent( "blue_door0", "Open" ) end + +red_fd_button = func_button:new({}) +function red_fd_button:ondamage() OutputEvent( "red_door0", "Open" ) end +function red_fd_button:ontouch() OutputEvent( "red_door0", "Open" ) end + diff --git a/maps/ff_well.txt b/maps/ff_well.txt new file mode 100644 index 0000000..067034a --- /dev/null +++ b/maps/ff_well.txt @@ -0,0 +1,5 @@ +CAPTURE THE FLAG + +Fight your way through the enemy base and bring back the flag to you own. The flag is located at the back of the base, high up overlooking the bridge. Open the water route using a detpack for a new route into the enemy base. + +The capture point is located in your own base, in the chamber below your flag room. \ No newline at end of file diff --git a/maps/ff_well_soundscapes.txt b/maps/ff_well_soundscapes.txt new file mode 100644 index 0000000..92e26fd --- /dev/null +++ b/maps/ff_well_soundscapes.txt @@ -0,0 +1,165 @@ +// The Well soundscape file +// Author: Mervaka +// Some sections based on existing valve soundscapes but modified + +"ff.drips1" +{ + "playrandom" + { + "volume" "0.1,0.3" + "pitch" "90,120" + "time" "0.5, 5.0" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/water/ff_distant_drip1.wav" + "wave" "ambient/water/ff_distant_drip2.wav" + "wave" "ambient/water/ff_distant_drip3.wav" + "wave" "ambient/water/ff_distant_drip4.wav" + } + } +} + +// Yard between two bases +"Well.yard" +{ + // DSP: 0 : "Normal (off)" + "dsp" "1" + "dsp_volume" "0.4" + + // constant wind base + "playlooping" + { + "volume" "0.2" + "pitch" "100" + "wave" "ambient/wind/ff_wasteland_wind.wav" + } + + // Wind gusts (based on cliffe's cs_assault settings) + "playrandom" + { + "time" "20,30" + "volume" "0.3,0.4" + "pitch" "90,110" + + "rndwave" + { + "wave" "ambient/wind/wind_snippet1.wav" + "wave" "ambient/wind/wind_snippet2.wav" + "wave" "ambient/wind/wind_snippet3.wav" + "wave" "ambient/wind/wind_snippet4.wav" + "wave" "ambient/wind/wind_snippet5.wav" + } + } +} + +// Large Open Flag Room +"Well.flagroom" +{ + // DSP: // 1 : "Generic" + "dsp" "1" + "dsp_volume" "0.6" + + // constant ambient base + "playlooping" + { + "volume" "0.1" + "pitch" "100" + "wave" "ambient/atmosphere/ff_ambience.wav" + } + "playsoundscape" + { + "name" "ff.drips1" + "volume" "1.0" + } + +} + +// Centre Bunker +"Well.bunker" +{ + "dsp" "1" + "dsp_volume" "0.5" + + "playsoundscape" + { + "name" "Well.yard" + "volume" "0.6" + } +} + +// Ramp Room, Front Door, and Resups +"Well.front" +{ + // DSP: 0 : "Normal (off)" + "dsp" "1" + "dsp_volume" "0.5" + // General ambient noise + "playlooping" + { + "volume" "0.1" + "pitch" "100" + "wave" "ambient/push/inside_amb1.wav" + } + + // constant ambient base + "playlooping" + { + "volume" "0.02" + "pitch" "100" + "wave" "ambient/atmosphere/ff_ambience.wav" + } + +// wind blowing through warehouse + "playrandom" + { + "time" "20,30" + "volume" "0.1,0.2" + "pitch" "90,110" + + "rndwave" + { + "ambient/wind/windgust.wav" + "ambient/wind/wind_moan1.wav" + "ambient/wind/wind_moan2.wav" + "ambient/wind/wind_moan4.wav" + } + } + + "playrandom" + { + "time" "30,60" + "volume" "0.3,0.5" + "pitch" "90,100" + "position" "random" + "soundlevel" "SNDLVL_140db" + "rndwave" + { + "wave" "ambient/materials/metal4.wav" + "wave" "ambient/materials/rustypipes1.wav" + "wave" "ambient/materials/rustypipes2.wav" + } + } +} + +// Attic +"Well.4bags" +{ + // DSP: 0 : "Normal (off)" + "dsp" "1" + "dsp_volume" "0.5 +" + "playsoundscape" + { + "name" "Well.front" + "volume" "1.0" + } + // constant ambient base + + "playsoundscape" + { + "name" "ff.drips1" + "volume" "0.1" + } +} \ No newline at end of file diff --git a/maps/includes/base.lua b/maps/includes/base.lua new file mode 100644 index 0000000..4354971 --- /dev/null +++ b/maps/includes/base.lua @@ -0,0 +1,198 @@ + +-- base.lua + + +----------------------------------------------------------------------------- +-- This file is loaded automatically whenever a map is loaded. +-- Do not change this file. +----------------------------------------------------------------------------- +local _G = getfenv(0) + + +----------------------------------------------------------------------------- +-- defines +----------------------------------------------------------------------------- +-- Events +EVENT_ALLOWED = true +EVENT_DISALLOWED = false + + +----------------------------------------------------------------------------- +-- set a cvar, but check to make sure it's not already set correctly +----------------------------------------------------------------------------- +function set_cvar( cvarname, value ) + if GetConvar( cvarname ) ~= value then + SetConvar( cvarname, value ) + end +end + + +----------------------------------------------------------------------------- +-- Output Events +----------------------------------------------------------------------------- +function OpenDoor(name) OutputEvent( name, "Open" ) end +function CloseDoor(name) OutputEvent( name, "Close" ) end +function ToggleDoor(name) OutputEvent( name, "Toggle" ) end + + +----------------------------------------------------------------------------- +-- baseclass (everything derives from this guy) +----------------------------------------------------------------------------- +baseclass = { } +function baseclass:new (o) + -- create object if user does not provide one + o = o or {} + setmetatable(o, self) + self.__index = self + return o +end + + +----------------------------------------------------------------------------- +-- reset everything +----------------------------------------------------------------------------- +function RespawnAllPlayers() + ApplyToAll({ AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, AT.kStopPrimedGrens, AT.kReloadClips, AT.kAllowRespawn, AT.kReturnDroppedItems }) +end + + +----------------------------------------------------------------------------- +-- lowercase c "Broadcast" functions, because uppercase C "BroadCast" functions are lame +----------------------------------------------------------------------------- +function BroadcastMessage( message ) + BroadCastMessage( message ) +end + +function BroadcastMessageToPlayer( player, message ) + BroadCastMessageToPlayer( player, message ) +end + +function BroadcastSound( soundname ) + BroadCastSound( soundname ) +end + +function BroadcastSoundToPlayer( player, soundname ) + BroadCastSoundToPlayer( player, soundname ) +end + + +----------------------------------------------------------------------------- +-- trigger_ff_script +----------------------------------------------------------------------------- +trigger_ff_script = baseclass:new({}) +function trigger_ff_script:allowed() return EVENT_ALLOWED end +function trigger_ff_script:ontouch() end +function trigger_ff_script:ontrigger() end +function trigger_ff_script:onendtouch() end +function trigger_ff_script:onfailtouch() end +function trigger_ff_script:onexplode() return EVENT_ALLOWED end +function trigger_ff_script:onbuild() return EVENT_ALLOWED end +function trigger_ff_script:onfailuse() end +function trigger_ff_script:onuse() end +function trigger_ff_script:onactive() end +function trigger_ff_script:oninactive() end +function trigger_ff_script:onremoved() end +function trigger_ff_script:onrestored() end + +function trigger_ff_script:spawn() + + -- notify the bot if this is a goal type + local info = CastToTriggerScript(entity) + if(info ~= nil) then + if self.botgoaltype and self.team then + info:SetBotGoalInfo(self.botgoaltype, self.team) + end + end +end + + +----------------------------------------------------------------------------- +-- trigger_ff_clip +----------------------------------------------------------------------------- +trigger_ff_clip = baseclass:new({}) +function trigger_ff_clip:spawn() + local clip = CastToTriggerClip(entity) + if (clip ~= nil) then + if self.clipflags then + clip:SetClipFlags(self.clipflags) + end + end +end + + +----------------------------------------------------------------------------- +-- func_button +----------------------------------------------------------------------------- +func_button = baseclass:new({}) +function func_button:allowed() return true end +function func_button:ondamage() end +function func_button:ontouch() end +function func_button:onuse() end +function func_button:onfailuse() end + + +----------------------------------------------------------------------------- +-- info_ff_script +----------------------------------------------------------------------------- +info_ff_script = baseclass:new({ model = "models/items/healthkit.mdl" }) +function info_ff_script:onreturn() end +function info_ff_script:ondrop() end +function info_ff_script:onownerdie() end +function info_ff_script:onownerforcerespawn() end +function info_ff_script:onownerfeign() end +function info_ff_script:onactive() end +function info_ff_script:oninactive() end +function info_ff_script:onremoved() end +function info_ff_script:onrestored() end +function info_ff_script:onexplode() end +function info_ff_script:dropatspawn() return false end +function info_ff_script:usephysics() return false end +function info_ff_script:hasshadow() return true end + +-- anims must be named certain things... +function info_ff_script:hasanimation() return false end + +-- For when this object is carried, these offsets are used to place +-- the info_ff_script relative to the objects GetAbsOrigin() +function info_ff_script:attachoffset() + local offset = Vector( 0, 0, 0 ) + return offset +end + +function info_ff_script:precache() + PrecacheModel(self.model) +end + +function info_ff_script:spawn() + -- set model and skin + local info = CastToInfoScript( entity ) + info:SetModel(self.model) + if self.modelskin then + info:SetSkin(self.modelskin) + end + + -- setup touch flags + if self.touchflags ~= nil then info:SetTouchFlags(self.touchflags) end + if self.disallowtouchflags ~= nil then info:SetDisallowTouchFlags(self.disallowtouchflags) end + + -- notify the bot if this is a goal type + if(info ~= nil) then + if self.botgoaltype then + info:SetBotGoalInfo(self.botgoaltype) + end + end + + if self.renderfx ~= nil then + info:SetRenderFx(self.renderfx) + end +end +function info_ff_script:gettouchsize( mins, maxs ) end +function info_ff_script:getphysicssize( mins, maxs ) end +function info_ff_script:getbloatsize() return 12 end + + +----------------------------------------------------------------------------- +-- info_ff_teamspawn +----------------------------------------------------------------------------- +info_ff_teamspawn = baseclass:new({}) +function info_ff_teamspawn:validspawn() return true end diff --git a/maps/includes/base_ad.lua b/maps/includes/base_ad.lua new file mode 100644 index 0000000..b1442c4 --- /dev/null +++ b/maps/includes/base_ad.lua @@ -0,0 +1,833 @@ +-- base_ad.lua +-- Attack / Defend gametype + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay") + +----------------------------------------------------------------------------- +-- globals +----------------------------------------------------------------------------- +if NUM_PHASES == nil then NUM_PHASES = 3; end +if INITIAL_ROUND_LENGTH == nil then INITIAL_ROUND_LENGTH = 90 +POINTS_PER_CAPTURE = 25 +POINTS_PER_PERIOD = 1 +POSTCAP_TIMER = 2 + +if ATTACKERS == nil then ATTACKERS = Team.kBlue; end +if DEFENDERS == nil then DEFENDERS = Team.kRed; end +--if MAP_LENGTH == nil then MAP_LENGTH = 1436; end -- 23 minutes 56 seconds, 4 seconds less than the default timelimit of 24 minutes. + +if ATTACKERS_OBJECTIVE_ENTITY == nil then ATTACKERS_OBJECTIVE_ENTITY = nil end + +INITIAL_FUSE_TIMER = 80 +BLOW_CP1_ROUTE_TIMER = 300 +BLOW_CP2_ROUTE_TIMER = 780 + +allow_win = true +phase = 1 +current_timer = 0 +carried_by = nil + +function startup( ) + + SetGameDescription( "Attack Defend" ) + + -- 4 seconds less than mp_timelimit, just as was the case when it was fixed (I assume it always takes 4 seconds to initialise?) + MAP_LENGTH = (60 * GetConvar( "mp_timelimit" )) - 4; + PERIOD_TIME = MAP_LENGTH * POINTS_PER_PERIOD / 100; + + -- set up team limit + -- disable all teams + for i = Team.kBlue, Team.kGreen do + local team = GetTeam( i ) + if i then + team:SetPlayerLimit( -1 ) + end + end + + -- then re-enable attackers/defenders + local team = GetTeam( ATTACKERS ) + team:SetPlayerLimit( 0 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + local team = GetTeam( DEFENDERS ) + team:SetPlayerLimit( 0 ) + team:SetClassLimit( Player.kCivilian, -1 ) + team:SetClassLimit(Player.kScout, -1) + + -- Should this be map specific? + SetTeamName( ATTACKERS, "#FF_Attackers") + SetTeamName( DEFENDERS, "#FF_Defenders" ) + + -- start the timer for the points + AddScheduleRepeating( "addpoints", PERIOD_TIME, addpoints ) + + setup_door_timer( "cp1_gate", INITIAL_ROUND_LENGTH ) + setup_map_timers() + + allow_win = true + + cp1_flag.enabled = true + cp1_flag.team = ATTACKERS + for i,v in ipairs({"cp1_flag", "cp2_flag", "cp3_flag"}) do + local flag = GetInfoScriptByName(v) + if flag then + flag:SetModel(_G[v].model) + flag:SetSkin(teamskins[ATTACKERS]) + if i == 1 then + flag:Restore() + else + flag:Remove() + end + end + end + + -- Remove future phase flags + flag_remove( "cp2_flag" ) + flag_remove( "cp3_flag" ) + + -- add map initialise stuff. Needs to be done via lua for synchronisation + AddSchedule("blow_first_gate", INITIAL_FUSE_TIMER, blow_first_gate ) + AddSchedule("blow_cp1_extra_route", BLOW_CP1_ROUTE_TIMER, blow_cp1_extra_route ) + AddSchedule("blow_cp2_extra_route", BLOW_CP2_ROUTE_TIMER, blow_cp2_extra_route ) + + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + UpdateTeamObjectiveIcon( GetTeam(ATTACKERS), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(DEFENDERS), ATTACKERS_OBJECTIVE_ENTITY ) +end + +function blow_first_gate( ) + OutputEvent( "fuse01", "StartForward" ) -- delay of 80 secs +end + +function blow_cp1_extra_route( ) + OutputEvent( "cp1_extraroute", "Break" ) -- delay of 300 secs +end + +function blow_cp2_extra_route( ) + OutputEvent( "cp2_extraroute", "Break" ) -- delay of 780 secs +end + + +----------------------------------------- +-- Remove a flag by name +----------------------------------------- +function flag_remove( flag_name ) + local flag = GetInfoScriptByName( flag_name ) + if flag then + flag:Remove() + _G[flag_name].enabled = false + end +end + +----------------------------------------- +-- Restore a flag by name +----------------------------------------- +function flag_restore( flag_name ) + local flag = GetInfoScriptByName( flag_name ) + if flag then + flag:Restore() + _G[flag_name].enabled = true + end +end + +----------------------------------------- +-- +----------------------------------------- +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + player:AddHealth( 400 ) + player:AddArmor( 400 ) + + -- Remove stuff + player:RemoveAmmo( Ammo.kNails, 400 ) + player:RemoveAmmo( Ammo.kShells, 400 ) + player:RemoveAmmo( Ammo.kRockets, 400 ) + player:RemoveAmmo( Ammo.kCells, 400 ) + player:RemoveAmmo( Ammo.kGren2, 4 ) + + -- Add items (similar to both teams) + player:AddAmmo( Ammo.kShells, 200 ) + player:AddAmmo( Ammo.kRockets, 30 ) + player:AddAmmo( Ammo.kNails, 200 ) + + -- Defenders get... + if player:GetTeamId() == DEFENDERS then + -- Player is at full armor now, so we can + -- easily reduce by some percent + -- but were not going to because + -- theres no reason to do so + -- player:RemoveArmor( ( player:GetArmor() * .25 ) ) + + player:RemoveAmmo( Ammo.kGren1, 4 ) + player:AddAmmo( Ammo.kCells, 200 ) + elseif player:GetTeamId() == ATTACKERS then + -- Attackers get... + player:AddAmmo( Ammo.kCells, 200 ) + end + +-- if player:GetTeamId() == ATTACKERS then + UpdateObjectiveIcon( player, ATTACKERS_OBJECTIVE_ENTITY ) +-- elseif player:GetTeamId() == DEFENDERS then +-- UpdateObjectiveIcon( player, nil ) +-- end +end + +function addpoints( ) + local team = GetTeam( DEFENDERS ) + team:AddScore( POINTS_PER_PERIOD ) +end + +----------------------------------------- +-- base flag +----------------------------------------- +-- default +base_ad_flag = baseflag:new({ + modelskin = teamskins[ATTACKERS], + name = "base_ad_flag", + team = ATTACKERS, + phase = 1, + hudicon = team_hudicons[ATTACKERS], + touchflags = {AllowFlags.kOnlyPlayers, AllowFlags.kBlue, AllowFlags.kGreen, AllowFlags.kYellow} +}) + + -- if ATTACKERS == Team.kRed then + -- ConsoleToAll("Setting up RED ATTACKERS FLAG") + -- base_ad_flag.hudicon = "hud_flag_red.vtf" + -- base_ad_flag.touchflags = {AllowFlags.kOnlyPlayers, AllowFlags.kRed} + -- elseif ATTACKERS == Team.kGreen then + -- ConsoleToAll("Setting up GREEN ATTACKERS FLAG") + -- base_ad_flag.hudicon = "hud_flag_green.vtf" + -- base_ad_flag.touchflags = {AllowFlags.kOnlyPlayers, AllowFlags.kGreen} + -- elseif ATTACKERS == Team.kBlue then + -- ConsoleToAll("Setting up BLUE ATTACKERS FLAG") + -- base_ad_flag.hudicon = "hud_flag_blue.vtf" + -- base_ad_flag.touchflags = {AllowFlags.kOnlyPlayers, AllowFlags.kBlue} + -- elseif ATTACKERS == Team.kYellow then + -- ConsoleToAll("Setting up Yellow ATTACKERS FLAG") + -- base_ad_flag.hudicon = "hud_flag_yellow.vtf" + -- base_ad_flag.touchflags = {AllowFlags.kOnlyPlayers, AllowFlags.kYellow} + -- end +end + +function base_ad_flag:dropitemcmd( owner_entity ) +-- DO NOTHING! +-- -- throw the flag +-- local flag = CastToInfoScript(entity) +-- flag:Drop(FLAG_RETURN_TIME, FLAG_THROW_SPEED) +-- +-- if IsPlayer( owner_entity ) then +-- local player = CastToPlayer( owner_entity ) +-- player:RemoveEffect( EF.kSpeedlua1 ) +-- +-- -- Remove any hud icons with identifier "base_ad_flag" +-- RemoveHudItem( player, "base_ad_flag" ) +-- end +end + + +function base_ad_flag:touch( touch_entity ) + -- should only respond to players + if (IsPlayer(touch_entity) == false) then + return + end + + local player = CastToPlayer(touch_entity) + local teamId = player:GetTeamId() + + -- pickup if they can + if self.notouch then + if self.notouch[player:GetId()] then return; end + end + + if teamId == ATTACKERS and phase == self.phase then + if phase == 1 then + --BroadCastMessageToPlayer(player, "#FF_AD_TAKE1") + SmartMessage(player, "#FF_AD_TAKE1", "#FF_TEAMPICKUP", "#FF_OTHERTEAMPICKUP", Color.kGreen, Color.kGreen, Color.kRed) + elseif phase == 2 then + --BroadCastMessageToPlayer(player, "#FF_AD_TAKE2") + SmartMessage(player, "#FF_AD_TAKE2", "#FF_TEAMPICKUP", "#FF_OTHERTEAMPICKUP", Color.kGreen, Color.kGreen, Color.kRed) + else + --BroadCastMessageToPlayer(player, "#FF_AD_TAKE3") + SmartMessage(player, "#FF_AD_TAKE3", "#FF_TEAMPICKUP", "#FF_OTHERTEAMPICKUP", Color.kGreen, Color.kGreen, Color.kRed) + end + + SmartSound(player, "yourteam.flagstolen", "yourteam.flagstolen", "otherteam.flagstolen") + RandomFlagTouchSpeak( player ) + + -- have player pick up the flag and lose his disguise (for spy class) + local flag = CastToInfoScript( entity ) + if flag ~= nil then + flag:Pickup( player) + player:AddEffect( EF.kSpeedlua1, -1, 0, 0.65 ) + player:SetDisguisable( false ) + -- if the player is a spy, then force him to lose his cloak + player:SetCloakable( false ) + + self.hudicon = team_hudicons[ATTACKERS] + -- Add hud icon to show we're carrying the flag + AddHudIcon( player, self.hudicon, flag:GetName(), self.hudx, self.hudy, self.hudstatusiconw, self.hudstatusiconh, self.hudalign ) + + -- change objective icons + ATTACKERS_OBJECTIVE_ENTITY = player + UpdateTeamObjectiveIcon( GetTeam(ATTACKERS), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(DEFENDERS), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateObjectiveIcon( player, GetEntityByName( "cp"..self.phase.."_cap" ) ) + + LogLuaEvent(player:GetId(), 0, "flag_touch", "flag_name", flag:GetName(), "player_origin", (string.format("%0.2f",player:GetOrigin().x) .. ", " .. string.format("%0.2f",player:GetOrigin().y) .. ", " .. string.format("%0.1f",player:GetOrigin().z) ), "player_health", "" .. player:GetHealth()); + -- show on the deathnotice board + --ObjectiveNotice( player, "grabbed the flag" ) + + carried_by = player:GetName() + destroy_return_timer() + update_hud() + end + end +end + +function base_ad_flag:onownerdie( owner_entity ) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + player:RemoveEffect( EF.kSpeedlua1 ) + + player:SetDisguisable( true ) + player:SetCloakable( true ) + + -- Remove any hud icons with identifier "base_ad_flag" + RemoveHudItem( player, "base_ad_flag" ) + + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + UpdateObjectiveIcon( player, nil ) + UpdateTeamObjectiveIcon( GetTeam(ATTACKERS), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(DEFENDERS), ATTACKERS_OBJECTIVE_ENTITY ) + + -- remove flag icon from hud + RemoveHudItem( player, flag:GetName() ) + RemoveHudItemFromAll( flag:GetName() .. "_c" ) + AddHudIconToAll( self.hudstatusicondropped, ( flag:GetName() .. "_d" ), self.hudstatusiconx, self.hudstatusicony, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconalign ) + self.status = 2 + + setup_return_timer() + update_hud() + end +end + +function base_ad_flag:onreturn( ) + -- let the teams know that the flag was returned + local team = GetTeam( self.team ) + SmartTeamMessage(team, "#FF_TEAMRETURN", "#FF_OTHERTEAMRETURN", Color.kYellow, Color.kYellow) + SmartTeamSound(team, "yourteam.flagreturn", "otherteam.flagreturn") + SmartTeamSpeak(team, "CTF_FLAGBACK", "CTF_EFLAGBACK") + local flag = CastToInfoScript( entity ) + + RemoveHudItemFromAll( flag:GetName() .. "_d" ) + RemoveHudItemFromAll( flag:GetName() .. "_c" ) + AddHudIconToAll( self.hudstatusiconhome, ( flag:GetName() .. "_h" ), self.hudstatusiconx, self.hudstatusicony, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconalign ) + self.status = 0 + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + UpdateTeamObjectiveIcon( GetTeam(ATTACKERS), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(DEFENDERS), ATTACKERS_OBJECTIVE_ENTITY ) + + LogLuaEvent(0, 0, "flag_returned","flag_name",flag:GetName()); + + destroy_return_timer() + update_hud() +end + +----------------------------------------- +-- base capture point +----------------------------------------- +base_ad_cap = basecap:new({ + phase = 0, + doorname = "cp2_gate", + duration = 90, + team = ATTACKERS +}) + +function base_ad_cap:allowed ( allowed_entity ) + if phase ~= self.phase then + return false + end + + -- only respond to players + if ( IsPlayer( allowed_entity ) == false ) then + return false + end + + if allow_win == false then + return false + end + + local player = CastToPlayer( allowed_entity ) + + -- check if the player has the flag + for i,v in ipairs( self.item ) do + if player:HasItem( v ) then + player:RemoveEffect( EF.kSpeedlua1 ) + + -- Remove any hud icons with identifier "base_ad_flag" + RemoveHudItem( player, "base_ad_flag" ) + + return true + end + end + + return false +end + +function base_ad_cap:oncapture( player, item ) + + if phase == 1 then + map_cap1() + elseif phase == 2 then + map_cap2() + else + allow_win = false + map_attackers_win() + end + + player:AddFortPoints(500, "#FF_FORTPOINTS_CAPTUREPOINT") + + if self.closedoor then + CloseDoor(self.closedoor) + end + + -- remove objective icon + ATTACKERS_OBJECTIVE_ENTITY = nil + UpdateTeamObjectiveIcon( GetTeam(ATTACKERS), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(DEFENDERS), ATTACKERS_OBJECTIVE_ENTITY ) + + -- Remove previous phase flag + flag_remove( item ) + + -- Delay for a couple seconds after the cap + AddSchedule( "cap_delay_timer", POSTCAP_TIMER, cap_delay_timer, self ) +end + +----------------------------------------- +-- waste a couple seconds before respawning/ending +----------------------------------------- +function cap_delay_timer( cap ) + if phase == NUM_PHASES then + -- it's the last round. end and stuff + GoToIntermission() + RemoveSchedule( "addpoints" ) + else + phase = phase + 1 + + -- setup double cap points for the last round + if phase == NUM_PHASES then + POINTS_PER_CAPTURE = POINTS_PER_CAPTURE * 2 + end + + -- Restore next flag + if phase == 2 then + flag_restore( "cp2_flag" ) + elseif phase == 3 then + flag_restore( "cp3_flag" ) + end + + -- update objective icon + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + + setup_door_timer( cap.doorname, cap.duration) + ApplyToAll( { AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, AT.kStopPrimedGrens, AT.kReloadClips } ) + end +end + +function setup_door_timer( doorname, duration ) + AddSchedule( "round_start", duration, round_start, doorname ) + if duration > 65 then AddSchedule( "round_60secwarn", duration-60, round_60secwarn ) end + if duration > 35 then AddSchedule( "round_30secwarn", duration-30, round_30secwarn ) end + if duration > 15 then AddSchedule( "round_10secwarn", duration-10, round_10secwarn ) end +end + +function round_start( doorname ) + BroadCastMessage( "#FF_AD_GATESOPEN" ) + BroadCastSound( "otherteam.flagstolen" ) + SpeakAll( "AD_GATESOPEN" ) + OpenDoor( doorname ) +end + +function round_60secwarn( ) + BroadCastMessage( "#FF_ROUND_60SECWARN" ) +end + +function round_30secwarn( ) + BroadCastMessage( "#FF_ROUND_30SECWARN" ) +end + +function round_10secwarn( ) + BroadCastMessage( "#FF_ROUND_10SECWARN" ) +end + + +---------------- +-- map timers -- +---------------- + +function setup_map_timers( ) + local timelimit = MAP_LENGTH + + AddSchedule( "map_10mintimer", timelimit-600, map_timewarn, 600 ) + AddSchedule( "map_5mintimer", timelimit-300, map_timewarn, 300 ) + AddSchedule( "map_2mintimer", timelimit-120, map_timewarn, 120 ) + AddSchedule( "map_60sectimer", timelimit-60, map_timewarn, 60 ) + AddSchedule( "map_30sectimer", timelimit-30, map_timewarn, 30 ) + AddSchedule( "map_10sectimer", timelimit-10, map_timewarn, 10 ) + AddSchedule( "map_9sectimer", timelimit-9, map_timewarn, 9 ) + AddSchedule( "map_8sectimer", timelimit-8, map_timewarn, 8 ) + AddSchedule( "map_7sectimer", timelimit-7, map_timewarn, 7 ) + AddSchedule( "map_6sectimer", timelimit-6, map_timewarn, 6 ) + AddSchedule( "map_5sectimer", timelimit-5, map_timewarn, 5 ) + AddSchedule( "map_4sectimer", timelimit-4, map_timewarn, 4 ) + AddSchedule( "map_3sectimer", timelimit-3, map_timewarn, 3 ) + AddSchedule( "map_2sectimer", timelimit-2, map_timewarn, 2 ) + AddSchedule( "map_1sectimer", timelimit-1, map_timewarn, 1 ) + AddSchedule( "map_timer", timelimit, map_defenders_win ) +end + +function map_attackers_win( ) + RemoveSchedule( "map_10mintimer" ) + RemoveSchedule( "map_5mintimer" ) + RemoveSchedule( "map_2mintimer" ) + RemoveSchedule( "map_60sectimer" ) + RemoveSchedule( "map_30sectimer" ) + RemoveSchedule( "map_10sectimer" ) + RemoveSchedule( "map_9sectimer" ) + RemoveSchedule( "map_8sectimer" ) + RemoveSchedule( "map_7sectimer" ) + RemoveSchedule( "map_6sectimer" ) + RemoveSchedule( "map_5sectimer" ) + RemoveSchedule( "map_4sectimer" ) + RemoveSchedule( "map_3sectimer" ) + RemoveSchedule( "map_2sectimer" ) + RemoveSchedule( "map_1sectimer" ) + RemoveSchedule( "map_timer" ) + BroadCastSound( "yourteam.flagcap" ) + --BroadCastMessage("#FF_AD_" .. TeamName(ATTACKERS) .. "#FF_WIN") + BroadCastMessage( "#FF_AD_BLUEWIN" ) + --SpeakAll( "AD_" .. TeamName( ATTACKERS ) .. "CAP".. TeamName( DEFENDERS ) ) + SpeakAll( "AD_CAP" ) +end + +function map_defenders_win( ) + if allow_win == false then + return false + end + + --BroadCastSound("yourteam.flagcap") + BroadCastMessage("#FF_AD_REDWIN") + --SpeakAll( "AD_HOLD_" .. TeamName(DEFENDERS) ) + SpeakAll( "AD_HOLD" ) + allow_win = false + --Defenders wins, call Intermission! + phase = NUM_PHASES + RemoveSchedule( "addpoints" ) + addpoints() + AddSchedule( "cap_delay_timer", POSTCAP_TIMER, cap_delay_timer, self ) +end + +function map_timewarn( time ) + BroadCastMessage( "#FF_MAP_" .. time .. "SECWARN" ) + SpeakAll( "AD_" .. time .. "SEC" ) +end + +function map_cap1( ) + BroadCastSound( "yourteam.flagcap" ) + BroadCastMessage( "#FF_AD_CAP1" ) + SpeakAll( "AD_CP1" ) + --SpeakAll("AD_CP1_" .. TeamName(ATTACKERS)) +end + +function map_cap2( ) + BroadCastSound( "yourteam.flagcap" ) + BroadCastMessage( "#FF_AD_CAP2" ) + SpeakAll( "AD_CP2" ) + --SpeakAll("AD_CP2_" .. TeamName(ATTACKERS)) +end + +function timer_schedule() + current_timer = current_timer -1 +end + +function setup_return_timer() + RemoveSchedule( "timer_tobase_schedule" ) + current_timer = FLAG_RETURN_TIME + + AddScheduleRepeatingNotInfinitely( "timer_return_schedule", 1, timer_schedule, current_timer) +end + +function destroy_return_timer() + RemoveSchedule( "timer_return_schedule" ) +end + +----------------------------------------- +-- spawn info stuffs +----------------------------------------- +function start_allowedmethod( self, player_entity ) + + if ( IsPlayer( player_entity ) == false ) then + return false + end + + local player = CastToPlayer( player_entity ) + local teamId = player:GetTeamId( ) + + return (teamId == ATTACKERS and phase == 1) +end + +function alpha_allowedmethod( self, player_entity ) + if ( IsPlayer( player_entity ) == false ) then + return false + end + + local player = CastToPlayer( player_entity ) + local teamId = player:GetTeamId( ) + + return (teamId == ATTACKERS and phase == 2) + or (teamId == DEFENDERS and phase == 1) +end + +function beta_allowedmethod( self, player_entity ) + if ( IsPlayer( player_entity ) == false ) then + return false + end + + local player = CastToPlayer( player_entity ) + local teamId = player:GetTeamId( ) + + return (teamId == ATTACKERS and phase == 3) + or (teamId == DEFENDERS and phase == 2) +end + +function final_allowedmethod( self, player_entity ) + if ( IsPlayer( player_entity ) == false ) then + return false + end + + local player = CastToPlayer( player_entity ) + local teamId = player:GetTeamId( ) + + return (teamId == DEFENDERS and phase == 3) +end + + +----------------------------------------- +-- instanciate everything +----------------------------------------- +cp1_flag = base_ad_flag:new({ phase = 1 }) +cp2_flag = base_ad_flag:new({ phase = 2 }) +cp3_flag = base_ad_flag:new({ phase = 3 }) + +cp1_cap = base_ad_cap:new({ item={"cp1_flag"}, phase = 1, doorname = "cp2_gate", closedoor = "cp1_exit"}) +cp2_cap = base_ad_cap:new({ item={"cp2_flag"}, phase = 2, doorname = "cp3_gate", closedoor = "cp2_exit"}) +cp3_cap = base_ad_cap:new({ item={"cp3_flag"}, phase = 3, doorname = "", closedoor = "cp3_exit"}) + +start_door = respawndoor:new({allowed = start_allowedmethod}) +start_spawn = {validspawn = start_allowedmethod} +alpha_door = respawndoor:new({allowed = alpha_allowedmethod}) +alpha_spawn = {validspawn = alpha_allowedmethod} +beta_door = respawndoor:new({allowed = beta_allowedmethod}) +beta_spawn = {validspawn = beta_allowedmethod} +final_door = respawndoor:new({allowed = final_allowedmethod}) +final_spawn = {validspawn = final_allowedmethod} + + +------------------------------------------------ +-- hud info +------------------------------------------------ +function flaginfo( player_entity ) + + local player = CastToPlayer( player_entity ) + + local flag = GetInfoScriptByName("cp"..phase.."_flag") + local flagname = flag:GetName() + + attackers = ATTACKERS + defenders = DEFENDERS + + --RemoveHudItemFromAll( "background" ) + --AddHudIconToAll( "hud_statusbar_256_128.vtf", "background", -64, 32, 128, 70, 3 ) + + RemoveHudItem( player, "cp_flag_c" ) + RemoveHudItem( player, "cp_flag_d" ) + RemoveHudItem( player, "cp_flag_h" ) + RemoveHudItem( player, "flag_tobase_timer" ) + RemoveHudItem( player, "flag_tobase_text" ) + RemoveHudItem( player, "flag_return_timer" ) + RemoveHudItem( player, "flag_return_text" ) + RemoveHudItem( player, "flag_carried_by" ) + RemoveHudItem( player, "flag_carried_by2" ) + RemoveHudItem( player, "flag_athome" ) + RemoveHudItem( player, "flag_athome2" ) + + if attackers == Team.kBlue then + hudstatusicondropped = "hud_flag_dropped_blue.vtf" + hudstatusiconhome = "hud_flag_home_blue.vtf" + hudstatusiconcarried = "hud_flag_carried_blue.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kRed then + hudstatusicondropped = "hud_flag_dropped_red.vtf" + hudstatusiconhome = "hud_flag_home_red.vtf" + hudstatusiconcarried = "hud_flag_carried_red.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + elseif attackers == Team.kYellow then + hudstatusicondropped = "hud_flag_dropped_yellow.vtf" + hudstatusiconhome = "hud_flag_home_yellow.vtf" + hudstatusiconcarried = "hud_flag_carried_yellow.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kGreen then + hudstatusicondropped = "hud_flag_dropped_green.vtf" + hudstatusiconhome = "hud_flag_home_green.vtf" + hudstatusiconcarried = "hud_flag_carried_green.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + end + + flag_hudstatusiconx = 4 + flag_hudstatusicony = 42 + flag_hudstatusiconw = 15 + flag_hudstatusiconh = 15 + flag_hudstatusiconalign = 3 + text_hudstatusx = 0 + text_hudstatusy = flag_hudstatusicony + 24 + text_hudstatusalign = 4 + + if _G[flagname].enabled == true then + if flag:IsCarried() then + AddHudText(player, "flag_carried_by", "#AD_FlagCarriedBy", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudText(player, "flag_carried_by2", carried_by, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + AddHudIcon(player, hudstatusiconcarried, ( "cp_flag_c" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif flag:IsDropped() and _G[flagname].status == 2 then + AddHudText(player, "flag_return_text", "#AD_FlagReturn", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudTimer(player, "flag_return_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign) + AddHudIcon(player, hudstatusicondropped, ( "cp_flag_d" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif _G[flagname].status == 0 then + AddHudText(player, "flag_athome", "#AD_FlagIsAt", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudText(player, "flag_athome2", "#AD_ASpawn", text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + AddHudIcon(player, hudstatusiconhome, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + end + + RemoveHudItem( player, "Zone_Team"..attackers ) + RemoveHudItem( player, "Zone_Team"..defenders ) + RemoveHudItem( player, "Zone_Phase"..attackers ) + RemoveHudItem( player, "Zone_Phase"..defenders ) + + od_hudstatusiconx = -28 + od_hudstatusicony = 38 + od_hudstatusiconw = 24 + od_hudstatusiconh = 24 + od_hudstatusiconalign = 3 + + if player:GetTeamId() == attackers then + AddHudIcon( player, "hud_offense.vtf", "Zone_Team"..attackers, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..attackers, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + else + AddHudIcon( player, "hud_defense.vtf", "Zone_Team"..defenders, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..defenders, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + end + +end + +function update_hud() + + local flag = GetInfoScriptByName("cp"..phase.."_flag") + local flagname = flag:GetName() + + attackers = ATTACKERS + defenders = DEFENDERS + + --RemoveHudItemFromAll( "background" ) + --AddHudIconToAll( "hud_statusbar_256_128.vtf", "background", -64, 32, 128, 70, 3 ) + + RemoveHudItemFromAll( "cp_flag_c" ) + RemoveHudItemFromAll( "cp_flag_d" ) + RemoveHudItemFromAll( "cp_flag_h" ) + RemoveHudItemFromAll( "flag_tobase_timer" ) + RemoveHudItemFromAll( "flag_tobase_text" ) + RemoveHudItemFromAll( "flag_return_timer" ) + RemoveHudItemFromAll( "flag_return_text" ) + RemoveHudItemFromAll( "flag_carried_by" ) + RemoveHudItemFromAll( "flag_carried_by2" ) + RemoveHudItemFromAll( "flag_athome" ) + RemoveHudItemFromAll( "flag_athome2" ) + + if attackers == Team.kBlue then + hudstatusicondropped = "hud_flag_dropped_blue.vtf" + hudstatusiconhome = "hud_flag_home_blue.vtf" + hudstatusiconcarried = "hud_flag_carried_blue.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kRed then + hudstatusicondropped = "hud_flag_dropped_red.vtf" + hudstatusiconhome = "hud_flag_home_red.vtf" + hudstatusiconcarried = "hud_flag_carried_red.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + elseif attackers == Team.kYellow then + hudstatusicondropped = "hud_flag_dropped_yellow.vtf" + hudstatusiconhome = "hud_flag_home_yellow.vtf" + hudstatusiconcarried = "hud_flag_carried_yellow.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kGreen then + hudstatusicondropped = "hud_flag_dropped_green.vtf" + hudstatusiconhome = "hud_flag_home_green.vtf" + hudstatusiconcarried = "hud_flag_carried_green.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + end + + flag_hudstatusiconx = 4 + flag_hudstatusicony = 42 + flag_hudstatusiconw = 15 + flag_hudstatusiconh = 15 + flag_hudstatusiconalign = 3 + text_hudstatusx = 0 + text_hudstatusy = flag_hudstatusicony + 24 + text_hudstatusalign = 4 + + if _G[flagname].enabled == true then + if flag:IsCarried() then + AddHudTextToAll("flag_carried_by", "#AD_FlagCarriedBy", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudTextToAll("flag_carried_by2", carried_by, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + AddHudIconToAll( hudstatusiconcarried, ( "cp_flag_c" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif flag:IsDropped() and _G[flagname].status == 2 then + AddHudTextToAll("flag_return_text", "#AD_FlagReturn", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudTimerToAll("flag_return_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign) + AddHudIconToAll( hudstatusicondropped, ( "cp_flag_d" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif _G[flagname].status == 0 then + AddHudTextToAll("flag_athome", "#AD_FlagIsAt", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudTextToAll("flag_athome2", "#AD_ASpawn", text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + AddHudIconToAll( hudstatusiconhome, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + else + AddHudTextToAll("flag_tobase_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudTimerToAll("flag_tobase_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign) + AddHudIconToAll(hudstatusicontobase, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + + RemoveHudItemFromAll( "Zone_Team"..attackers ) + RemoveHudItemFromAll( "Zone_Team"..defenders ) + RemoveHudItemFromAll( "Zone_Phase"..attackers ) + RemoveHudItemFromAll( "Zone_Phase"..defenders ) + + od_hudstatusiconx = -28 + od_hudstatusicony = 38 + od_hudstatusiconw = 24 + od_hudstatusiconh = 24 + od_hudstatusiconalign = 3 + + AddHudIconToTeam( GetTeam(attackers), "hud_offense.vtf", "Zone_Team"..attackers, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIconToTeam( GetTeam(attackers), "hud_cp_"..phase..".vtf", "Zone_Phase"..attackers, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + + AddHudIconToTeam( GetTeam(defenders), "hud_defense.vtf", "Zone_Team"..defenders, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIconToTeam( GetTeam(defenders), "hud_cp_"..phase..".vtf", "Zone_Phase"..defenders, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + +end diff --git a/maps/includes/base_adzone.lua b/maps/includes/base_adzone.lua new file mode 100644 index 0000000..1b2c91e --- /dev/null +++ b/maps/includes/base_adzone.lua @@ -0,0 +1,1105 @@ + +-- base_adzone.lua +-- Attack and Defend the Zone gametype + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay") + +----------------------------------------------------------------------------- +-- global overrides that you can do what you want with +----------------------------------------------------------------------------- + +FORT_POINTS_PER_INITIAL_TOUCH = 200 +FORT_POINTS_PER_PERIOD = 50 +FORT_POINTS_PER_DEFEND = 100 + +POINTS_PER_INITIAL_TOUCH = 1 +POINTS_PER_PERIOD = 1 + +DELAY_BEFORE_PERIOD_POINTS = 2 +PERIOD_TIME = 1 +FLAG_RETURN_TIME = 0 +INITIAL_ROUND_PERIOD = 60 + +DELAY_BEFORE_DEFENSE_PERIOD_SCORING = 30 +DEFENSE_PERIOD_TIME = 10 +POINTS_PER_DEFENSE_PERIOD = POINTS_PER_PERIOD -- same as attackers +POINTS_PER_DEFENSE_60SEC_BONUS = POINTS_PER_PERIOD * 5 -- attackers period points * 5 +POINTS_PER_DEFENSE_SHUTOUT = POINTS_PER_DEFENSE_60SEC_BONUS * 10 --default, not used if GET_ROUND_PERIOD_FROM_TIMELIMIT is set to true + +ATTACKERS_OBJECTIVE_ENTITY = nil +DEFENDERS_OBJECTIVE_ENTITY = nil +ENABLE_ATTACKERS_OBJECTIVE = true -- puts attackers objective on the zone +ENABLE_DEFENDERS_OBJECTIVE = true -- puts defenders objective on the zone + +GET_ROUND_PERIOD_FROM_TIMELIMIT = true +NUMBER_OF_ROUNDS = 4 +ROUND_PERIOD = 600 --default, not used if GET_ROUND_PERIOD_FROM_TIMELIMIT is set to true + +ZONE_COLOR = "green" + +USE_ZONE_AREA = true + +NUM_DEFENDER_ONLY_PACKS = 0 + +----------------------------------------------------------------------------- +-- global variables and other shit that shouldn't be messed with +----------------------------------------------------------------------------- + +phase = 1 +zone_status = false +zone_area_status = false +gates_open = false + +current_timer = DELAY_BEFORE_DEFENSE_PERIOD_SCORING +current_seconds = 0 + +attackers = Team.kBlue +defenders = Team.kRed + +scoring_team = Team.kRed + +local teamdata = { + [Team.kBlue] = { skin = "0", beamcolour = "0 0 255" }, + [Team.kRed] = { skin = "1", beamcolour = "255 0 0" } +} + +-- stores attackers in the zone +local zone_collection = Collection() +-- stores attackers in the zone area +local zone_area_collection = Collection() +-- stores if the player has touched the cap point (for 1 touch per death) +local playerTouchedTable = {} + +----------------------------------------------------------------------------- +-- Entity definitions (flags/command points/backpacks etc.) +----------------------------------------------------------------------------- + +-- zone +base_zone_trigger = trigger_ff_script:new({}) +zone = base_zone_trigger:new({}) + +-- area around zone +base_zone_area_trigger = trigger_ff_script:new({}) +zone_area = base_zone_area_trigger:new({}) + +-- respawns +attacker_spawn = info_ff_teamspawn:new({ validspawn = function(self,player) + return player:GetTeamId() == attackers +end }) +defender_spawn = info_ff_teamspawn:new({ validspawn = function(self,player) + return player:GetTeamId() == defenders +end }) + + +----------------------------------------------------------------------------- +-- functions that do sh... stuff +----------------------------------------------------------------------------- + +-- sounds, right? +function precache() + PrecacheSound("otherteam.flagstolen") -- doors open sound + PrecacheSound("otherteam.drop") -- warning sound + PrecacheSound("yourteam.flagreturn") -- scoring sound + PrecacheSound("misc.bloop") -- minutes remaining + PrecacheSound("misc.doop") -- attackers capping sound +end + +-- pretty standard setup, aside from scoring starting +function startup() + + SetGameDescription( "Attack Defend the Zone" ) + + -- set up team limits on each team + SetPlayerLimit( Team.kBlue, 0 ) + SetPlayerLimit( Team.kRed, 0 ) + SetPlayerLimit( Team.kYellow, -1 ) + SetPlayerLimit( Team.kGreen, -1 ) + + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- set class limits + set_classlimits() + + AddSchedule( "round_start", INITIAL_ROUND_PERIOD, round_start) + if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_30SecWarning" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_10SecWarning" ) end + if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5sec" , INITIAL_ROUND_PERIOD - 5 , schedulemessagetoall, "5" ) end + if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4sec" , INITIAL_ROUND_PERIOD - 4 , schedulemessagetoall, "4" ) end + if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3sec" , INITIAL_ROUND_PERIOD - 3, schedulemessagetoall, "3" ) end + if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2sec" , INITIAL_ROUND_PERIOD - 2, schedulemessagetoall, "2" ) end + if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1sec" , INITIAL_ROUND_PERIOD - 1, schedulemessagetoall, "1" ) end + + -- sounds + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_PERIOD - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_PERIOD - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_PERIOD - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_PERIOD - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_PERIOD - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_PERIOD - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_PERIOD - 1 , schedulecountdown, 1 ) end + + -- get round times if its set to + if GET_ROUND_PERIOD_FROM_TIMELIMIT == true then + local timelimit = GetConvar( "mp_timelimit" ) + -- convert mp_timelimit from minutes to seconds and divide by the number of rounds minus initial round period + ROUND_PERIOD = timelimit * 60 / NUMBER_OF_ROUNDS - INITIAL_ROUND_PERIOD - 1 + POINTS_PER_DEFENSE_SHUTOUT = ROUND_PERIOD / ( 3 / ( POINTS_PER_DEFENSE_PERIOD / 4 ) ) + -- now lock mp_timelimit, so things don't get weird + AddScheduleRepeating( "set_cvar-mp_timelimit", 1, set_cvar, "mp_timelimit", timelimit ) + end + + if ENABLE_ATTACKERS_OBJECTIVE then ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "zone" ) end + if ENABLE_DEFENDERS_OBJECTIVE then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "zone" ) end + + custom_startup() + + current_timer = INITIAL_ROUND_PERIOD + AddScheduleRepeatingNotInfinitely( "timer_schedule", 1, timer_schedule, current_timer ) + + update_zone_text( nil ) + update_zone_status( false ) +end + +----------------------------------------------------------------------------- +-- player_ functions +----------------------------------------------------------------------------- + +-- spawns attackers with flags +function player_spawn( player_entity ) + + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + + player:SetCloakable( true ) + player:SetDisguisable( true ) + + -- nade/detpack limits + set_itemlimits( player ) + + -- wtf, scout or med on d? are you mental? + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + local classt = "Scout" + if player:GetClass() == Player.kMedic then classt = "Medic" end + local id = player:GetId() + AddSchedule("force_changemessage"..id, 2, schedulechangemessage, player, "No "..classt.."s on defense. Autoswitching to Soldier." ) + AddSchedule("force_change"..id, 2, forcechange, player) + end + + -- objective icon + if player:GetTeamId() == attackers then + UpdateObjectiveIcon( player, ATTACKERS_OBJECTIVE_ENTITY ) + elseif player:GetTeamId() == defenders then + UpdateObjectiveIcon( player, DEFENDERS_OBJECTIVE_ENTITY ) + end + + -- remove any players not on a team from playertouchedtable + for playerx, recordx in pairs(playerTouchedTable) do + if GetPlayerByID( playerx ) then + local playert = GetPlayerByID( playerx ) + if playert:GetTeamId() ~= attackers then + playerTouchedTable[playerx] = nil + end + end + end + + if player:GetTeamId() ~= attackers then return end + + -- add to table and reset touched to 0 + playerTouchedTable[player:GetId()] = {touched = false, allowed = true, points = 0} + +end + +function player_killed( player, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + -- Entity that is attacking + local attacker = damageinfo:GetAttacker() + + -- If no attacker do nothing + if not attacker then return end + + local player_attacker = nil + + -- get the attacking player + if IsPlayer(attacker) then + attacker = CastToPlayer(attacker) + player_attacker = attacker + elseif IsSentrygun(attacker) then + attacker = CastToSentrygun(attacker) + player_attacker = attacker:GetOwner() + elseif IsDetpack(attacker) then + attacker = CastToDetpack(attacker) + player_attacker = attacker:GetOwner() + elseif IsDispenser(attacker) then + attacker = CastToDispenser(attacker) + player_attacker = attacker:GetOwner() + else + return + end + + -- if still no attacking player after all that, forget about it + if not player_attacker then return end + + -- If player killed self or teammate do nothing + if (player:GetId() == player_attacker:GetId()) or (player:GetTeamId() == player_attacker:GetTeamId()) then + return + end + + -- If player is an attacker, then do stuff + if player:GetTeamId() == attackers then + -- show scored points + BroadCastMessageToPlayer( player, "You scored "..playerTouchedTable[player:GetId()].points.." team points that run" ) + AddScheduleRepeatingNotInfinitely( "timer_return_schedule", .5, BroadCastMessageToPlayer, 4, player, "You scored "..playerTouchedTable[player:GetId()].points.." team points that run") + -- Check if he's in the zone + for playerx in zone_collection.items do + playerx = CastToPlayer(playerx) + if playerx:GetId() == player:GetId() then + player_attacker:AddFortPoints( FORT_POINTS_PER_DEFEND, "Defending the Zone" ) + return + end + end + -- Check if he's in the zone area + for playerx in zone_area_collection.items do + playerx = CastToPlayer(playerx) + if playerx:GetId() == player:GetId() then + if playerTouchedTable[player:GetId()].touched == false then + player_attacker:AddFortPoints( FORT_POINTS_PER_DEFEND * 2, "Denying Attacker from Scoring" ) + else + player_attacker:AddFortPoints( FORT_POINTS_PER_DEFEND / 2, "Defending the Zone Area" ) + end + return + end + end + end + +end + +function player_ondamage( player, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + -- Get Damage Force + local damage = damageinfo:GetDamage() + + -- Entity that is attacking + local attacker = damageinfo:GetAttacker() + + -- If no attacker do nothing + if not attacker then return end + + local player_attacker = nil + + -- get the attacking player + if IsPlayer(attacker) then + attacker = CastToPlayer(attacker) + player_attacker = attacker + elseif IsSentrygun(attacker) then + attacker = CastToSentrygun(attacker) + player_attacker = attacker:GetOwner() + elseif IsDetpack(attacker) then + attacker = CastToDetpack(attacker) + player_attacker = attacker:GetOwner() + elseif IsDispenser(attacker) then + attacker = CastToDispenser(attacker) + player_attacker = attacker:GetOwner() + else + return + end + + -- if still no attacking player after all that, forget about it + if not player_attacker then return end + + -- If player killed self or teammate do nothing + if (player:GetId() == player_attacker:GetId()) or (player:GetTeamId() == player_attacker:GetTeamId()) then + return + end + + -- If player (victim) is an attacker, then do stuff + if player:GetTeamId() == attackers then + -- Check if he's in the zone + for playerx in zone_collection.items do + playerx = CastToPlayer(playerx) + if playerx:GetId() == player:GetId() then + if (damage > 100) then damage = 100 end + player_attacker:AddFortPoints( damage, "Protecting the Zone" ) + return + end + end + -- Check if he's in the zone area + for playerx in zone_area_collection.items do + playerx = CastToPlayer(playerx) + if playerx:GetId() == player:GetId() then + if (damage > 50) then damage = 50 end + player_attacker:AddFortPoints( damage, "Protecting the Zone Area" ) + return + end + end + end + +end + +----------------------------------------------------------------------------- +-- zone triggers +----------------------------------------------------------------------------- + +-- only attackers! +function base_zone_trigger:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == attackers then + if not gates_open then return EVENT_DISALLOWED end + return EVENT_ALLOWED + end + if player:GetTeamId() == defenders then + BroadCastMessageToPlayer( player, "ADZ_Defend" ) + return EVENT_DISALLOWED + end + end + return EVENT_DISALLOWED +end + +-- registers attackers as they enter the zone +function base_zone_trigger:ontouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + player:SetCloakable( false ) + player:SetDisguisable( false ) + + local playerid = player:GetId() + zone_collection:AddItem( player ) + + local team = GetTeam(attackers) + -- if it's the first touch, give points and stuff + if playerTouchedTable[playerid].touched == false then + team:AddScore( POINTS_PER_INITIAL_TOUCH ) + player:AddFortPoints( FORT_POINTS_PER_INITIAL_TOUCH, "Initial Point Touch" ) + + RemoveSchedule( "shutout" ) -- O scores, no D shutout (put in all O scoring spots for safety, haha) + + SmartTeamSound( GetTeam(defenders), "yourteam.flagreturn", "misc.doop" ) + + playerTouchedTable[playerid].touched = true + playerTouchedTable[playerid].points = playerTouchedTable[playerid].points + POINTS_PER_INITIAL_TOUCH + + if zone_collection:Count() == 1 then + AddSchedule( "period_init", DELAY_BEFORE_PERIOD_POINTS, init_scoring, team ) + end + elseif zone_collection:Count() == 1 then + SmartTeamSound( GetTeam(defenders), "otherteam.drop", nil ) + end + if zone_collection:Count() == 1 then + -- activate the cap point, bro + zone_turnon() + end + + update_zone_status( true ) + + end +end + +-- deregisters attackers as they leave the zone +function base_zone_trigger:onendtouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + player:SetCloakable( true ) + player:SetDisguisable( true ) + + zone_collection:RemoveItem( player ) + end +end + +-- clear collection and start defender points when everyone's left +function base_zone_trigger:oninactive( ) + -- Clear out the flags in the collection + zone_collection:RemoveAllItems() + init_defender_countdown() + zone_turnoff() + update_zone_status( false ) +end + +----------------------------------------------------------------------------- +-- zone area triggers +----------------------------------------------------------------------------- + +-- only attackers! +function base_zone_area_trigger:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == attackers then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +-- registers attackers as they enter the zone area +function base_zone_area_trigger:ontouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + if player:GetTeamId() == defenders then return end + update_zone_area_status( true ) + zone_area_collection:AddItem( player ) + end +end + +-- registers attackers as they enter the zone area +function base_zone_area_trigger:onendtouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + if player:GetTeamId() == defenders then return end + zone_area_collection:RemoveItem( player ) + end +end + +-- updates the hud if no one is in the zone area. +function base_zone_area_trigger:oninactive() + update_zone_area_status( false ) + zone_area_collection:RemoveAllItems() +end + + +----------------------------------------------------------------------------- +-- zone functions +----------------------------------------------------------------------------- + +function update_zone_status( on ) + RemoveHudItemFromAll( "Zone_Status" ) + if on then + AddHudIconToAll( "hud_zone_on_"..ZONE_COLOR..".vtf", "Zone_Status", -64, 32, 88, 88, 3 ) + zone_status = true; + else + AddHudIconToAll( "hud_zone_off.vtf", "Zone_Status", -64, 32, 88, 88, 3 ) + zone_status = false; + end + update_zone_text( nil ) +end + +function update_zone_area_status( on ) + if USE_ZONE_AREA then + RemoveHudItemFromAll( "Zone_Area_Status" ) + if on then + AddHudIconToAll( "hud_zone_area_active_"..ZONE_COLOR..".vtf", "Zone_Area_Status", -56, 40, 72, 72, 3 ) + zone_area_status = true; + else + AddHudIconToAll( "hud_zone_area_inactive.vtf", "Zone_Area_Status", -56, 40, 72, 72, 3 ) + zone_area_status = false; + end + end +end + +function flaginfo( player_entity ) + local player = CastToPlayer( player_entity ) + RemoveHudItem( player, "Zone_Status" ) + RemoveHudItem( player, "Zone_Area_Status" ) + if USE_ZONE_AREA then + if zone_area_status then + AddHudIcon( player, "hud_zone_area_active_"..ZONE_COLOR..".vtf", "Zone_Area_Status", -56, 40, 72, 72, 3 ) + else + AddHudIcon( player, "hud_zone_area_inactive.vtf", "Zone_Area_Status", -56, 40, 72, 72, 3 ) + end + end + if zone_status then + AddHudIcon( player, "hud_zone_on_"..ZONE_COLOR..".vtf", "Zone_Status", -64, 32, 88, 88, 3 ) + else + AddHudIcon( player, "hud_zone_off.vtf", "Zone_Status", -64, 32, 88, 88, 3 ) + end + update_zone_text( player ) + update_round_info( player ) +end + +function zone_turnon( ) + zone_on_outputs() + + -- init attacker scoring + AddSchedule( "period_init", DELAY_BEFORE_PERIOD_POINTS, init_scoring, team ) + AddSchedule( "period_init_alarm", DELAY_BEFORE_PERIOD_POINTS - 1, init_scoring_alarm ) + -- stop defender point countdown + DeleteSchedule( "timer_schedule" ) + RemoveSchedule( "defenders_period_scoring" ) + RemoveSchedule( "init_defenders_period_scoring" ) +end +function zone_turnoff( ) + zone_off_outputs() + + -- stop attacker scoring + DeleteSchedule( "period_init" ) + DeleteSchedule( "period_init_alarm" ) + DeleteSchedule( "period_scoring" ) + zone_scoring = false +end + +function update_zone_text( player ) + local text_align = 4 + local text_x = 40 + local text_line1y = 84 + local text_line2y = text_line1y + 8 + local text_line3y = text_line2y + 8 + + if IsPlayer( player ) then + -- defender period scoring text and timer + RemoveHudItem(player, "defender_points_timer") + RemoveHudItem(player, "defender_points_text") + RemoveHudItem(player, "defender_points_text2") + -- attackers in the zone text + RemoveHudItem(player, "attackers_in_text") + RemoveHudItem(player, "attackers_in_text2") + RemoveHudItem(player, "attackers_in_text3") + -- gates open in text and timer + RemoveHudItem(player, "gates_open_text") + RemoveHudItem(player, "gates_open_text2") + RemoveHudItem(player, "gates_open_timer") + if gates_open == true then + if not zone_status then + AddHudText( player, "defender_points_text", "#FF_Defenders", text_x, text_line1y, text_align ) + AddHudText( player, "defender_points_text2", "#ADZ_ScoreNotice", text_x, text_line2y, text_align ) + AddHudTimer( player, "defender_points_timer", current_timer +1, -1, text_x, text_line3y, text_align ) + else + AddHudText( player, "attackers_in_text", "#FF_Attackers", text_x, text_line1y, text_align ) + AddHudText( player, "attackers_in_text2", "#ADZ_AreIn", text_x, text_line2y, text_align ) + AddHudText( player, "attackers_in_text3", "#ADZ_TheZone", text_x, text_line3y, text_align ) + end + else + AddHudText( player, "gates_open_text", "#ADZ_GATES", text_x, text_line1y, text_align ) + AddHudText( player, "gates_open_text2", "#ADZ_OPENIN", text_x, text_line2y, text_align ) + AddHudTimer( player, "gates_open_timer", current_timer, -1, text_x, text_line3y, text_align ) + end + else + -- defender period scoring text and timer + RemoveHudItemFromAll("defender_points_timer") + RemoveHudItemFromAll("defender_points_text") + RemoveHudItemFromAll("defender_points_text2") + -- attackers in the zone text + RemoveHudItemFromAll("attackers_in_text") + RemoveHudItemFromAll("attackers_in_text2") + RemoveHudItemFromAll("attackers_in_text3") + -- gates open in text and timer + RemoveHudItemFromAll("gates_open_text") + RemoveHudItemFromAll("gates_open_text2") + RemoveHudItemFromAll("gates_open_timer") + if gates_open == true then + if not zone_status then + AddHudTextToAll( "defender_points_text", "#FF_Defenders", text_x, text_line1y, text_align ) + AddHudTextToAll( "defender_points_text2", "#ADZ_ScoreNotice", text_x, text_line2y, text_align ) + AddHudTimerToAll( "defender_points_timer", current_timer +1, -1, text_x, text_line3y, text_align ) + else + AddHudTextToAll( "attackers_in_text", "#FF_Attackers", text_x, text_line1y, text_align ) + AddHudTextToAll( "attackers_in_text2", "#ADZ_AreIn", text_x, text_line2y, text_align ) + AddHudTextToAll( "attackers_in_text3", "#ADZ_TheZone", text_x, text_line3y, text_align ) + end + else + AddHudTextToAll( "gates_open_text", "#ADZ_GATES", text_x, text_line1y, text_align ) + AddHudTextToAll( "gates_open_text2", "#ADZ_OPENIN", text_x, text_line2y, text_align ) + AddHudTimerToAll( "gates_open_timer", current_timer, -1, text_x, text_line3y, text_align ) + end + end +end + +function update_round_info( player ) + + RemoveHudItem( player, "Zone_Round" ) + RemoveHudItem( player, "Zone_Team"..attackers ) + RemoveHudItem( player, "Zone_Team"..defenders ) + RemoveHudItem( player, "Zone_Phase"..attackers ) + RemoveHudItem( player, "Zone_Phase"..defenders ) + + od_hudstatusiconx = 28 + od_hudstatusicony = 48 + od_hudstatusiconw = 24 + od_hudstatusiconh = 24 + od_hudstatusiconalign = 3 + + AddHudText( player, "Zone_Round", "#ADZ_Round", od_hudstatusiconx + od_hudstatusiconw / 2, od_hudstatusicony - 10, 4 ) + if player:GetTeamId() == attackers then + AddHudIcon( player, "hud_offense.vtf", "Zone_Team"..attackers, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..attackers, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + elseif player:GetTeamId() == defenders then + AddHudIcon( player, "hud_defense.vtf", "Zone_Team"..defenders, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..defenders, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + end + +end + +function init_defender_countdown() + -- init defender scoring + current_timer = DELAY_BEFORE_DEFENSE_PERIOD_SCORING + RemoveSchedule( "timer_schedule" ) + AddScheduleRepeatingNotInfinitely( "timer_schedule", 1, timer_schedule, current_timer ) + AddSchedule( "init_defenders_period_scoring", current_timer, init_defenders_period_scoring ) +end + +----------------------------------------------------------------------------- +-- Scheduled functions that do stuff +----------------------------------------------------------------------------- + +-- Sends a message to all after the determined time +function schedulechangemessage( player, message ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + BroadCastMessageToPlayer( player, message ) + end +end + +-- force a scout/med to switch to soli if they haven't +function forcechange( player ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + ApplyToPlayer( player, { AT.kChangeClassSoldier, AT.kRespawnPlayers } ) + end +end + +-- Sends a message to all after the determined time +function schedulemessagetoall( message ) + BroadCastMessage( message ) +end + +-- Plays a sound to all after the determined time +function schedulesound( sound ) + BroadCastSound( sound ) +end + + +function schedulecountdown( time ) + BroadCastMessage( ""..time.."" ) + SpeakAll( "AD_" .. time .. "SEC" ) +end + +function timer_schedule() + current_timer = current_timer -1 +end + +----------------------------------------------------------------------------- +-- Scoring +----------------------------------------------------------------------------- + +-- Adds points based on time inside cap room and number of attackers inside cap room +function period_scoring( team ) + team:AddScore( POINTS_PER_PERIOD ) + SmartTeamSound( GetTeam(defenders), "yourteam.flagreturn", "misc.doop" ) + + for player in zone_collection.items do + player = CastToPlayer(player) + + if player ~= nil then + player:AddFortPoints( FORT_POINTS_PER_PERIOD, "Touching the Point" ) + playerTouchedTable[player:GetId()].points = playerTouchedTable[player:GetId()].points + POINTS_PER_PERIOD + else + ConsoleToAll("LUA ERROR: player_addfortpoints: Unable to find player") + end + end +end + +-- Initializes the period_scoring (allows for a delay after initial touch) +function init_scoring( team ) + if zone_collection:Count() > 0 then + team:AddScore( POINTS_PER_PERIOD ) + AddScheduleRepeating( "period_scoring", PERIOD_TIME, period_scoring, team) + + for player in zone_collection.items do + player = CastToPlayer(player) + if player ~= nil then + player:AddFortPoints( FORT_POINTS_PER_PERIOD, "Touching the Point" ) + playerTouchedTable[player:GetId()].points = playerTouchedTable[player:GetId()].points + POINTS_PER_PERIOD + else + ConsoleToAll("LUA ERROR: player_addfortpoints: Unable to find player") + end + end + end +end + +-- Initializes the period_scoring (allows for a delay after initial touch) +function init_scoring_alarm( ) + if zone_collection:Count() > 0 then + SmartTeamSound( GetTeam(defenders), "otherteam.drop", nil ) + end +end + +function init_defenders_period_scoring() + local team = GetTeam( defenders ) + team:AddScore( POINTS_PER_DEFENSE_PERIOD ) + SmartTeamSound( GetTeam(attackers), "yourteam.flagreturn", "misc.doop" ) + + current_seconds = 30 + + AddScheduleRepeating( "defenders_period_scoring", DEFENSE_PERIOD_TIME, defenders_period_scoring ) + current_timer = DEFENSE_PERIOD_TIME + RemoveSchedule( "timer_schedule" ) + AddScheduleRepeatingNotInfinitely( "timer_schedule", 1, timer_schedule, current_timer ) + update_zone_text( nil ) +end + +function defenders_period_scoring( ) + local team = GetTeam( defenders ) + team:AddScore( POINTS_PER_DEFENSE_PERIOD ) + SmartTeamSound( GetTeam(attackers), "yourteam.flagreturn", "misc.doop" ) + + if current_seconds >= 60 then + BroadCastMessage( "Defenders get "..POINTS_PER_DEFENSE_60SEC_BONUS.." bonus points" ) + team:AddScore( POINTS_PER_DEFENSE_60SEC_BONUS ) + current_seconds = 0 + else + current_seconds = current_seconds + 10 + end + + current_timer = DEFENSE_PERIOD_TIME + RemoveSchedule( "timer_schedule" ) + AddScheduleRepeatingNotInfinitely( "timer_schedule", 1, timer_schedule, current_timer ) + update_zone_text( nil ) +end + +function shutout( ) + + -- attackers instead of defenders, because the teams switched + local teamid = attackers + + -- but after the last round, use defenders + if phase >= NUMBER_OF_ROUNDS then + teamid = defenders + end + + local team = GetTeam( teamid ) + AddSchedule( "defenders_shutout_msg", 3, BroadCastMessage, "#ADZ_NoScore" ) + team:AddScore( POINTS_PER_DEFENSE_SHUTOUT ) +end + +----------------------------------------------------------------------------- +-- Round start/end +----------------------------------------------------------------------------- + +-- Opens the gates and schedules the round's end. +function round_start() + -- Opens the gates and all that lovely stuff + OpenDoor("frontgate") + BroadCastMessage( "#FF_AD_GATESOPEN" ) + BroadCastSound( "otherteam.flagstolen" ) + SpeakAll( "AD_GATESOPEN" ) + + gates_open = true + + openstartdoor() + + AddSchedule( "round_end", ROUND_PERIOD, round_end) + AddSchedule( "shutout", ROUND_PERIOD, shutout) + init_defender_countdown() + update_zone_status( false ) + + if phase < NUMBER_OF_ROUNDS then + -- Sets up the end of a round, and the appropriate timed messages + if ROUND_PERIOD > 300 then AddSchedule( "phase" .. phase .. "5minwarn" , ROUND_PERIOD - 300 , schedulemessagetoall, "#ADZ_Switch5Min" ) end + if ROUND_PERIOD > 120 then AddSchedule( "phase" .. phase .. "2minwarn" , ROUND_PERIOD - 120 , schedulemessagetoall, "#ADZ_Switch2Min" ) end + if ROUND_PERIOD > 60 then AddSchedule( "phase" .. phase .. "1minwarn" , ROUND_PERIOD - 60 , schedulemessagetoall, "#ADZ_Switch1Min" ) end + if ROUND_PERIOD > 30 then AddSchedule( "phase" .. phase .. "30secwarn" , ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_Switch30Sec" ) end + if ROUND_PERIOD > 10 then AddSchedule( "phase" .. phase .. "10secwarn" , ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_Switch10Sec" ) end + if ROUND_PERIOD > 5 then AddSchedule( "phase" .. phase .. "5secwarn" , ROUND_PERIOD - 5 , schedulemessagetoall, "5" ) end + if ROUND_PERIOD > 4 then AddSchedule( "phase" .. phase .. "4secwarn" , ROUND_PERIOD - 4 , schedulemessagetoall, "4" ) end + if ROUND_PERIOD > 3 then AddSchedule( "phase" .. phase .. "3secwarn" , ROUND_PERIOD - 3, schedulemessagetoall, "3" ) end + if ROUND_PERIOD > 2 then AddSchedule( "phase" .. phase .. "2secwarn" , ROUND_PERIOD - 2, schedulemessagetoall, "2" ) end + if ROUND_PERIOD > 1 then AddSchedule( "phase" .. phase .. "1secwarn" , ROUND_PERIOD - 1, schedulemessagetoall, "1" ) end + AddSchedule( "phase" .. phase .. "switchmessage" , ROUND_PERIOD, schedulemessagetoall, "#ADZ_Switch" ) + else + if ROUND_PERIOD > 300 then AddSchedule( "phase" .. phase .. "5minwarn" , ROUND_PERIOD - 300 , schedulemessagetoall, "#ADZ_End5Min" ) end + if ROUND_PERIOD > 120 then AddSchedule( "phase" .. phase .. "2minwarn" , ROUND_PERIOD - 120 , schedulemessagetoall, "#ADZ_End2Min" ) end + if ROUND_PERIOD > 60 then AddSchedule( "phase" .. phase .. "1minwarn" , ROUND_PERIOD - 60 , schedulemessagetoall, "#ADZ_End1Min" ) end + if ROUND_PERIOD > 30 then AddSchedule( "phase" .. phase .. "30secwarn" , ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_End30Sec" ) end + if ROUND_PERIOD > 10 then AddSchedule( "phase" .. phase .. "10secwarn" , ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_End10Sec" ) end + if ROUND_PERIOD > 5 then AddSchedule( "phase" .. phase .. "5secwarn" , ROUND_PERIOD - 5 , schedulemessagetoall, "5" ) end + if ROUND_PERIOD > 4 then AddSchedule( "phase" .. phase .. "4secwarn" , ROUND_PERIOD - 4 , schedulemessagetoall, "4" ) end + if ROUND_PERIOD > 3 then AddSchedule( "phase" .. phase .. "3secwarn" , ROUND_PERIOD - 3, schedulemessagetoall, "3" ) end + if ROUND_PERIOD > 2 then AddSchedule( "phase" .. phase .. "2secwarn" , ROUND_PERIOD - 2, schedulemessagetoall, "2" ) end + if ROUND_PERIOD > 1 then AddSchedule( "phase" .. phase .. "1secwarn" , ROUND_PERIOD - 1, schedulemessagetoall, "1" ) end + end + + -- sounds + if ROUND_PERIOD > 300 then AddSchedule( "phase" .. phase .. "5minwarnsound" , ROUND_PERIOD - 300 , schedulesound, "misc.bloop" ) end + if ROUND_PERIOD > 120 then AddSchedule( "phase" .. phase .. "2minwarnsound" , ROUND_PERIOD - 120 , schedulesound, "misc.bloop" ) end + if ROUND_PERIOD > 60 then AddSchedule( "phase" .. phase .. "1minwarnsound" , ROUND_PERIOD - 60 , schedulesound, "misc.bloop" ) end + if ROUND_PERIOD > 30 then AddSchedule( "phase" .. phase .. "30secwarnsound" , ROUND_PERIOD - 30 , schedulesound, "misc.bloop" ) end + if ROUND_PERIOD > 10 then AddSchedule( "phase" .. phase .. "10secwarnsound" , ROUND_PERIOD - 10 , schedulesound, "misc.bloop" ) end + if ROUND_PERIOD > 5 then AddSchedule( "phase" .. phase .. "5secwarnsound" , ROUND_PERIOD - 5 , schedulecountdown, 5 ) end + if ROUND_PERIOD > 4 then AddSchedule( "phase" .. phase .. "4secwarnsound" , ROUND_PERIOD - 4 , schedulecountdown, 4 ) end + if ROUND_PERIOD > 3 then AddSchedule( "phase" .. phase .. "3secwarnsound" , ROUND_PERIOD - 3 , schedulecountdown, 3 ) end + if ROUND_PERIOD > 2 then AddSchedule( "phase" .. phase .. "2secwarnsound" , ROUND_PERIOD - 2 , schedulecountdown, 2 ) end + if ROUND_PERIOD > 1 then AddSchedule( "phase" .. phase .. "1secwarnsound" , ROUND_PERIOD - 1 , schedulecountdown, 1 ) end + +end + +-- Checks to see if it's the first or second round, then either swaps teams, or ends the game. +function round_end() + + if phase == NUMBER_OF_ROUNDS then + DeleteSchedule( "period_scoring" ) + DeleteSchedule( "defenders_period_scoring" ) + DeleteSchedule( "init_defenders_period_scoring" ) + DeleteSchedule( "set_cvar-mp_timelimit" ) + update_zone_text( nil ) + GoToIntermission() + return + else + phase = phase + 1 + gates_open = false + end + + if attackers == Team.kBlue then + attackers = Team.kRed + defenders = Team.kBlue + + onswitch_bluetodef() + else + attackers = Team.kBlue + defenders = Team.kRed + + onswitch_redtodef() + end + + -- switches some prop model's skins so teams spawn in appropriatly-coloured rooms. + OutputEvent( "prop_defender", "Skin", teamdata[defenders].skin ) + OutputEvent( "prop_attacker", "Skin", teamdata[attackers].skin ) + + -- reset the doors + CloseDoor("frontgate") + attacker_door_trigger = adz_door:new({ team = attackers, door = "attacker_door" }) + defender_door_trigger = adz_door:new({ team = defenders, door = "defender_door" }) + + -- switch them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- reset schedules + DeleteSchedule( "period_scoring" ) + DeleteSchedule( "period_init" ) + DeleteSchedule( "defenders_period_scoring" ) + DeleteSchedule( "init_defenders_period_scoring" ) + AddSchedule( "round_start", INITIAL_ROUND_PERIOD, round_start) + -- gate timer + current_timer = INITIAL_ROUND_PERIOD + AddScheduleRepeatingNotInfinitely( "timer_schedule", 1, timer_schedule, current_timer ) + + -- reset player touched table + playerTouchedTable = {} + -- remove all leftovers from the cap point collection + zone_collection:RemoveAllItems() + zone_area_collection:RemoveAllItems() + -- respawn, obviously + RespawnAllPlayers() + + -- switch pack touchflags + if NUM_DEFENDER_ONLY_PACKS > 0 then + -- get correct allow flags + if defenders == Team.kRed then pack_allowflags = AllowFlags.kRed + elseif defenders == Team.kBlue then pack_allowflags = AllowFlags.kBlue + elseif defenders == Team.kGreen then pack_allowflags = AllowFlags.kGreen + elseif defenders == Team.kYellow then pack_allowflags = AllowFlags.kYellow end + + -- this is a workaround due to how the touchflags are set in base.lua + for i=1,NUM_DEFENDER_ONLY_PACKS do + entity = GetEntityByName( "adz_pack_defender"..i ) + local info = CastToInfoScript( entity ) + info:SetTouchFlags({ pack_allowflags }) + end + end + + -- MORE scheduled message loveliness. + if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_30SecWarning" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_10SecWarning" ) end + if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5sec" , INITIAL_ROUND_PERIOD - 5 , schedulemessagetoall, "5" ) end + if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4sec" , INITIAL_ROUND_PERIOD - 4 , schedulemessagetoall, "4" ) end + if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3sec" , INITIAL_ROUND_PERIOD - 3, schedulemessagetoall, "3" ) end + if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2sec" , INITIAL_ROUND_PERIOD - 2, schedulemessagetoall, "2" ) end + if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1sec" , INITIAL_ROUND_PERIOD - 1, schedulemessagetoall, "1" ) end + + -- sounds + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_PERIOD - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_PERIOD - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_PERIOD - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_PERIOD - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_PERIOD - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_PERIOD - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_PERIOD - 1 , schedulecountdown, 1 ) end + + -- clear them zones + update_zone_status( false ) + zone_turnoff() + + set_classlimits() + onswitch() +end + +-- I dunno, does something, not sure what! +function RespawnAllPlayers() + ApplyToAll({ AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, AT.kStopPrimedGrens, AT.kReloadClips, AT.kAllowRespawn, AT.kReturnDroppedItems }) +end + +----------------------------------------------------------------------------- +-- output functions +----------------------------------------------------------------------------- + +function custom_startup() + return +end + +function zone_on_outputs() + OutputEvent( "zone_alarm", "PlaySound" ) + OutputEvent( "zone_light", "TurnOn" ) + OutputEvent( "zone_spot", "LightOn" ) + OutputEvent( "zone_rotate_clock", "Start" ) + OutputEvent( "zone_rotate_counterclock", "Start" ) + OutputEvent( "zone_tesla", "DoSpark" ) +end +function zone_off_outputs() + OutputEvent( "zone_alarm", "StopSound" ) + OutputEvent( "zone_light", "TurnOff" ) + OutputEvent( "zone_spot", "LightOff" ) + OutputEvent( "zone_rotate_clock", "Stop" ) + OutputEvent( "zone_rotate_counterclock", "Stop" ) +end +function onswitch_bluetodef() +end +function onswitch_redtodef() + return +end +function onswitch() + return +end +function openstartdoor() + return +end +function onreset_outputs() + return +end +function set_classlimits() + -- reset them limits + local team = GetTeam(attackers) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, 0) + team:SetClassLimit(Player.kMedic, 0) + team:SetClassLimit(Player.kSniper, 1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) + + + team = GetTeam(defenders) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, -1) + team:SetClassLimit(Player.kMedic, -1) + team:SetClassLimit(Player.kSniper, 1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) +end +function set_itemlimits( player ) + player:RemoveAmmo( Ammo.kManCannon, 1 ) + -- give demo 1 mirv, and only 1 mirv + if player:GetClass() == Player.kDemoman or player:GetClass() == Player.kEngineer then + player:RemoveAmmo( Ammo.kGren2, 4 ) + player:AddAmmo( Ammo.kGren2, 1 ) + end + if player:GetTeamId() == defenders then + player:RemoveAmmo( Ammo.kDetpack, 1 ) + end +end + +----------------------------------------------------------------------------- +-- respawn shields +----------------------------------------------------------------------------- +hurt = trigger_ff_script:new({ team = Team.kUnassigned }) +function hurt:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == attackers then + return EVENT_ALLOWED + end + end + + return EVENT_DISALLOWED +end + +-- red lasers hurt blue and vice-versa + +red_laser_hurt = hurt:new({ team = Team.kBlue }) +blue_laser_hurt = hurt:new({ team = Team.kRed }) + +----------------------------------------------------------------------------- +-- backpacks, doors, etc. etc. +----------------------------------------------------------------------------- + +adz_pack = genericbackpack:new({ + health = 35, + armor = 35, + grenades = 20, + nails = 50, + shells = 300, + rockets = 15, + gren1 = 1, + gren2 = 0, + cells = 120, + respawntime = 10, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch"}) + +function adz_pack:dropatspawn() return false end + +if defenders == Team.kRed then pack_allowflags = AllowFlags.kRed +elseif defenders == Team.kBlue then pack_allowflags = AllowFlags.kBlue +elseif defenders == Team.kGreen then pack_allowflags = AllowFlags.kGreen +elseif defenders == Team.kYellow then pack_allowflags = AllowFlags.kYellow end + +adz_pack_defender1 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender2 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender3 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender4 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender5 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender6 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender7 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender8 = adz_pack:new({ touchflags = {pack_allowflags} }) +adz_pack_defender9 = adz_pack:new({ touchflags = {pack_allowflags} }) + +adz_defender_pack1 = adz_pack_defender1 +adz_defender_pack2 = adz_pack_defender2 +adz_defender_pack3 = adz_pack_defender3 +adz_defender_pack4 = adz_pack_defender4 +adz_defender_pack5 = adz_pack_defender5 +adz_defender_pack6 = adz_pack_defender6 +adz_defender_pack7 = adz_pack_defender7 +adz_defender_pack8 = adz_pack_defender8 +adz_defender_pack9 = adz_pack_defender9 + +------------------------------------------------------------------ +--Resup Doors +------------------------------------------------------------------ + +adz_door = trigger_ff_script:new({ team = Team.kUnassigned, door = nil }) + +function adz_door:allowed( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + return player:GetTeamId() == self.team + end + + return EVENT_DISALLOWED +end + +function adz_door:ontrigger( touch_entity ) + if IsPlayer( touch_entity ) then + OutputEvent(self.door, "Open") + end +end + +attacker_door_trigger = adz_door:new({ team = attackers, door = "attacker_door" }) +defender_door_trigger = adz_door:new({ team = defenders, door = "defender_door" }) \ No newline at end of file diff --git a/maps/includes/base_chatcommands.lua b/maps/includes/base_chatcommands.lua new file mode 100644 index 0000000..c297df3 --- /dev/null +++ b/maps/includes/base_chatcommands.lua @@ -0,0 +1,457 @@ +--[[ +================================================================================================================ +== base_chatcommands.lua +== -- Allows maps to use player chat as commands to perform +== -- various functions +================================================================================================================ +== Instructions +== -- To add commands: +=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +chatbase_addcommand( "commandname", "Command description", "command example" ) +function chat_commandname( player, parameter1, parameter2, ... ) + -- perform some task +end +=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +== -- The description and example parameters are both optional +== -- Do NOT put the command prefix in either the example or the commandname parameters +== -- The player parameter will always get sent to chat_commandname functions, but the others are optional +== -- Parameters are sent by players in this format !commandname param1 param2 ... +== -- +== -- To add player settings: +=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +chatbase_addplayersetting( "settingname", default_value, "Setting description" ) +=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +== -- The description is optional +== -- +== -- To get a setting value for a player: +=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +chatbase_getplayersetting( player, "settingname" ) +=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +== -- +== -- To set a setting value for a player: +=~~ Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +chatbase_setplayersetting( player, "settingname", value ) +=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= +== -- +== -- Settings: +== -- -- The settings below should be copied, pasted, and altered into your maps .lua if you want to +== -- -- change any of them +================================================================================================================ +]]-- + +-- chat command settings +CHAT_COMMAND_PREFIX = "!" -- Command prefix, all commands must start with this string +CHAT_COMMAND_HIDECHATSTRING = true -- Determines if the chat string is shown if it executes a command +CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY = false -- If false, the server will notify players that chat commands + -- are enabled for the map ONLY IF non-default chat commands exist +CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT = 0 -- Number of times to repeat the notification (set to -1 for infinite) +CHAT_COMMAND_PERIODIC_NOTIFY_PERIOD = 60 -- Time between notifications (in seconds) + +-- theme settings +-- 0 = orange 1 = blue 2 = red 3 = yellow 4 = green +-- 5 = white 6 = black 7 = gray 8 = purple 9 = teal +CHAT_COMMAND_COLOR_MAIN = 0 -- used most often +CHAT_COMMAND_COLOR_HIGHLIGHT1 = 5 -- used to emphasize something +CHAT_COMMAND_COLOR_HIGHLIGHT2 = 5 -- used to emphasize something +CHAT_COMMAND_COLOR_HIGHLIGHT3 = 5 -- used to emphasize something +CHAT_COMMAND_COLOR_ERROR = 2 -- used for error messages + +-- chat command debug settings +CHAT_COMMAND_DEBUG = false +CHAT_COMMAND_DEBUG_PREFIX = "[lua-chatcommands] " + +--[[ +===================================== +== GLOBAL VARS +===================================== +== Do NOT edit these unless you know +== exactly what you're doing +===================================== +]]-- + +-- chat commands global table +chatbase_commands = {} +chatbase_players = {} +chatbase_settings = {} + +chatbase_defaultcommands = {"help","disablenotify"} + +--[[ +===================================== +== CHAT COMMAND FUNCTIONS +===================================== +== +===================================== +]]-- + +------------------------------------- +-- Setup +------------------------------------- + +function chatbase_addcommand( command, description, example ) + chatbase_debug( "Adding command "..tostring(command).." with desc "..tostring(description).." and example "..tostring(example) ) + chatbase_commands[command] = {} + chatbase_commands[command].description = description + chatbase_commands[command].example = example +end + +function chatbase_addplayersetting( setting, default, description ) + chatbase_debug( "Adding setting "..tostring(setting).." with default "..tostring(default).." and desc "..tostring(description) ) + chatbase_settings[setting] = {} + chatbase_settings[setting].default = default + chatbase_settings[setting].description = description +end + +------------------------------------- +-- Utilities +------------------------------------- + +function chatbase_customcommandsexist() + -- check that non-default commands exist + chatbase_debug("Checking if custom commands exist") + local nondefexist = false + for command,values in pairs(chatbase_commands) do + local found = false + chatbase_debug("Checking command "..tostring(command)) + for i,defcommand in pairs(chatbase_defaultcommands) do + chatbase_debug(" -> Against default command "..tostring(defcommand)) + if defcommand == command then + chatbase_debug("Command "..tostring(command).." is default") + found = true + end + end + if not found then + chatbase_debug("Command "..tostring(command).." is not default") + nondefexist = true + break; + end + end + + chatbase_debug("Custom commands exist: "..tostring(nondefexist)) + return nondefexist; +end + +------------------------------------- +-- Notifications +------------------------------------- + +function chatbase_setupnotify() + chatbase_debug("setupnotify called") + -- if notifications are completely disabled, return early + if CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY then return end + chatbase_debug("setupnotify got past disabled check") + + -- if only default commands exist, then theres no reason to notify + if not chatbase_customcommandsexist() then return end + chatbase_debug("setupnotify got past custom commands check") + + -- call a function that will notify anyone that meets the requirements every NOTIFY_PERIOD + AddScheduleRepeating( "chatbase_notifyenabled", CHAT_COMMAND_PERIODIC_NOTIFY_PERIOD, chatbase_notifyenabled ) +end + +-- wait 10 seconds to setup notification, just to be safe that all commands are registered +AddSchedule("chatbase_setupnotify", 10, chatbase_setupnotify) + +function chatbase_notifyenabled() + chatbase_debug("notifyenabled called") + -- if notifications are completely disabled, return early + if CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY then return end + chatbase_debug("notifyenabled got past disabled check") + + -- if only default commands exist, then theres no reason to notify + if not chatbase_customcommandsexist() then return end + chatbase_debug("notifyenabled got past custom commands check") + + -- notify any players that deserve it + for i,v in pairs(chatbase_players) do + chatbase_debug("checking player ID "..i) + local player = CastToPlayer(v.player) + if IsPlayer(player) then + chatbase_debug("--> IsPlayer") + -- only notify if they havent set their setting to disable notifications + if v.settings["disablenotify"] ~= true then + chatbase_debug("--> disablenotify not true | REPEAT: "..CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT.." numtimesnotified: "..tostring(v.settings["numtimesnotified"])) + -- check repeat type + if CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT == 0 and v.settings["numtimesnotified"] == 0 then + -- only show once + v.settings["numtimesnotified"] = v.settings["numtimesnotified"]+1 + chatbase_notifyplayer(player) + end + if CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT > 0 and v.settings["numtimesnotified"] <= CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT then + -- repeat a set number of times + v.settings["numtimesnotified"] = v.settings["numtimesnotified"]+1 + chatbase_notifyplayer(player) + end + if CHAT_COMMAND_PERIODIC_NOTIFY_REPEAT < 0 then + -- repeat infinitely (var is set to a negative number) + v.settings["numtimesnotified"] = v.settings["numtimesnotified"]+1 + chatbase_notifyplayer(player) + end + end + end + end +end + +function chatbase_notifyplayer(player) + if not IsPlayer(player) then chatbase_error("function chatbase_notifyplayer: Notifying a nonplayer"); return; end + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Chat commands are enabled for this map. Type "..CHAT_COMMAND_PREFIX.."help to see what is available") +end + +------------------------------------- +-- Player Table Functions +------------------------------------- + +function chatbase_addplayer(player) + if not IsPlayer(player) then chatbase_error("function chatbase_addplayer: Trying to add a nonplayer"); return; end + + -- add an entry for the player + chatbase_players[player:GetId()] = {} + chatbase_players[player:GetId()].player = player + chatbase_players[player:GetId()].settings = {} + for setting,values in pairs(chatbase_settings) do + chatbase_players[player:GetId()].settings[setting] = values.default + end +end + +function chatbase_removeplayer(player) + -- param could be a player or a playerid + if tonumber(player) then player = GetPlayerByID(player) end + if not IsPlayer(player) then chatbase_error("function chatbase_removeplayer: Trying to remove a nonplayer"); return; end + + -- clear their entry + chatbase_players[player:GetId()] = nil +end + +------------------------------------- +-- Player Settings Functions +------------------------------------- + +function chatbase_getplayersetting( player, setting ) + -- param could be a player or a playerid + if tonumber(player) then player = GetPlayerByID(player) end + if not IsPlayer(player) then chatbase_error("function chatbase_getplayersetting: Trying to get setting of a nonplayer"); return nil; end + + if chatbase_players[player:GetId()] ~= nil then + return chatbase_players[player:GetId()].settings[setting] + else + chatbase_error("function chatbase_getplayersetting: Player not found in the table"); + return nil + end +end + +function chatbase_setplayersetting( player, setting, value ) + -- param could be a player or a playerid + if tonumber(player) then player = GetPlayerByID(player) end + if not IsPlayer(player) then chatbase_error("function chatbase_setplayersetting: Trying to set setting of a nonplayer"); return false; end + + if chatbase_players[player:GetId()] ~= nil then + chatbase_players[player:GetId()].settings[setting] = value; + return true + else + chatbase_error("function chatbase_setplayersetting: Player not found in the table"); + return false + end +end + +------------------------------------- +-- Debug/Messaging +------------------------------------- + +function chatbase_error( str ) + ConsoleToAll(CHAT_COMMAND_DEBUG_PREFIX.."[ERROR] "..str) +end + +function chatbase_debug( str ) + if CHAT_COMMAND_DEBUG then ConsoleToAll(CHAT_COMMAND_DEBUG_PREFIX..str) end +end + +--[[ +===================================== +== DEFAULT COMMAND IMPLEMENTATION +===================================== +== +===================================== +]]-- + +chatbase_addcommand( "help", "Display a list of all available commands" ) +function chat_help( player ) + ChatToPlayer( player, "^"..CHAT_COMMAND_COLOR_MAIN.."Chat Commands:") + for command,values in pairs(chatbase_commands) do + local command_text = "^"..CHAT_COMMAND_COLOR_HIGHLIGHT1..CHAT_COMMAND_PREFIX..command + if values.description ~= nil then + command_text = command_text.. " ^"..CHAT_COMMAND_COLOR_MAIN.."- ".."^"..CHAT_COMMAND_COLOR_HIGHLIGHT2..values.description + end + if values.example ~= nil then + command_text = command_text.. " ^"..CHAT_COMMAND_COLOR_MAIN.."(example: "..CHAT_COMMAND_PREFIX..values.example..")" + end + ChatToPlayer( player, command_text ) + end +end + +if not CHAT_COMMAND_DISABLE_PERIODIC_NOTIFY then + +chatbase_addcommand( "disablenotify", "Disables the periodic notification that chat commands are enabled" ) +function chat_disablenotify( player ) + chatbase_setplayersetting( player, "disablenotify", true ) + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_MAIN.."Periodic \"chat commands are enabled\" notifications disabled") +end + +end + +--[[ +===================================== +== DEFAULT SETTING IMPLEMENTATION +===================================== +== +===================================== +]]-- + +chatbase_addplayersetting( "disablenotify", false, "Disables periodic notifications that chat commands are enabled" ) +chatbase_addplayersetting( "numtimesnotified", 0, "Number of times the player has been notified that chat commands are enabled" ) + +--[[ +===================================== +== CALLBACKS +===================================== +== +===================================== +]]-- + +-- player_onchat() +---- handle chat commands + +-- save parent player_onchat +local base_player_onchat = player_onchat + +function player_onchat( player, chatstring ) + + -- call parent onchat function if it exists + if base_player_onchat ~= nil then base_player_onchat(player,chatstring) end + + local player = CastToPlayer( player ) + + -- string.gsub call removes all control characters (newlines, return carriages, etc) + -- string.sub call removes the playername: part of the string, leaving just the message + local message = string.sub( string.gsub( chatstring, "%c", "" ), string.len(player:GetName())+3 ) + + chatbase_debug("Message: "..message) + + local prefix = string.sub(message,1,string.len(CHAT_COMMAND_PREFIX)) + + chatbase_debug("Prefix: "..prefix) + + -- if the first character of the string doesn't match the prefix, then we don't care about it + if prefix ~= CHAT_COMMAND_PREFIX then return true; end + + -- strip the prefix character + message = string.sub( message, 1+string.len(CHAT_COMMAND_PREFIX) ) + + chatbase_debug("Message: "..message) + + -- if there is no message at all, return + if string.match(message, "%a+") == nil then return true end + + -- get command and parameters + local command = string.lower( string.match(message, "%a+") ) + local paramstring = string.sub(message, string.len(command)+2) + local params = explode(" ", paramstring) + -- loop through all params and convert any numbers to actual numbers + for i,param in pairs(params) do + -- tonumber() returns nil if it can't convert to a number + if tonumber(param) ~= nil then + param = tonumber(param) + end + chatbase_debug(" Param "..i..": "..param) + end + -- insert the player as the first param always + table.insert( params, 1, player ) + + -- find function to call + local func, finderror = findfunction("chat_"..command) + + if func ~= nil then + if CHAT_COMMAND_DEBUG then ConsoleToAll(CHAT_COMMAND_DEBUG_PREFIX.."Function for "..command.." found"); end + -- translates to chat_( , , ... ) e.g. chat_help() or chat_set( "varname", 5 ) + func(unpack(params)) + else + ChatToPlayer(player, "^"..CHAT_COMMAND_COLOR_ERROR.."Unexpected error while executing command") + chat_error("Command function find error for "..command.."("..paramstring.."):".. finderror) + return true + end + + if CHAT_COMMAND_HIDECHATSTRING then + return false + else + return true + end +end + +-- player_connected() +---- keep track of players + +-- save parent player_connected +local base_player_connected = player_connected + +function player_connected( player ) + + -- call parent onchat function if it exists + if base_player_connected ~= nil then base_player_connected(player) end + + local player = CastToPlayer( player ) + + chatbase_addplayer( player ) +end + +-- player_disconnected() +---- keep track of players + +-- save parent player_disconnected +local base_player_disconnected = player_disconnected + +function player_disconnected( player ) + + -- call parent onchat function if it exists + if base_player_disconnected ~= nil then base_player_disconnected(player) end + + local player = CastToPlayer( player ) + + chatbase_removeplayer( player ) +end + +--[[ +===================================== +== HELPERS +===================================== +== +===================================== +]]-- + +-- Find a function with the given string name in the global table +function findfunction(x) + assert(type(x) == "string") + local f=_G + for v in x:gmatch("[^%.]+") do + if type(f) ~= "table" then + return nil, "looking for '"..v.."' expected table, not "..type(f) + end + f=f[v] + end + if type(f) == "function" then + return f + else + return nil, "expected function, not "..type(f) + end +end + +-- Explode a string by the given divider +function explode(div,str) + if (div=='') then return false end + local pos,arr = 0,{} + -- for each divider found + for st,sp in function() return string.find(str,div,pos,true) end do + table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider + pos = sp + 1 -- Jump past current divider + end + table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider + return arr +end diff --git a/maps/includes/base_cp.lua b/maps/includes/base_cp.lua new file mode 100644 index 0000000..23827d9 --- /dev/null +++ b/maps/includes/base_cp.lua @@ -0,0 +1,1620 @@ +-- base_cp.lua + +-- if you want base cp with the default setup, +-- include base_cp_default.lua in your map's lua file +-- and then include base_cp.lua + +function startup() + + SetGameDescription( "Control Points" ) + + -- disable certain teams + for i,v in pairs(disabled_teams) do + SetPlayerLimit( v, -1 ) + end + + -- set up team limits + for i1,v1 in pairs(teams) do + local team = GetTeam(v1) + for i2,v2 in ipairs(team_info[team:GetTeamId()].class_limits) do + team:SetClassLimit( i2, v2 ) + end + end + + RemoveAllCPAmmoAndArmor() + + for i,v in ipairs(command_points) do + RemoveSchedule( "cp" .. v.cp_number .. "_cap_timer" ) + ResetCPCapping( v ) + AddScheduleRepeating( "cp" .. v.cp_number .. "_cap_zone_timer", CAP_ZONE_TIMER_INTERVAL, cap_zone_timer, v ) + end +end + +function precache() + + -- precache the cap sounds + for i in pairs(good_cap_sounds) do + PrecacheSound(good_cap_sounds[i]) + PrecacheSound(bad_cap_sounds[i]) + end + + PrecacheSound("misc.thunder") + + PrecacheSound("Buttons.snd9") + PrecacheSound("Buttons.snd45") + + PrecacheSound("ff_cz2.teleport_exit") + + PrecacheSound("k_lab.teleport_post_winddown") + PrecacheSound("novaprospekt.teleport_post_thunder") + PrecacheSound("NPC_Ichthyosaur.AttackGrowl") + PrecacheSound("Streetwar.d3_c17_11_die") + PrecacheSound("streetwar.Ba_UseConsoleSounds") + + PrecacheSound( "yourteam.flagcap" ) + PrecacheSound( "otherteam.flagcap" ) +end + +function PlayerStartTouchingCapZone( touch_entity, cp ) + + local player = CastToPlayer(touch_entity) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] == cp then return end + + local team_number = player:GetTeamId() + + PLAYER_TOUCHING_CP_ZONE[player:GetId()] = cp + + cp.touching_players[team_number]:AddItem( player ) + cp.former_touching_players[team_number]:RemoveItem( player ) + cp.cap_speed[team_number] = cp.cap_speed[team_number] + ( player:MaxSpeed() / 10 ) + + if team_number ~= cp.defending_team then + player:SetCloakable( false ) + end + + local cp_zone_hudicon = cp_zone_icons[team_number] + AddHudIcon( player, cp_zone_hudicon.hudicon, cp_zone_hudicon.hudicon, cp_zone_hudicon.hudx, cp_zone_hudicon.hudy, cp_zone_hudicon.hudwidth, cp_zone_hudicon.hudheight, cp_zone_hudicon.hudalign ) + +end + +function PlayerStopTouchingCapZone( touch_entity, cp ) + + local player = CastToPlayer(touch_entity) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] == nil then return end + + local team_number = player:GetTeamId() + + PLAYER_TOUCHING_CP_ZONE[player:GetId()] = nil + + cp.touching_players[team_number]:RemoveItem( player ) + cp.former_touching_players[team_number]:AddItem( player ) + cp.cap_speed[team_number] = cp.cap_speed[team_number] - ( player:MaxSpeed() / 10 ) + + -- clamp + if cp.cap_speed[team_number] < 0 then + cp.cap_speed[team_number] = 0 + end + + player:SetCloakable( true ) + + RemoveHudItem( player, cp_zone_icons[team_number].hudicon ) + +end + + +function DrawCCAlarmIcon( cc_team_number ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + + -- turn on alarm + if team_info[cc_team_number].cc_touch_count > 0 then + + RemoveHudItemFromAll( cc_team_number .. "-ccalarmicon_neutral" ) + AddHudIconToAll( team_info[cc_team_number].ccalarmicon, cc_team_number .. "-ccalarmicon", team_info[cc_team_number].ccalarmiconx, team_info[cc_team_number].ccalarmicony, team_info[cc_team_number].ccalarmiconwidth, team_info[cc_team_number].ccalarmiconheight, team_info[cc_team_number].ccalarmiconalign ) + + -- turn off alarm + else + + RemoveHudItemFromAll( cc_team_number .. "-ccalarmicon" ) + AddHudIconToAll( team_info[Team.kUnassigned].ccalarmicon, cc_team_number .. "-ccalarmicon_neutral", team_info[cc_team_number].ccalarmiconx, team_info[cc_team_number].ccalarmicony, team_info[cc_team_number].ccalarmiconwidth, team_info[cc_team_number].ccalarmiconheight, team_info[cc_team_number].ccalarmiconalign ) + + end + +end + +function EntityStartTouchingCC( touch_entity, cc_team_number ) + + if ENTITY_TOUCHING_CC[touch_entity:GetId()] ~= nil then return end + + ENTITY_TOUCHING_CC[touch_entity:GetId()] = cc_team_number + + team_info[cc_team_number].cc_touch_count = team_info[cc_team_number].cc_touch_count + 1 + + -- turn on alarm + if team_info[cc_team_number].cc_touch_count > 0 then + + OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_sound", "PlaySound" ) + OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_light", "TurnOn" ) + OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_beam", "Color", team_info[touch_entity:GetTeamId()].skybeam_color ) + + end + + DrawCCAlarmIcon( cc_team_number ) + +end + +function EntityStopTouchingCC( touch_entity, cc_team_number ) + + if ENTITY_TOUCHING_CC[touch_entity:GetId()] == nil then return end + + ENTITY_TOUCHING_CC[touch_entity:GetId()] = nil + + team_info[cc_team_number].cc_touch_count = team_info[cc_team_number].cc_touch_count - 1 + + -- turn off alarm + if team_info[cc_team_number].cc_touch_count <= 0 then + + team_info[cc_team_number].cc_touch_count = 0 + + OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_sound", "StopSound" ) + OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_light", "TurnOff" ) + OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_beam", "Color", team_info[Team.kUnassigned].skybeam_color ) + + end + + DrawCCAlarmIcon( cc_team_number ) + +end + +function player_disconnected( player ) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] ~= nil then + PlayerStopTouchingCapZone( player, PLAYER_TOUCHING_CP_ZONE[player:GetId()] ) + end + + if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then + EntityStopTouchingCC( player, ENTITY_TOUCHING_CC[player:GetId()] ) + end + +end + +function player_switchteam( player, currentteam, desiredteam ) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] ~= nil then + PlayerStopTouchingCapZone( player, PLAYER_TOUCHING_CP_ZONE[player:GetId()] ) + end + + if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then + EntityStopTouchingCC( player, ENTITY_TOUCHING_CC[player:GetId()] ) + end + + return true + +end + +----------------------------------------------------------------------------- +-- timed scoring +----------------------------------------------------------------------------- +function cp_score_timer( cp_number, team_number ) + + local team = GetTeam(team_number) + team:AddScore(command_points[cp_number].point_value[team_number]) + +end + +----------------------------------------------------------------------------- +-- notify the players of the total cap. +-- Also, create a logic_relay in your map named fullcap_trigger to pass outputs to your entities. +----------------------------------------------------------------------------- +function complete_control_notification ( team_number ) + + local team = GetTeam(team_number) + SmartTeamSound(team, "yourteam.flagcap", "otherteam.flagcap") + SmartTeamSpeak(team, "CZ_GOTALL", "CZ_THEYGOTALL") + SmartTeamMessage(team, "#FF_CZ2_YOURTEAM_COMPLETE", "#FF_CZ2_OTHERTEAM_COMPLETE", Color.kGreen, Color.kRed) + OutputEvent( "fullcap_trigger", "Trigger" ) + +end + +----------------------------------------------------------------------------- +-- reset everything after the total cap. +----------------------------------------------------------------------------- +function complete_control_respawn () + ApplyToAll( { AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, kReloadClips } ) +end + +----------------------------------------------------------------------------- +-- emit a sound from an entity +----------------------------------------------------------------------------- +function EmitSound( entity, sound ) + + entity:EmitSound(sound) + +end + +----------------------------------------------------------------------------- +-- remove all the ammo and armor from the entire map +----------------------------------------------------------------------------- +function RemoveAllCPAmmoAndArmor() + + -- Remove all ammo and armor from CPs + local c = Collection() + c:GetByName(cp_ammo_and_armor_names, { CF.kNone }) + for item in c.items do + item = CastToInfoScript(item) + item:Remove() + end + +end + +----------------------------------------------------------------------------- +-- does the player have a flag? +----------------------------------------------------------------------------- +function PlayerHasFlag( player ) + + -- check if the player has a flag + for i,v in ipairs(flags) do + if player:HasItem(v) then + -- player has a flag + return true + end + end + + -- player doesn't have a flag + return false + +end + +----------------------------------------------------------------------------- +-- return carried flags +----------------------------------------------------------------------------- +function ReturnFlagFromPlayer( player ) + + -- Get all carried flags and ... + local c = Collection() + c:GetByName(flags, { CF.kInfoScript_Carried, }) + + -- ... return the flag that the player is carrying. + for item in c.items do + item = CastToInfoScript(item) + carrier = item:GetCarrier() + if player:GetId() == carrier:GetId() then + item:Return() + end + end + +end + +----------------------------------------------------------------------------- +-- resupply a player when a cp is capped +----------------------------------------------------------------------------- +function CapResupply( player, scale, givethegoodshit ) + + -- give the player health and armor + if cap_resupply.health ~= nil and cap_resupply.health ~= 0 then player:AddHealth( cap_resupply.health * scale ) end + if cap_resupply.armor ~= nil and cap_resupply.armor ~= 0 then player:AddArmor( cap_resupply.armor * scale ) end + + -- give the player ammo + if cap_resupply.nails ~= nil and cap_resupply.nails ~= 0 then player:AddAmmo( Ammo.kNails, cap_resupply.nails * scale ) end + if cap_resupply.shells ~= nil and cap_resupply.shells ~= 0 then player:AddAmmo( Ammo.kShells, cap_resupply.shells * scale ) end + if cap_resupply.rockets ~= nil and cap_resupply.rockets ~= 0 then player:AddAmmo( Ammo.kRockets, cap_resupply.rockets * scale ) end + if cap_resupply.cells ~= nil and cap_resupply.cells ~= 0 then player:AddAmmo( Ammo.kCells, cap_resupply.cells * scale ) end + + if givethegoodshit then + -- give the player the good shit + if cap_resupply.detpacks ~= nil and cap_resupply.detpacks ~= 0 then player:AddAmmo( Ammo.kDetpack, cap_resupply.detpacks * scale ) end + if cap_resupply.mancannons ~= nil and cap_resupply.mancannons ~= 0 then player:AddAmmo( Ammo.kManCannon, cap_resupply.mancannons * scale ) end + if cap_resupply.gren1 ~= nil and cap_resupply.gren1 ~= 0 then player:AddAmmo( Ammo.kGren1, cap_resupply.gren1 * scale ) end + if cap_resupply.gren2 ~= nil and cap_resupply.gren2 ~= 0 then player:AddAmmo( Ammo.kGren2, cap_resupply.gren2 * scale ) end + end + +end + +function player_killed ( player_victim, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + -- Entity that is attacking + local attacker = damageinfo:GetAttacker() + + -- If no attacker do nothing + if not attacker then return end + + local player_attacker = nil + + -- get the attacking player + if IsPlayer(attacker) then + attacker = CastToPlayer(attacker) + player_attacker = attacker + elseif IsSentrygun(attacker) then + attacker = CastToSentrygun(attacker) + player_attacker = attacker:GetOwner() + elseif IsDetpack(attacker) then + attacker = CastToDetpack(attacker) + player_attacker = attacker:GetOwner() + elseif IsDispenser(attacker) then + attacker = CastToDispenser(attacker) + player_attacker = attacker:GetOwner() + end + + -- if still no attacking player after all that, try the inflictor + if not player_attacker then + + -- Entity that is attacking + local inflictor = damageinfo:GetInflictor() + + if inflictor then + if IsSentrygun(inflictor) then + inflictor = CastToSentrygun(inflictor) + player_attacker = inflictor:GetOwner() + elseif IsDetpack(inflictor) then + inflictor = CastToDetpack(inflictor) + player_attacker = inflictor:GetOwner() + elseif IsDispenser(inflictor) then + inflictor = CastToDispenser(inflictor) + player_attacker = inflictor:GetOwner() + end + end + + end + + -- if still no attacking player after all that, forget about it + if not player_attacker then return end + + -- if victim killed self or teammate do nothing + if (player_victim:GetId() == player_attacker:GetId()) or (player_victim:GetTeamId() == player_attacker:GetTeamId()) then return end + + local player_victim_touching_cp = PLAYER_TOUCHING_CP_ZONE[player_victim:GetId()] + local player_attacker_touching_cp = PLAYER_TOUCHING_CP_ZONE[player_attacker:GetId()] + + -- the victim is standing in a zone + if player_victim_touching_cp ~= nil then + + -- the victim is defending a cp or trying to capture a neutral cp + if player_victim:GetTeamId() == player_victim_touching_cp.defending_team or player_victim_touching_cp.defending_team == Team.kUnassigned then + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_victim_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + -- the victim is trying to capture the attacker's cp + else + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_victim_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_DEFENDPOINT") + + end + + end + + -- the attacker is standing in a zone + if player_attacker_touching_cp ~= nil then + + -- the attacker is defending a cp + if player_attacker:GetTeamId() == player_attacker_touching_cp.defending_team then + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_attacker_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_DEFENDPOINT") + + -- the attacker is trying to capture a cp + else + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_attacker_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + end + + end + + -- loop through all former players of each command point + for k,v in ipairs(command_points) do + + -- victim's team + for i in v.former_touching_players[player_victim:GetTeamId()].items do + + i = CastToPlayer( i ) + + -- the victim was in an active zone + if i:GetId() == player_victim:GetId() then + + -- the victim is defending a cp or trying to capture a neutral cp + if player_victim:GetTeamId() == v.defending_team or v.defending_team == Team.kUnassigned then + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + -- the victim is trying to capture the attacker's cp + else + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST") + + end + + end + + end + + -- attacker's team + for i in v.former_touching_players[player_attacker:GetTeamId()].items do + + i = CastToPlayer( i ) + + -- the attacker was in an active zone + if i:GetId() == player_attacker:GetId() then + + -- the attacker is defending a cp + if player_attacker:GetTeamId() == v.defending_team then + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST") + + -- the attacker is trying to capture a cp + else + + CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + end + + end + + end + + end + +end + +----------------------------------------------------------------------------- +-- change the cp's defending team, its related visuals, and its scoring +----------------------------------------------------------------------------- +function ChangeCPDefendingTeam( cp_number, new_defending_team ) + + local cp = command_points[cp_number] + + -- Change the skybeam color + OutputEvent( "cp" .. cp_number .. "_skybeam", "Color", team_info[new_defending_team].skybeam_color ) + + -- Change the light color + for i in pairs(team_info) do + -- turn off all other lights as well + local input_name = "TurnOff" + local input2_name = "LightOff" + if i == new_defending_team then + input_name = "TurnOn" + input2_name = "LightOn" + end + OutputEvent( "cp" .. cp_number .. "_light_" .. team_info[i].team_name, input_name ) + OutputEvent( "cp" .. cp_number .. "_spotlight_" .. team_info[i].team_name, input2_name ) + end + + -- Change the rotating flag around + OutputEvent( "cp" .. cp_number .. "_flag_rotator", "Reverse") + OutputEvent( "cp" .. cp_number .. "_flag", "Skin", team_info[new_defending_team].skin ) + OutputEvent( "cp" .. cp_number .. "_flag", team_info[new_defending_team].flag_visibility) + + -- remove old flaginfo icons and add new ones + RemoveHudItemFromAll( cp_number .. "-background-" .. cp.defending_team ) + RemoveHudItemFromAll( cp_number .. "-foreground-" .. cp.defending_team ) + + AddHudIconToAll( icons[ new_defending_team ].teamicon, cp_number .. "-background-" .. new_defending_team, cp.hudposx, cp.hudposy, cp.hudwidth, cp.hudheight, cp.hudalign) + AddHudIconToAll( cp.hudstatusicon, cp_number .. "-foreground-" .. new_defending_team, cp.hudposx, cp.hudposy, cp.hudwidth, cp.hudheight, cp.hudalign) + + local schedule_name = "cp" .. cp_number .. "_score_timer" + + -- stop an existing timer + if cp.defending_team ~= Team.kUnassigned then + RemoveSchedule( schedule_name ) + end + + -- only worry with score timer for TEAM1 and TEAM2 + if new_defending_team ~= Team.kUnassigned then + + -- start the score timer + AddScheduleRepeating( schedule_name, cp.score_timer_interval[new_defending_team], cp_score_timer, cp_number, new_defending_team ) + + end + + cp.defending_team = new_defending_team + +end + +----------------------------------------------------------------------------- +-- restore all items in a CP +----------------------------------------------------------------------------- +function RestoreCPItems( cp_number, old_defending_team, new_defending_team ) + + local c = Collection() + c:GetByName( { "cp_cp" .. cp_number .. "_ammo", "cz2_cp" .. cp_number .. "_ammo", "cp_cp" .. cp_number .. "_armor", "cz2_cp" .. cp_number .. "_armor" }, { CF.kNone } ) + for item in c.items do + item = CastToInfoScript(item) + + -- restore this CP's ammo and armor + item:Restore() + + -- Also set the touchflags so only the defending team can use the packs + item:SetTouchFlags(team_info[new_defending_team].touchflags) + end + +end + +----------------------------------------------------------------------------- +-- reset team cp capping stuff +----------------------------------------------------------------------------- +function ResetTeamCPCapping( cp, team_number, do_total_reset, set_next_cap_zone_timer ) + + cp.cap_status[team_number] = 0 + cp.next_cap_zone_timer[team_number] = set_next_cap_zone_timer + + RemoveHudItemFromAll( cp.cp_number .. "-capstatusicon-" .. team_number ) + RemoveHudItemFromAll( cp.cp_number .. "-caplockicon-" .. team_number ) + OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[team_number].team_name .. "_capsprites", "HideSprite" ) + OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[team_number].team_name .. "_capsound", "StopSound" ) + + if cp.former_touching_players[team_number]:Count() > 0 then + cp.former_touching_players[team_number]:RemoveAllItems() + end + + if do_total_reset then + if cp.touching_players[team_number]:Count() > 0 then + cp.touching_players[team_number]:RemoveAllItems() + end + + cp.cap_speed[team_number] = 0 + end + +end + +----------------------------------------------------------------------------- +-- reset all cp capping stuff +----------------------------------------------------------------------------- +function ResetCPCapping( cp ) + + for i,v in pairs(teams) do + ResetTeamCPCapping( cp, v, true, 0 ) + end + +end + +----------------------------------------------------------------------------- +-- the cp has definitely been captured +----------------------------------------------------------------------------- +function CaptureCP( cp_number, new_defending_team ) + + local cp = command_points[cp_number] + local old_defending_team = cp.defending_team + + RestoreCPItems(cp_number, old_defending_team, new_defending_team) + + -- Give points to team and player + local team = GetTeam(new_defending_team) + team:AddScore(cp.point_value[new_defending_team]) + + -- Find out if any team has complete control + local team_with_complete_control = Team.kUnassigned + local control_count = { [TEAM1] = 0, [TEAM2] = 0 } + control_count[new_defending_team] = 1 + for i,v in ipairs(command_points) do + if v.defending_team ~= Team.kUnassigned and v.cp_number ~= cp_number then + control_count[v.defending_team] = control_count[v.defending_team] + 1 + end + if control_count[v.defending_team] == CP_COUNT then + team_with_complete_control = v.defending_team + break + end + end + + if team_with_complete_control ~= Team.kUnassigned then + + if ENABLE_COMPLETE_CONTROL_POINTS then + -- Bonus points for complete control + team:AddScore(POINTS_FOR_COMPLETE_CONTROL) + end + + if ENABLE_COMPLETE_CONTROL_RESET then + + AddSchedule("complete_control_notification", 0.1, complete_control_notification, team_with_complete_control) + + -- Reset all command points + for i,v in ipairs(command_points) do + ChangeCPDefendingTeam(v.cp_number, Team.kUnassigned) + ResetCPCapping( v ) + end + + -- reset colors of respawn beams + --OutputEvent( team_info[TEAM1].team_name .. "_respawn_beam", "Color", team_info[Team.kUnassigned].respawnbeam_color[0] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[1] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[2] ) + --OutputEvent( team_info[TEAM2].team_name .. "_respawn_beam", "Color", team_info[Team.kUnassigned].respawnbeam_color[0] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[1] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[2] ) + + if ENABLE_FLAGS then + -- Return all flags + local c = Collection() + c:GetByName(flags, { CF.kNone }) + for item in c.items do + item = CastToInfoScript(item) + item:Return() + end + end + + RemoveAllCPAmmoAndArmor() + + if ENABLE_COMPLETE_CONTROL_RESPAWN then + AddSchedule("complete_control_respawn", 1.0, complete_control_respawn) + end + + -- get out now if resetting + return + + end + + end + + ChangeCPDefendingTeam(cp_number, new_defending_team) + + -- change the colors this team's respawn beams + --local beam_team = team_info[new_defending_team] + --beam_team.respawnbeam_color[beam_team.color_index] = beam_team.respawnbeam_color[Team.kUnassigned] + (control_count[new_defending_team] * 35) + --OutputEvent( beam_team.team_name .. "_respawn_beam", "Color", beam_team.respawnbeam_color[0] .. " " .. beam_team.respawnbeam_color[1] .. " " .. beam_team.respawnbeam_color[2] ) + + SmartTeamMessage( team, "#FF_CZ2_YOURTEAM_CP" .. cp_number, "#FF_CZ2_OTHERTEAM_CP" .. cp_number, Color.kGreen, Color.kRed ) + + -- sounds will get more and more crazy + --SmartTeamSound( team, good_cap_sounds[control_count[new_defending_team]], bad_cap_sounds[control_count[new_defending_team]] ) + + -- caes: changed it to announce the cp number captured/lost + SmartTeamSpeak( team, good_cap_sounds[cp_number], bad_cap_sounds[cp_number] ) +end + + +----------------------------------------------------------------------------- +-- a cp's defending team successfully defended or capped +----------------------------------------------------------------------------- +function SuccessfulCPDefense( cp, team_number, is_a_cap ) + + -- reward the touching players + for i in cp.touching_players[team_number].items do + i = CastToPlayer( i ) + if is_a_cap then + CapResupply( i, 1.00, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 100, "#FF_FORTPOINTS_CAPTUREPOINT") + i:SetCloakable( true ) + else + CapResupply( i, 0.50, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 50, "#FF_FORTPOINTS_DEFENDPOINT") + end + end + + -- reward the former touching players + for i in cp.former_touching_players[team_number].items do + i = CastToPlayer( i ) + if is_a_cap then + CapResupply( i, 0.50, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + else + CapResupply( i, 0.25, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST") + end + end + + -- no need to keep them around for future rewards + cp.former_touching_players[team_number]:RemoveAllItems() + +end + + +----------------------------------------------------------------------------- +-- timed cp capping +----------------------------------------------------------------------------- +function cap_zone_timer( cp ) + + local new_defending_team = Team.kUnassigned + local other_team = Team.kUnassigned + local last_cap_status = {} + local total_cap_speed = 0 + local total_cap_status = 0 + + for i,v in pairs(teams) do + total_cap_speed = total_cap_speed + cp.cap_speed[v] + total_cap_status = total_cap_status + cp.cap_status[v] + end + + for i,v in pairs(teams) do + + -- don't bother doing some stuff if nothing has changed + last_cap_status[v] = cp.cap_status[v] + + -- after one team caps a cp, the other team can't touch that cp for X seconds + if cp.next_cap_zone_timer[v] > 0 then + + cp.next_cap_zone_timer[v] = cp.next_cap_zone_timer[v] - CAP_ZONE_TIMER_INTERVAL + + local lock_percent = math.min( 1.0, cp.next_cap_zone_timer[v] / cp.delay_before_retouch[v] ) + local minlockhudwidth = cp.hudwidth * 0.333 + local minlockhudheight = cp.hudheight * 0.333 + + AddHudIconToAll( icons[v].lockicon, cp.cp_number .. "-caplockicon-" .. v, cp.hudposx, cp.hudposy + cp_zone_icons[v].hudposy_offset, minlockhudwidth + ( (cp.hudwidth - minlockhudwidth) * lock_percent ), minlockhudheight + ( (cp.hudheight - minlockhudheight) * lock_percent ), cp.hudalign) + + -- clamp + if cp.next_cap_zone_timer[v] <= 0 then + cp.next_cap_zone_timer[v] = 0 + RemoveHudItemFromAll( cp.cp_number .. "-caplockicon-" .. v ) + end + + -- this team is standing in the zone + elseif cp.cap_speed[v] > 0 then + + -- don't bother with cap_status calculations for the defending team + if v == cp.defending_team then + + cp.cap_status[v] = cp.cap_requirement[v] + + -- calculate cap status + else + + -- every vote counts + local affected_cap_speed = cp.cap_speed[v] - ( total_cap_speed - cp.cap_speed[v] ) + + cp.cap_status[v] = cp.cap_status[v] + affected_cap_speed + + -- clamp + if cp.cap_status[v] < 0 then + + cp.cap_status[v] = 0 + + -- potential capping team + elseif cp.cap_status[v] >= cp.cap_requirement[v] then + + new_defending_team = v + + -- clamp + cp.cap_status[v] = cp.cap_requirement[v] + + end + end + + -- this team is not standing in the zone + else + if v == cp.defending_team then + -- don't bother with cap_status calculations for the defending team + cp.cap_status[v] = 0 + else + -- decrease cap status + cp.cap_status[v] = cp.cap_status[v] - ( CAP_ZONE_NOTOUCH_SPEED + total_cap_speed ) + + -- clamp + if cp.cap_status[v] < 0 then + cp.cap_status[v] = 0 + end + end + end + + -- don't bother doing some stuff if nothing has changed + if cp.cap_status[v] ~= last_cap_status[v] then + + -- draw the cap status icon + if cp.cap_status[v] > 0 then + + local cap_percent = cp.cap_status[v] / cp.cap_requirement[v] + local minhudwidth = cp.hudwidth * 0.333 + local minhudheight = cp.hudheight * 0.333 + AddHudIconToAll( cp_zone_icons[v].hudicon, cp.cp_number .. "-capstatusicon-" .. v, cp.hudposx, cp.hudposy + cp_zone_icons[v].hudposy_offset, minhudwidth + ( (cp.hudwidth - minhudwidth) * cap_percent ), minhudheight + ( (cp.hudheight - minhudheight) * cap_percent ), cp.hudalign) + OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[v].team_name .. "_capsprites", "ShowSprite" ) + OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[v].team_name .. "_capsound", "PlaySound" ) + + -- remove the cap status icon, remove former touching players, and reward defenders + else + + -- reward the defenders + if v ~= cp.defending_team and cp.defending_team ~= Team.kUnassigned then + SuccessfulCPDefense( cp, cp.defending_team, false ) + end + + -- reset the other team's cp capping stuff + ResetTeamCPCapping( cp, v, false, 0 ) + + end + + end + + if new_defending_team ~= v then + other_team = v + end + + end + + -- someone capped this cp + if new_defending_team ~= Team.kUnassigned then + + -- cap the cp + SuccessfulCPDefense( cp, new_defending_team, true ) + CaptureCP( cp.cp_number, new_defending_team ) + + -- reset the other team's cp capping stuff + ResetTeamCPCapping( cp, other_team, false, cp.delay_before_retouch[other_team] ) + + end + +end + + +----------------------------------------------------------------------------- +-- triggers +----------------------------------------------------------------------------- + +cp_base_trigger = trigger_ff_script:new({ team = Team.kUnassigned, failtouch_message = "" }) + +function cp_base_trigger:allowed( allowed_entity ) + + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +function cp_base_trigger:onfailtouch( touch_entity ) + + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + BroadCastMessageToPlayer( player, failtouch_message ) + end +end + +cp_team1_door_trigger = cp_base_trigger:new({ team = TEAM1 , failtouch_message = "#FF_NOTALLOWEDDOOR" }) +cp_team2_door_trigger = cp_base_trigger:new({ team = TEAM2 , failtouch_message = "#FF_NOTALLOWEDDOOR" }) + + +----------------------------------------------------------------------------- +-- packs +----------------------------------------------------------------------------- +cp_base_pack = genericbackpack:new({ + health = 100, + armor = 300, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + detpacks = 0, + mancannons = 0, + gren1 = 0, + gren2 = 0, + respawntime = 1, + touchflags = team_info[Team.kUnassigned].touchflags, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + cp_number = 0, + botgoaltype = Bot.kBackPack_Ammo, +}) + +function cp_base_pack:dropatspawn() return false end + +cp_team1_respawn_pack = cp_base_pack:new( { touchflags = team_info[TEAM1].touchflags } ) +cp_team2_respawn_pack = cp_base_pack:new( { touchflags = team_info[TEAM2].touchflags } ) + +cp_cp1_ammo = ammobackpack:new({cp_number = 1}) +cp_cp2_ammo = ammobackpack:new({cp_number = 2}) +cp_cp3_ammo = ammobackpack:new({cp_number = 3}) +cp_cp4_ammo = ammobackpack:new({cp_number = 4}) +cp_cp5_ammo = ammobackpack:new({cp_number = 5}) + +cp_cp1_armor = armorkit:new({cp_number = 1}) +cp_cp2_armor = armorkit:new({cp_number = 2}) +cp_cp3_armor = armorkit:new({cp_number = 3}) +cp_cp4_armor = armorkit:new({cp_number = 4}) +cp_cp5_armor = armorkit:new({cp_number = 5}) + + +----------------------------------------------------------------------------- +-- grenade packs +----------------------------------------------------------------------------- +cp_base_grenade_pack = cp_base_pack:new({ + detpacks = 1, + mancannons = 1, + gren1 = 4, + gren2 = 4, + respawntime = 15, + touchflags = team_info[Team.kUnassigned].touchflags, + botgoaltype = Bot.kBackPack_Grenades, +}) + +cp_team1_grenade_pack = cp_base_grenade_pack:new( { touchflags = team_info[TEAM1].touchflags } ) +cp_team2_grenade_pack = cp_base_grenade_pack:new( { touchflags = team_info[TEAM2].touchflags } ) + + +----------------------------------------------------------------------------- +-- cp zones +----------------------------------------------------------------------------- + +cp_base_cp_zone = trigger_ff_script:new({ + item = "", + team = 0, + botgoaltype = Bot.kFlagCap, + cp_number = 0, +}) + +function cp_base_cp_zone:ontrigger( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if ENABLE_FLAGS or not ENABLE_CP_TELEPORTERS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- Allow players on defending team to teleport back to base + if player:GetTeamId() == command_points[self.cp_number].defending_team then + + if player:IsInUse() then + -- respawn the player + ApplyToPlayer( player, { AT.kRespawnPlayers, kReloadClips } ) + + OutputEvent( "cp" .. self.cp_number .. "_respawn_enter_sound", "PlaySound" ) + AddSchedule("cp" .. self.cp_number .. "_respawn_" .. player:GetId(), 0.1, EmitSound, player, "ff_cz2.teleport_exit") + else + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_RESPAWN") + end + + end + + end + +end + +function cp_base_cp_zone:ontouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these zones are used + if ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + local cp = command_points[self.cp_number] + PlayerStartTouchingCapZone( player, cp ) + end + +end + +function cp_base_cp_zone:onendtouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these zones are used + if ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + local cp = command_points[self.cp_number] + PlayerStopTouchingCapZone( player, cp ) + end +end + +cp_cp1_cp_zone = cp_base_cp_zone:new({ cp_number = 1 }) +cp_cp2_cp_zone = cp_base_cp_zone:new({ cp_number = 2 }) +cp_cp3_cp_zone = cp_base_cp_zone:new({ cp_number = 3 }) +cp_cp4_cp_zone = cp_base_cp_zone:new({ cp_number = 4 }) +cp_cp5_cp_zone = cp_base_cp_zone:new({ cp_number = 5 }) + + +----------------------------------------------------------------------------- +-- cp triggers +----------------------------------------------------------------------------- + +cp_base_cp_trigger = trigger_ff_script:new({ + item = "", + team = 0, + botgoaltype = Bot.kFlagCap, + cp_number = 0, +}) + +function cp_base_cp_trigger:ontrigger( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS or not ENABLE_CP_TELEPORTERS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- Allow players on defending team to teleport back to base + if player:GetTeamId() == command_points[self.cp_number].defending_team then + + if player:IsInUse() then + -- check if the player has a flag + for i,v in ipairs(flags) do + -- return the flag + if player:HasItem(v) then ReturnFlagFromPlayer(player) end + end + + -- respawn the player + ApplyToPlayer( player, { AT.kRespawnPlayers, kReloadClips } ) + + OutputEvent( "cp" .. self.cp_number .. "_respawn_enter_sound", "PlaySound" ) + AddSchedule("cp" .. self.cp_number .. "_respawn_" .. player:GetId(), 0.1, EmitSound, player, "ff_cz2.teleport_exit") + else + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_RESPAWN") + end + + end + + end + +end + +function cp_base_cp_trigger:ontouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + local cp = command_points[self.cp_number] + + -- No capping if player's team already defends this CP + if player:GetTeamId() == cp.defending_team then return end + + -- get out if player doesn't have flag + if not PlayerHasFlag(player) then return end + + ReturnFlagFromPlayer(player) + + CaptureCP(self.cp_number, player:GetTeamId()) + player:AddFortPoints((cp.point_value[player:GetTeamId()]) * 100, "#FF_FORTPOINTS_CAPTUREPOINT") + end + +end + +cp_cp1_cp_trigger = cp_base_cp_trigger:new({ cp_number = 1 }) +cp_cp2_cp_trigger = cp_base_cp_trigger:new({ cp_number = 2 }) +cp_cp3_cp_trigger = cp_base_cp_trigger:new({ cp_number = 3 }) +cp_cp4_cp_trigger = cp_base_cp_trigger:new({ cp_number = 4 }) +cp_cp5_cp_trigger = cp_base_cp_trigger:new({ cp_number = 5 }) + + +----------------------------------------------------------------------------- +-- flags +----------------------------------------------------------------------------- + +cp_base_flag = info_ff_script:new({ + name = "Base Flag", + team = 0, + model = "models/flag/flag.mdl", + tosssound = "Flag.Toss", + modelskin = 0, + dropnotouchtime = 2, + capnotouchtime = 2, + botgoaltype = Bot.kFlag, + hudicon = "", + hudx = 5, + hudy = 180, + hudalign = 1, + touchflags = team_info[Team.kUnassigned].touchflags +}) + +function cp_base_flag:precache() + PrecacheSound(self.tosssound) + info_ff_script.precache(self) +end + +function cp_base_flag:spawn() + self.notouch = { } + info_ff_script.spawn(self) +end + +function cp_base_flag:addnotouch(player_id, duration) + self.notouch[player_id] = duration + AddSchedule(self.name .. "-" .. player_id, duration, self.removenotouch, self, player_id) +end + +function cp_base_flag.removenotouch(self, player_id) + self.notouch[player_id] = nil +end + +function cp_base_flag:touch( touch_entity ) + local player = CastToPlayer( touch_entity ) + + if player:GetTeamId() ~= self.team then return end + + -- pickup if they can + if self.notouch[player:GetId()] then return end + + -- make sure they don't have any flags already + for i,v in ipairs(flags) do + if player:HasItem(v) then return end + end + + -- if the player is a spy, then force him to lose his disguise + player:SetDisguisable( false ) + player:SetCloakable( false ) + + -- note: this seems a bit backwards (Pickup verb fits Player better) + local flag = CastToInfoScript(entity) + flag:Pickup(player) + player:AddEffect( EF.kSpeedlua1, -1, 0, FLAG_CARRIER_SPEED ) + AddHudIcon( player, self.hudicon, flag:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign ) +end + +function cp_base_flag:onownerdie( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) +end + +function cp_base_flag:onownerfeign( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) +end +function cp_base_flag:onownercloak( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) +end +function cp_base_flag:dropitemcmd( owner_entity ) + -- throw the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, FLAG_THROW_SPEED) +end + +function cp_base_flag:ondrop( owner_entity ) + local flag = CastToInfoScript(entity) + flag:EmitSound(self.tosssound) +end + +function cp_base_flag:onloseitem( owner_entity ) + -- let the player that lost the flag put on a disguise + local player = CastToPlayer( owner_entity ) + player:SetDisguisable(true) + player:SetCloakable(true) + + self:addnotouch(player:GetId(), self.capnotouchtime) + + --player:RemoveEffect( EF.kSpeedlua1 ) + -- remove flag icon from hud + local flag = CastToInfoScript(entity) + RemoveHudItem( player, flag:GetName() ) +end + +function cp_base_flag:onreturn( ) +end + +cp_team1_flag = cp_base_flag:new({ + team = TEAM1, + modelskin = 0, + name = team_info[TEAM1].team_name .. " flag", + hudicon = "hud_flag_" .. team_info[TEAM1].team_name .. ".vtf", + hudx = 5, + hudy = 180, + hudwidth = 48, + hudheight = 48, + touchflags = team_info[TEAM1].touchflags +}) + +cp_team2_flag = cp_base_flag:new({ + team = TEAM2, + modelskin = 1, + name = team_info[TEAM2].team_name .. " flag", + hudicon = "hud_flag_" .. team_info[TEAM2].team_name .. ".vtf", + hudx = 5, + hudy = 180, + hudwidth = 48, + hudheight = 48, + touchflags = team_info[TEAM2].touchflags +}) + + +----------------------------------------------------------------------------- +-- flag dispensers +----------------------------------------------------------------------------- +cp_base_flag_dispenser = trigger_ff_script:new({ + name = "Base Flag Dispenser", + team = Team.kUnassigned, + dropnotouchtime = 2, + botgoaltype = Bot.kFlag, + hudicon = "", + hudx = 5, + hudy = 180, + hudwidth = 48, + hudheight = 48, + hudalign = 1, + flags = {"flag"} +}) + +function cp_base_flag_dispenser:allowed ( allowed_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS then return EVENT_DISALLOWED end + + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team then + + -- Player can't have a flag + local playerhasflag = false + + for i,v in ipairs(self.flags) do + if player:HasItem(v) then + playerhasflag = true + break + end + end + + -- get out if player doesn't have flag + if not playerhasflag then + return EVENT_ALLOWED + end + end + end + return EVENT_DISALLOWED +end + +function cp_base_flag_dispenser:ontouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + + local player = CastToPlayer( trigger_entity ) + + local c = Collection() + c:GetByName( self.flags, { CF.kNone } ) + -- give the player an inactive flag + for item in c.items do + item = CastToInfoScript(item) + if item:IsInactive() then + -- if the player is a spy, then force him to lose his disguise + player:SetDisguisable( false ) + player:SetCloakable( false ) + + -- note: this seems a bit backwards (Pickup verb fits Player better) + item:Pickup(player) + player:AddEffect( EF.kSpeedlua1, -1, 0, FLAG_CARRIER_SPEED ) + AddHudIcon( player, self.hudicon, item:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign ) + + player:EmitSound("Buttons.snd9") + + -- all done + break + end + end + end +end + +cp_team1_flag_dispenser = cp_base_flag_dispenser:new({ + name = team_info[TEAM1].team_name .. " flag dispenser", + team = TEAM1, + hudicon = "hud_flag_" .. team_info[TEAM1].team_name .. ".vtf", + flags = { team_info[TEAM1].team_name .. "_flag" } +}) + +cp_team2_flag_dispenser = cp_base_flag_dispenser:new({ + name = team_info[TEAM2].team_name .. " flag dispenser", + team = TEAM2, + hudicon = "hud_flag_" .. team_info[TEAM2].team_name .. ".vtf", + flags = { team_info[TEAM2].team_name .. "_flag" } +}) + + +----------------------------------------------------------------------------- +-- command centers +----------------------------------------------------------------------------- + +cp_base_command_center = trigger_ff_script:new({ team = Team.kUnassigned, enemy_team = Team.kUnassigned }) +function cp_base_command_center:onexplode( explosion_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return EVENT_ALLOWED end + + if IsDetpack( explosion_entity ) then + local detpack = CastToDetpack(explosion_entity) + + -- don't let assholes destroy their own team's command center + if detpack:GetTeamId() == self.team then return EVENT_ALLOWED end + + local points = CC_DESTROY_POINTS + for i,v in ipairs(command_points) do + if v.defending_team == self.team then + -- taking CP 1 away from team2 is worth more than taking CP 5 away from them + points = points + v.point_value[self.team] + + -- Remove all ammo and armor from CPs + local c = Collection() + c:GetByName({"cp_cp" .. v.cp_number .. "_ammo", "cz2_cp" .. v.cp_number .. "_ammo", "cp_cp" .. v.cp_number .. "_armor", "cz2_cp" .. v.cp_number .. "_armor"}, { CF.kNone }) + for item in c.items do + item = CastToInfoScript(item) + item:Remove() + end + + -- reset the CP + ChangeCPDefendingTeam(v.cp_number, Team.kUnassigned) + end + + -- reset the other team's cp capping stuff + ResetTeamCPCapping( v, self.team, false, v.delay_before_retouch[self.team] * 2.0 ) + end + + local team = detpack:GetTeam() + team:AddScore(points) + + local player = detpack:GetOwner() + player:AddFortPoints(points * 100, "#FF_FORTPOINTS_DESTROY_CC" ) + + SmartSound(player, "misc.thunder", "misc.thunder", "misc.thunder") + SmartMessage(player, "#FF_CZ2_YOU_CC", "#FF_CZ2_YOURTEAM_CC", "#FF_CZ2_OTHERTEAM_CC", Color.kGreen, Color.kGreen, Color.kRed) + SpeakAll( team_info[self.team].detcc_sentence ) + +-- EntityStopTouchingCC( detpack, self.team ) + + end + + return EVENT_ALLOWED +end + +function cp_base_command_center:ontouch( trigger_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + +-- if IsDetpack( trigger_entity ) then +-- local detpack = CastToDetpack( trigger_entity ) +-- if detpack:GetTeamId() ~= self.team then +-- EntityStartTouchingCC( detpack, self.team ) +-- end +-- end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + if player:GetTeamId() ~= self.team then + EntityStartTouchingCC( player, self.team ) + end + end + +end + +function cp_base_command_center:onendtouch( trigger_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + +-- if IsDetpack( trigger_entity ) then +-- local detpack = CastToDetpack( trigger_entity ) +-- if detpack:GetTeamId() ~= self.team then +-- EntityStopTouchingCC( detpack, self.team ) +-- end +-- end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + if player:GetTeamId() ~= self.team then + EntityStopTouchingCC( player, self.team ) + end + end +end + +cp_team1_command_center = cp_base_command_center:new({ team = TEAM1, enemy_team = TEAM2 }) +cp_team2_command_center = cp_base_command_center:new({ team = TEAM2, enemy_team = TEAM1 }) + + +------------------------------------------- +-- cc computers +------------------------------------------- + +cp_base_cc_computer = trigger_ff_script:new({ prefix = "unassigned", enemy_team = Team.kUnassigned }) + +function cp_base_cc_computer:ontrigger( trigger_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- Allow spies to open the enemy doors + if player:GetTeamId() == self.enemy_team and player:GetClass() == Player.kSpy then + + if player:IsInUse() then + for i,v in ipairs(doors) do + -- open each enemy door + OutputEvent( self.prefix .. v, "Open" ) + end + else + -- tell the player they can open the enemy doors + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_DOORS") + end + + end + end +end + +cp_team1_cc_computer = cp_base_cc_computer:new({ prefix = team_info[TEAM1].team_name, enemy_team = TEAM2 }) +cp_team2_cc_computer = cp_base_cc_computer:new({ prefix = team_info[TEAM2].team_name, enemy_team = TEAM1 }) + + +------------------------------------------- +-- cp flaginfo +------------------------------------------- + +function flaginfo( player_entity ) + + local player = CastToPlayer( player_entity ) + + for i,v in ipairs(command_points) do + + AddHudIcon( player, icons[ v.defending_team ].teamicon , v.cp_number .. "-background-" .. v.defending_team , command_points[v.cp_number].hudposx, command_points[v.cp_number].hudposy, command_points[v.cp_number].hudwidth, command_points[v.cp_number].hudheight, command_points[v.cp_number].hudalign) + AddHudIcon( player, command_points[v.cp_number].hudstatusicon, v.cp_number .. "-foreground-" .. v.defending_team , command_points[v.cp_number].hudposx, command_points[v.cp_number].hudposy, command_points[v.cp_number].hudwidth, command_points[v.cp_number].hudheight, command_points[v.cp_number].hudalign) + + end + + DrawCCAlarmIcon( TEAM1 ) + DrawCCAlarmIcon( TEAM2 ) + +end + + +------------------------------------------- +-- cp teleporters +------------------------------------------- + +trigger_teleport = trigger_ff_script:new({}) +cp_base_teleporter = trigger_teleport:new({ cp_number = 0, next_teleport_tick = 0 }) + +function cp_base_teleporter:allowed( allowed_entity ) + + -- check whether cc-to-cp teleporters are enabled + if not ENABLE_CC or not ENABLE_CC_TELEPORTERS then return EVENT_DISALLOWED end + + local stime = GetServerTime() + + if self.next_teleport_tick > stime then return end + + if IsPlayer( allowed_entity ) then + + local player = CastToPlayer( allowed_entity ) + -- Allow players on defending team to teleport to cp + if player:GetTeamId() == command_points[self.cp_number].defending_team then + + if player:IsInUse() then + -- teleport the player + local team_name = team_info[player:GetTeamId()].team_name + + if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then + team_name = team_info[ENTITY_TOUCHING_CC[player:GetId()]].team_name + end + + OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_enter_sound", "PlaySound" ) + --OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_exit_sound", "PlaySound", "", 0.1 ) + OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_tesla", "DoSpark", "", 0.1 ) + + --self.next_teleport_tick = stime + 1.0 + + ApplyToPlayer( player, { AT.kStopPrimedGrens, kReloadClips } ) + + return EVENT_ALLOWED + else + -- tell the player they can teleport + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_TELEPORT") + end + + end + end + + return EVENT_DISALLOWED + +end + +-- team1 teleporters +cp_team1_teleporter_cp1 = cp_base_teleporter:new({ cp_number = 1 }) +cp_team1_teleporter_cp2 = cp_base_teleporter:new({ cp_number = 2 }) +cp_team1_teleporter_cp3 = cp_base_teleporter:new({ cp_number = 3 }) +cp_team1_teleporter_cp4 = cp_base_teleporter:new({ cp_number = 4 }) +cp_team1_teleporter_cp5 = cp_base_teleporter:new({ cp_number = 5 }) + +-- team2 teleporters +cp_team2_teleporter_cp1 = cp_base_teleporter:new({ cp_number = 1 }) +cp_team2_teleporter_cp2 = cp_base_teleporter:new({ cp_number = 2 }) +cp_team2_teleporter_cp3 = cp_base_teleporter:new({ cp_number = 3 }) +cp_team2_teleporter_cp4 = cp_base_teleporter:new({ cp_number = 4 }) +cp_team2_teleporter_cp5 = cp_base_teleporter:new({ cp_number = 5 }) + + +----------------------------------------------------------------------------- +-- locations +----------------------------------------------------------------------------- + +location_cp1 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_ONE", team = NO_TEAM }) +location_cp2 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_TWO", team = NO_TEAM }) +location_cp3 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_THREE", team = NO_TEAM }) +location_cp4 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_FOUR", team = NO_TEAM }) +location_cp5 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_FIVE", team = NO_TEAM }) + +location_cp1_path = location_info:new({ text = "#FF_LOCATION_CP1_PATH", team = TEAM1 }) +location_cp2_path = location_info:new({ text = "#FF_LOCATION_CP2_PATH", team = TEAM1 }) +location_cp3_path = location_info:new({ text = "#FF_LOCATION_CP3_PATH", team = NO_TEAM }) +location_cp4_path = location_info:new({ text = "#FF_LOCATION_CP4_PATH", team = TEAM2 }) +location_cp5_path = location_info:new({ text = "#FF_LOCATION_CP5_PATH", team = TEAM2 }) + +location_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = NO_TEAM }) + +location_blue_base = location_info:new({ text = "#FF_LOCATION_BASE", team = TEAM1 }) +location_blue_cc = location_info:new({ text = "#FF_LOCATION_COMMAND_CENTER", team = TEAM1 }) +location_blue_outside_base = location_info:new({ text = "#FF_LOCATION_OUTSIDE_BASE", team = TEAM1 }) +location_blue_canal = location_info:new({ text = "#FF_LOCATION_CANAL", team = TEAM1 }) +location_blue_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = TEAM1 }) + +location_red_base = location_info:new({ text = "#FF_LOCATION_BASE", team = TEAM2 }) +location_red_cc = location_info:new({ text = "#FF_LOCATION_COMMAND_CENTER", team = TEAM2 }) +location_red_outside_base = location_info:new({ text = "#FF_LOCATION_OUTSIDE_BASE", team = TEAM2 }) +location_red_canal = location_info:new({ text = "#FF_LOCATION_CANAL", team = TEAM2 }) +location_red_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = TEAM2 }) + + +----------------------------------------------------------------------------- +-- backwards compatiblity - use "cp_*" names in your map instead! +----------------------------------------------------------------------------- +base_team_trigger = cp_base_trigger +blue_door_trigger = cp_team1_door_trigger +red_door_trigger = cp_team2_door_trigger + +cz2_base_pack = cp_base_pack +cz2_blue_respawn_pack = cp_team1_respawn_pack +cz2_red_respawn_pack = cp_team2_respawn_pack + +cz2_cp1_ammo = cp_cp1_ammo +cz2_cp2_ammo = cp_cp2_ammo +cz2_cp3_ammo = cp_cp3_ammo +cz2_cp4_ammo = cp_cp4_ammo +cz2_cp5_ammo = cp_cp5_ammo + +cz2_cp1_armor = cp_cp1_armor +cz2_cp2_armor = cp_cp2_armor +cz2_cp3_armor = cp_cp3_armor +cz2_cp4_armor = cp_cp4_armor +cz2_cp5_armor = cp_cp5_armor + +cz2_base_grenade_pack = cp_base_grenade_pack +cz2_blue_grenade_pack = cp_team1_grenade_pack +cz2_red_grenade_pack = cp_team2_grenade_pack + +base_cp_zone = cp_base_cp_zone +cp1_zone = cp_cp1_cp_zone +cp2_zone = cp_cp2_cp_zone +cp3_zone = cp_cp3_cp_zone +cp4_zone = cp_cp4_cp_zone +cp5_zone = cp_cp5_cp_zone + +base_cp_trigger = cp_base_cp_trigger +cp1_trigger = cp_cp1_cp_trigger +cp2_trigger = cp_cp2_cp_trigger +cp3_trigger = cp_cp3_cp_trigger +cp4_trigger = cp_cp4_cp_trigger +cp5_trigger = cp_cp5_cp_trigger + +base_cp_flag = cp_base_flag +blue_flag = cp_team1_flag +red_flag = cp_team2_flag + +cp_base_flag_dispenser = base_cp_flag_dispenser +blue_flag_dispenser = cp_team1_flag_dispenser +red_flag_dispenser = cp_team2_flag_dispenser + +base_command_center = cp_base_command_center +blue_command_center = cp_team1_command_center +red_command_center = cp_team2_command_center + +base_cp_cc_computer = cp_base_cc_computer +blue_cc_computer = cp_team1_cc_computer +red_cc_computer = cp_team2_cc_computer + +base_cp_teleporter = cp_base_teleporter +blue_teleporter_cp1 = cp_team1_teleporter_cp1 +blue_teleporter_cp2 = cp_team1_teleporter_cp2 +blue_teleporter_cp3 = cp_team1_teleporter_cp3 +blue_teleporter_cp4 = cp_team1_teleporter_cp4 +blue_teleporter_cp5 = cp_team1_teleporter_cp5 +red_teleporter_cp1 = cp_team2_teleporter_cp1 +red_teleporter_cp2 = cp_team2_teleporter_cp2 +red_teleporter_cp3 = cp_team2_teleporter_cp3 +red_teleporter_cp4 = cp_team2_teleporter_cp4 +red_teleporter_cp5 = cp_team2_teleporter_cp5 + + diff --git a/maps/includes/base_cp_default.lua b/maps/includes/base_cp_default.lua new file mode 100644 index 0000000..b5cc4ea --- /dev/null +++ b/maps/includes/base_cp_default.lua @@ -0,0 +1,234 @@ +-- base_cp_default.lua + +-- if you want to customize these base cp defaults, copy all of this file's contents +-- into your map's lua file, edit what you want, and then include base_cp.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay") +IncludeScript("base_location") +IncludeScript("base_respawnturret") + +----------------------------------------------------------------------------- +-- globals +----------------------------------------------------------------------------- + + +-- teams +TEAM1 = Team.kBlue +TEAM2 = Team.kRed +DISABLED_TEAM3 = Team.kYellow +DISABLED_TEAM4 = Team.kGreen + +teams = { TEAM1, TEAM2 } +disabled_teams = { DISABLED_TEAM3, DISABLED_TEAM4 } + +team_info = { + + [Team.kUnassigned] = { + team_name = "neutral", + enemy_team = Team.kUnassigned, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen }, + skybeam_color = "128 128 128", + respawnbeam_color = { [0] = 100, [1] = 100, [2] = 100 }, + color_index = 1, + skin = "0", + flag_visibility = "TurnOff", + cc_touch_count = 0, + ccalarmicon = "hud_secdown.vtf", ccalarmiconx = 0, ccalarmicony = 0, ccalarmiconwidth = 16, ccalarmiconheight = 16, ccalarmiconalign = 2, + detcc_sentence = "HTD_DOORS", + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = 0, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = -1, + } + }, + + [TEAM1] = { + team_name = "blue", + enemy_team = TEAM2, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue }, + skybeam_color = "64 64 255", + respawnbeam_color = { [0] = 100, [1] = 100, [2] = 100 }, + color_index = 2, + skin = "0", + flag_visibility = "TurnOn", + cc_touch_count = 0, + ccalarmicon = "hud_secup_blue.vtf", ccalarmiconx = 60, ccalarmicony = 5, ccalarmiconwidth = 16, ccalarmiconheight = 16, ccalarmiconalign = 2, + detcc_sentence = "CZ_BCC_DET", + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = 0, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = -1, + } + }, + + [TEAM2] = { + team_name = "red", + enemy_team = TEAM1, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kRed }, + skybeam_color = "255 64 64", + respawnbeam_color = { [0] = 100, [1] = 100, [2] = 100 }, + color_index = 0, + skin = "1", + flag_visibility = "TurnOn", + cc_touch_count = 0, + ccalarmicon = "hud_secup_red.vtf", ccalarmiconx = 60, ccalarmicony = 5, ccalarmiconwidth = 16, ccalarmiconheight = 16, ccalarmiconalign = 3, + detcc_sentence = "CZ_RCC_DET", + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = 0, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = -1, + } + } +} + + +-- command points +CP_COUNT = 5 + +command_points = { + [1] = { cp_number = 1, defending_team = Team.kUnassigned, cap_requirement = { [TEAM1] = 1000, [TEAM2] = 1000 }, cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, delay_before_retouch = { [TEAM1] = 4.0, [TEAM2] = 4.0 }, touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, point_value = { [TEAM1] = 1, [TEAM2] = 5 }, score_timer_interval = { [TEAM1] = 30.00, [TEAM2] = 15.00 }, hudstatusicon = "hud_cp_1.vtf", hudposx = -40, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + [2] = { cp_number = 2, defending_team = Team.kUnassigned, cap_requirement = { [TEAM1] = 1000, [TEAM2] = 1000 }, cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, delay_before_retouch = { [TEAM1] = 4.0, [TEAM2] = 4.0 }, touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, point_value = { [TEAM1] = 2, [TEAM2] = 4 }, score_timer_interval = { [TEAM1] = 26.25, [TEAM2] = 18.75 }, hudstatusicon = "hud_cp_2.vtf", hudposx = -20, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + [3] = { cp_number = 3, defending_team = Team.kUnassigned, cap_requirement = { [TEAM1] = 1000, [TEAM2] = 1000 }, cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, delay_before_retouch = { [TEAM1] = 4.0, [TEAM2] = 4.0 }, touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, point_value = { [TEAM1] = 3, [TEAM2] = 3 }, score_timer_interval = { [TEAM1] = 22.50, [TEAM2] = 22.50 }, hudstatusicon = "hud_cp_3.vtf", hudposx = 0, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + [4] = { cp_number = 4, defending_team = Team.kUnassigned, cap_requirement = { [TEAM1] = 1000, [TEAM2] = 1000 }, cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, delay_before_retouch = { [TEAM1] = 4.0, [TEAM2] = 4.0 }, touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, point_value = { [TEAM1] = 4, [TEAM2] = 2 }, score_timer_interval = { [TEAM1] = 18.75, [TEAM2] = 26.25 }, hudstatusicon = "hud_cp_4.vtf", hudposx = 20, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 }, + [CP_COUNT] = { cp_number = 5, defending_team = Team.kUnassigned, cap_requirement = { [TEAM1] = 1000, [TEAM2] = 1000 }, cap_status = { [TEAM1] = 0, [TEAM2] = 0 }, cap_speed = { [TEAM1] = 0, [TEAM2] = 0 }, next_cap_zone_timer = { [TEAM1] = 0, [TEAM2] = 0 }, delay_before_retouch = { [TEAM1] = 4.0, [TEAM2] = 4.0 }, touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, former_touching_players = { [TEAM1] = Collection(), [TEAM2] = Collection() }, point_value = { [TEAM1] = 5, [TEAM2] = 1 }, score_timer_interval = { [TEAM1] = 15.00, [TEAM2] = 30.00 }, hudstatusicon = "hud_cp_5.vtf", hudposx = 40, hudposy = 56, hudalign = 4, hudwidth = 16, hudheight = 16 } +} + + +-- scoring +POINTS_FOR_COMPLETE_CONTROL = 100 +CC_DESTROY_POINTS = 15 + + +-- zones +CAP_ZONE_TIMER_INTERVAL = 0.2 +CAP_ZONE_NOTOUCH_SPEED = 10 +PLAYER_TOUCHING_CP_ZONE = {} +ENTITY_TOUCHING_CC = {} + + +-- flags +ENABLE_FLAGS = false +FLAG_CARRIER_SPEED = 0.75 +FLAG_RETURN_TIME = 0 +flags = { team_info[TEAM1].team_name .. "_flag", team_info[TEAM2].team_name .. "flag" } + + +-- teleporting +ENABLE_CC_TELEPORTERS = true +ENABLE_CP_TELEPORTERS = true + + +-- command center +ENABLE_CC = true + + +-- complete control +ENABLE_COMPLETE_CONTROL_POINTS = true +ENABLE_COMPLETE_CONTROL_RESET = true +ENABLE_COMPLETE_CONTROL_RESPAWN = true +COMPLETE_CONTROL_RESPAWN_DELAY = 1 + + +-- door names (prefixes will automatically be added based on the trigger's team) +doors = { "_flagroom_door_top" , "_flagroom_door_bottom", "_base_door_01_left", "_base_door_01_right", "_base_door_02_left", "_base_door_02_right" } + + +-- cp capture sounds +good_cap_sounds = { + [1] = "CZ_GOTCP1", + [2] = "CZ_GOTCP2", + [3] = "CZ_GOTCP3", + [4] = "CZ_GOTCP4", + [5] = "CZ_GOTCP5" +} +bad_cap_sounds = { + [1] = "CZ_LOSTCP1", + [2] = "CZ_LOSTCP2", + [3] = "CZ_LOSTCP3", + [4] = "CZ_LOSTCP4", + [5] = "CZ_LOSTCP5" +} + + +-- cp status background icons +icons = { + [TEAM1] = { teamicon = "hud_cp_" .. team_info[TEAM1].team_name .. ".vtf", lockicon = "hud_cp_locked.vtf" }, + [TEAM2] = { teamicon = "hud_cp_" .. team_info[TEAM2].team_name .. ".vtf", lockicon = "hud_cp_locked.vtf" }, + [Team.kUnassigned] = { teamicon = "hud_cp_neutral.vtf" } +} + + +-- cp cap status icons +cp_zone_icons = { + [TEAM1] = { hudicon = "hud_flag_" .. team_info[TEAM1].team_name .. ".vtf", hudx = 5, hudy = 162, hudwidth = 48, hudheight = 48, hudalign = 1, hudposy_offset = -20 }, + [TEAM2] = { hudicon = "hud_flag_" .. team_info[TEAM2].team_name .. ".vtf", hudx = 5, hudy = 162, hudwidth = 48, hudheight = 48, hudalign = 1, hudposy_offset = 20 } +} + + +-- All of the CP ammo and armor (mainly used for removing all ammo and armor when command points reset) +cp_ammo_and_armor_names = { + "cp_cp1_ammo", + "cp_cp2_ammo", + "cp_cp3_ammo", + "cp_cp4_ammo", + "cp_cp5_ammo", + + -- backwards compatiblity - use "cp_*" names in your map instead! + "cz2_cp1_ammo", + "cz2_cp2_ammo", + "cz2_cp3_ammo", + "cz2_cp4_ammo", + "cz2_cp5_ammo", + + "cp_cp1_armor", + "cp_cp2_armor", + "cp_cp3_armor", + "cp_cp4_armor", + "cp_cp5_armor", + + -- backwards compatiblity - use "cp_*" names in your map instead! + "cz2_cp1_armor", + "cz2_cp2_armor", + "cz2_cp3_armor", + "cz2_cp4_armor", + "cz2_cp5_armor", +} + +cap_resupply = { + health = 100, + armor = 100, + nails = 100, + shells = 100, + cells = 100, + grenades = 50, + rockets = 50, + detpacks = 0, + mancannons = 1, + gren1 = 2, + gren2 = 1 +} + diff --git a/maps/includes/base_cp_sequential.lua b/maps/includes/base_cp_sequential.lua new file mode 100644 index 0000000..bab9786 --- /dev/null +++ b/maps/includes/base_cp_sequential.lua @@ -0,0 +1,1735 @@ +-- base_cp.lua + +-- if you want base cp with the default setup, +-- include base_cp_default.lua in your map's lua file +-- and then include base_cp.lua + +if OBJECTIVE_TEAM1 == nil then OBJECTIVE_TEAM1 = nil end +if OBJECTIVE_TEAM2 == nil then OBJECTIVE_TEAM2 = nil end + +function startup() + SetGameDescription( "Sequential Control Points" ) + + -- disable certain teams + for i,v in pairs(disabled_teams) do + SetPlayerLimit( v, -1 ) + end + + -- set up team limits + for i1,v1 in pairs(teams) do + local team = GetTeam(v1) + for i2,v2 in ipairs(team_info[team:GetTeamId()].class_limits) do + team:SetClassLimit( i2, v2 ) + end + end + + RemoveAllCPAmmoAndArmor() + + ChangeCPDefendingTeam( 1, TEAM1 ) + ChangeCPDefendingTeam( CP_COUNT, TEAM2 ) + + for i,v in ipairs(command_points) do + RemoveSchedule( "cp" .. v.cp_number .. "_cap_timer" ) + ResetCPCapping( v ) + AddScheduleRepeating( "cp" .. v.cp_number .. "_cap_zone_timer", CAP_ZONE_TIMER_INTERVAL, cap_zone_timer, v ) + end + + OBJECTIVE_TEAM1 = "cp2_zone" + OBJECTIVE_TEAM2 = "cp4_zone" + UpdateTeamObjectiveIcon( GetTeam(TEAM1), GetEntityByName( OBJECTIVE_TEAM1 ) ) + UpdateTeamObjectiveIcon( GetTeam(TEAM2), GetEntityByName( OBJECTIVE_TEAM2 ) ) +end + +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 400 ) + player:AddArmor( 400 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + + if player:GetTeamId() == TEAM1 then + UpdateObjectiveIcon( player, GetEntityByName( OBJECTIVE_TEAM1 ) ) + elseif player:GetTeamId() == TEAM2 then + UpdateObjectiveIcon( player, GetEntityByName( OBJECTIVE_TEAM2 ) ) + end +end + +function precache() + + -- precache the cap sounds + for i in pairs(good_cap_sounds) do + PrecacheSound(good_cap_sounds[i]) + PrecacheSound(bad_cap_sounds[i]) + end + + PrecacheSound("misc.thunder") + + PrecacheSound("Buttons.snd9") + PrecacheSound("Buttons.snd45") + + PrecacheSound("ff_cz2.teleport_exit") + + PrecacheSound("k_lab.teleport_post_winddown") + PrecacheSound("novaprospekt.teleport_post_thunder") + PrecacheSound("NPC_Ichthyosaur.AttackGrowl") + PrecacheSound("Streetwar.d3_c17_11_die") + PrecacheSound("streetwar.Ba_UseConsoleSounds") + + PrecacheSound("misc.thunder") + PrecacheSound("misc.woop") + PrecacheSound("misc.bloop") + + PrecacheSound("otherteam.flagstolen") + PrecacheSound("yourteam.flagcap") + PrecacheSound("otherteam.flagcap") +end + +function PlayerStartTouchingCapZone( touch_entity, cp ) + + local player = CastToPlayer(touch_entity) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] == cp then return end + + if player:GetTeamId() == TEAM1 then + if cp.cp_number > 1 then + local last_team1_cp = cp.cp_number - 1 + if command_points[last_team1_cp].defending_team ~= TEAM1 then return end + end + elseif player:GetTeamId() == TEAM2 then + if cp.cp_number < CP_COUNT then + local last_team2_cp = cp.cp_number + 1 + if command_points[last_team2_cp].defending_team ~= TEAM2 then return end + end + end + + local team_number = player:GetTeamId() + + PLAYER_TOUCHING_CP_ZONE[player:GetId()] = cp + + cp.touching_players[team_number]:AddItem( player ) + cp.former_touching_players[team_number]:RemoveItem( player ) + if player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic then + cp.cap_speed[team_number] = cp.cap_speed[team_number] + ( player:MaxSpeed() * 1.5 / 10 ) + else + cp.cap_speed[team_number] = cp.cap_speed[team_number] + ( player:MaxSpeed() / 10 ) + end + + if team_number ~= cp.defending_team then + player:SetCloakable( false ) + end + + local cp_zone_hudicon = cp_zone_icons[team_number] + AddHudIcon( player, cp_zone_hudicon.hudicon, cp_zone_hudicon.hudicon, cp_zone_hudicon.hudx, cp_zone_hudicon.hudy, cp_zone_hudicon.hudwidth, cp_zone_hudicon.hudheight, cp_zone_hudicon.hudalign ) + + event_StartTouchingCP( touch_entity, cp ) +end + +function PlayerStopTouchingCapZone( touch_entity, cp ) + + local player = CastToPlayer(touch_entity) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] == nil then return end + + local team_number = player:GetTeamId() + + PLAYER_TOUCHING_CP_ZONE[player:GetId()] = nil + + cp.touching_players[team_number]:RemoveItem( player ) + cp.former_touching_players[team_number]:AddItem( player ) + + if player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic then + cp.cap_speed[team_number] = cp.cap_speed[team_number] - ( player:MaxSpeed() * 1.5 / 10 ) + else + cp.cap_speed[team_number] = cp.cap_speed[team_number] - ( player:MaxSpeed() / 10 ) + end + + -- clamp + if cp.cap_speed[team_number] < 0 then + cp.cap_speed[team_number] = 0 + end + + player:SetCloakable( true ) + + RemoveHudItem( player, cp_zone_icons[team_number].hudicon ) + + event_StopTouchingCP( touch_entity, cp ) + +end + + +function DrawCCAlarmIcon( cc_team_number ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + + -- turn on alarm + if team_info[cc_team_number].cc_touch_count > 0 then + + RemoveHudItemFromAll( cc_team_number .. "-ccalarmicon_neutral" ) + AddHudIconToAll( team_info[cc_team_number].ccalarmicon, cc_team_number .. "-ccalarmicon", team_info[cc_team_number].ccalarmiconx, team_info[cc_team_number].ccalarmicony, team_info[cc_team_number].ccalarmiconwidth, team_info[cc_team_number].ccalarmiconheight, team_info[cc_team_number].ccalarmiconalign ) + + -- turn off alarm + else + + RemoveHudItemFromAll( cc_team_number .. "-ccalarmicon" ) + AddHudIconToAll( team_info[Team.kUnassigned].ccalarmicon, cc_team_number .. "-ccalarmicon_neutral", team_info[cc_team_number].ccalarmiconx, team_info[cc_team_number].ccalarmicony, team_info[cc_team_number].ccalarmiconwidth, team_info[cc_team_number].ccalarmiconheight, team_info[cc_team_number].ccalarmiconalign ) + + end + +end + +function EntityStartTouchingCC( touch_entity, cc_team_number ) + + if ENTITY_TOUCHING_CC[touch_entity:GetId()] ~= nil then return end + + ENTITY_TOUCHING_CC[touch_entity:GetId()] = cc_team_number + + team_info[cc_team_number].cc_touch_count = team_info[cc_team_number].cc_touch_count + 1 + + -- turn on alarm + if team_info[cc_team_number].cc_touch_count > 0 then + + event_StartTouchingCC( touch_entity, cc_team_number ) + + end + + DrawCCAlarmIcon( cc_team_number ) + +end + +function EntityStopTouchingCC( touch_entity, cc_team_number ) + + if ENTITY_TOUCHING_CC[touch_entity:GetId()] == nil then return end + + ENTITY_TOUCHING_CC[touch_entity:GetId()] = nil + + team_info[cc_team_number].cc_touch_count = team_info[cc_team_number].cc_touch_count - 1 + + -- turn off alarm + if team_info[cc_team_number].cc_touch_count <= 0 then + + team_info[cc_team_number].cc_touch_count = 0 + + event_StopTouchingCC( touch_entity, cc_team_number ) + + end + + DrawCCAlarmIcon( cc_team_number ) + +end + +function player_disconnected( player ) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] ~= nil then + PlayerStopTouchingCapZone( player, PLAYER_TOUCHING_CP_ZONE[player:GetId()] ) + end + + if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then + EntityStopTouchingCC( player, ENTITY_TOUCHING_CC[player:GetId()] ) + end + +end + +function player_switchteam( player, currentteam, desiredteam ) + + if PLAYER_TOUCHING_CP_ZONE[player:GetId()] ~= nil then + PlayerStopTouchingCapZone( player, PLAYER_TOUCHING_CP_ZONE[player:GetId()] ) + end + + if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then + EntityStopTouchingCC( player, ENTITY_TOUCHING_CC[player:GetId()] ) + end + + return true + +end + +----------------------------------------------------------------------------- +-- timed scoring +----------------------------------------------------------------------------- +function cp_score_timer( cp_number, team_number ) + + local team = GetTeam(team_number) + team:AddScore(command_points[cp_number].point_value[team_number]) + +end + +----------------------------------------------------------------------------- +-- notify the players of the total cap. +-- Also, create a logic_relay in your map named fullcap_trigger to pass outputs to your entities. +----------------------------------------------------------------------------- +function complete_control_notification ( team_number ) + local team = GetTeam(team_number) + SmartTeamSound(team, "yourteam.flagcap", "otherteam.flagcap") + SmartTeamSpeak(team, "CZ_GOTALL", "CZ_THEYGOTALL") + SmartTeamMessage(team, "#FF_CZ2_YOURTEAM_COMPLETE", "#FF_CZ2_OTHERTEAM_COMPLETE", Color.kGreen, Color.kRed) + OutputEvent( "fullcap_trigger", "Trigger" ) + + OBJECTIVE_TEAM1 = "cp2_zone" + OBJECTIVE_TEAM2 = "cp4_zone" + UpdateTeamObjectiveIcon( GetTeam(TEAM1), GetEntityByName( OBJECTIVE_TEAM1 ) ) + UpdateTeamObjectiveIcon( GetTeam(TEAM2), GetEntityByName( OBJECTIVE_TEAM2 ) ) +end + +----------------------------------------------------------------------------- +-- reset everything after the total cap. +----------------------------------------------------------------------------- +function complete_control_respawn () + ApplyToAll( { AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, kReloadClips } ) +end + +----------------------------------------------------------------------------- +-- emit a sound from an entity +----------------------------------------------------------------------------- +function EmitSound( entity, sound ) + + entity:EmitSound(sound) + +end + +----------------------------------------------------------------------------- +-- remove all the ammo and armor from the entire map +----------------------------------------------------------------------------- +function RemoveAllCPAmmoAndArmor() + + -- Remove all ammo and armor from CPs + local c = Collection() + c:GetByName(cp_ammo_and_armor_names, { CF.kNone }) + for item in c.items do + item = CastToInfoScript(item) + item:Remove() + end + +end + +----------------------------------------------------------------------------- +-- does the player have a flag? +----------------------------------------------------------------------------- +function PlayerHasFlag( player ) + + -- check if the player has a flag + for i,v in ipairs(flags) do + if player:HasItem(v) then + -- player has a flag + return true + end + end + + -- player doesn't have a flag + return false + +end + +----------------------------------------------------------------------------- +-- return carried flags +----------------------------------------------------------------------------- +function ReturnFlagFromPlayer( player ) + + -- Get all carried flags and ... + local c = Collection() + c:GetByName(flags, { CF.kInfoScript_Carried, }) + + -- ... return the flag that the player is carrying. + for item in c.items do + item = CastToInfoScript(item) + carrier = item:GetCarrier() + if player:GetId() == carrier:GetId() then + item:Return() + end + end + +end + +----------------------------------------------------------------------------- +-- resupply a player when a cp is capped +----------------------------------------------------------------------------- +function CapResupply( player, scale, givethegoodshit ) + + -- give the player health and armor + if cap_resupply.health ~= nil and cap_resupply.health ~= 0 then player:AddHealth( cap_resupply.health * scale ) end + if cap_resupply.armor ~= nil and cap_resupply.armor ~= 0 then player:AddArmor( cap_resupply.armor * scale ) end + + -- give the player ammo + if cap_resupply.nails ~= nil and cap_resupply.nails ~= 0 then player:AddAmmo( Ammo.kNails, cap_resupply.nails * scale ) end + if cap_resupply.shells ~= nil and cap_resupply.shells ~= 0 then player:AddAmmo( Ammo.kShells, cap_resupply.shells * scale ) end + if cap_resupply.rockets ~= nil and cap_resupply.rockets ~= 0 then player:AddAmmo( Ammo.kRockets, cap_resupply.rockets * scale ) end + if cap_resupply.cells ~= nil and cap_resupply.cells ~= 0 then player:AddAmmo( Ammo.kCells, cap_resupply.cells * scale ) end + + if givethegoodshit then + -- give the player the good shit + if cap_resupply.detpacks ~= nil and cap_resupply.detpacks ~= 0 then player:AddAmmo( Ammo.kDetpack, cap_resupply.detpacks * scale ) end + if cap_resupply.mancannons ~= nil and cap_resupply.mancannons ~= 0 then player:AddAmmo( Ammo.kManCannon, cap_resupply.mancannons * scale ) end + if cap_resupply.gren1 ~= nil and cap_resupply.gren1 ~= 0 then player:AddAmmo( Ammo.kGren1, cap_resupply.gren1 * scale ) end + if cap_resupply.gren2 ~= nil and cap_resupply.gren2 ~= 0 then player:AddAmmo( Ammo.kGren2, cap_resupply.gren2 * scale ) end + end + +end + +function player_killed ( player_victim, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + -- Entity that is attacking + local attacker = damageinfo:GetAttacker() + + -- If no attacker do nothing + if not attacker then return end + + local player_attacker = nil + + -- get the attacking player + if IsPlayer(attacker) then + attacker = CastToPlayer(attacker) + player_attacker = attacker + elseif IsSentrygun(attacker) then + attacker = CastToSentrygun(attacker) + player_attacker = attacker:GetOwner() + elseif IsDetpack(attacker) then + attacker = CastToDetpack(attacker) + player_attacker = attacker:GetOwner() + elseif IsDispenser(attacker) then + attacker = CastToDispenser(attacker) + player_attacker = attacker:GetOwner() + end + + -- if still no attacking player after all that, try the inflictor + if not player_attacker then + + -- Entity that is attacking + local inflictor = damageinfo:GetInflictor() + + if inflictor then + if IsSentrygun(inflictor) then + inflictor = CastToSentrygun(inflictor) + player_attacker = inflictor:GetOwner() + elseif IsDetpack(inflictor) then + inflictor = CastToDetpack(inflictor) + player_attacker = inflictor:GetOwner() + elseif IsDispenser(inflictor) then + inflictor = CastToDispenser(inflictor) + player_attacker = inflictor:GetOwner() + end + end + + end + + -- if still no attacking player after all that, forget about it + if not player_attacker then return end + + -- if victim killed self or teammate do nothing + if (player_victim:GetId() == player_attacker:GetId()) or (player_victim:GetTeamId() == player_attacker:GetTeamId()) then return end + + local player_victim_touching_cp = PLAYER_TOUCHING_CP_ZONE[player_victim:GetId()] + local player_attacker_touching_cp = PLAYER_TOUCHING_CP_ZONE[player_attacker:GetId()] + + -- the victim is standing in a zone + if player_victim_touching_cp ~= nil then + + -- the victim is defending a cp or trying to capture a neutral cp + if player_victim:GetTeamId() == player_victim_touching_cp.defending_team or player_victim_touching_cp.defending_team == Team.kUnassigned then + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_victim_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + -- the victim is trying to capture the attacker's cp + else + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_victim_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_DEFENDPOINT") + + end + + end + + -- the attacker is standing in a zone + if player_attacker_touching_cp ~= nil then + + -- the attacker is defending a cp + if player_attacker:GetTeamId() == player_attacker_touching_cp.defending_team then + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_attacker_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_DEFENDPOINT") + + -- the attacker is trying to capture a cp + else + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((player_attacker_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + end + + end + + -- loop through all former players of each command point + for k,v in ipairs(command_points) do + + -- victim's team + for i in v.former_touching_players[player_victim:GetTeamId()].items do + + i = CastToPlayer( i ) + + -- the victim was in an active zone + if i:GetId() == player_victim:GetId() then + + -- the victim is defending a cp or trying to capture a neutral cp + if player_victim:GetTeamId() == v.defending_team or v.defending_team == Team.kUnassigned then + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + -- the victim is trying to capture the attacker's cp + else + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST") + + end + + end + + end + + -- attacker's team + for i in v.former_touching_players[player_attacker:GetTeamId()].items do + + i = CastToPlayer( i ) + + -- the attacker was in an active zone + if i:GetId() == player_attacker:GetId() then + + -- the attacker is defending a cp + if player_attacker:GetTeamId() == v.defending_team then + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST") + + -- the attacker is trying to capture a cp + else + + --CapResupply( player_attacker, 0.25, false ) + player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + + end + + end + + end + + end + +end + +----------------------------------------------------------------------------- +-- change the cp's defending team, its related visuals, and its scoring +----------------------------------------------------------------------------- +function ChangeCPDefendingTeam( cp_number, new_defending_team ) + + local cp = command_points[cp_number] + + if cp_number > 1 and cp_number < CP_COUNT then + if new_defending_team == TEAM1 then + ResetCPCapping( command_points[cp_number - 1] ) + elseif new_defending_team == TEAM2 then + ResetCPCapping( command_points[cp_number + 1] ) + end + end + + event_ChangeCPDefendingTeam( cp_number, new_defending_team ) + + -- remove old flaginfo icons and add new ones + RemoveHudItemFromAll( cp_number .. "-background-" .. cp.defending_team ) + RemoveHudItemFromAll( cp_number .. "-foreground-" .. cp.defending_team ) + + AddHudIconToAll( icons[ new_defending_team ].teamicon, cp_number .. "-background-" .. new_defending_team, cp.hudposx, cp.hudposy, cp.hudwidth, cp.hudheight, cp.hudalign) + AddHudIconToAll( cp.hudstatusicon, cp_number .. "-foreground-" .. new_defending_team, cp.hudposx, cp.hudposy, cp.hudwidth, cp.hudheight, cp.hudalign) + + local schedule_name = "cp" .. cp_number .. "_score_timer" + + -- stop an existing timer + if cp.defending_team ~= Team.kUnassigned then + RemoveSchedule( schedule_name ) + end + + -- only worry with score timer for TEAM1 and TEAM2 + if new_defending_team ~= Team.kUnassigned then + + -- start the score timer + AddScheduleRepeating( schedule_name, cp.score_timer_interval[new_defending_team], cp_score_timer, cp_number, new_defending_team ) + + end + + cp.defending_team = new_defending_team + +end + +----------------------------------------------------------------------------- +-- restore all items in a CP +----------------------------------------------------------------------------- +function RestoreCPItems( cp_number, old_defending_team, new_defending_team ) + + local c = Collection() + c:GetByName( { "cp_cp" .. cp_number .. "_ammo", "cz2_cp" .. cp_number .. "_ammo", "cp_cp" .. cp_number .. "_armor", "cz2_cp" .. cp_number .. "_armor" }, { CF.kNone } ) + for item in c.items do + item = CastToInfoScript(item) + + -- restore this CP's ammo and armor + item:Restore() + + -- Also set the touchflags so only the defending team can use the packs + item:SetTouchFlags(team_info[new_defending_team].touchflags) + end + +end + +----------------------------------------------------------------------------- +-- reset team cp capping stuff +----------------------------------------------------------------------------- +function ResetTeamCPCapping( cp, team_number, do_total_reset, set_next_cap_zone_timer ) + + cp.cap_status[team_number] = 0 + cp.next_cap_zone_timer[team_number] = set_next_cap_zone_timer + + RemoveHudItemFromAll( cp.cp_number .. "-capstatusicon-" .. team_number ) + RemoveHudItemFromAll( cp.cp_number .. "-caplockicon-" .. team_number ) + event_ResetTeamCPCapping( cp, team_number ) + + if cp.former_touching_players[team_number]:Count() > 0 then + cp.former_touching_players[team_number]:RemoveAllItems() + end + + if do_total_reset then + if cp.touching_players[team_number]:Count() > 0 then + cp.touching_players[team_number]:RemoveAllItems() + end + + cp.cap_speed[team_number] = 0 + end + +end + +----------------------------------------------------------------------------- +-- reset all cp capping stuff +----------------------------------------------------------------------------- +function ResetCPCapping( cp ) + + for i,v in pairs(teams) do + ResetTeamCPCapping( cp, v, true, 0 ) + end + +end + +----------------------------------------------------------------------------- +-- reset and lock a capture point for a certain amount of time +----------------------------------------------------------------------------- +function LockCPCapping( cp, lock_time ) + + for i,v in pairs(teams) do + ResetTeamCPCapping( cp, v, true, lock_time ) + end + +end + +----------------------------------------------------------------------------- +-- reset and lock a capture point for a certain amount of time +----------------------------------------------------------------------------- +function StopCPScoring( cp_number ) + + local cp = command_points[cp_number] + + if cp.defending_team ~= Team.kUnassigned then + RemoveSchedule( "cp" .. cp_number .. "_score_timer" ) + end + +end + +----------------------------------------------------------------------------- +-- the cp has definitely been captured +----------------------------------------------------------------------------- +function CaptureCP( cp_number, new_defending_team ) + + local cp = command_points[cp_number] + local old_defending_team = cp.defending_team + + RestoreCPItems(cp_number, old_defending_team, new_defending_team) + + -- Give points to team and player + local team = GetTeam(new_defending_team) + team:AddScore(cp.point_value[new_defending_team]) + + -- Find out if any team has complete control + local team_with_complete_control = Team.kUnassigned + local control_count = { [TEAM1] = 0, [TEAM2] = 0 } + control_count[new_defending_team] = 1 + for i,v in ipairs(command_points) do + if v.defending_team ~= Team.kUnassigned and v.cp_number ~= cp_number then + control_count[v.defending_team] = control_count[v.defending_team] + 1 + end + if control_count[v.defending_team] == CP_COUNT then + team_with_complete_control = v.defending_team + break + end + end + + -- update objective icons if not all cp's captured + if team_with_complete_control == Team.kUnassigned then + if new_defending_team == TEAM1 then + OBJECTIVE_TEAM1 = "cp"..(cp_number+1).."_zone" + if old_defending_team ~= Team.kUnassigned then + OBJECTIVE_TEAM2 = "cp"..(cp_number).."_zone" + end + elseif new_defending_team == TEAM2 then + OBJECTIVE_TEAM2 = "cp"..(cp_number-1).."_zone" + if old_defending_team ~= Team.kUnassigned then + OBJECTIVE_TEAM1 = "cp"..(cp_number).."_zone" + end + end + UpdateTeamObjectiveIcon( GetTeam(TEAM1), GetEntityByName( OBJECTIVE_TEAM1 ) ) + UpdateTeamObjectiveIcon( GetTeam(TEAM2), GetEntityByName( OBJECTIVE_TEAM2 ) ) + end + + if team_with_complete_control ~= Team.kUnassigned then + + if ENABLE_COMPLETE_CONTROL_POINTS then + -- Bonus points for complete control + team:AddScore(POINTS_FOR_COMPLETE_CONTROL) + end + + if ENABLE_COMPLETE_CONTROL_RESET then + + AddSchedule("complete_control_notification", 0.1, complete_control_notification, team_with_complete_control) + + if ENABLE_COMPLETE_CONTROL_RESPAWN then + + -- change the team of the capped cp + ChangeCPDefendingTeam(cp_number, new_defending_team) + + -- Lock all command points + -- Stop periodic scoring for all command points + for i,v in ipairs(command_points) do + StopCPScoring( i ) + LockCPCapping( v, COMPLETE_CONTROL_RESPAWN_DELAY ) + end + + AddSchedule("complete_control", COMPLETE_CONTROL_RESPAWN_DELAY, TeamCompleteControl, team_with_complete_control ) + else + TeamCompleteControl( team_with_complete_control ) + end + + -- get out now if resetting + return + + end + + end + + ChangeCPDefendingTeam(cp_number, new_defending_team) + + -- change the colors this team's respawn beams + --local beam_team = team_info[new_defending_team] + --beam_team.respawnbeam_color[beam_team.color_index] = beam_team.respawnbeam_color[Team.kUnassigned] + (control_count[new_defending_team] * 35) + --OutputEvent( beam_team.team_name .. "_respawn_beam", "Color", beam_team.respawnbeam_color[0] .. " " .. beam_team.respawnbeam_color[1] .. " " .. beam_team.respawnbeam_color[2] ) + + SmartTeamMessage( team, "#FF_CZ2_YOURTEAM_CP" .. cp_number, "#FF_CZ2_OTHERTEAM_CP" .. cp_number, Color.kGreen, Color.kRed ) + + -- sounds will get more and more crazy + --SmartTeamSound( team, good_cap_sounds[control_count[new_defending_team]], bad_cap_sounds[control_count[new_defending_team]] ) + + -- caes: changed it to announce the cp number captured/lost + SmartTeamSpeak( team, good_cap_sounds[cp_number], bad_cap_sounds[cp_number] ) +end + +function TeamCompleteControl( control_team ) + + -- Reset all command points + for i,v in ipairs(command_points) do + ChangeCPDefendingTeam(v.cp_number, Team.kUnassigned) + ResetCPCapping( v ) + end + + ChangeCPDefendingTeam( 1, TEAM1 ) + ChangeCPDefendingTeam( CP_COUNT, TEAM2 ) + + -- reset colors of respawn beams + --OutputEvent( team_info[TEAM1].team_name .. "_respawn_beam", "Color", team_info[Team.kUnassigned].respawnbeam_color[0] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[1] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[2] ) + --OutputEvent( team_info[TEAM2].team_name .. "_respawn_beam", "Color", team_info[Team.kUnassigned].respawnbeam_color[0] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[1] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[2] ) + + if ENABLE_FLAGS then + -- Return all flags + local c = Collection() + c:GetByName(flags, { CF.kNone }) + for item in c.items do + item = CastToInfoScript(item) + item:Return() + end + end + + RemoveAllCPAmmoAndArmor() + + if ENABLE_COMPLETE_CONTROL_RESPAWN then + complete_control_respawn() + end + +end + + +----------------------------------------------------------------------------- +-- a cp's defending team successfully defended or capped +----------------------------------------------------------------------------- +function SuccessfulCPDefense( cp, team_number, is_a_cap ) + + -- reward the touching players + for i in cp.touching_players[team_number].items do + i = CastToPlayer( i ) + if is_a_cap then + CapResupply( i, 0.50, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 100, "#FF_FORTPOINTS_CAPTUREPOINT") + i:SetCloakable( true ) + else + --CapResupply( i, 0.50, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 50, "#FF_FORTPOINTS_DEFENDPOINT") + end + end + + -- reward the former touching players + for i in cp.former_touching_players[team_number].items do + i = CastToPlayer( i ) + if is_a_cap then + --CapResupply( i, 0.50, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST") + else + --CapResupply( i, 0.25, is_a_cap ) + i:AddFortPoints((cp.point_value[team_number]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST") + end + end + + -- no need to keep them around for future rewards + cp.former_touching_players[team_number]:RemoveAllItems() + +end + + +----------------------------------------------------------------------------- +-- timed cp capping +----------------------------------------------------------------------------- +function cap_zone_timer( cp ) + + local new_defending_team = Team.kUnassigned + local other_team = Team.kUnassigned + local last_cap_status = {} + local total_cap_speed = 0 + local total_cap_status = 0 + + for i,v in pairs(teams) do + total_cap_speed = total_cap_speed + cp.cap_speed[v] + total_cap_status = total_cap_status + cp.cap_status[v] + end + + for i,v in pairs(teams) do + + -- don't bother doing some stuff if nothing has changed + last_cap_status[v] = cp.cap_status[v] + + -- after one team caps a cp, the other team can't touch that cp for X seconds + if cp.next_cap_zone_timer[v] > 0 then + + cp.next_cap_zone_timer[v] = cp.next_cap_zone_timer[v] - CAP_ZONE_TIMER_INTERVAL + + local lock_percent = math.min( 1.0, cp.next_cap_zone_timer[v] / cp.delay_before_retouch[v] ) + local minlockhudwidth = cp.hudwidth * 0.333 + local minlockhudheight = cp.hudheight * 0.333 + + AddHudIconToAll( icons[v].lockicon, cp.cp_number .. "-caplockicon-" .. v, cp.hudposx, cp.hudposy + cp_zone_icons[v].hudposy_offset, minlockhudwidth + ( (cp.hudwidth - minlockhudwidth) * lock_percent ), minlockhudheight + ( (cp.hudheight - minlockhudheight) * lock_percent ), cp.hudalign) + + -- clamp + if cp.next_cap_zone_timer[v] <= 0 then + cp.next_cap_zone_timer[v] = 0 + RemoveHudItemFromAll( cp.cp_number .. "-caplockicon-" .. v ) + end + + -- this team is standing in the zone + elseif cp.cap_speed[v] > 0 then + + -- don't bother with cap_status calculations for the defending team + if v == cp.defending_team then + + cp.cap_status[v] = cp.cap_requirement[v] + + -- calculate cap status + else + + -- every vote counts + local affected_cap_speed = cp.cap_speed[v] - ( total_cap_speed - cp.cap_speed[v] ) + + cp.cap_status[v] = cp.cap_status[v] + affected_cap_speed + + -- clamp + if cp.cap_status[v] < 0 then + + cp.cap_status[v] = 0 + + -- potential capping team + elseif cp.cap_status[v] >= cp.cap_requirement[v] then + + new_defending_team = v + + -- clamp + cp.cap_status[v] = cp.cap_requirement[v] + + end + end + + -- this team is not standing in the zone + else + if v == cp.defending_team then + -- don't bother with cap_status calculations for the defending team + cp.cap_status[v] = 0 + else + -- decrease cap status + cp.cap_status[v] = cp.cap_status[v] - ( CAP_ZONE_NOTOUCH_SPEED + total_cap_speed ) + + -- clamp + if cp.cap_status[v] < 0 then + cp.cap_status[v] = 0 + end + end + end + + -- don't bother doing some stuff if nothing has changed + if cp.cap_status[v] ~= last_cap_status[v] then + + -- draw the cap status icon + if cp.cap_status[v] > 0 then + + local cap_percent = cp.cap_status[v] / cp.cap_requirement[v] + local minhudwidth = cp.hudwidth * 0.333 + local minhudheight = cp.hudheight * 0.333 + AddHudIconToAll( cp_zone_icons[v].hudicon, cp.cp_number .. "-capstatusicon-" .. v, cp.hudposx, cp.hudposy + cp_zone_icons[v].hudposy_offset, minhudwidth + ( (cp.hudwidth - minhudwidth) * cap_percent ), minhudheight + ( (cp.hudheight - minhudheight) * cap_percent ), cp.hudalign) + -- only do this event once, when the team first starts capping + if last_cap_status[v] <= 0 then + event_StartTeamCPCapping( cp, v ) + end + + -- remove the cap status icon, remove former touching players, and reward defenders + else + + -- reward the defenders + if v ~= cp.defending_team and cp.defending_team ~= Team.kUnassigned then + SuccessfulCPDefense( cp, cp.defending_team, false ) + end + + -- reset the other team's cp capping stuff + ResetTeamCPCapping( cp, v, false, 0 ) + + end + + end + + if new_defending_team ~= v then + other_team = v + end + + end + + -- someone capped this cp + if new_defending_team ~= Team.kUnassigned then + + -- cap the cp + SuccessfulCPDefense( cp, new_defending_team, true ) + CaptureCP( cp.cp_number, new_defending_team ) + + -- reset the other team's cp capping stuff + ResetTeamCPCapping( cp, other_team, false, cp.delay_before_retouch[other_team] ) + + end + +end + + +----------------------------------------------------------------------------- +-- triggers +----------------------------------------------------------------------------- + +cp_base_trigger = trigger_ff_script:new({ team = Team.kUnassigned, failtouch_message = "" }) + +function cp_base_trigger:allowed( allowed_entity ) + + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + return EVENT_DISALLOWED +end + +function cp_base_trigger:onfailtouch( touch_entity ) + + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + BroadCastMessageToPlayer( player, failtouch_message ) + end +end + +cp_team1_door_trigger = cp_base_trigger:new({ team = TEAM1 , failtouch_message = "#FF_NOTALLOWEDDOOR" }) +cp_team2_door_trigger = cp_base_trigger:new({ team = TEAM2 , failtouch_message = "#FF_NOTALLOWEDDOOR" }) + + +----------------------------------------------------------------------------- +-- packs +----------------------------------------------------------------------------- +cp_base_pack = genericbackpack:new({ + health = 100, + armor = 300, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + detpacks = 0, + mancannons = 0, + gren1 = 0, + gren2 = 0, + respawntime = 1, + touchflags = team_info[Team.kUnassigned].touchflags, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + cp_number = 0, + botgoaltype = Bot.kBackPack_Ammo, +}) + +function cp_base_pack:dropatspawn() return false end + +cp_team1_respawn_pack = cp_base_pack:new( { touchflags = team_info[TEAM1].touchflags } ) +cp_team2_respawn_pack = cp_base_pack:new( { touchflags = team_info[TEAM2].touchflags } ) + +cp_cp1_ammo = ammobackpack:new({cp_number = 1}) +cp_cp2_ammo = ammobackpack:new({cp_number = 2}) +cp_cp3_ammo = ammobackpack:new({cp_number = 3}) +cp_cp4_ammo = ammobackpack:new({cp_number = 4}) +cp_cp5_ammo = ammobackpack:new({cp_number = 5}) + +cp_cp1_armor = armorkit:new({cp_number = 1}) +cp_cp2_armor = armorkit:new({cp_number = 2}) +cp_cp3_armor = armorkit:new({cp_number = 3}) +cp_cp4_armor = armorkit:new({cp_number = 4}) +cp_cp5_armor = armorkit:new({cp_number = 5}) + + +----------------------------------------------------------------------------- +-- grenade packs +----------------------------------------------------------------------------- +cp_base_grenade_pack = cp_base_pack:new({ + detpacks = 1, + mancannons = 1, + gren1 = 4, + gren2 = 4, + respawntime = 15, + touchflags = team_info[Team.kUnassigned].touchflags, + botgoaltype = Bot.kBackPack_Grenades, +}) + +cp_team1_grenade_pack = cp_base_grenade_pack:new( { touchflags = team_info[TEAM1].touchflags } ) +cp_team2_grenade_pack = cp_base_grenade_pack:new( { touchflags = team_info[TEAM2].touchflags } ) + + +----------------------------------------------------------------------------- +-- cp zones +----------------------------------------------------------------------------- + +cp_base_cp_zone = trigger_ff_script:new({ + item = "", + team = 0, + botgoaltype = Bot.kFlagCap, + cp_number = 0, +}) + +function cp_base_cp_zone:ontrigger( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if ENABLE_FLAGS or not ENABLE_CP_TELEPORTERS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- Allow players on defending team to teleport back to base + if player:GetTeamId() == command_points[self.cp_number].defending_team then + + if player:IsInUse() then + -- respawn the player + ApplyToPlayer( player, { AT.kRespawnPlayers, kReloadClips } ) + + OutputEvent( "cp" .. self.cp_number .. "_respawn_enter_sound", "PlaySound" ) + AddSchedule("cp" .. self.cp_number .. "_respawn_" .. player:GetId(), 0.1, EmitSound, player, "ff_cz2.teleport_exit") + else + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_RESPAWN") + end + + end + + end + +end + +function cp_base_cp_zone:ontouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these zones are used + if ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + local cp = command_points[self.cp_number] + PlayerStartTouchingCapZone( player, cp ) + end + +end + +function cp_base_cp_zone:onendtouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these zones are used + if ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + local cp = command_points[self.cp_number] + PlayerStopTouchingCapZone( player, cp ) + end +end + +cp_cp1_cp_zone = cp_base_cp_zone:new({ cp_number = 1 }) +cp_cp2_cp_zone = cp_base_cp_zone:new({ cp_number = 2 }) +cp_cp3_cp_zone = cp_base_cp_zone:new({ cp_number = 3 }) +cp_cp4_cp_zone = cp_base_cp_zone:new({ cp_number = 4 }) +cp_cp5_cp_zone = cp_base_cp_zone:new({ cp_number = 5 }) + + +----------------------------------------------------------------------------- +-- cp triggers +----------------------------------------------------------------------------- + +cp_base_cp_trigger = trigger_ff_script:new({ + item = "", + team = 0, + botgoaltype = Bot.kFlagCap, + cp_number = 0, +}) + +function cp_base_cp_trigger:ontrigger( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS or not ENABLE_CP_TELEPORTERS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- Allow players on defending team to teleport back to base + if player:GetTeamId() == command_points[self.cp_number].defending_team then + + if player:IsInUse() then + -- check if the player has a flag + for i,v in ipairs(flags) do + -- return the flag + if player:HasItem(v) then ReturnFlagFromPlayer(player) end + end + + -- respawn the player + ApplyToPlayer( player, { AT.kRespawnPlayers, kReloadClips } ) + + OutputEvent( "cp" .. self.cp_number .. "_respawn_enter_sound", "PlaySound" ) + AddSchedule("cp" .. self.cp_number .. "_respawn_" .. player:GetId(), 0.1, EmitSound, player, "ff_cz2.teleport_exit") + else + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_RESPAWN") + end + + end + + end + +end + +function cp_base_cp_trigger:ontouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + local cp = command_points[self.cp_number] + + -- No capping if player's team already defends this CP + if player:GetTeamId() == cp.defending_team then return end + + -- get out if player doesn't have flag + if not PlayerHasFlag(player) then return end + + ReturnFlagFromPlayer(player) + + CaptureCP(self.cp_number, player:GetTeamId()) + player:AddFortPoints((cp.point_value[player:GetTeamId()]) * 100, "#FF_FORTPOINTS_CAPTUREPOINT") + end + +end + +cp_cp1_cp_trigger = cp_base_cp_trigger:new({ cp_number = 1 }) +cp_cp2_cp_trigger = cp_base_cp_trigger:new({ cp_number = 2 }) +cp_cp3_cp_trigger = cp_base_cp_trigger:new({ cp_number = 3 }) +cp_cp4_cp_trigger = cp_base_cp_trigger:new({ cp_number = 4 }) +cp_cp5_cp_trigger = cp_base_cp_trigger:new({ cp_number = 5 }) + + +----------------------------------------------------------------------------- +-- flags +----------------------------------------------------------------------------- + +cp_base_flag = info_ff_script:new({ + name = "Base Flag", + team = 0, + model = "models/flag/flag.mdl", + tosssound = "Flag.Toss", + modelskin = 0, + dropnotouchtime = 2, + capnotouchtime = 2, + botgoaltype = Bot.kFlag, + hudicon = "", + hudx = 5, + hudy = 180, + hudalign = 1, + touchflags = team_info[Team.kUnassigned].touchflags +}) + +function cp_base_flag:precache() + PrecacheSound(self.tosssound) + info_ff_script.precache(self) +end + +function cp_base_flag:spawn() + self.notouch = { } + info_ff_script.spawn(self) +end + +function cp_base_flag:addnotouch(player_id, duration) + self.notouch[player_id] = duration + AddSchedule(self.name .. "-" .. player_id, duration, self.removenotouch, self, player_id) +end + +function cp_base_flag.removenotouch(self, player_id) + self.notouch[player_id] = nil +end + +function cp_base_flag:touch( touch_entity ) + local player = CastToPlayer( touch_entity ) + + if player:GetTeamId() ~= self.team then return end + + -- pickup if they can + if self.notouch[player:GetId()] then return end + + -- make sure they don't have any flags already + for i,v in ipairs(flags) do + if player:HasItem(v) then return end + end + + -- if the player is a spy, then force him to lose his disguise + player:SetDisguisable( false ) + player:SetCloakable( false ) + + -- note: this seems a bit backwards (Pickup verb fits Player better) + local flag = CastToInfoScript(entity) + flag:Pickup(player) + player:AddEffect( EF.kSpeedlua1, -1, 0, FLAG_CARRIER_SPEED ) + AddHudIcon( player, self.hudicon, flag:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign ) +end + +function cp_base_flag:onownerdie( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) +end + +function cp_base_flag:onownerfeign( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) +end +function cp_base_flag:onownercloak( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) +end +function cp_base_flag:dropitemcmd( owner_entity ) + -- throw the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, FLAG_THROW_SPEED) +end + +function cp_base_flag:ondrop( owner_entity ) + local flag = CastToInfoScript(entity) + flag:EmitSound(self.tosssound) +end + +function cp_base_flag:onloseitem( owner_entity ) + -- let the player that lost the flag put on a disguise + local player = CastToPlayer( owner_entity ) + player:SetDisguisable(true) + player:SetCloakable(true) + + self:addnotouch(player:GetId(), self.capnotouchtime) + + --player:RemoveEffect( EF.kSpeedlua1 ) + -- remove flag icon from hud + local flag = CastToInfoScript(entity) + RemoveHudItem( player, flag:GetName() ) +end + +function cp_base_flag:onreturn( ) +end + +cp_team1_flag = cp_base_flag:new({ + team = TEAM1, + modelskin = 0, + name = team_info[TEAM1].team_name .. " flag", + hudicon = "hud_flag_" .. team_info[TEAM1].team_name .. ".vtf", + hudx = 5, + hudy = 180, + hudwidth = 48, + hudheight = 48, + touchflags = team_info[TEAM1].touchflags +}) + +cp_team2_flag = cp_base_flag:new({ + team = TEAM2, + modelskin = 1, + name = team_info[TEAM2].team_name .. " flag", + hudicon = "hud_flag_" .. team_info[TEAM2].team_name .. ".vtf", + hudx = 5, + hudy = 180, + hudwidth = 48, + hudheight = 48, + touchflags = team_info[TEAM2].touchflags +}) + + +----------------------------------------------------------------------------- +-- flag dispensers +----------------------------------------------------------------------------- +cp_base_flag_dispenser = trigger_ff_script:new({ + name = "Base Flag Dispenser", + team = Team.kUnassigned, + dropnotouchtime = 2, + botgoaltype = Bot.kFlag, + hudicon = "", + hudx = 5, + hudy = 180, + hudwidth = 48, + hudheight = 48, + hudalign = 1, + flags = {"flag"} +}) + +function cp_base_flag_dispenser:allowed ( allowed_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS then return EVENT_DISALLOWED end + + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team then + + -- Player can't have a flag + local playerhasflag = false + + for i,v in ipairs(self.flags) do + if player:HasItem(v) then + playerhasflag = true + break + end + end + + -- get out if player doesn't have flag + if not playerhasflag then + return EVENT_ALLOWED + end + end + end + return EVENT_DISALLOWED +end + +function cp_base_flag_dispenser:ontouch( trigger_entity ) + + -- check whether flags are used, and in turn wheter these triggers are used + if not ENABLE_FLAGS then return end + + if IsPlayer( trigger_entity ) then + + local player = CastToPlayer( trigger_entity ) + + local c = Collection() + c:GetByName( self.flags, { CF.kNone } ) + -- give the player an inactive flag + for item in c.items do + item = CastToInfoScript(item) + if item:IsInactive() then + -- if the player is a spy, then force him to lose his disguise + player:SetDisguisable( false ) + player:SetCloakable( false ) + + -- note: this seems a bit backwards (Pickup verb fits Player better) + item:Pickup(player) + player:AddEffect( EF.kSpeedlua1, -1, 0, FLAG_CARRIER_SPEED ) + AddHudIcon( player, self.hudicon, item:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign ) + + player:EmitSound("Buttons.snd9") + + -- all done + break + end + end + end +end + +cp_team1_flag_dispenser = cp_base_flag_dispenser:new({ + name = team_info[TEAM1].team_name .. " flag dispenser", + team = TEAM1, + hudicon = "hud_flag_" .. team_info[TEAM1].team_name .. ".vtf", + flags = { team_info[TEAM1].team_name .. "_flag" } +}) + +cp_team2_flag_dispenser = cp_base_flag_dispenser:new({ + name = team_info[TEAM2].team_name .. " flag dispenser", + team = TEAM2, + hudicon = "hud_flag_" .. team_info[TEAM2].team_name .. ".vtf", + flags = { team_info[TEAM2].team_name .. "_flag" } +}) + + +----------------------------------------------------------------------------- +-- command centers +----------------------------------------------------------------------------- + +cp_base_command_center = trigger_ff_script:new({ team = Team.kUnassigned, enemy_team = Team.kUnassigned }) +function cp_base_command_center:onexplode( explosion_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return EVENT_ALLOWED end + + if IsDetpack( explosion_entity ) then + local detpack = CastToDetpack(explosion_entity) + + -- don't let assholes destroy their own team's command center + if detpack:GetTeamId() == self.team then return EVENT_ALLOWED end + + local points = CC_DESTROY_POINTS + for i,v in ipairs(command_points) do + if v.defending_team == self.team then + -- taking CP 1 away from team2 is worth more than taking CP 5 away from them + points = points + v.point_value[self.team] + + -- Remove all ammo and armor from CPs + local c = Collection() + c:GetByName({"cp_cp" .. v.cp_number .. "_ammo", "cz2_cp" .. v.cp_number .. "_ammo", "cp_cp" .. v.cp_number .. "_armor", "cz2_cp" .. v.cp_number .. "_armor"}, { CF.kNone }) + for item in c.items do + item = CastToInfoScript(item) + item:Remove() + end + + -- reset the CP + ChangeCPDefendingTeam(v.cp_number, Team.kUnassigned) + end + + -- reset the other team's cp capping stuff + ResetTeamCPCapping( v, self.team, false, v.delay_before_retouch[self.team] * 2.0 ) + end + + local team = detpack:GetTeam() + team:AddScore(points) + + local player = detpack:GetOwner() + player:AddFortPoints(points * 100, "#FF_FORTPOINTS_DESTROY_CC" ) + + SmartSound(player, "misc.thunder", "misc.thunder", "misc.thunder") + SmartMessage(player, "#FF_CZ2_YOU_CC", "#FF_CZ2_YOURTEAM_CC", "#FF_CZ2_OTHERTEAM_CC", Color.kGreen, Color.kGreen, Color.kRed) + SpeakAll( team_info[self.team].detcc_sentence ) + +-- EntityStopTouchingCC( detpack, self.team ) + + end + + return EVENT_ALLOWED +end + +function cp_base_command_center:ontouch( trigger_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + +-- if IsDetpack( trigger_entity ) then +-- local detpack = CastToDetpack( trigger_entity ) +-- if detpack:GetTeamId() ~= self.team then +-- EntityStartTouchingCC( detpack, self.team ) +-- end +-- end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + if player:GetTeamId() ~= self.team then + EntityStartTouchingCC( player, self.team ) + end + end + +end + +function cp_base_command_center:onendtouch( trigger_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + +-- if IsDetpack( trigger_entity ) then +-- local detpack = CastToDetpack( trigger_entity ) +-- if detpack:GetTeamId() ~= self.team then +-- EntityStopTouchingCC( detpack, self.team ) +-- end +-- end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + if player:GetTeamId() ~= self.team then + EntityStopTouchingCC( player, self.team ) + end + end +end + +cp_team1_command_center = cp_base_command_center:new({ team = TEAM1, enemy_team = TEAM2 }) +cp_team2_command_center = cp_base_command_center:new({ team = TEAM2, enemy_team = TEAM1 }) + + +------------------------------------------- +-- cc computers +------------------------------------------- + +cp_base_cc_computer = trigger_ff_script:new({ prefix = "unassigned", enemy_team = Team.kUnassigned }) + +function cp_base_cc_computer:ontrigger( trigger_entity ) + + -- check whether command centers are enabled + if not ENABLE_CC then return end + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- Allow spies to open the enemy doors + if player:GetTeamId() == self.enemy_team and player:GetClass() == Player.kSpy then + + if player:IsInUse() then + for i,v in ipairs(doors) do + -- open each enemy door + OutputEvent( self.prefix .. v, "Open" ) + end + else + -- tell the player they can open the enemy doors + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_DOORS") + end + + end + end +end + +cp_team1_cc_computer = cp_base_cc_computer:new({ prefix = team_info[TEAM1].team_name, enemy_team = TEAM2 }) +cp_team2_cc_computer = cp_base_cc_computer:new({ prefix = team_info[TEAM2].team_name, enemy_team = TEAM1 }) + + +------------------------------------------- +-- cp flaginfo +------------------------------------------- + +function flaginfo( player_entity ) + + local player = CastToPlayer( player_entity ) + + for i,v in ipairs(command_points) do + + ConsoleToAll( "CP Number: " .. v.cp_number ) + ConsoleToAll( "Team: " .. v.defending_team ) + ConsoleToAll( "Icon: " .. icons[ v.defending_team ].teamicon ) + + AddHudIcon( player, icons[ v.defending_team ].teamicon , v.cp_number .. "-background-" .. v.defending_team , command_points[v.cp_number].hudposx, command_points[v.cp_number].hudposy, command_points[v.cp_number].hudwidth, command_points[v.cp_number].hudheight, command_points[v.cp_number].hudalign) + AddHudIcon( player, command_points[v.cp_number].hudstatusicon, v.cp_number .. "-foreground-" .. v.defending_team , command_points[v.cp_number].hudposx, command_points[v.cp_number].hudposy, command_points[v.cp_number].hudwidth, command_points[v.cp_number].hudheight, command_points[v.cp_number].hudalign) + + end + + DrawCCAlarmIcon( TEAM1 ) + DrawCCAlarmIcon( TEAM2 ) + +end + + +------------------------------------------- +-- cp teleporters +------------------------------------------- + +trigger_teleport = trigger_ff_script:new({}) +cp_base_teleporter = trigger_teleport:new({ cp_number = 0, next_teleport_tick = 0 }) + +function cp_base_teleporter:allowed( allowed_entity ) + + -- check whether cc-to-cp teleporters are enabled + if not ENABLE_CC or not ENABLE_CC_TELEPORTERS then return EVENT_DISALLOWED end + + local stime = GetServerTime() + + if self.next_teleport_tick > stime then return end + + if IsPlayer( allowed_entity ) then + + local player = CastToPlayer( allowed_entity ) + -- Allow players on defending team to teleport to cp + if player:GetTeamId() == command_points[self.cp_number].defending_team then + + if player:IsInUse() then + -- teleport the player + local team_name = team_info[player:GetTeamId()].team_name + + if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then + team_name = team_info[ENTITY_TOUCHING_CC[player:GetId()]].team_name + end + + OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_enter_sound", "PlaySound" ) + --OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_exit_sound", "PlaySound", "", 0.1 ) + OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_tesla", "DoSpark", "", 0.1 ) + + --self.next_teleport_tick = stime + 1.0 + + ApplyToPlayer( player, { AT.kStopPrimedGrens, kReloadClips } ) + + return EVENT_ALLOWED + else + -- tell the player they can teleport + BroadCastMessageToPlayer(player, "#FF_CZ2_USE_TELEPORT") + end + + end + end + + return EVENT_DISALLOWED + +end + +-- team1 teleporters +cp_team1_teleporter_cp1 = cp_base_teleporter:new({ cp_number = 1 }) +cp_team1_teleporter_cp2 = cp_base_teleporter:new({ cp_number = 2 }) +cp_team1_teleporter_cp3 = cp_base_teleporter:new({ cp_number = 3 }) +cp_team1_teleporter_cp4 = cp_base_teleporter:new({ cp_number = 4 }) +cp_team1_teleporter_cp5 = cp_base_teleporter:new({ cp_number = 5 }) + +-- team2 teleporters +cp_team2_teleporter_cp1 = cp_base_teleporter:new({ cp_number = 1 }) +cp_team2_teleporter_cp2 = cp_base_teleporter:new({ cp_number = 2 }) +cp_team2_teleporter_cp3 = cp_base_teleporter:new({ cp_number = 3 }) +cp_team2_teleporter_cp4 = cp_base_teleporter:new({ cp_number = 4 }) +cp_team2_teleporter_cp5 = cp_base_teleporter:new({ cp_number = 5 }) + + +----------------------------------------------------------------------------- +-- locations +----------------------------------------------------------------------------- + +location_cp1 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_ONE", team = NO_TEAM }) +location_cp2 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_TWO", team = NO_TEAM }) +location_cp3 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_THREE", team = NO_TEAM }) +location_cp4 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_FOUR", team = NO_TEAM }) +location_cp5 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_FIVE", team = NO_TEAM }) + +location_cp1_path = location_info:new({ text = "#FF_LOCATION_CP1_PATH", team = TEAM1 }) +location_cp2_path = location_info:new({ text = "#FF_LOCATION_CP2_PATH", team = TEAM1 }) +location_cp3_path = location_info:new({ text = "#FF_LOCATION_CP3_PATH", team = NO_TEAM }) +location_cp4_path = location_info:new({ text = "#FF_LOCATION_CP4_PATH", team = TEAM2 }) +location_cp5_path = location_info:new({ text = "#FF_LOCATION_CP5_PATH", team = TEAM2 }) + +location_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = NO_TEAM }) + +location_blue_base = location_info:new({ text = "#FF_LOCATION_BASE", team = TEAM1 }) +location_blue_cc = location_info:new({ text = "#FF_LOCATION_COMMAND_CENTER", team = TEAM1 }) +location_blue_outside_base = location_info:new({ text = "#FF_LOCATION_OUTSIDE_BASE", team = TEAM1 }) +location_blue_canal = location_info:new({ text = "#FF_LOCATION_CANAL", team = TEAM1 }) +location_blue_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = TEAM1 }) + +location_red_base = location_info:new({ text = "#FF_LOCATION_BASE", team = TEAM2 }) +location_red_cc = location_info:new({ text = "#FF_LOCATION_COMMAND_CENTER", team = TEAM2 }) +location_red_outside_base = location_info:new({ text = "#FF_LOCATION_OUTSIDE_BASE", team = TEAM2 }) +location_red_canal = location_info:new({ text = "#FF_LOCATION_CANAL", team = TEAM2 }) +location_red_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = TEAM2 }) + + +----------------------------------------------------------------------------- +-- backwards compatiblity - use "cp_*" names in your map instead! +----------------------------------------------------------------------------- +base_team_trigger = cp_base_trigger +blue_door_trigger = cp_team1_door_trigger +red_door_trigger = cp_team2_door_trigger + +cz2_base_pack = cp_base_pack +cz2_blue_respawn_pack = cp_team1_respawn_pack +cz2_red_respawn_pack = cp_team2_respawn_pack + +cz2_cp1_ammo = cp_cp1_ammo +cz2_cp2_ammo = cp_cp2_ammo +cz2_cp3_ammo = cp_cp3_ammo +cz2_cp4_ammo = cp_cp4_ammo +cz2_cp5_ammo = cp_cp5_ammo + +cz2_cp1_armor = cp_cp1_armor +cz2_cp2_armor = cp_cp2_armor +cz2_cp3_armor = cp_cp3_armor +cz2_cp4_armor = cp_cp4_armor +cz2_cp5_armor = cp_cp5_armor + +cz2_base_grenade_pack = cp_base_grenade_pack +cz2_blue_grenade_pack = cp_team1_grenade_pack +cz2_red_grenade_pack = cp_team2_grenade_pack + +base_cp_zone = cp_base_cp_zone +cp1_zone = cp_cp1_cp_zone +cp2_zone = cp_cp2_cp_zone +cp3_zone = cp_cp3_cp_zone +cp4_zone = cp_cp4_cp_zone +cp5_zone = cp_cp5_cp_zone + +base_cp_trigger = cp_base_cp_trigger +cp1_trigger = cp_cp1_cp_trigger +cp2_trigger = cp_cp2_cp_trigger +cp3_trigger = cp_cp3_cp_trigger +cp4_trigger = cp_cp4_cp_trigger +cp5_trigger = cp_cp5_cp_trigger + +base_cp_flag = cp_base_flag +blue_flag = cp_team1_flag +red_flag = cp_team2_flag + +cp_base_flag_dispenser = base_cp_flag_dispenser +blue_flag_dispenser = cp_team1_flag_dispenser +red_flag_dispenser = cp_team2_flag_dispenser + +base_command_center = cp_base_command_center +blue_command_center = cp_team1_command_center +red_command_center = cp_team2_command_center + +base_cp_cc_computer = cp_base_cc_computer +blue_cc_computer = cp_team1_cc_computer +red_cc_computer = cp_team2_cc_computer + +base_cp_teleporter = cp_base_teleporter +blue_teleporter_cp1 = cp_team1_teleporter_cp1 +blue_teleporter_cp2 = cp_team1_teleporter_cp2 +blue_teleporter_cp3 = cp_team1_teleporter_cp3 +blue_teleporter_cp4 = cp_team1_teleporter_cp4 +blue_teleporter_cp5 = cp_team1_teleporter_cp5 +red_teleporter_cp1 = cp_team2_teleporter_cp1 +red_teleporter_cp2 = cp_team2_teleporter_cp2 +red_teleporter_cp3 = cp_team2_teleporter_cp3 +red_teleporter_cp4 = cp_team2_teleporter_cp4 +red_teleporter_cp5 = cp_team2_teleporter_cp5 + + diff --git a/maps/includes/base_ctf.lua b/maps/includes/base_ctf.lua new file mode 100644 index 0000000..3feeee2 --- /dev/null +++ b/maps/includes/base_ctf.lua @@ -0,0 +1,151 @@ + +-- base_ctf.lua +-- Capture the flag gametype + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay"); + +----------------------------------------------------------------------------- +-- entities +----------------------------------------------------------------------------- + +-- hudalign and hudstatusiconalign : 0 = HUD_LEFT, 1 = HUD_RIGHT, 2 = HUD_CENTERLEFT, 3 = HUD_CENTERRIGHT +-- (pixels from the left / right of the screen / left of the center of the screen / right of center of screen, +-- AfterShock +blue_flag = baseflag:new({team = Team.kBlue, + modelskin = 0, + name = "Blue Flag", + hudicon = "hud_flag_blue_new.vtf", + hudx = 5, + hudy = 80, + hudwidth = 70, + hudheight = 70, + hudalign = 1, + hudstatusicondropped = "hud_flag_dropped_blue.vtf", + hudstatusiconhome = "hud_flag_home_blue.vtf", + hudstatusiconcarried = "hud_flag_carried_blue.vtf", + hudstatusiconx = 60, + hudstatusicony = 5, + hudstatusiconw = 15, + hudstatusiconh = 15, + hudstatusiconalign = 2, + objectiveicon = true, + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kRed,AllowFlags.kYellow,AllowFlags.kGreen}}) + +red_flag = baseflag:new({team = Team.kRed, + modelskin = 1, + name = "Red Flag", + hudicon = "hud_flag_red_new.vtf", + hudx = 5, + hudy = 150, + hudwidth = 70, + hudheight = 70, + hudalign = 1, + hudstatusicondropped = "hud_flag_dropped_red.vtf", + hudstatusiconhome = "hud_flag_home_red.vtf", + hudstatusiconcarried = "hud_flag_carried_red.vtf", + hudstatusiconx = 60, + hudstatusicony = 5, + hudstatusiconw = 15, + hudstatusiconh = 15, + hudstatusiconalign = 3, + objectiveicon = true, + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue,AllowFlags.kYellow,AllowFlags.kGreen}}) + +yellow_flag = baseflag:new({team = Team.kYellow, + modelskin = 2, + name = "Yellow Flag", + hudicon = "hud_flag_yellow_new.vtf", + hudx = 5, + hudy = 220, + hudwidth = 70, + hudheight = 70, + hudalign = 1, + hudstatusicondropped = "hud_flag_dropped_yellow.vtf", + hudstatusiconhome = "hud_flag_home_yellow.vtf", + hudstatusiconcarried = "hud_flag_carried_yellow.vtf", + hudstatusiconx = 53, + hudstatusicony = 25, + hudstatusiconw = 15, + hudstatusiconh = 15, + hudstatusiconalign = 2, + objectiveicon = true, + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue,AllowFlags.kRed,AllowFlags.kGreen} }) + +green_flag = baseflag:new({team = Team.kGreen, + modelskin = 3, + name = "Green Flag", + hudicon = "hud_flag_green_new.vtf", + hudx = 5, + hudy = 290, + hudwidth = 70, + hudheight = 70, + hudalign = 1, + hudstatusicondropped = "hud_flag_dropped_green.vtf", + hudstatusiconhome = "hud_flag_home_green.vtf", + hudstatusiconcarried = "hud_flag_carried_green.vtf", + hudstatusiconx = 53, + hudstatusicony = 25, + hudstatusiconw = 15, + hudstatusiconh = 15, + hudstatusiconalign = 3, + objectiveicon = true, + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue,AllowFlags.kRed,AllowFlags.kYellow} }) + +-- red cap point +red_cap = basecap:new({team = Team.kRed, + item = {"blue_flag","yellow_flag","green_flag"}}) + +-- blue cap point +blue_cap = basecap:new({team = Team.kBlue, + item = {"red_flag","yellow_flag","green_flag"}}) + +-- yellow cap point +yellow_cap = basecap:new({team = Team.kYellow, + item = {"blue_flag","red_flag","green_flag"}}) + +-- green cap point +green_cap = basecap:new({team = Team.kGreen, + item = {"blue_flag","red_flag","yellow_flag"}}) + +----------------------------------------------------------------------------- +-- map handlers +----------------------------------------------------------------------------- +function startup() + + SetGameDescription( "Capture the Flag" ) + + -- set up team limits on each team + SetPlayerLimit(Team.kBlue, 0) + SetPlayerLimit(Team.kRed, 0) + SetPlayerLimit(Team.kYellow, -1) + SetPlayerLimit(Team.kGreen, -1) + + -- CTF maps generally don't have civilians, + -- so override in map LUA file if you want 'em + local team = GetTeam(Team.kBlue) + team:SetClassLimit(Player.kCivilian, -1) + + team = GetTeam(Team.kRed) + team:SetClassLimit(Player.kCivilian, -1) +end + +function precache() + -- precache sounds + PrecacheSound("yourteam.flagstolen") + PrecacheSound("otherteam.flagstolen") + PrecacheSound("yourteam.flagcap") + PrecacheSound("otherteam.flagcap") + PrecacheSound("yourteam.drop") + PrecacheSound("otherteam.drop") + PrecacheSound("yourteam.flagreturn") + PrecacheSound("otherteam.flagreturn") +end + +--flaginfo runs whenever the player spawns or uses the flaginfo command. +--Right now it just refreshes the HUD items; this ensures that players who just joined the server have the right information +function flaginfo( player_entity ) + flaginfo_base(player_entity) --see base_teamplay.lua +end \ No newline at end of file diff --git a/maps/includes/base_ctf4.lua b/maps/includes/base_ctf4.lua new file mode 100644 index 0000000..1d33dfd --- /dev/null +++ b/maps/includes/base_ctf4.lua @@ -0,0 +1,34 @@ + +-- base_ctf4.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_ctf") + +----------------------------------------------------------------------------- +-- map level handlers +----------------------------------------------------------------------------- +function startup() + SetGameDescription( "4-way CTF" ) + + -- set up team limits + SetPlayerLimit(Team.kBlue, 0) + SetPlayerLimit(Team.kRed, 0) + SetPlayerLimit(Team.kYellow, 0) + SetPlayerLimit(Team.kGreen, 0) + + -- CTF maps generally don't have civilians, + -- so override in map LUA file if you want 'em + local team = GetTeam(Team.kBlue) + team:SetClassLimit(Player.kCivilian, -1) + + team = GetTeam(Team.kRed) + team:SetClassLimit(Player.kCivilian, -1) +end + +--flaginfo runs whenever the player spawns or uses the flaginfo command. +--Right now it just refreshes the HUD items; this ensures that players who just joined the server have the right information +function flaginfo( player_entity ) + flaginfo_base(player_entity) --see base_teamplay.lua +end \ No newline at end of file diff --git a/maps/includes/base_fortball.lua b/maps/includes/base_fortball.lua new file mode 100644 index 0000000..4348b7a --- /dev/null +++ b/maps/includes/base_fortball.lua @@ -0,0 +1,689 @@ +-- base_fortball.lua + +-- if you want base fortball with the default setup, +-- include base_fortball_default.lua in your map's lua file +-- and then include base_fortball.lua + +-- precache (sounds) +function precache() + PrecacheSound("misc.bizwarn") + PrecacheSound("misc.bloop") + PrecacheSound("misc.buzwarn") + PrecacheSound("misc.dadeda") + PrecacheSound("misc.deeoo") + PrecacheSound("misc.doop") + PrecacheSound("misc.woop") + + PrecacheSound("otherteam.flagstolen") + PrecacheSound("yourteam.flagcap") + PrecacheSound("otherteam.flagcap") + + -- Unagi Power! Unagi! + PrecacheSound("misc.unagi_spatial") + + -- goalie sounds + --PrecacheSound( goalie_sound_loop ) + --PrecacheSound( goalie_sound_idle ) + --PrecacheSound( goalie_sound_pain ) + --PrecacheSound( goalie_sound_kill ) +end + +function startup() + SetGameDescription( "Fortball" ) + + -- disable certain teams + for i,v in pairs(disabled_teams) do + SetPlayerLimit( v, -1 ) + end + + -- set up team limits + for i1,v1 in pairs(teams) do + local team = GetTeam(v1) + for i2,v2 in ipairs(team_info[team:GetTeamId()].class_limits) do + team:SetClassLimit( i2, v2 ) + end + end + + local ball = GetEntityByName( "ball" ) + for i,v in pairs(teams) do + objective_entities[v] = ball + end + + the_wall_reset() + +end + +function the_wall_reset() + OutputEvent( "the_wall", "Enable" ) + OutputEvent( "the_wall_laser_blue", "TurnOn" ) + OutputEvent( "the_wall_laser_red", "TurnOn" ) + AddSchedule("the_wall_disable", THE_WALL_TIMER_DISABLE, the_wall_disable ) + AddSchedule("the_wall_10secwarn", THE_WALL_TIMER_WARN, the_wall_10secwarn ) +end + +function the_wall_disable() + OutputEvent( "the_wall", "Disable" ) + OutputEvent( "the_wall_laser_blue", "TurnOff" ) + OutputEvent( "the_wall_laser_red", "TurnOff" ) + BroadCastMessage("#FF_ROUND_STARTED") + BroadCastSound("otherteam.flagstolen") +end + +function the_wall_10secwarn() + BroadCastMessage("#FF_MAP_10SECWARN") + AddSchedule("the_wall_9secwarn", 1, the_wall_9secwarn ) +end + +function the_wall_9secwarn() + BroadCastMessage("#FF_MAP_9SECWARN") + AddSchedule("the_wall_8secwarn", 1, the_wall_8secwarn ) +end + +function the_wall_8secwarn() + BroadCastMessage("#FF_MAP_8SECWARN") + AddSchedule("the_wall_7secwarn", 1, the_wall_7secwarn ) +end + +function the_wall_7secwarn() + BroadCastMessage("#FF_MAP_7SECWARN") + AddSchedule("the_wall_6secwarn", 1, the_wall_6secwarn ) +end + +function the_wall_6secwarn() + BroadCastMessage("#FF_MAP_6SECWARN") + AddSchedule("the_wall_5secwarn", 1, the_wall_5secwarn ) +end + +function the_wall_5secwarn() + BroadCastMessage("#FF_MAP_5SECWARN") + SpeakAll( "AD_5SEC" ) + AddSchedule("the_wall_4secwarn", 1, the_wall_4secwarn ) +end + +function the_wall_4secwarn() + BroadCastMessage("#FF_MAP_4SECWARN") + SpeakAll( "AD_4SEC" ) + AddSchedule("the_wall_3secwarn", 1, the_wall_3secwarn ) +end + +function the_wall_3secwarn() + BroadCastMessage("#FF_MAP_3SECWARN") + SpeakAll( "AD_3SEC" ) + AddSchedule("the_wall_2secwarn", 1, the_wall_2secwarn ) +end + +function the_wall_2secwarn() + BroadCastMessage("#FF_MAP_2SECWARN") + SpeakAll( "AD_2SEC" ) + AddSchedule("the_wall_1secwarn", 1, the_wall_1secwarn ) +end + +function the_wall_1secwarn() + BroadCastMessage("#FF_MAP_1SECWARN") + SpeakAll( "AD_1SEC" ) +end + +function goalie_bounds_notification(player) + BroadCastSoundToPlayer( player, "misc.buzwarn" ) + BroadCastMessageToPlayer(player, "#FF_WATERPOLO_GOALIE_BOUNDS") +end + +function reset_ball_carrier() + if ball_carrier ~= nil and IsPlayer( ball_carrier ) then + local player = CastToPlayer(ball_carrier) + UpdateObjectiveIcon( player, objective_entities[player:GetTeamId()] ) + if not BALL_ALWAYS_ENEMY_OBJECTIVE then + local enemy_team = team_info[player:GetTeamId()].enemy_team + objective_entities[enemy_team] = GetEntityByName( "ball" ) + UpdateTeamObjectiveIcon( GetTeam(enemy_team), objective_entities[enemy_team] ) + end + end + ball_carrier = nil +end + +-- Give everyone a full resupply, but strip grenades +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + + -- god damn right + player:RemoveAmmo( Ammo.kDetpack, 1 ) + player:RemoveAmmo( Ammo.kManCannon, 1 ) + player:RemoveAmmo( Ammo.kGren1, 4 ) + player:RemoveAmmo( Ammo.kGren2, 4 ) + + -- goalies run fast + if player:GetClass() ~= Player.kCivilian then + player:RemoveEffect( EF.kSpeedlua1 ) + else + player:AddEffect( EF.kSpeedlua1, -1, 0, GOALIE_SPEED ) + + -- stop the goalie loop sound + --player:StopSound( goalie_sound_loop ) + + -- play the goalie loop sound + --player:EmitSound( goalie_sound_loop ) + end + + -- objective + UpdateObjectiveIcon( player, objective_entities[player:GetTeamId()] ) +end + +function player_onkill( player ) + -- stop the goalie loop sound + --if player:GetClass() == Player.kCivilian then + --player:StopSound( goalie_sound_loop ) + --end + + return true +end + +function player_killed( player ) + -- stop the goalie loop sound + --if player:GetClass() == Player.kCivilian then + --player:StopSound( goalie_sound_loop ) + --end +end + +function player_switchteam( player, currentteam, desiredteam ) + + -- stop the goalie loop sound + --if player:GetClass() == Player.kCivilian then + --player:StopSound( goalie_sound_loop ) + --end + + return true + +end + +function player_disconnected( player ) + + if ball_carrier ~= nil then + if ball_carrier:GetId() == player:GetId() then + reset_ball_carrier() + end + end + + -- stop the goalie loop sound + --if player:GetClass() == Player.kCivilian then + --player:StopSound( goalie_sound_loop ) + --end + +end + +function remove_hud_items(ball, player) + + RemoveHudItem( player, ball:GetName() ) + + local team = player:GetTeamId() + + if (team == TEAM1) then + RemoveHudItemFromAll( "ball-icon-blue" ) + elseif (team == TEAM2) then + RemoveHudItemFromAll( "ball-icon-red" ) + end + +end + +function player_ondamage( player, damageinfo ) + -- goalies have "UNAGI POWER, UNAGI!" + local attacker = damageinfo:GetAttacker() + if IsPlayer( attacker ) then + attacker = CastToPlayer( attacker ) + if attacker:GetClass() == Player.kCivilian and attacker:GetTeamId() ~= player:GetTeamId() then + ConsoleToAll( "Goalie, " .. attacker:GetName() .. ", has UNAGI POWER, UNAGI!" ) + --attacker:EmitSound("misc.unagi_spatial") + attacker:AddFortPoints( POINTS_PER_GOALIE_ATTACK, "#FF_FORTPOINTS_GOALIE_ATTACK" ) + damageinfo:ScaleDamage(69) + --attacker:EmitSound( goalie_sound_kill ) + elseif attacker:GetClass() == Player.kSniper and player:GetClass() ~= Player.kCivilian then + -- snipers do less damage to non-goalies + damageinfo:ScaleDamage(0.1) + end + end + + if player:GetClass() == Player.kCivilian then + + if player:GetTeamId() == player:GetLocationTeam() then + + -- goalies are invincible in their team's locations + damageinfo:ScaleDamage(0) + --player:EmitSound( goalie_sound_idle ) + + else + + -- goalies take more damage outside their team's locations + damageinfo:ScaleDamage(3) + --player:EmitSound( goalie_sound_pain ) + + end + + end +end + + +----------------------------------------------------------------------------- +-- ball information +-- status: 0 = home, 1 = carried, 2 = dropped +----------------------------------------------------------------------------- +base_ball = info_ff_script:new({ + name = "base ball", + team = Team.kUnassigned, + model = "models/items/ball/ball.mdl", + modelskin = 0, + tosssound = "Flag.toss", + dropnotouchtime = 0, + capnotouchtime = 2, + hudicon = "hud_ball", + hudx = 5, + hudy = 210, + hudwidth = 48, + hudheight = 48, + hudalign = 1, + hudstatusiconbluex = 60, + hudstatusiconbluey = 5, + hudstatusiconredx = 60, + hudstatusiconredy = 5, + hudstatusiconblue = "hud_ball.vtf", + hudstatusiconred = "hud_ball.vtf", + hudstatusiconw = 15, + hudstatusiconh = 15, + hudstatusiconbluealign = 2, + hudstatusiconredalign = 3, + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed}, + botgoaltype = Bot.kFlag, + status = 0 +}) + +function base_ball:hasanimation() return false end +function base_ball:usephysics() return true end + +function base_ball:touch( touch_entity ) + if IsPlayer( touch_entity ) then + + local player = CastToPlayer( touch_entity ) + if self.notouch[player:GetId()] then return end + + local ball = CastToInfoScript( entity ) + + if player:GetClass() ~= Player.kCivilian then + -- if the player is a spy, then force him to lose his disguise + player:SetDisguisable( false ) + player:SetCloakable( false ) + + ConsoleToAll( player:GetName() .. " has the ball!" ) + --SmartSound( player, "misc.bloop", "misc.bloop", "misc.bloop" ) + SmartSound(player, "yourteam.flagstolen", "yourteam.flagstolen", "otherteam.flagstolen") + SmartSpeak(player, "CTF_YOUHAVEBALL", "CTF_TEAMHASBALL", "CTF_ENEMYHASBALL") + SmartMessage( player, "#FF_WATERPOLO_YOU_PICKUP", "#FF_WATERPOLO_TEAM_PICKUP", "#FF_WATERPOLO_ENEMY_PICKUP", Color.kGreen, Color.kGreen, Color.kRed ) + ball:Pickup( player ) + + AddHudIcon( player, self.hudicon, ball:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign ) + local team = player:GetTeamId() + if (team == TEAM1) then + AddHudIconToAll( self.hudstatusiconblue, "ball-icon-blue", self.hudstatusiconbluex, self.hudstatusiconbluey, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconbluealign ) + elseif (team == TEAM2) then + AddHudIconToAll( self.hudstatusiconred, "ball-icon-red", self.hudstatusiconredx, self.hudstatusiconredy, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconredalign ) + end + + -- 100 points for initial touch on ball + if self.status == 0 then player:AddFortPoints(POINTS_PER_INITIALTOUCH, "#FF_FORTPOINTS_INITIALTOUCH") end + self.status = 1 + + UpdateObjectiveIcon( player, goal_entities[player:GetTeamId()] ) + ball_carrier = player + + if not BALL_ALWAYS_ENEMY_OBJECTIVE then + local enemy_team = team_info[player:GetTeamId()].enemy_team + objective_entities[enemy_team] = nil + UpdateTeamObjectiveIcon( GetTeam(enemy_team), objective_entities[enemy_team] ) + end + + -- goalies return the ball + else + if ball:IsDropped() then + -- if pressing +use + if player:IsInUse() then + ConsoleToAll( "Goalie, " .. player:GetName() .. ", returned the ball!" ) + SmartSound( player, "misc.deeoo", "misc.deeoo", "misc.deeoo" ) + SmartMessage( player, "#FF_WATERPOLO_YOU_RETURN", "#FF_WATERPOLO_TEAM_GOALIE_RETURN", "#FF_WATERPOLO_ENEMY_GOALIE_RETURN" ) + player:AddFortPoints( POINTS_PER_GOALIE_RETURN, "#FF_FORTPOINTS_GOALIE_RETURN" ) + ball:Return() + self.status = 0 + else + BroadCastMessageToPlayer(player, "#FF_WATERPOLO_USE_RETURN") + end + end + end + end +end + +function base_ball:onownerdie( owner_entity ) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + -- drop the ball + ConsoleToAll( player:GetName() .. " died and dropped the ball!" ) + local ball = CastToInfoScript( entity ) + ball:Drop(BALL_RETURN_TIME, 0.0) + remove_hud_items(ball, player) + self.status = 2 + + reset_ball_carrier() + end +end + +function base_ball:ownercloak( owner_entity ) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + -- drop the ball + ConsoleToAll( player:GetName() .. " cloaked and dropped the ball!" ) + local ball = CastToInfoScript( entity ) + ball:Drop(BALL_RETURN_TIME, 0.0) + remove_hud_items(ball, player) + self.status = 2 + + reset_ball_carrier() + end +end + +function base_ball:ownerfeign( owner_entity ) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + -- drop the ball + ConsoleToAll( player:GetName() .. " feigned and dropped the ball!" ) + local ball = CastToInfoScript( entity ) + ball:Drop(BALL_RETURN_TIME, 0.0) + remove_hud_items(ball, player) + self.status = 2 + + reset_ball_carrier() + end +end + +function base_ball:dropitemcmd( drop_entity ) + if IsPlayer( drop_entity ) then + -- throw the ball + local ball = CastToInfoScript( entity ) + + local player = CastToPlayer( drop_entity ) + if not player:IsInUse() then + ball:Drop(BALL_RETURN_TIME, BALL_THROW_SPEED) + else + ball:Drop(BALL_RETURN_TIME, BALL_THROW_SPEED * 0.333) + end + + ConsoleToAll( player:GetName() .. " passed the ball!" ) + remove_hud_items(ball, player) + self.status = 2 + + reset_ball_carrier() + + SmartSound( player, "misc.woop", "misc.woop", "misc.woop" ) + + -- Make it so the player can't touch the ball for 1 second + -- (so it can't be thrown and not stick to the player) + self:addnotouch(player:GetId(), 1) + end +end + +function base_ball:ondrop( owner_entity ) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + -- let the teams know that the flag was dropped + SmartSound(player, "yourteam.drop", "yourteam.drop", "otherteam.drop") + SmartMessage(player, "#FF_YOUBALLDROP", "#FF_TEAMBALLDROP", "#FF_ENEMYBALLDROP", Color.kYellow, Color.kYellow, Color.kYellow) + end + + local ball = CastToInfoScript(entity) + ball:EmitSound(self.tosssound) +end + +function base_ball:onloseitem( owner_entity ) + if IsPlayer( owner_entity ) then + -- let the player that lost the ball put on a disguise + local player = CastToPlayer( owner_entity ) + player:SetDisguisable(true) + player:SetCloakable( true ) + + self:addnotouch(player:GetId(), self.capnotouchtime) + end +end + +function base_ball:spawn() + self.notouch = { } + info_ff_script.spawn(self) + self.status = 0 +end + +function base_ball:addnotouch( player_id, duration ) + self.notouch[player_id] = duration + AddSchedule(self.name .. "-" .. player_id, duration, self.removenotouch, self, player_id) +end + +function base_ball.removenotouch(self, player_id) + self.notouch[player_id] = nil +end + +-- For when this object is carried, these offsets are used to place +-- the info_ff_script relative to the players feet +function base_ball:attachoffset() + -- x = forward/backward + -- y = left/right + -- z = up/down + local offset = Vector( 32, 0, 0 ) + return offset +end + +function base_ball:precache() + PrecacheSound(self.tosssound) + info_ff_script.precache(self) +end + +function base_ball:onreturn() + ConsoleToAll( "The ball has returned!" ) + SpeakAll ( "CTF_BALLRETURN" ) + BroadCastMessage( "#FF_WATERPOLO_BALL_RETURN", Color.kYellow ) + self.status = 0 + + reset_ball_carrier() +end + +ball = base_ball:new({ + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed}, + botgoaltype = Bot.kFlag +}) + + + + +-- generic goal +base_goal = trigger_ff_script:new({ + health = 100, + armor = 300, + grenades = 200, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + detpacks = 0, + mancannons = 0, + gren1 = 0, + gren2 = 0, + item = "", + team = 0, + botgoaltype = Bot.kFlagCap +}) + +function base_goal:spawn() + if self.team ~= Team.kUnassigned then + goal_entities[self.team] = entity + end +end + +function base_goal:allowed ( allowed_entity ) + if IsPlayer( allowed_entity ) then + -- player has to be carrying the item + local player = CastToPlayer( allowed_entity ) + return player:HasItem( self.item ) + end + + return EVENT_DISALLOWED +end + +function base_goal:ontrigger ( trigger_entity ) + if IsPlayer( trigger_entity ) then + + -- player should capture now + local player = CastToPlayer( trigger_entity ) + if player:HasItem( self.item ) then + local team = GetTeam( self.team ) + team:AddScore( POINTS_PER_CAPTURE ) + ConsoleToAll( team:GetName() .. " team scores!" ) + + local ball = GetInfoScriptByName( self.item ) + ball:Return() + + remove_hud_items(ball, player) + + if player:GetTeamId() == self.team then + ConsoleToAll( player:GetName() .. " scored a goal!" ) + -- show on the deathnotice board + ObjectiveNotice( player, "scored a goal" ) + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") + SmartSpeak(player, "CTF_YOUSCORE", "CTF_TEAMSCORE", "CTF_THEYSCORE") + SmartMessage( player, "#FF_WATERPOLO_YOU_GOAL", "#FF_WATERPOLO_TEAM_GOAL", "#FF_WATERPOLO_ENEMY_GOAL", Color.kGreen, Color.kGreen, Color.kRed) + player:AddFortPoints( POINTS_PER_CAPTURE * 100, "#FF_FORTPOINTS_GOAL" ) + else + ConsoleToAll( player:GetName() .. " scored an own goal!\nWait, what?! Kill him like that Columbian a few years ago! OWN GOAL! OWN GOAL!" ) + -- show on the deathnotice board + ObjectiveNotice( player, "scored an own goal" ) + SmartSound(player, "otherteam.flagcap", "otherteam.flagcap", "yourteam.flagcap") + SmartSpeak(player, "CTF_THEYSCORE", "CTF_THEYSCORE", "CTF_TEAMSCORE") + SmartMessage( player, "#FF_WATERPOLO_YOU_OWN_GOAL", "#FF_WATERPOLO_TEAM_OWN_GOAL", "#FF_WATERPOLO_ENEMY_OWN_GOAL", Color.kRed, Color.kRed, Color.kGreen) + player:AddFortPoints( -POINTS_PER_CAPTURE * 100, "#FF_FORTPOINTS_OWN_GOAL" ) + end + + ApplyToAll({ AT.kRespawnPlayers, AT.kReloadClips }) + + the_wall_reset() + end + end +end + +-- on blue's side of map, but points go to red +blue_goal = base_goal:new({ item = "ball", team = TEAM2 }) + +-- on red's side of map, but points go to blue +red_goal = base_goal:new({ item = "ball", team = TEAM1 }) + + + + +-- respawns a goalie +base_goalie_respawner = trigger_ff_script:new({ team = Team.kUnassigned }) + +function base_goalie_respawner:ontouch( trigger_entity ) + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + if player:GetClass() == Player.kCivilian and player:GetTeamId() == self.team then + -- respawn the goalie + ApplyToPlayer(player, { AT.kRespawnPlayers }) + AddSchedule("goalie_bounds_notification_" .. player:GetId(), 0.1, goalie_bounds_notification, player ) + end + end + +end + +-- goalie respawner +blue_goalie_respawner = base_goalie_respawner:new({ team = TEAM1 }) +red_goalie_respawner = base_goalie_respawner:new({ team = TEAM2 }) + + + + +-- returns the item +base_item_returner = trigger_ff_script:new({ item = "", message = "" }) + +function base_item_returner:allowed ( allowed_entity ) + + if IsPlayer( allowed_entity ) then + -- player has to be carrying the item or be a goalie + local player = CastToPlayer( allowed_entity ) + if player:HasItem( self.item ) or player:GetClass() == Player.kCivilian then + return EVENT_ALLOWED + end + end + + return EVENT_DISALLOWED + +end + +function base_item_returner:ontrigger ( trigger_entity ) + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + if player:GetClass() ~= Player.kCivilian then + -- return the item + local item = GetInfoScriptByName( self.item ) + item:Return() + remove_hud_items(item, player) + ConsoleToAll( player:GetName() .. self.message ) + SpeakAll ( "CTF_BALLRETURN" ) + SmartMessage( player, "#FF_WATERPOLO_YOU_BOUNDS", "#FF_WATERPOLO_TEAM_BOUNDS", "#FF_WATERPOLO_ENEMY_BOUNDS", Color.kYellow, Color.kYellow, Color.kYellow ) + else + -- respawn the goalie + ApplyToPlayer(player, { AT.kRespawnPlayers }) + AddSchedule("goalie_bounds_notification_" .. player:GetId(), 0.1, goalie_bounds_notification, player ) + end + end + +end + +-- ball stripper +ball_stripper = base_item_returner:new({ item = "ball", message = " took the ball out of bounds!" }) + +-- spawn ammo packs +waterpolo_pack_spawn_blue = blue_ammobackpack +waterpolo_pack_spawn_red = red_ammobackpack + +fortball_pack_spawn_blue = blue_ammobackpack +fortball_pack_spawn_red = red_ammobackpack + +-- unique fortball spawns (goalies spawn on top of the goal) +bluespawn = { validspawn = function(self,player) return player:GetTeamId() == TEAM1 and player:GetClass() ~= Player.kCivilian and player:GetClass() ~= Player.kSniper end } +redspawn = { validspawn = function(self,player) return player:GetTeamId() == TEAM2 and player:GetClass() ~= Player.kCivilian and player:GetClass() ~= Player.kSniper end } +bluespawn_goalie = { validspawn = function(self,player) return player:GetTeamId() == TEAM1 and player:GetClass() == Player.kCivilian end } +redspawn_goalie = { validspawn = function(self,player) return player:GetTeamId() == TEAM2 and player:GetClass() == Player.kCivilian end } +bluespawn_sniper = { validspawn = function(self,player) return player:GetTeamId() == TEAM1 and player:GetClass() == Player.kSniper end } +redspawn_sniper = { validspawn = function(self,player) return player:GetTeamId() == TEAM2 and player:GetClass() == Player.kSniper end } + + +----------------------------------------------------------------------------- +-- unique fortball locations +----------------------------------------------------------------------------- +location_ballsonia = location_info:new({ text = "Ballsonia", team = Team.kUnassigned }) +location_midfield = location_info:new({ text = "Midfield", team = Team.kUnassigned }) +location_blue_side = location_info:new({ text = "Blue Side", team = TEAM1 }) +location_red_side = location_info:new({ text = "Red Side", team = TEAM2 }) +location_blue_goal = location_info:new({ text = "Blue Goal", team = TEAM1 }) +location_red_goal = location_info:new({ text = "Red Goal", team = TEAM2 }) +location_upper_deck = location_info:new({ text = "Upper Deck", team = Team.kUnassigned }) +location_blue_upper_deck = location_info:new({ text = "Blue Upper Deck", team = TEAM1 }) +location_red_upper_deck = location_info:new({ text = "Red Upper Deck", team = TEAM2 }) +location_nose_bleeds = location_info:new({ text = "Nose Bleeds", team = Team.kUnassigned }) +location_blue_nose_bleeds = location_info:new({ text = "Blue Nose Bleeds", team = TEAM1 }) +location_red_nose_bleeds = location_info:new({ text = "Red Nose Bleeds", team = TEAM2 }) +location_rainy_sky = location_info:new({ text = "Rainy Sky", team = Team.kUnassigned }) +location_death_hills = location_info:new({ text = "Death Hills", team = Team.kUnassigned }) +location_sideroom1 = location_info:new({ text = "Side Room 1", team = Team.kUnassigned }) +location_sideroom2 = location_info:new({ text = "Side Room 2", team = Team.kUnassigned }) + diff --git a/maps/includes/base_fortball_default.lua b/maps/includes/base_fortball_default.lua new file mode 100644 index 0000000..0116dc4 --- /dev/null +++ b/maps/includes/base_fortball_default.lua @@ -0,0 +1,101 @@ +-- base_fortball_default.lua + +-- if you want to customize these base fortball defaults, copy all of this file's contents +-- into your map's lua file, edit what you want, and then include base_fortball.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay"); +IncludeScript("base_location"); + +-- set genericbackpack's disallow touch flags for not letting goalies pick up anything +genericbackpack.disallowtouchflags = {AllowFlags.kCivilian} + +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- + +-- teams +TEAM1 = Team.kBlue +TEAM2 = Team.kRed +DISABLED_TEAM3 = Team.kYellow +DISABLED_TEAM4 = Team.kGreen + +teams = { TEAM1, TEAM2 } +disabled_teams = { DISABLED_TEAM3, DISABLED_TEAM4 } + +team_info = { + [Team.kUnassigned] = { + team_name = "neutral", + enemy_team = Team.kUnassigned, + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = 0, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = 0, + }, + }, + [TEAM1] = { + team_name = "blue", + enemy_team = TEAM2, + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = -1, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = 1, + }, + }, + [TEAM2] = { + team_name = "red", + enemy_team = TEAM1, + class_limits = { + [Player.kScout] = 0, + [Player.kSniper] = -1, + [Player.kSoldier] = 0, + [Player.kDemoman] = 0, + [Player.kMedic] = 0, + [Player.kHwguy] = 0, + [Player.kPyro] = 0, + [Player.kSpy] = 0, + [Player.kEngineer] = 0, + [Player.kCivilian] = 1, + }, + }, +} + +-- objectives +objective_entities = { [TEAM1] = nil, [TEAM2] = nil } +goal_entities = { [TEAM1] = nil, [TEAM2] = nil } +ball_carrier = nil +BALL_ALWAYS_ENEMY_OBJECTIVE = true + +-- scoring +POINTS_PER_GOAL = 10 +POINTS_PER_INITIALTOUCH = 100 +POINTS_PER_GOALIE_RETURN = 50 +POINTS_PER_GOALIE_ATTACK = 10 +BALL_RETURN_TIME = 15 +BALL_THROW_SPEED = 2048 +GOALIE_SPEED = 2.0 +THE_WALL_TIMER_DISABLE = 12.5 +THE_WALL_TIMER_WARN = 2.5 + +-- goalie sounds +goalie_sound_loop = "ff_waterpolo.psychotic_goalie" +goalie_sound_idle = "NPC_BlackHeadcrab.Talk" +goalie_sound_pain = "NPC_BlackHeadcrab.ImpactAngry" +goalie_sound_kill = "NPC_BlackHeadcrab.Telegraph" + diff --git a/maps/includes/base_hunted.lua b/maps/includes/base_hunted.lua new file mode 100644 index 0000000..57b36d6 --- /dev/null +++ b/maps/includes/base_hunted.lua @@ -0,0 +1,471 @@ + +-- base_hunted.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay"); +IncludeScript("base_location"); + +----------------------------------------------------------------------------- +-- Basic hunted-style gameplay. Respawns all players when the VIP is killed +----------------------------------------------------------------------------- +POINTS_PER_HUNTED_DEATH = 5 +POINTS_PER_HUNTED_DEATH_FOR_ASSASSIN = 5 +POINTS_PER_HUNTED_ESCAPE = 10 +POINTS_PER_HUNTED_ESCAPE_FOR_HUNTED = 10 +POINTS_PER_HUNTED_ESCAPE_FOR_BODYGUARDS = 10 +POINTS_PER_HUNTED_ATTACK = 2 +HUNTED_ALLIES_TEAM = Team.kRed +HUNTED_ENTITY = nil +LAST_HUNTED_LOCATION = nil +ESCAPE_DOOR_BUTTON_UNLOCKED = true + +-- escape_door_top is also defined as a base_escape_door object down below +escape_door = { + entity_names = { "escape_door_top", "escape_door_bottom" }, + isopen = false, + openicon = "hud_door_open.vtf", + closedicon = "hud_door_closed.vtf", + hudposx = 0, + hudposy = 32, + hudwidth = 64, + hudheight = 32, + hudalignx = 4, + hudaligny = 0 +} + +-- precache sounds +function precache() + PrecacheSound("ff_hunted.thunder") + PrecacheSound("ff_hunted.cheer") + PrecacheSound("ff_hunted.dying_bird") + PrecacheSound("ff_hunted.dying_bird_full") + PrecacheSound("ff_hunted.dying_bird_full") + PrecacheSound("ff_hunted.i_am_the_werewolf") + PrecacheSound("ff_hunted.i_fight_vampires") + PrecacheSound("ff_hunted.werewolf_howling") + PrecacheSound("ff_hunted.werewolf_movies") + PrecacheSound("ff_hunted.werewolves_howling") + + PrecacheSound("otherteam.flagstolen") +end + +function startup() + SetGameDescription( "Hunted" ) + + -- set up team names + SetTeamName( Team.kBlue, "The Hunted" ) + SetTeamName( Team.kRed, "Bodyguards" ) + SetTeamName( Team.kYellow, "Assassins" ) + SetTeamName( Team.kGreen, "Green Kid Touchers" ) + + -- set up team limits + SetPlayerLimit( Team.kBlue, 1 ) -- There can be only one Highlander! + SetPlayerLimit( Team.kRed, 0 ) -- Unlimited bodyguards. + SetPlayerLimit( Team.kYellow, 6 ) -- Only 6 assassins, but can we dynamically change this based on maxplayers and/or the current playercount? + SetPlayerLimit( Team.kGreen, -1 ) -- Fuck green. + + local team = GetTeam( Team.kBlue ) + team:SetAllies( Team.kRed ) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, -1 ) + team:SetClassLimit( Player.kSoldier, -1 ) + team:SetClassLimit( Player.kDemoman, -1 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, 0 ) + + team = GetTeam( Team.kRed ) + team:SetAllies( Team.kBlue ) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, 1 ) + team:SetClassLimit( Player.kSoldier, 0 ) + team:SetClassLimit( Player.kDemoman, -1 ) + team:SetClassLimit( Player.kMedic, 0 ) + team:SetClassLimit( Player.kHwguy, 0 ) + team:SetClassLimit( Player.kPyro, 1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, 0 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + team = GetTeam( Team.kYellow ) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, 0 ) + team:SetClassLimit( Player.kSoldier, -1 ) + team:SetClassLimit( Player.kDemoman, -1 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, 1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + RemoveSchedule( "hunted_location_timer" ) + AddScheduleRepeating( "hunted_location_timer" , 1.0, hunted_location_timer ) + +end + +------------------------------------------- +-- hunted flaginfo +------------------------------------------- + +function flaginfo( player_entity ) + + local player = CastToPlayer( player_entity ) + + if escape_door.isopen then + RemoveHudItem( player, "escape_door_closed" ) + AddHudIcon( player, escape_door.openicon, "escape_door_open", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny ) + else + RemoveHudItem( player, "escape_door_open" ) + AddHudIcon( player, escape_door.closedicon, "escape_door_closed", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny ) + end + +end + +function hunted_location_timer() + + if HUNTED_ENTITY ~= nil then + + local player = CastToPlayer( HUNTED_ENTITY ) + + if player:GetLocation() ~= LAST_HUNTED_LOCATION then + + LAST_HUNTED_LOCATION = player:GetLocation() + RemoveHudItem( player, "hunted_location" ) + AddHudTextToTeam( GetTeam(Team.kRed), "hunted_location", "Hunted Location: " .. player:GetLocation(), 4, 44, 0, 1 ) + RemoveHudItemFromTeam( GetTeam(Team.kYellow), "hunted_location" ) + + end + + elseif LAST_HUNTED_LOCATION ~= nil then + + LAST_HUNTED_LOCATION = nil + RemoveHudItemFromAll( "hunted_location" ) + + end + +end + + +function respawn_everyone() + ApplyToAll({ AT.kAllowRespawn, AT.kRespawnPlayers, AT.kRemoveProjectiles, AT.kStopPrimedGrens }) + + AddSchedule( "close_escape_doors", 4.0, close_escape_doors ) +end + +function close_escape_doors() + for i,v in ipairs(escape_door.entity_names) do + -- close each enemy escape door + OutputEvent( v, "Close" ) + end +end + +function lock_escape_door_button() + ESCAPE_DOOR_BUTTON_UNLOCKED = false +end + +function unlock_escape_door_button() + ESCAPE_DOOR_BUTTON_UNLOCKED = true +end + +function hunted_escape_notification() + BroadCastMessage( "The Hunted escaped!" ) + BroadCastSound ( "ff_hunted.cheer" ) +end + +function player_ondamage( player, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + local attacker = damageinfo:GetAttacker() + local inflictor = damageinfo:GetInflictor() + + -- hunted has body armor on and only takes damage from certain things + if player:GetTeamId() == Team.kBlue then + + local weapon = damageinfo:GetInflictor():GetClassName() + local attacker_is_buildable = false + + if IsSentrygun(attacker) or IsDispenser(attacker) or IsSentrygun(inflictor) or IsDispenser(inflictor) then + + attacker_is_buildable = true + + end + + if attacker_is_buildable ~= true and weapon ~= "ff_weapon_sniperrifle" and weapon ~= "ff_weapon_crowbar" and weapon ~= "ff_projectile_dart" and weapon ~= "ff_weapon_knife" then + + damageinfo:ScaleDamage(0) + + else + + -- BroadCastSound ( "ff_hunted.dying_bird" ) + + end + + -- hunted also has quad damage + else + + if IsPlayer( attacker ) then + + attacker = CastToPlayer( attacker ) + + if attacker:GetTeamId() == Team.kBlue and player:GetTeamId() ~= HUNTED_ALLIES_TEAM then + + damageinfo:ScaleDamage(4) + attacker:AddFortPoints( POINTS_PER_HUNTED_ATTACK * 10, "Hunted Attack" ) + ConsoleToAll( "The Hunted, " .. attacker:GetName() .. ", dealt quad damage to" .. player:GetName() .. "!" ) + + end + + end + + end + +end + +function player_onkill( player ) + -- Don't let blue hunted suicide. + if player:GetTeamId() == Team.kBlue then + return false + end + return true +end + +-- We only care when The Hunted is killed by another player +function player_killed ( player_victim, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + -- Entity that is attacking + local attacker = damageinfo:GetAttacker() + + -- If no attacker do nothing + if not attacker then return end + + local player_attacker = nil + + -- get the attacking player + if IsPlayer(attacker) then + attacker = CastToPlayer(attacker) + player_attacker = attacker + elseif IsSentrygun(attacker) then + attacker = CastToSentrygun(attacker) + player_attacker = attacker:GetOwner() + elseif IsDetpack(attacker) then + attacker = CastToDetpack(attacker) + player_attacker = attacker:GetOwner() + elseif IsDispenser(attacker) then + attacker = CastToDispenser(attacker) + player_attacker = attacker:GetOwner() + end + + -- if still no attacking player after all that, try the inflictor + if not player_attacker then + + -- Entity that is attacking + local inflictor = damageinfo:GetInflictor() + + if inflictor then + if IsSentrygun(inflictor) then + inflictor = CastToSentrygun(inflictor) + player_attacker = inflictor:GetOwner() + elseif IsDetpack(inflictor) then + inflictor = CastToDetpack(inflictor) + player_attacker = inflictor:GetOwner() + elseif IsDispenser(inflictor) then + inflictor = CastToDispenser(inflictor) + player_attacker = inflictor:GetOwner() + end + end + + end + + -- if still no attacking player after all that, forget about it + if not player_attacker then return end + + if player_victim:GetTeamId() == Team.kBlue then + ConsoleToAll( "The Hunted, " .. player_victim:GetName() .. ", was assassinated!" ) + BroadCastMessage( "The Hunted was assassinated!" ) + -- BroadCastSound ( "ff_hunted.werewolves_howling" ) + BroadCastSound ( "ff_hunted.thunder" ) + local team = GetTeam( Team.kYellow ) + team:AddScore( POINTS_PER_HUNTED_DEATH ) + ApplyToAll( { AT.kDisallowRespawn } ) + AddSchedule("respawn_everyone", 2, respawn_everyone) + end +end + +function player_disconnected( player ) + if player:GetTeamId() == Team.kBlue then + HUNTED_ENTITY = nil + UpdateObjectiveIcon( player, HUNTED_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(Team.kRed), HUNTED_ENTITY ) + RemoveHudItemFromAll("hunted_location") + end +end + + +BLOCKTEAMCHANGE = {} + +function player_switchteam( player, currentteam, desiredteam ) + local i = player:GetId() + local stime = GetServerTime() + + if desiredteam == Team.kBlue then + local delaytime = BLOCKTEAMCHANGE[i] + if delaytime ~= nil and delaytime > stime then + return false + end + + BLOCKTEAMCHANGE[i] = stime + 10; + end + + if player:GetTeamId() == Team.kBlue then + HUNTED_ENTITY = nil + UpdateObjectiveIcon( player, HUNTED_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(Team.kRed), HUNTED_ENTITY ) + RemoveHudItemFromAll("hunted_location") + end + + return true +end + +-- Give everyone a full resupply, but strip grenades from assassins +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 100 ) + player:AddAmmo( Ammo.kNails, 300 ) + player:AddAmmo( Ammo.kShells, 300 ) + player:AddAmmo( Ammo.kRockets, 300 ) + player:AddAmmo( Ammo.kCells, 300 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + player:AddAmmo( Ammo.kManCannon, 1 ) + + if player:GetTeamId() ~= Team.kYellow then + player:AddAmmo( Ammo.kGren1, 4 ) + player:AddAmmo( Ammo.kGren2, 4 ) + end + + -- AddHudText( player, "escape_door_text", "ESCAPE DOOR:", 0, 32, 4 ) + + if player:GetTeamId() == Team.kRed then + UpdateObjectiveIcon( player, HUNTED_ENTITY ) + if HUNTED_ENTITY ~= nil then + local player_hunted = CastToPlayer( HUNTED_ENTITY ) + AddHudText( player, "hunted_location", "Hunted Location: " .. player_hunted:GetLocation(), 4, 44, 0, 1 ) + end + elseif player:GetTeamId() == Team.kYellow then + UpdateObjectiveIcon( player, nil ) + else + HUNTED_ENTITY = player + UpdateObjectiveIcon( player, GetEntityByName("hunted_escape") ) + UpdateTeamObjectiveIcon( GetTeam(Team.kRed), HUNTED_ENTITY ) + end + +-- if player:GetTeamId() == Team.kRed then +-- BroadCastSoundToPlayer(player, "ff_hunted.i_fight_vampires") +-- elseif player:GetTeamId() == Team.kYellow then +-- BroadCastSoundToPlayer(player, "ff_hunted.werewolf_howling") +-- else +-- BroadCastSoundToPlayer(player, "ff_hunted.i_am_the_werewolf") +-- end +end + + +-- escape portal entrance +hunted_escape = trigger_ff_script:new({ + botgoaltype = Bot.kHuntedEscape, + team = Team.kBlue +}) + +-- escape touch +function hunted_escape:ontouch( touch_entity ) + + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + if player:GetTeamId() == Team.kBlue then + player:AddFrags( POINTS_PER_HUNTED_ESCAPE_FOR_HUNTED ) + player:AddFortPoints( POINTS_PER_HUNTED_ESCAPE_FOR_HUNTED * 10, "Hunted Escape" ) + + ConsoleToAll( "The Hunted, " .. player:GetName() .. ", escaped!" ) + + local team = GetTeam( Team.kBlue ) + team:AddScore( POINTS_PER_HUNTED_ESCAPE ) + team = GetTeam( Team.kRed ) + team:AddScore( POINTS_PER_HUNTED_ESCAPE ) + + ApplyToAll({ AT.kAllowRespawn, AT.kRespawnPlayers, AT.kRemoveProjectiles, AT.kStopPrimedGrens }) + AddSchedule( "hunted_escape_notification", 0.1, hunted_escape_notification ) + AddSchedule( "close_escape_doors", 4.0, close_escape_doors ) + + end + end + +end + + +base_escape_door = trigger_ff_script:new({}) + +function base_escape_door:onopen() + + BroadCastMessage("Escape Door Open!") + BroadCastSound("otherteam.flagstolen") + + escape_door.isopen = true + + RemoveHudItemFromAll( "escape_door_closed" ) + AddHudIconToAll( escape_door.openicon, "escape_door_open", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny ) + +end + +function base_escape_door:onfullyclosed() + + BroadCastMessage("Escape Door Closed!") + -- BroadCastSound("otherteam.flagstolen") + + escape_door.isopen = false + + RemoveHudItemFromAll( "escape_door_open" ) + AddHudIconToAll( escape_door.closedicon, "escape_door_closed", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny ) + +end + +escape_door_top = base_escape_door + + +base_escape_door_button = func_button:new({}) + +function base_escape_door_button:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if ESCAPE_DOOR_BUTTON_UNLOCKED then + lock_escape_door_button() + AddSchedule( "unlock_escape_door_button", 6.66, unlock_escape_door_button ) + return EVENT_ALLOWED + end + end + + return EVENT_DISALLOWED +end + +-- TODO this doesn't work +function base_escape_door_button:onfailuse( use_entity ) + if IsPlayer( use_entity ) then + local player = CastToPlayer( use_entity ) + BroadCastMessageToPlayer( player, "#FF_NOTALLOWEDBUTTON" ) + end +end + +escape_door_button_left = base_escape_door_button +escape_door_button_right = base_escape_door_button +escape_door_button_inside = base_escape_door_button + diff --git a/maps/includes/base_id.lua b/maps/includes/base_id.lua new file mode 100644 index 0000000..741fa8d --- /dev/null +++ b/maps/includes/base_id.lua @@ -0,0 +1,926 @@ + +-- base_id.lua +-- Invade / Defend gametype + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay") + +----------------------------------------------------------------------------- +-- globals +----------------------------------------------------------------------------- +if POINTS_PER_CAPTURE == nil then POINTS_PER_CAPTURE = 10; end +if POINTS_PER_PERIOD == nil then POINTS_PER_PERIOD = 2; end +if PERIOD_TIME == nil then PERIOD_TIME = 30; end +if NUM_PHASES == nil then NUM_PHASES = 4; end +if INITIAL_ROUND_DELAY == nil then INITIAL_ROUND_DELAY = 45; end +if ROUND_DELAY == nil then ROUND_DELAY = 20; end +if onroundreset == nil then onroundreset = function() end end +if FLAG_RETURN_TIME == nil then FLAG_RETURN_TIME = 60; end +if ATTACKERS_OBJECTIVE_ENTITY == nil then ATTACKERS_OBJECTIVE_ENTITY = nil end +if DEFENDERS_OBJECTIVE_ENTITY == nil then DEFENDERS_OBJECTIVE_ENTITY = nil end +if DEFENDERS_OBJECTIVE_ONFLAG == nil then DEFENDERS_OBJECTIVE_ONFLAG = true end +if DEFENDERS_OBJECTIVE_ONCARRIER == nil then DEFENDERS_OBJECTIVE_ONCARRIER = true end +if TEAM_SWITCH_DELAY == nil then TEAM_SWITCH_DELAY = 2 end +if RESPAWN_AFTER_CAP == nil then RESPAWN_AFTER_CAP = false end +if RESPAWN_DELAY == nil then RESPAWN_DELAY = 2 end + +basecap = trigger_ff_script:new({ + health = 100, + armor = 300, + grenades = 200, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + detpacks = 1, + mancannons = 1, + gren1 = 0, + gren2 = 0, + item = "", + team = 0, + botgoaltype = Bot.kFlagCap, +}) + +function basecap:allowed ( allowed_entity ) + if IsPlayer( allowed_entity ) then + -- get the player and his team + local player = CastToPlayer( allowed_entity ) + local team = player:GetTeam() + + -- check if the player is on our team + if team:GetTeamId() ~= self.team then + return false + end + + -- check if the player has the flag + for i,v in ipairs(self.item) do + local flag = GetInfoScriptByName(v) + + -- Make sure flag isn't nil + if flag then + if player:HasItem(flag:GetName()) then + return true + end + end + end + end + + return false +end + +function basecap:ontrigger ( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- player should capture now + for i,v in ipairs( self.item ) do + + -- find the flag and cast it to an info_ff_script + local flag = GetInfoScriptByName(v) + + -- Make sure flag isn't nil + if flag then + + -- check if the player is carrying the flag + if player:HasItem(flag:GetName()) then + + -- reward player for capture + player:AddFortPoints(FORTPOINTS_PER_CAPTURE, "#FF_FORTPOINTS_CAPTUREFLAG") + + -- reward player's team for capture + local team = player:GetTeam() + team:AddScore(POINTS_PER_CAPTURE) + + -- Remove any hud icons + -- local flag2 = CastToInfoScript(flag) + RemoveHudItem( player, flag:GetName() ) + RemoveHudItemFromAll( flag:GetName() .. "_c" ) + + LogLuaEvent(player:GetId(), 0, "flag_capture","flag_name",flag:GetName()) + + -- return the flag + flag:Return() + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then player:AddHealth(self.health) end + if self.armor ~= nil and self.armor ~= 0 then player:AddArmor(self.armor) end + + -- give the player some ammo + if self.nails ~= nil and self.nails ~= 0 then player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then player:AddAmmo(Ammo.kGren2, self.gren2) end + + self:oncapture( player, v ) + end + end + end + end +end + +function basecap:oncapture(player, item) + -- let the teams know that a capture occured + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") + SmartSpeak(player, "CTF_YOUCAP", "CTF_TEAMCAP", "CTF_THEYCAP") + SmartMessage(player, "#FF_YOUCAP", "#FF_TEAMCAP", "#FF_OTHERTEAMCAP", Color.kGreen, Color.kGreen, Color.kRed) +end + +function baseflag:spawn() + self.notouch = { } + info_ff_script.spawn(self) + local flag = CastToInfoScript( entity ) + LogLuaEvent(0, 0, "flag_spawn","flag_name",flag:GetName()) + + self.status = 0 + + update_hud() +end + +function baseflag:ownercloak( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + + RemoveHudItem( player, flag:GetName() ) + self.status = 2 + + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_return_timer() + update_hud() +end + +function baseflag:dropitemcmd( owner_entity ) + + if allowdrop == false then return end + + --Used by logging + self.flagtoss = true + + -- throw the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, FLAG_THROW_SPEED) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + + RemoveHudItem( player, flag:GetName() ) + self.status = 2 + + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_return_timer() + update_hud() +end + +function baseflag:onownerforcerespawn( owner_entity ) + local flag = CastToInfoScript( entity ) + local player = CastToPlayer( owner_entity ) + player:SetDisguisable( true ) + player:SetCloakable( true ) + RemoveHudItem( player, flag:GetName() ) + flag:Drop(0, FLAG_THROW_SPEED) + + RemoveHudItem( player, flag:GetName() ) + self.status = 2 + + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + update_hud() +end + +function baseflag:onreturn( ) + -- let the teams know that the flag was returned + local team = GetTeam( self.team ) + SmartTeamMessage(team, "#FF_TEAMRETURN", "#FF_OTHERTEAMRETURN", Color.kYellow, Color.kYellow) + SmartTeamSound(team, "yourteam.flagreturn", "otherteam.flagreturn") + SmartTeamSpeak(team, "CTF_FLAGBACK", "CTF_EFLAGBACK") + local flag = CastToInfoScript( entity ) + + self.status = 0 + + LogLuaEvent(0, 0, "flag_returned","flag_name",flag:GetName()); + + + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = flag end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + destroy_return_timer() + update_hud() +end + +phase = 1 +current_flag = "cp1_flag" --currently only used by Palermo for hacky flag returning in water +attackers = Team.kBlue +defenders = Team.kRed +current_timer = 0 +carried_by = nil + +function startup() + SetGameDescription( "Invade Defend" ) + + -- set up team limits + local team = GetTeam( Team.kBlue ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kRed ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kYellow ) + team:SetPlayerLimit( -1 ) + + team = GetTeam( Team.kGreen ) + team:SetPlayerLimit( -1 ) + + -- CTF maps generally don't have civilians, + -- so override in map LUA file if you want 'em + local team = GetTeam(Team.kBlue) + team:SetClassLimit(Player.kCivilian, -1) + + team = GetTeam(Team.kRed) + team:SetClassLimit(Player.kCivilian, -1) + + -- set them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- start the timer for the points + AddScheduleRepeating("addpoints", PERIOD_TIME, addpoints) + + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + + cp1_flag.enabled = true + for i,v in ipairs({"cp1_flag", "cp2_flag", "cp3_flag", "cp4_flag", "cp5_flag", "cp6_flag", "cp7_flag", "cp8_flag"}) do + local flag = GetInfoScriptByName(v) + if flag then + flag:SetModel(_G[v].model) + flag:SetSkin(teamskins[attackers]) + if i == 1 then + flag:Restore() + else + flag:Remove() + end + end + end + + flags_set_team( attackers ) + + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) +end + +-- Give everyone a full resupply, but strip secondary grenades +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + player:AddAmmo( Ammo.kManCannon, 1 ) + + player:RemoveAmmo( Ammo.kGren2, 4 ) + + if player:GetTeamId() == attackers then + UpdateObjectiveIcon( player, ATTACKERS_OBJECTIVE_ENTITY ) + elseif player:GetTeamId() == defenders then + UpdateObjectiveIcon( player, DEFENDERS_OBJECTIVE_ENTITY ) + end +end + +function addpoints() + local team = GetTeam(defenders) + team:AddScore(POINTS_PER_PERIOD) +end + +function precache() + -- precache sounds + PrecacheSound("yourteam.flagstolen") + PrecacheSound("otherteam.flagstolen") + PrecacheSound("yourteam.flagcap") + PrecacheSound("otherteam.flagcap") + PrecacheSound("yourteam.drop") + PrecacheSound("otherteam.drop") + PrecacheSound("yourteam.flagreturn") + PrecacheSound("otherteam.flagreturn") +-- PrecacheSound("vox.yourcap") +-- PrecacheSound("vox.enemycap") +-- PrecacheSound("vox.yourstole") +-- PrecacheSound("vox.enemystole") +-- PrecacheSound("vox.yourflagret") +-- PrecacheSound("vox.enemyflagret") +end + +-- kinda ghetto, sure +function flags_set_team( teamid ) + -- set all flags teams + cp1_flag.team = teamid + cp2_flag.team = teamid + cp3_flag.team = teamid + cp4_flag.team = teamid + cp5_flag.team = teamid + cp6_flag.team = teamid + cp7_flag.team = teamid + cp8_flag.team = teamid +end + +----------------------------------------- +--Backpacks +----------------------------------------- +idbackpack = genericbackpack:new({team = nil}) + +function idbackpack:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + + if player:GetTeamId() ~= self.team then + return false + end + + local dispensed = 0 + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then dispensed = dispensed + player:AddHealth( self.health ) end + if self.armor ~= nil and self.armor ~= 0 then dispensed = dispensed + player:AddArmor( self.armor ) end + + -- give player ammo + if self.nails ~= nil and self.nails ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren2, self.gren2) end + + -- if the player took ammo, then have the backpack respawn with a delay + if dispensed >= 1 then + local backpack = CastToInfoScript(entity); + if backpack then + backpack:EmitSound(self.touchsound); + backpack:Respawn(self.respawntime); + end + end + end +end + +backpack_attackers = idbackpack:new({team = attackers}) +backpack_defenders = idbackpack:new({team = defenders}) + + +----------------------------------------- +-- base flag +----------------------------------------- +base_id_flag = baseflag:new({ + phase = 1, + enabled = nil, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue, AllowFlags.kRed }, + hudicon = BLUE_FLAG_HUD_ICON, +}) +function base_id_flag:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + -- pickup if they can + if self.notouch[player:GetId()] then return; end + + if player:GetTeamId() == attackers and phase == self.phase and self.enabled then + SmartSound(player, "yourteam.flagstolen", "yourteam.flagstolen", "otherteam.flagstolen") + RandomFlagTouchSpeak( player ) +--SmartSound(player, "vox.yourstole", "vox.yourstole", "vox.enemystole") + SmartMessage(player, "#FF_YOUPICKUP", "#FF_TEAMPICKUP", "#FF_OTHERTEAMPICKUP", Color.kGreen, Color.kGreen, Color.kRed) + + local flag = CastToInfoScript(entity) + flag:Pickup(player) + player:SetDisguisable( false ) + -- if the player is a spy, then force him to lose his cloak + player:SetCloakable( false ) + + self.hudicon = team_hudicons[attackers] + + AddHudIcon( player, self.hudicon, flag:GetName(), self.hudx, self.hudy, self.hudstatusiconw, self.hudstatusiconh, self.hudalign ) + + -- log action in stats + LogLuaEvent(player:GetId(), 0, "flag_touch", "flag_name", flag:GetName(), "player_origin", (string.format("%0.2f",player:GetOrigin().x) .. ", " .. string.format("%0.2f",player:GetOrigin().y) .. ", " .. string.format("%0.1f",player:GetOrigin().z) ), "player_health", "" .. player:GetHealth()); + + -- change objective icons + ATTACKERS_OBJECTIVE_ENTITY = player + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..self.phase.."_cap" ) end + if DEFENDERS_OBJECTIVE_ONCARRIER then DEFENDERS_OBJECTIVE_ENTITY = player end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + UpdateObjectiveIcon( player, GetEntityByName( "cp"..self.phase.."_cap" ) ) + + carried_by = player:GetName() + destroy_return_timer() + update_hud() + end + end +end + +function player_switchclass( player, current, desired ) + return true +end + +function base_id_flag:onownerdie( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, flag:GetName() ) + + player:SetDisguisable( true ) + player:SetCloakable( true ) + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = flag end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + UpdateObjectiveIcon( player, nil ) + + self.status = 2 + + setup_return_timer() + update_hud() +end + +----------------------------------------- +-- base capture point +----------------------------------------- +base_id_cap = basecap:new({ + phase = 0, +}) + +function base_id_cap:allowed ( touch_entity ) + if phase ~= self.phase then + return EVENT_DISALLOWED + end + + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + + if player:GetTeamId() == defenders then + BroadCastMessageToPlayer( player, "#AD_Defend" ) + else + for i,v in ipairs(self.item) do + if player:HasItem( v ) then + return EVENT_ALLOWED + end + end + end + end + + return EVENT_DISALLOWED +end + +function base_id_cap:oncapture(player, item) + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") +--SmartSound(player, "vox.yourcap", "vox.yourcap", "vox.enemycap") + SmartSpeak(player, "CTF_YOUCAP", "CTF_TEAMCAP", "CTF_THEYCAP") + SmartMessage(player, "#FF_YOUCAP", "#FF_TEAMCAP", "#FF_OTHERTEAMCAP", Color.kGreen, Color.kGreen, Color.kRed) + + local flag_item = GetInfoScriptByName( item ) + RemoveHudItem( player, flag_item:GetName() ) + + -- turn off this flag + for i,v in ipairs(self.item) do + _G[v].enabled = nil + local flag = GetInfoScriptByName(v) + if flag then + flag:Remove() + end + end + + -- show on the deathnotice board + ObjectiveNotice( player, "captured point "..phase ) + + if phase == NUM_PHASES then + -- it's the last round. end and stuff + AddSchedule("team_switch_delay", TEAM_SWITCH_DELAY, round_end) + else + if RESPAWN_AFTER_CAP then + AddSchedule("respawn_all", RESPAWN_DELAY, respawn_all) + else + phase = phase + 1 + end + + -- enable the next flag after a time + AddSchedule("flag_start", ROUND_DELAY, flag_start, self.next) + if ROUND_DELAY > 30 then AddSchedule("flag_30secwarn", ROUND_DELAY-30, flag_30secwarn) end + if ROUND_DELAY > 10 then AddSchedule("flag_10secwarn", ROUND_DELAY-10, flag_10secwarn) end current_flag = self.next + + -- clear objective icon + ATTACKERS_OBJECTIVE_ENTITY = nil + if DEFENDERS_OBJECTIVE_ONFLAG or DEFENDERS_OBJECTIVE_ONCARRIER then DEFENDERS_OBJECTIVE_ENTITY = nil + else DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_tobase_timer() + update_hud() + end + +end + +function respawn_all() + RespawnAllPlayers() + phase = phase + 1 +end + + +function round_end() + phase = 1 + current_flag = "cp1_flag" + if attackers == Team.kBlue then + attackers = Team.kRed + defenders = Team.kBlue + else + attackers = Team.kBlue + defenders = Team.kRed + end + + -- set all flag teams to new attackers + flags_set_team( attackers ) + + -- switch them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- enable the first flag + cp1_flag.enabled = true + cp1_flag.status = 0 + local flag = GetInfoScriptByName("cp1_flag") + if flag then + flag:Restore() + flag:SetSkin(teamskins[attackers]) + end + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + -- reset the timer on points + AddScheduleRepeating("addpoints", PERIOD_TIME, addpoints) + + -- respawn the players + RespawnAllPlayers() + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + + -- run custom round reset stuff + onroundreset() + update_hud() +end + +function setup_door_timer(doorname, duration) + CloseDoor(doorname) + AddSchedule("round_start", duration, round_start, doorname) + AddSchedule("round_30secwarn", duration-30, round_30secwarn) + AddSchedule("round_10secwarn", duration-10, round_10secwarn) +end + +function round_start(doorname) + BroadCastMessage("#FF_AD_GATESOPEN") + BroadCastSound( "otherteam.flagstolen" ) + OpenDoor(doorname) +end +function round_30secwarn() BroadCastMessage("#FF_ROUND_30SECWARN") end +function round_10secwarn() BroadCastMessage("#FF_ROUND_10SECWARN") end + +function flag_start(flagname) + BroadCastMessage("#AD_FlagAtBase") + _G[flagname].enabled = true + _G[flagname].status = 0 + local flag = GetInfoScriptByName(flagname) + if flag then + flag:Restore() + flag:SetSkin(teamskins[attackers]) + end + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = flag end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + update_hud() +end +function flag_30secwarn() BroadCastMessage("#AD_30SecReturn") end +function flag_10secwarn() BroadCastMessage("#AD_10SecReturn") end + + +function timer_schedule() + current_timer = current_timer -1 +end + +function setup_return_timer() + RemoveSchedule( "timer_tobase_schedule" ) + current_timer = FLAG_RETURN_TIME + + AddScheduleRepeatingNotInfinitely( "timer_return_schedule", 1, timer_schedule, current_timer) +end + +function destroy_return_timer() + RemoveSchedule( "timer_return_schedule" ) +end + +function setup_tobase_timer() + RemoveSchedule( "timer_return_schedule" ) + current_timer = ROUND_DELAY + + AddScheduleRepeatingNotInfinitely( "timer_tobase_schedule", 1, timer_schedule, current_timer) +end + +function destroy_tobase_timer() + RemoveSchedule( "timer_tobase_schedule" ) +end + +------------------------------------------------ +-- instanciate them +------------------------------------------------ +cp1_flag = base_id_flag:new({phase = 1}) +cp2_flag = base_id_flag:new({phase = 2}) +cp3_flag = base_id_flag:new({phase = 3}) +cp4_flag = base_id_flag:new({phase = 4}) +cp5_flag = base_id_flag:new({phase = 5}) +cp6_flag = base_id_flag:new({phase = 6}) +cp7_flag = base_id_flag:new({phase = 7}) +cp8_flag = base_id_flag:new({phase = 8}) +cp1_cap = base_id_cap:new({phase = 1, item = {"cp1_flag"}, next = "cp2_flag"}) +cp2_cap = base_id_cap:new({phase = 2, item = {"cp2_flag"}, next = "cp3_flag"}) +cp3_cap = base_id_cap:new({phase = 3, item = {"cp3_flag"}, next = "cp4_flag"}) +cp4_cap = base_id_cap:new({phase = 4, item = {"cp4_flag"}, next = "cp5_flag"}) +cp5_cap = base_id_cap:new({phase = 5, item = {"cp5_flag"}, next = "cp6_flag"}) +cp6_cap = base_id_cap:new({phase = 6, item = {"cp6_flag"}, next = "cp7_flag"}) +cp7_cap = base_id_cap:new({phase = 7, item = {"cp7_flag"}, next = "cp8_flag"}) +cp8_cap = base_id_cap:new({phase = 8, item = {"cp8_flag"}, next = nil}) + +base_attacker_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player) + return player:GetTeamId() == attackers and phase == self.phase +end }) +base_defender_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player) + return player:GetTeamId() == defenders and phase == self.phase +end }) +cp1_attacker = base_attacker_spawn:new({phase=1}) +cp2_attacker = base_attacker_spawn:new({phase=2}) +cp3_attacker = base_attacker_spawn:new({phase=3}) +cp4_attacker = base_attacker_spawn:new({phase=4}) +cp5_attacker = base_attacker_spawn:new({phase=5}) +cp6_attacker = base_attacker_spawn:new({phase=6}) +cp7_attacker = base_attacker_spawn:new({phase=7}) +cp8_attacker = base_attacker_spawn:new({phase=8}) +cp1_defender = base_defender_spawn:new({phase=1}) +cp2_defender = base_defender_spawn:new({phase=2}) +cp3_defender = base_defender_spawn:new({phase=3}) +cp4_defender = base_defender_spawn:new({phase=4}) +cp5_defender = base_defender_spawn:new({phase=5}) +cp6_defender = base_defender_spawn:new({phase=6}) +cp7_defender = base_defender_spawn:new({phase=7}) +cp8_defender = base_defender_spawn:new({phase=8}) + +------------------------------------------------ +-- hud info +------------------------------------------------ +function flaginfo( player_entity ) + + local player = CastToPlayer( player_entity ) + + local flag = GetInfoScriptByName("cp"..phase.."_flag") + local flagname = flag:GetName() + + --RemoveHudItemFromAll( "background" ) + --AddHudIconToAll( "hud_statusbar_256_128.vtf", "background", -64, 32, 128, 70, 3 ) + + RemoveHudItem( player, "cp_flag_c" ) + RemoveHudItem( player, "cp_flag_d" ) + RemoveHudItem( player, "cp_flag_h" ) + RemoveHudItem( player, "flag_tobase_timer" ) + RemoveHudItem( player, "flag_tobase_text" ) + RemoveHudItem( player, "flag_return_timer" ) + RemoveHudItem( player, "flag_return_text" ) + RemoveHudItem( player, "flag_carried_by" ) + RemoveHudItem( player, "flag_carried_by2" ) + RemoveHudItem( player, "flag_athome" ) + RemoveHudItem( player, "flag_athome2" ) + + if attackers == Team.kBlue then + hudstatusicondropped = "hud_flag_dropped_blue.vtf" + hudstatusiconhome = "hud_flag_home_blue.vtf" + hudstatusiconcarried = "hud_flag_carried_blue.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kRed then + hudstatusicondropped = "hud_flag_dropped_red.vtf" + hudstatusiconhome = "hud_flag_home_red.vtf" + hudstatusiconcarried = "hud_flag_carried_red.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + elseif attackers == Team.kYellow then + hudstatusicondropped = "hud_flag_dropped_yellow.vtf" + hudstatusiconhome = "hud_flag_home_yellow.vtf" + hudstatusiconcarried = "hud_flag_carried_yellow.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kGreen then + hudstatusicondropped = "hud_flag_dropped_green.vtf" + hudstatusiconhome = "hud_flag_home_green.vtf" + hudstatusiconcarried = "hud_flag_carried_green.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + end + + flag_hudstatusiconx = 4 + flag_hudstatusicony = 42 + flag_hudstatusiconw = 15 + flag_hudstatusiconh = 15 + flag_hudstatusiconalign = 3 + text_hudstatusx = 0 + text_hudstatusy = flag_hudstatusicony + 24 + text_hudstatusalign = 4 + + local CPnumber = phase - 1 + + if _G[flagname].enabled == true then + if flag:IsCarried() then + AddHudText(player, "flag_carried_by", "#AD_FlagCarriedBy", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudText(player, "flag_carried_by2", carried_by, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + AddHudIcon(player, hudstatusiconcarried, ( "cp_flag_c" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif flag:IsDropped() and _G[flagname].status == 2 then + if CPnumber > 0 then + AddHudTextToAll("flag_return_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + else + AddHudTextToAll("flag_return_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + end + AddHudTimer(player, "flag_return_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign) + AddHudIcon(player, hudstatusicondropped, ( "cp_flag_d" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif _G[flagname].status == 0 then + AddHudText(player, "flag_athome", "#AD_FlagIsAt", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + if CPnumber > 0 then + AddHudText(player, "flag_athome2", "Capture Point "..CPnumber, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + else + AddHudText(player, "flag_athome2", "#AD_ASpawn", text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + end + AddHudIcon(player, hudstatusiconhome, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + else + if CPnumber > 0 then + AddHudText(player, "flag_tobase_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + else + AddHudText(player, "flag_tobase_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + end + AddHudTimer(player, "flag_tobase_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign) + AddHudIcon(player, hudstatusicontobase, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + + RemoveHudItem( player, "Zone_Team"..attackers ) + RemoveHudItem( player, "Zone_Team"..defenders ) + RemoveHudItem( player, "Zone_Phase"..attackers ) + RemoveHudItem( player, "Zone_Phase"..defenders ) + + od_hudstatusiconx = -28 + od_hudstatusicony = 38 + od_hudstatusiconw = 24 + od_hudstatusiconh = 24 + od_hudstatusiconalign = 3 + + if player:GetTeamId() == attackers then + AddHudIcon( player, "hud_offense.vtf", "Zone_Team"..attackers, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..attackers, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + else + AddHudIcon( player, "hud_defense.vtf", "Zone_Team"..defenders, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..defenders, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + end + +end + +function update_hud() + + local flag = GetInfoScriptByName("cp"..phase.."_flag") + local flagname = flag:GetName() + + --RemoveHudItemFromAll( "background" ) + --AddHudIconToAll( "hud_statusbar_256_128.vtf", "background", -64, 32, 128, 70, 3 ) + + RemoveHudItemFromAll( "cp_flag_c" ) + RemoveHudItemFromAll( "cp_flag_d" ) + RemoveHudItemFromAll( "cp_flag_h" ) + RemoveHudItemFromAll( "flag_tobase_timer" ) + RemoveHudItemFromAll( "flag_tobase_text" ) + RemoveHudItemFromAll( "flag_return_timer" ) + RemoveHudItemFromAll( "flag_return_text" ) + RemoveHudItemFromAll( "flag_carried_by" ) + RemoveHudItemFromAll( "flag_carried_by2" ) + RemoveHudItemFromAll( "flag_athome" ) + RemoveHudItemFromAll( "flag_athome2" ) + + if attackers == Team.kBlue then + hudstatusicondropped = "hud_flag_dropped_blue.vtf" + hudstatusiconhome = "hud_flag_home_blue.vtf" + hudstatusiconcarried = "hud_flag_carried_blue.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kRed then + hudstatusicondropped = "hud_flag_dropped_red.vtf" + hudstatusiconhome = "hud_flag_home_red.vtf" + hudstatusiconcarried = "hud_flag_carried_red.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + elseif attackers == Team.kYellow then + hudstatusicondropped = "hud_flag_dropped_yellow.vtf" + hudstatusiconhome = "hud_flag_home_yellow.vtf" + hudstatusiconcarried = "hud_flag_carried_yellow.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kGreen then + hudstatusicondropped = "hud_flag_dropped_green.vtf" + hudstatusiconhome = "hud_flag_home_green.vtf" + hudstatusiconcarried = "hud_flag_carried_green.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + end + + flag_hudstatusiconx = 4 + flag_hudstatusicony = 42 + flag_hudstatusiconw = 15 + flag_hudstatusiconh = 15 + flag_hudstatusiconalign = 3 + text_hudstatusx = 0 + text_hudstatusy = flag_hudstatusicony + 24 + text_hudstatusalign = 4 + + local CPnumber = phase - 1 + + if _G[flagname].enabled == true then + if flag:IsCarried() then + AddHudTextToAll("flag_carried_by", "#AD_FlagCarriedBy", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + AddHudTextToAll("flag_carried_by2", carried_by, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + AddHudIconToAll( hudstatusiconcarried, ( "cp_flag_c" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif flag:IsDropped() and _G[flagname].status == 2 then + if CPnumber > 0 then + AddHudTextToAll("flag_return_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + else + AddHudTextToAll("flag_return_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + end + AddHudTimerToAll("flag_return_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign) + AddHudIconToAll( hudstatusicondropped, ( "cp_flag_d" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif _G[flagname].status == 0 then + AddHudTextToAll("flag_athome", "#AD_FlagIsAt", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + if CPnumber > 0 then + AddHudTextToAll("flag_athome2", "Capture Point "..CPnumber, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + else + AddHudTextToAll("flag_athome2", "#AD_ASpawn", text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0) + end + AddHudIconToAll( hudstatusiconhome, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + else + if CPnumber > 0 then + AddHudTextToAll("flag_tobase_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + else + AddHudTextToAll("flag_tobase_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0) + end + AddHudTimerToAll("flag_tobase_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign) + AddHudIconToAll(hudstatusicontobase, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + + RemoveHudItemFromAll( "Zone_Team"..attackers ) + RemoveHudItemFromAll( "Zone_Team"..defenders ) + RemoveHudItemFromAll( "Zone_Phase"..attackers ) + RemoveHudItemFromAll( "Zone_Phase"..defenders ) + + od_hudstatusiconx = -28 + od_hudstatusicony = 38 + od_hudstatusiconw = 24 + od_hudstatusiconh = 24 + od_hudstatusiconalign = 3 + + AddHudIconToTeam( GetTeam(attackers), "hud_offense.vtf", "Zone_Team"..attackers, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIconToTeam( GetTeam(attackers), "hud_cp_"..phase..".vtf", "Zone_Phase"..attackers, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + + AddHudIconToTeam( GetTeam(defenders), "hud_defense.vtf", "Zone_Team"..defenders, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIconToTeam( GetTeam(defenders), "hud_cp_"..phase..".vtf", "Zone_Phase"..defenders, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + +end diff --git a/maps/includes/base_id_new.lua b/maps/includes/base_id_new.lua new file mode 100644 index 0000000..d0eef12 --- /dev/null +++ b/maps/includes/base_id_new.lua @@ -0,0 +1,1189 @@ + +-- base_id_new.lua +-- Invade / Defend gametype +-- New scoring system included +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay") + +----------------------------------------------------------------------------- +-- globals. Copy these your yourmap.lua if you want to change them. +----------------------------------------------------------------------------- +if NUM_PHASES == nil then NUM_PHASES = 4; end +if INITIAL_ROUND_DELAY == nil then INITIAL_ROUND_DELAY = 45; end +--How long it takes for the next flag to become available +if ROUND_DELAY == nil then ROUND_DELAY = 20; end +FLAG_RETURN_TIME = 60 +--A little pause before teams switch +TEAM_SWITCH_DELAY = 5 +--If true, all players will respawn when a flag is capped +if RESPAWN_AFTER_CAP == nil then RESPAWN_AFTER_CAP = false end +if RESPAWN_DELAY == nil then RESPAWN_DELAY = 2 end + +--Every cap has a time limit. The score for a capture decreases as time passes +if CAP_TIME_LIMIT == nil then CAP_TIME_LIMIT = 240 end +if SECONDS_PER_POINT == nil then SECONDS_PER_POINT = 12 end + +SECONDS_FOR_ONE_FULL_ROUND = INITIAL_ROUND_DELAY + TEAM_SWITCH_DELAY + ROUND_DELAY * (NUM_PHASES-1) + CAP_TIME_LIMIT * NUM_PHASES +--SECONDS_FOR_TWO_FULL_ROUNDS = (INITIAL_ROUND_DELAY + TEAM_SWITCH_DELAY + ROUND_DELAY * (NUM_PHASES-1) + CAP_TIME_LIMIT * NUM_PHASES) * 2 +--ConsoleToAll("SECONDS_FOR_ONE_FULL_ROUND = "..SECONDS_FOR_ONE_FULL_ROUND) +----------------------------------------------------------------------------- + +if ATTACKERS_OBJECTIVE_ENTITY == nil then ATTACKERS_OBJECTIVE_ENTITY = nil end +if DEFENDERS_OBJECTIVE_ENTITY == nil then DEFENDERS_OBJECTIVE_ENTITY = nil end +if DEFENDERS_OBJECTIVE_ONFLAG == nil then DEFENDERS_OBJECTIVE_ONFLAG = true end +if DEFENDERS_OBJECTIVE_ONCARRIER == nil then DEFENDERS_OBJECTIVE_ONCARRIER = true end +if onroundreset == nil then onroundreset = function() end end + +instantswitch = false + +--let players instantly change class before the gates open +function player_switchclass( player, oldclassid, newclassid ) + --avoids problems with joining a server + if oldclassid == 0 then return true end + if instantswitch and oldclassid ~= newclassid then + --add 16 to convert classes to AT flags + ApplyToPlayer( player, {newclassid+16} ) + + --The player gets full ammo/grenades on class switch! + if player:GetTeamId() == attackers then + player:RemoveAmmo( Ammo.kGren2, 4 ) + elseif player:GetTeamId() == defenders then + player:RemoveAmmo( Ammo.kDetpack, 1) + end + end + return true +end + +basecap = trigger_ff_script:new({ + health = 100, + armor = 300, + grenades = 200, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + detpacks = 1, + mancannons = 1, + gren1 = 0, + gren2 = 0, + item = "", + team = 0, + botgoaltype = Bot.kFlagCap, +}) + +function basecap:ontrigger ( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- player should capture now + for i,v in ipairs( self.item ) do + + -- find the flag and cast it to an info_ff_script + local flag = GetInfoScriptByName(v) + + -- Make sure flag isn't nil + if flag then + + -- check if the player is carrying the flag + if player:HasItem(flag:GetName()) then + + -- reward player for capture + player:AddFortPoints(FORTPOINTS_PER_CAPTURE, "#FF_FORTPOINTS_CAPTUREFLAG") + + -- Remove any hud icons + RemoveHudItem( player, flag:GetName() ) + RemoveHudItemFromAll( flag:GetName() .. "_c" ) + + LogLuaEvent(player:GetId(), 0, "flag_capture","flag_name",flag:GetName()) + + -- return the flag + flag:Return() + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then player:AddHealth(self.health) end + if self.armor ~= nil and self.armor ~= 0 then player:AddArmor(self.armor) end + + -- give the player some ammo + if self.nails ~= nil and self.nails ~= 0 then player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then player:AddAmmo(Ammo.kGren2, self.gren2) end + + self:oncapture( player, v ) + end + end + end + end +end + +function baseflag:spawn() + self.notouch = { } + info_ff_script.spawn(self) + local flag = CastToInfoScript( entity ) + LogLuaEvent(0, 0, "flag_spawn","flag_name",flag:GetName()) + + self.status = 0 + + update_hud() +end + +function baseflag:ownercloak( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + + RemoveHudItem( player, flag:GetName() ) + self.status = 2 + + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_return_timer() + update_hud() +end + +function baseflag:dropitemcmd( owner_entity ) + + if allowdrop == false then return end + + --Used by logging + self.flagtoss = true + + -- throw the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, FLAG_THROW_SPEED) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + + RemoveHudItem( player, flag:GetName() ) + self.status = 2 + + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_return_timer() + update_hud() +end + +function baseflag:onownerforcerespawn( owner_entity ) + local flag = CastToInfoScript( entity ) + local player = CastToPlayer( owner_entity ) + player:SetDisguisable( true ) + player:SetCloakable( true ) + RemoveHudItem( player, flag:GetName() ) + flag:Drop(0, FLAG_THROW_SPEED) + + self.status = 2 + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + update_hud() +end + +function baseflag:onreturn( ) + -- let the teams know that the flag was returned + local team = GetTeam( self.team ) + SmartTeamMessage(team, "#FF_TEAMRETURN", "#FF_OTHERTEAMRETURN", Color.kYellow, Color.kYellow) + SmartTeamSound(team, "yourteam.flagreturn", "otherteam.flagreturn") + SmartTeamSpeak(team, "CTF_FLAGBACK", "CTF_EFLAGBACK") + local flag = CastToInfoScript( entity ) + + self.status = 0 + + LogLuaEvent(0, 0, "flag_returned","flag_name",flag:GetName()); + + -- objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = flag end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + destroy_return_timer() + update_hud() +end + +phase = 1 +current_flag = "cp1_flag" +attackers = Team.kBlue +defenders = Team.kRed +current_timer = 0 +carried_by = nil +rounds_elapsed = 0 +cap_timeleft = 0 + +--This is the default startup script for id maps. If you use startup() in your map, call this and then do your own stuff before/after. +function id_startup() + + SetGameDescription( "Invade Defend" ) + + -- set up team limits + local team = GetTeam( Team.kBlue ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kRed ) + team:SetPlayerLimit( 0 ) + + team = GetTeam( Team.kYellow ) + team:SetPlayerLimit( -1 ) + + team = GetTeam( Team.kGreen ) + team:SetPlayerLimit( -1 ) + + redScore = 0 + blueScore = 0 + + --map will end after red gets to attack + roundnumber = 1 + lastround = false + --the original timelimit. If a server admin changes mp_timelimit, the script won't adjust to it. + timelimit = GetConvar( "mp_timelimit" ) + + -- CTF maps generally don't have civilians, + -- so override in map LUA file if you want 'em + local team = GetTeam(Team.kBlue) + team:SetClassLimit(Player.kCivilian, -1) + + team = GetTeam(Team.kRed) + team:SetClassLimit(Player.kCivilian, -1) + + -- set them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + cap_timeleft = 0 + + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + + cp1_flag.enabled = true + for i,v in ipairs({"cp1_flag", "cp2_flag", "cp3_flag", "cp4_flag", "cp5_flag", "cp6_flag", "cp7_flag", "cp8_flag"}) do + local flag = GetInfoScriptByName(v) + if flag then + flag:SetModel(_G[v].model) + flag:SetSkin(teamskins[attackers]) + if i == 1 then + flag:Restore() + else + flag:Remove() + end + end + end + + flags_set_team( attackers ) + + ATTACKERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_flag" ) + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) +end + +function startup() + id_startup() +end + +-- Give everyone a full resupply, but strip secondary grenades for offense +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + player:AddAmmo( Ammo.kManCannon, 1 ) + + if player:GetTeamId() == attackers then + UpdateObjectiveIcon( player, ATTACKERS_OBJECTIVE_ENTITY ) + player:RemoveAmmo( Ammo.kGren2, 4 ) + elseif player:GetTeamId() == defenders then + UpdateObjectiveIcon( player, DEFENDERS_OBJECTIVE_ENTITY ) + player:RemoveAmmo( Ammo.kDetpack, 1) + end +end + +function precache() + -- precache sounds + PrecacheSound("yourteam.flagstolen") + PrecacheSound("otherteam.flagstolen") + PrecacheSound("yourteam.flagcap") + PrecacheSound("otherteam.flagcap") + PrecacheSound("yourteam.drop") + PrecacheSound("otherteam.drop") + PrecacheSound("yourteam.flagreturn") + PrecacheSound("otherteam.flagreturn") +end + +-- kinda ghetto, sure +function flags_set_team( teamid ) + -- set all flags teams + cp1_flag.team = teamid + cp2_flag.team = teamid + cp3_flag.team = teamid + cp4_flag.team = teamid + cp5_flag.team = teamid + cp6_flag.team = teamid + cp7_flag.team = teamid + cp8_flag.team = teamid +end + +----------------------------------------- +--Backpacks +----------------------------------------- +idbackpack = genericbackpack:new({team = nil}) + +function idbackpack:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + + if player:GetTeamId() ~= self.team then + return false + end + + local dispensed = 0 + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then dispensed = dispensed + player:AddHealth( self.health ) end + if self.armor ~= nil and self.armor ~= 0 then dispensed = dispensed + player:AddArmor( self.armor ) end + + -- give player ammo + if self.nails ~= nil and self.nails ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren2, self.gren2) end + + -- if the player took ammo, then have the backpack respawn with a delay + if dispensed >= 1 then + local backpack = CastToInfoScript(entity); + if backpack then + backpack:EmitSound(self.touchsound); + backpack:Respawn(self.respawntime); + end + end + end +end + +--These bags will switch teams with the map. +backpack_attackers = idbackpack:new({team = attackers}) +backpack_defenders = idbackpack:new({team = defenders}) + + +----------------------------------------- +-- base flag +----------------------------------------- +base_id_flag = baseflag:new({ + phase = 1, + enabled = nil, + touchflags = { AllowFlags.kOnlyPlayers, AllowFlags.kBlue, AllowFlags.kRed }, + hudicon = BLUE_FLAG_HUD_ICON, +}) +function base_id_flag:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + -- pickup if they can + if self.notouch[player:GetId()] then return; end + + if player:GetTeamId() == attackers and phase == self.phase and self.enabled then + SmartSound(player, "yourteam.flagstolen", "yourteam.flagstolen", "otherteam.flagstolen") + RandomFlagTouchSpeak( player ) + SmartMessage(player, "#FF_YOUPICKUP", "#FF_TEAMPICKUP", "#FF_OTHERTEAMPICKUP", Color.kGreen, Color.kGreen, Color.kRed) + + local flag = CastToInfoScript(entity) + flag:Pickup(player) + player:SetDisguisable( false ) + -- if the player is a spy, then force him to lose his cloak + player:SetCloakable( false ) + + self.hudicon = team_hudicons[attackers] + + AddHudIcon( player, self.hudicon, flag:GetName(), self.hudx, self.hudy, self.hudstatusiconw, self.hudstatusiconh, self.hudalign ) + + -- log action in stats + LogLuaEvent(player:GetId(), 0, "flag_touch", "flag_name", flag:GetName(), "player_origin", (string.format("%0.2f",player:GetOrigin().x) .. ", " .. string.format("%0.2f",player:GetOrigin().y) .. ", " .. string.format("%0.1f",player:GetOrigin().z) ), "player_health", "" .. player:GetHealth()); + + -- change objective icons + ATTACKERS_OBJECTIVE_ENTITY = player + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..self.phase.."_cap" ) end + if DEFENDERS_OBJECTIVE_ONCARRIER then DEFENDERS_OBJECTIVE_ENTITY = player end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + UpdateObjectiveIcon( player, GetEntityByName( "cp"..self.phase.."_cap" ) ) + + carried_by = player:GetName() + destroy_return_timer() + update_hud() + end + end +end + +function base_id_flag:onownerdie( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, flag:GetName() ) + + player:SetDisguisable( true ) + player:SetCloakable( true ) + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = flag end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + UpdateObjectiveIcon( player, nil ) + + self.status = 2 + + setup_return_timer() + update_hud() +end + +----------------------------------------- +-- base capture point +----------------------------------------- +base_id_cap = basecap:new({ + phase = 0, +}) + +function base_id_cap:allowed ( touch_entity ) + if phase ~= self.phase then + return EVENT_DISALLOWED + end + + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + + if player:GetTeamId() == defenders then + BroadCastMessageToPlayer( player, "#AD_Defend" ) + else + for i,v in ipairs(self.item) do + if player:HasItem( v ) then + return EVENT_ALLOWED + end + end + end + end + + return EVENT_DISALLOWED +end + +function base_id_cap:oncapture(player, item) + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") + SmartMessage(player, "#FF_YOUCAP", "#FF_TEAMCAP", "#FF_OTHERTEAMCAP", Color.kGreen, Color.kGreen, Color.kRed) + + --Custom map effects. Put a logic_relay in the map, eg. "cp1_relay_blue" to trigger when there's a cap. + if attackers == Team.kBlue then + OutputEvent( "cp"..self.phase.."_relay_blue", "Trigger" ) + else + OutputEvent( "cp"..self.phase.."_relay_red", "Trigger" ) + end + + local flag_item = GetInfoScriptByName( item ) + RemoveHudItem( player, flag_item:GetName() ) + + -- turn off this flag + for i,v in ipairs(self.item) do + _G[v].enabled = nil + local flag = GetInfoScriptByName(v) + if flag then + flag:Remove() + end + end + + + + --Team gets points for time left on the clock. + local team = player:GetTeam() + team:AddScore(math.ceil(cap_timeleft / SECONDS_PER_POINT)) + if attackers == Team.kBlue then + blueScore = blueScore + (math.ceil(cap_timeleft / SECONDS_PER_POINT)) + else + redScore = redScore + (math.ceil(cap_timeleft / SECONDS_PER_POINT)) + end + + -- show on the deathnotice board + ObjectiveNotice( player, "captured point "..phase.." for "..(math.ceil(cap_timeleft / SECONDS_PER_POINT)).." points" ) + + RemoveSchedule("cap_timer_schedule") + RemoveSchedule("forceRoundEnd") + RemoveSchedule("forceRoundWarn300") + RemoveSchedule("forceRoundWarn120") + RemoveSchedule("forceRoundWarn30") + RemoveSchedule("forceRoundWarn10") + RemoveSchedule("forceRoundWarn9") + RemoveSchedule("forceRoundWarn8") + RemoveSchedule("forceRoundWarn7") + RemoveSchedule("forceRoundWarn6") + RemoveSchedule("forceRoundWarn5") + RemoveSchedule("forceRoundWarn4") + RemoveSchedule("forceRoundWarn3") + RemoveSchedule("forceRoundWarn2") + RemoveSchedule("forceRoundWarn1") + cap_timeleft = 0 + + if phase == NUM_PHASES then + -- it's the last phase. end and stuff + rounds_elapsed = rounds_elapsed + 1 + + SmartTeamSpeak(GetTeam(attackers), "CZ_GOTALL", "CZ_THEYGOTALL") + freezeAllPlayers() + + --End the map if it's time. + if attackers == Team.kRed and lastround == true then + AddSchedule("QuitSched", 4, QuitIt()) + else + AddSchedule("team_switch_delay", TEAM_SWITCH_DELAY, round_end) + end + else + SmartSpeak(player, "CTF_YOUCAP", "CTF_TEAMCAP", "CTF_THEYCAP") + phase = phase + 1 + if RESPAWN_AFTER_CAP then + AddSchedule("respawn_all", RESPAWN_DELAY, respawn_all) + end + + -- enable the next flag after a time + AddSchedule("flag_start", ROUND_DELAY, flag_start, self.next) + if ROUND_DELAY > 30 then AddSchedule("flag_30secwarn", ROUND_DELAY-30, flag_30secwarn) end + if ROUND_DELAY > 10 then AddSchedule("flag_10secwarn", ROUND_DELAY-10, flag_10secwarn) end + + current_flag = self.next + + -- clear objective icon + ATTACKERS_OBJECTIVE_ENTITY = nil + if DEFENDERS_OBJECTIVE_ONFLAG or DEFENDERS_OBJECTIVE_ONCARRIER then DEFENDERS_OBJECTIVE_ENTITY = nil + else DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + setup_tobase_timer() + update_hud() + end +end + +function respawn_all() + RespawnAllPlayers() +end + +function round_end() + + phase = 1 + + if attackers == Team.kBlue then + attackers = Team.kRed + defenders = Team.kBlue + else + roundnumber = roundnumber + 1 + attackers = Team.kBlue + defenders = Team.kRed + AddHudTextToAll("finalround_text", "ROUND "..roundnumber, 20, od_hudstatusicony+5, 3, 0, 2) + end + + --ten minutes until the time limit, call it quits + if (GetServerTime() > 60 * timelimit - 600) and lastround == false and attackers == Team.kBlue then + lastround = true + AddHudTextToAll("finalround_text", "FINAL ROUND", 20, od_hudstatusicony+5, 3, 0, 2) + --ConsoleToAll("declaring last round: "..(timelimit - GetServerTime()/60).." minutes left until original map limit") + end + + -- set all flag teams to new attackers + flags_set_team( attackers ) + + -- switch them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- respawn the players + RespawnAllPlayers() + setup_door_timer("start_gate", INITIAL_ROUND_DELAY) + + --Telling players what's up + SmartTeamMessage(GetTeam(defenders), "You are now on defense. Move to command point 1", "You are now on Offense. When the gates open, attack!") + SmartTeamSpeak(GetTeam(attackers), "AD_ATTACK", "AD_DEFEND") + + if blueScore > redScore then + AddSchedule("WinningSpeak", 3, SmartTeamSpeak, GetTeam(Team.kBlue), "WINNING_YOURTEAM", "WINNING_ENEMYTEAM") + elseif redScore > blueScore then + AddSchedule("WinningSpeak", 3, SmartTeamSpeak, GetTeam(Team.kRed), "WINNING_YOURTEAM", "WINNING_ENEMYTEAM") + end + + current_flag = "cp1_flag" + + -- enable the first flag + cp1_flag.enabled = true + cp1_flag.status = 0 + local flag = GetInfoScriptByName("cp1_flag") + if flag then + flag:Restore() + flag:SetSkin(teamskins[attackers]) + end + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + DEFENDERS_OBJECTIVE_ENTITY = GetEntityByName( "cp"..phase.."_cap" ) + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + + update_hud() + + -- run custom round reset stuff + onroundreset() +end + +function setup_door_timer(doorname, duration) + CloseDoor(doorname) + AddSchedule("round_start", duration, round_start, doorname) + AddSchedule("round_30secwarn", duration-30, round_30secwarn) + AddSchedule("round_10secwarn", duration-10, round_10secwarn) + AddSchedule("round_5secwarn", duration-5, round_5secwarn) + AddSchedule("round_4secwarn", duration-4, round_4secwarn) + AddSchedule("round_3secwarn", duration-3, round_3secwarn) + AddSchedule("round_2secwarn", duration-2, round_2secwarn) + AddSchedule("round_1secwarn", duration-1, round_1secwarn) + --This overrides the schedules from the previous round + --Which should be over anyway, but don't fix what ain't broke, right? + AddSchedule("forceRoundEnd", CAP_TIME_LIMIT+duration, forceRoundEnd) + --Don't do vox as the gate opens becasue there's already an anouncement + if CAP_TIME_LIMIT >= 305 then AddSchedule("forceRoundWarn300", CAP_TIME_LIMIT+duration-300, forceRoundWarn300) end + if CAP_TIME_LIMIT >= 125 then AddSchedule("forceRoundWarn120", CAP_TIME_LIMIT+duration-120, forceRoundWarn120) end + AddSchedule("forceRoundWarn30", CAP_TIME_LIMIT+duration-30, forceRoundWarn30) + AddSchedule("forceRoundWarn10", CAP_TIME_LIMIT+duration-10, forceRoundWarn10) + AddSchedule("forceRoundWarn9", CAP_TIME_LIMIT+duration-9, forceRoundWarn9) + AddSchedule("forceRoundWarn8", CAP_TIME_LIMIT+duration-8, forceRoundWarn8) + AddSchedule("forceRoundWarn7", CAP_TIME_LIMIT+duration-7, forceRoundWarn7) + AddSchedule("forceRoundWarn6", CAP_TIME_LIMIT+duration-6, forceRoundWarn6) + AddSchedule("forceRoundWarn5", CAP_TIME_LIMIT+duration-5, forceRoundWarn5) + AddSchedule("forceRoundWarn4", CAP_TIME_LIMIT+duration-4, forceRoundWarn4) + AddSchedule("forceRoundWarn3", CAP_TIME_LIMIT+duration-3, forceRoundWarn3) + AddSchedule("forceRoundWarn2", CAP_TIME_LIMIT+duration-2, forceRoundWarn2) + AddSchedule("forceRoundWarn1", CAP_TIME_LIMIT+duration-1, forceRoundWarn1) + + instantswitch = true + + --Put more time on the clock if needed + if (60 * GetConvar( "mp_timelimit" ) - GetServerTime() - 4) < SECONDS_FOR_ONE_FULL_ROUND then + set_cvar("mp_timelimit", (GetServerTime() + SECONDS_FOR_ONE_FULL_ROUND)/60) + --ConsoleToAll("setting mp_timelimit: "..(GetServerTime() + SECONDS_FOR_ONE_FULL_ROUND/)60) + end +end + +function round_start(doorname) + cap_timeleft = CAP_TIME_LIMIT + AddScheduleRepeating( "cap_timer_schedule", 1, cap_timer_schedule) + BroadCastMessage("#FF_AD_GATESOPEN") + SpeakAll("AD_GATESOPEN") + OpenDoor(doorname) + update_hud() + instantswitch = false +end + +function cap_timer_schedule() + cap_timeleft = cap_timeleft - 1 + if cap_timeleft < 0 then cap_timeleft = 0 end +end + +function freezeAllPlayers() + local col = Collection() + col:GetByFilter( { CF.kPlayers, CF.kTeamBlue } ) + for temp in col.items do + local player = CastToPlayer( temp ) + if player then + player:Freeze(true) + end + end + col:GetByFilter( { CF.kPlayers, CF.kTeamRed } ) + for temp in col.items do + local player = CastToPlayer( temp ) + if player then + player:Freeze(true) + end + end +end + +function forceRoundEnd() + freezeAllPlayers() + + BroadCastMessage("#ADZ_Switch") + SpeakAll("CZ_POINTSRESET") + RemoveSchedule("cap_timer_schedule") + cap_timeleft = 0 + + rounds_elapsed = rounds_elapsed + 1 + + --These relays fire if the round times out + if attackers == Team.kBlue then + OutputEvent("timeout_relay_blue", "Trigger") + else + OutputEvent("timeout_relay_red", "Trigger") + end + + --cancel any flag action + local flag = GetInfoScriptByName(current_flag) + if flag then + flag:Remove() + end + RemoveHudItemFromAll(current_flag) + update_hud() + + --End the map if it's time + if attackers == Team.kRed and lastround == true then + AddSchedule("QuitSched", 4, QuitIt()) + else + AddSchedule("team_switch_delay", TEAM_SWITCH_DELAY, round_end) + end +end + +function QuitIt() + GoToIntermission() + if blueScore > redScore then + AddSchedule("WinSpeak", 1, SpeakAll, "WIN_BLUE") + elseif redScore > blueScore then + AddSchedule("WinSpeak", 1, SpeakAll, "WIN_RED") + end +end + +function forceRoundWarn300() + BroadCastMessage("#ADZ_Switch5Min") + SpeakAll("AD_300SEC") +end +function forceRoundWarn120() + BroadCastMessage("#ADZ_Switch2Min") + SpeakAll("AD_120SEC") +end +function forceRoundWarn30() + BroadCastMessage("#ADZ_Switch30Sec") + SpeakAll("AD_30SEC") +end +function forceRoundWarn10() + BroadCastMessage("#ADZ_Switch10Sec") + SpeakAll("AD_10SEC") +end +function forceRoundWarn9() + BroadCastMessage("9") + SpeakAll("AD_9SEC") +end +function forceRoundWarn8() + BroadCastMessage("8") + SpeakAll("AD_8SEC") +end +function forceRoundWarn7() + BroadCastMessage("7") + SpeakAll("AD_7SEC") +end +function forceRoundWarn6() + BroadCastMessage("6") + SpeakAll("AD_6SEC") +end +function forceRoundWarn5() + BroadCastMessage("5") + SpeakAll("AD_5SEC") +end +function forceRoundWarn4() + BroadCastMessage("4") + SpeakAll("AD_4SEC") +end +function forceRoundWarn3() + BroadCastMessage("3") + SpeakAll("AD_3SEC") +end +function forceRoundWarn2() + BroadCastMessage("2") + SpeakAll("AD_2SEC") +end +function forceRoundWarn1() + BroadCastMessage("1") + SpeakAll("AD_1SEC") +end + + +function round_30secwarn() + BroadCastMessage("#FF_ROUND_30SECWARN") +end +function round_10secwarn() + BroadCastMessage("#FF_ROUND_10SECWARN") +end +function round_5secwarn() + BroadCastMessage("5") + SpeakAll("AD_5SEC") +end +function round_4secwarn() + BroadCastMessage("4") + SpeakAll("AD_4SEC") +end +function round_3secwarn() + BroadCastMessage("3") + SpeakAll("AD_3SEC") +end +function round_2secwarn() + BroadCastMessage("2") + SpeakAll("AD_2SEC") +end +function round_1secwarn() + BroadCastMessage("1") + SpeakAll("AD_1SEC") +end + + +function flag_start(flagname) + BroadCastMessage("#AD_FlagAtBase") + _G[flagname].enabled = true + _G[flagname].status = 0 + local flag = GetInfoScriptByName(flagname) + if flag then + flag:Restore() + flag:SetSkin(teamskins[attackers]) + end + + --reset the cap timer + cap_timeleft = CAP_TIME_LIMIT + AddScheduleRepeating( "cap_timer_schedule", 1, cap_timer_schedule) + + AddSchedule("forceRoundEnd", CAP_TIME_LIMIT, forceRoundEnd) + if CAP_TIME_LIMIT >= 300 then AddSchedule("forceRoundWarn300", CAP_TIME_LIMIT-300, forceRoundWarn300) end + if CAP_TIME_LIMIT >= 120 then AddSchedule("forceRoundWarn120", CAP_TIME_LIMIT-120, forceRoundWarn120) end + AddSchedule("forceRoundWarn30", CAP_TIME_LIMIT-30, forceRoundWarn30) + AddSchedule("forceRoundWarn10", CAP_TIME_LIMIT-10, forceRoundWarn10) + AddSchedule("forceRoundWarn9", CAP_TIME_LIMIT-9, forceRoundWarn9) + AddSchedule("forceRoundWarn8", CAP_TIME_LIMIT-8, forceRoundWarn8) + AddSchedule("forceRoundWarn7", CAP_TIME_LIMIT-7, forceRoundWarn7) + AddSchedule("forceRoundWarn6", CAP_TIME_LIMIT-6, forceRoundWarn6) + AddSchedule("forceRoundWarn5", CAP_TIME_LIMIT-5, forceRoundWarn5) + AddSchedule("forceRoundWarn4", CAP_TIME_LIMIT-4, forceRoundWarn4) + AddSchedule("forceRoundWarn3", CAP_TIME_LIMIT-3, forceRoundWarn3) + AddSchedule("forceRoundWarn2", CAP_TIME_LIMIT-2, forceRoundWarn2) + AddSchedule("forceRoundWarn1", CAP_TIME_LIMIT-1, forceRoundWarn1) + + + -- change objective icon + ATTACKERS_OBJECTIVE_ENTITY = flag + if DEFENDERS_OBJECTIVE_ONFLAG then DEFENDERS_OBJECTIVE_ENTITY = flag end + UpdateTeamObjectiveIcon( GetTeam(attackers), ATTACKERS_OBJECTIVE_ENTITY ) + UpdateTeamObjectiveIcon( GetTeam(defenders), DEFENDERS_OBJECTIVE_ENTITY ) + update_hud() +end +function flag_30secwarn() BroadCastMessage("#AD_30SecReturn") end +function flag_10secwarn() BroadCastMessage("#AD_10SecReturn") end + + +function timer_schedule() + current_timer = current_timer -1 +end + +function setup_return_timer() + RemoveSchedule( "timer_tobase_schedule" ) + current_timer = FLAG_RETURN_TIME + + AddScheduleRepeatingNotInfinitely( "timer_return_schedule", 1, timer_schedule, current_timer) +end + +function destroy_return_timer() + RemoveSchedule( "timer_return_schedule" ) +end + +function setup_tobase_timer() + RemoveSchedule( "timer_return_schedule" ) + current_timer = ROUND_DELAY + + AddScheduleRepeatingNotInfinitely( "timer_tobase_schedule", 1, timer_schedule, current_timer) +end + +function destroy_tobase_timer() + RemoveSchedule( "timer_tobase_schedule" ) +end + +------------------------------------------------ +-- instanciate them +------------------------------------------------ +cp1_flag = base_id_flag:new({phase = 1}) +cp2_flag = base_id_flag:new({phase = 2}) +cp3_flag = base_id_flag:new({phase = 3}) +cp4_flag = base_id_flag:new({phase = 4}) +cp5_flag = base_id_flag:new({phase = 5}) +cp6_flag = base_id_flag:new({phase = 6}) +cp7_flag = base_id_flag:new({phase = 7}) +cp8_flag = base_id_flag:new({phase = 8}) +cp1_cap = base_id_cap:new({phase = 1, item = {"cp1_flag"}, next = "cp2_flag"}) +cp2_cap = base_id_cap:new({phase = 2, item = {"cp2_flag"}, next = "cp3_flag"}) +cp3_cap = base_id_cap:new({phase = 3, item = {"cp3_flag"}, next = "cp4_flag"}) +cp4_cap = base_id_cap:new({phase = 4, item = {"cp4_flag"}, next = "cp5_flag"}) +cp5_cap = base_id_cap:new({phase = 5, item = {"cp5_flag"}, next = "cp6_flag"}) +cp6_cap = base_id_cap:new({phase = 6, item = {"cp6_flag"}, next = "cp7_flag"}) +cp7_cap = base_id_cap:new({phase = 7, item = {"cp7_flag"}, next = "cp8_flag"}) +cp8_cap = base_id_cap:new({phase = 8, item = {"cp8_flag"}, next = nil}) + +base_attacker_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player) + return player:GetTeamId() == attackers and phase == self.phase +end }) +base_defender_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player) + return player:GetTeamId() == defenders and phase == self.phase +end }) +cp1_attacker = base_attacker_spawn:new({phase=1}) +cp2_attacker = base_attacker_spawn:new({phase=2}) +cp3_attacker = base_attacker_spawn:new({phase=3}) +cp4_attacker = base_attacker_spawn:new({phase=4}) +cp5_attacker = base_attacker_spawn:new({phase=5}) +cp6_attacker = base_attacker_spawn:new({phase=6}) +cp7_attacker = base_attacker_spawn:new({phase=7}) +cp8_attacker = base_attacker_spawn:new({phase=8}) +cp1_defender = base_defender_spawn:new({phase=1}) +cp2_defender = base_defender_spawn:new({phase=2}) +cp3_defender = base_defender_spawn:new({phase=3}) +cp4_defender = base_defender_spawn:new({phase=4}) +cp5_defender = base_defender_spawn:new({phase=5}) +cp6_defender = base_defender_spawn:new({phase=6}) +cp7_defender = base_defender_spawn:new({phase=7}) +cp8_defender = base_defender_spawn:new({phase=8}) + +------------------------------------------------ +-- hud info +------------------------------------------------ +function flaginfo( player_entity ) + + local player = CastToPlayer( player_entity ) + + local flag = GetInfoScriptByName("cp"..phase.."_flag") + local flagname = flag:GetName() + + RemoveHudItem( player, "cp_flag_c" ) + RemoveHudItem( player, "cp_flag_d" ) + RemoveHudItem( player, "cp_flag_h" ) + RemoveHudItem( player, "flag_tobase_timer" ) + RemoveHudItem( player, "flag_tobase_text" ) + RemoveHudItem( player, "flag_return_timer" ) + RemoveHudItem( player, "flag_return_text" ) + RemoveHudItem( player, "flag_carried_by" ) + RemoveHudItem( player, "flag_carried_by2" ) + RemoveHudItem( player, "flag_athome" ) + RemoveHudItem( player, "flag_athome2" ) + + if attackers == Team.kBlue then + hudstatusicondropped = "hud_flag_dropped_blue.vtf" + hudstatusiconhome = "hud_flag_home_blue.vtf" + hudstatusiconcarried = "hud_flag_carried_blue.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kRed then + hudstatusicondropped = "hud_flag_dropped_red.vtf" + hudstatusiconhome = "hud_flag_home_red.vtf" + hudstatusiconcarried = "hud_flag_carried_red.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + elseif attackers == Team.kYellow then + hudstatusicondropped = "hud_flag_dropped_yellow.vtf" + hudstatusiconhome = "hud_flag_home_yellow.vtf" + hudstatusiconcarried = "hud_flag_carried_yellow.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kGreen then + hudstatusicondropped = "hud_flag_dropped_green.vtf" + hudstatusiconhome = "hud_flag_home_green.vtf" + hudstatusiconcarried = "hud_flag_carried_green.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + end + + flag_hudstatusiconx = 4 + flag_hudstatusicony = 42 + flag_hudstatusiconw = 15 + flag_hudstatusiconh = 15 + flag_hudstatusiconalign = 3 + text_hudstatusx = 0 + text_hudstatusy = flag_hudstatusicony + 24 + text_hudstatusalign = 4 + + local CPnumber = phase - 1 + + if _G[flagname].enabled == true then + if flag:IsCarried() then + AddHudText(player, "flag_carried_by", "#AD_FlagCarriedBy", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + AddHudText(player, "flag_carried_by2", carried_by, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 2) + AddHudIcon(player, hudstatusiconcarried, ( "cp_flag_c" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif flag:IsDropped() and _G[flagname].status == 2 then + if CPnumber > 0 then + AddHudTextToAll("flag_return_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + else + AddHudTextToAll("flag_return_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + end + AddHudTimer(player, "flag_return_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 3) + AddHudIcon(player, hudstatusicondropped, ( "cp_flag_d" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif _G[flagname].status == 0 then + AddHudText(player, "flag_athome", "#AD_FlagIsAt", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + if CPnumber > 0 then + AddHudText(player, "flag_athome2", "Capture Point "..CPnumber, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 2) + else + AddHudText(player, "flag_athome2", "#AD_ASpawn", text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 2) + end + AddHudIcon(player, hudstatusiconhome, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + else + if CPnumber > 0 then + AddHudText(player, "flag_tobase_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + else + AddHudText(player, "flag_tobase_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + end + AddHudTimer(player, "flag_tobase_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 3) + AddHudIcon(player, hudstatusicontobase, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + + RemoveHudItem( player, "Zone_Team"..attackers ) + RemoveHudItem( player, "Zone_Team"..defenders ) + RemoveHudItem( player, "Zone_Phase"..attackers ) + RemoveHudItem( player, "Zone_Phase"..defenders ) + + od_hudstatusiconx = -28 + od_hudstatusicony = 38 + od_hudstatusiconw = 24 + od_hudstatusiconh = 24 + od_hudstatusiconalign = 3 + + RemoveHudItem(player, "cap_timer") + RemoveHudItem(player, "cap_timer_text") + if cap_timeleft > 0 then + AddHudText(player, "cap_timer_text", "Time left", 40, od_hudstatusicony, 2, 0, 2) + AddHudTimer(player, "cap_timer", cap_timeleft, -1, 40, od_hudstatusicony+10, 2, 0, 3) + end + + if lastround == true then AddHudText(player, "finalround_text", "FINAL ROUND", 20, od_hudstatusicony+5, 3, 0, 2) + else AddHudText(player, "finalround_text", "ROUND "..roundnumber, 20, od_hudstatusicony+5, 3, 0, 2) + end + + if player:GetTeamId() == attackers then + AddHudIcon( player, "hud_offense.vtf", "Zone_Team"..attackers, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..attackers, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + else + AddHudIcon( player, "hud_defense.vtf", "Zone_Team"..defenders, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIcon( player, "hud_cp_"..phase..".vtf", "Zone_Phase"..defenders, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + end + +end + +function update_hud() + + local flag = GetInfoScriptByName("cp"..phase.."_flag") + local flagname = flag:GetName() + + RemoveHudItemFromAll( "cp_flag_c" ) + RemoveHudItemFromAll( "cp_flag_d" ) + RemoveHudItemFromAll( "cp_flag_h" ) + RemoveHudItemFromAll( "flag_tobase_timer" ) + RemoveHudItemFromAll( "flag_tobase_text" ) + RemoveHudItemFromAll( "flag_return_timer" ) + RemoveHudItemFromAll( "flag_return_text" ) + RemoveHudItemFromAll( "flag_carried_by" ) + RemoveHudItemFromAll( "flag_carried_by2" ) + RemoveHudItemFromAll( "flag_athome" ) + RemoveHudItemFromAll( "flag_athome2" ) + + if attackers == Team.kBlue then + hudstatusicondropped = "hud_flag_dropped_blue.vtf" + hudstatusiconhome = "hud_flag_home_blue.vtf" + hudstatusiconcarried = "hud_flag_carried_blue.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kRed then + hudstatusicondropped = "hud_flag_dropped_red.vtf" + hudstatusiconhome = "hud_flag_home_red.vtf" + hudstatusiconcarried = "hud_flag_carried_red.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + elseif attackers == Team.kYellow then + hudstatusicondropped = "hud_flag_dropped_yellow.vtf" + hudstatusiconhome = "hud_flag_home_yellow.vtf" + hudstatusiconcarried = "hud_flag_carried_yellow.vtf" + hudstatusicontobase = "hud_flag_home_l.vtf" + elseif attackers == Team.kGreen then + hudstatusicondropped = "hud_flag_dropped_green.vtf" + hudstatusiconhome = "hud_flag_home_green.vtf" + hudstatusiconcarried = "hud_flag_carried_green.vtf" + hudstatusicontobase = "hud_flag_home_r.vtf" + end + + flag_hudstatusiconx = 4 + flag_hudstatusicony = 42 + flag_hudstatusiconw = 15 + flag_hudstatusiconh = 15 + flag_hudstatusiconalign = 3 + text_hudstatusx = 0 + text_hudstatusy = flag_hudstatusicony + 24 + text_hudstatusalign = 4 + + local CPnumber = phase - 1 + + if _G[flagname].enabled == true then + if flag:IsCarried() then + AddHudTextToAll("flag_carried_by", "#AD_FlagCarriedBy", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + AddHudTextToAll("flag_carried_by2", carried_by, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 2) + AddHudIconToAll( hudstatusiconcarried, ( "cp_flag_c" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif flag:IsDropped() and _G[flagname].status == 2 then + if CPnumber > 0 then + AddHudTextToAll("flag_return_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + else + AddHudTextToAll("flag_return_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + end + AddHudTimerToAll("flag_return_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 3) + AddHudIconToAll( hudstatusicondropped, ( "cp_flag_d" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + elseif _G[flagname].status == 0 then + AddHudTextToAll("flag_athome", "#AD_FlagIsAt", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + if CPnumber > 0 then + AddHudTextToAll("flag_athome2", "Capture Point "..CPnumber, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 2) + else + AddHudTextToAll("flag_athome2", "#AD_ASpawn", text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 2) + end + AddHudIconToAll( hudstatusiconhome, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + else + if CPnumber > 0 then + AddHudTextToAll("flag_tobase_text", "Flag will return to CP"..CPnumber.." in", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + else + AddHudTextToAll("flag_tobase_text", "#AD_FlagReturnBase", text_hudstatusx, text_hudstatusy, text_hudstatusalign, 0, 2) + end + AddHudTimerToAll("flag_tobase_timer", current_timer + 1, -1, text_hudstatusx, text_hudstatusy+8, text_hudstatusalign, 0, 3) + AddHudIconToAll(hudstatusicontobase, ( "cp_flag_h" ), flag_hudstatusiconx, flag_hudstatusicony, flag_hudstatusiconw, flag_hudstatusiconh, flag_hudstatusiconalign ) + end + + + RemoveHudItemFromAll( "Zone_Team"..attackers ) + RemoveHudItemFromAll( "Zone_Team"..defenders ) + RemoveHudItemFromAll( "Zone_Phase"..attackers ) + RemoveHudItemFromAll( "Zone_Phase"..defenders ) + + od_hudstatusiconx = -28 + od_hudstatusicony = 38 + od_hudstatusiconw = 24 + od_hudstatusiconh = 24 + od_hudstatusiconalign = 3 + + RemoveHudItemFromAll("cap_timer") + RemoveHudItemFromAll("cap_timer_text") + if cap_timeleft > 0 then + AddHudTextToAll("cap_timer_text", "Time left", 40, od_hudstatusicony, 2, 0, 2) + AddHudTimerToAll("cap_timer", cap_timeleft, -1, 40, od_hudstatusicony+10, 2, 0, 3) + end + + AddHudIconToTeam( GetTeam(attackers), "hud_offense.vtf", "Zone_Team"..attackers, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIconToTeam( GetTeam(attackers), "hud_cp_"..phase..".vtf", "Zone_Phase"..attackers, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + + AddHudIconToTeam( GetTeam(defenders), "hud_defense.vtf", "Zone_Team"..defenders, od_hudstatusiconx, od_hudstatusicony, od_hudstatusiconw, od_hudstatusiconh, od_hudstatusiconalign ) + AddHudIconToTeam( GetTeam(defenders), "hud_cp_"..phase..".vtf", "Zone_Phase"..defenders, od_hudstatusiconx + 2, od_hudstatusicony + 2, 20, 20, od_hudstatusiconalign ) + +end \ No newline at end of file diff --git a/maps/includes/base_idzone.lua b/maps/includes/base_idzone.lua new file mode 100644 index 0000000..e0ab1d5 --- /dev/null +++ b/maps/includes/base_idzone.lua @@ -0,0 +1,898 @@ + +-- base_idzone.lua +-- Invade / Defend the Zone gametype + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay") + +----------------------------------------------------------------------------- +-- global overrides that you can do what you want with +----------------------------------------------------------------------------- + +FORT_POINTS_PER_INITIAL_TOUCH = 200 +FORT_POINTS_PER_PERIOD = 50 +FORT_POINTS_PER_DEFEND = 100 + +POINTS_PER_INITIAL_TOUCH = 1 +POINTS_PER_PERIOD = 1 + +DELAY_BEFORE_PERIOD_POINTS = 2 +PERIOD_TIME = 1 +INITIAL_ROUND_PERIOD = 60 +ROUND_SETUP_PERIOD = 17 + +DEFENSE_PERIOD_TIME = 60 +POINTS_PER_DEFENSE_PERIOD = 1 + +DEFAULT_POINTS_TO_CAP = 10 +NUMBER_OF_CAP_POINTS = 3 +DELAY_BEFORE_TEAMSWITCH = 2 +DELAY_AFTER_CAP = 3 + +ZONE_COLOR = "blue" + +----------------------------------------------------------------------------- +-- global variables and other shit that shouldn't be messed with +----------------------------------------------------------------------------- + +phase = 1 +zone_points = 0 +zone_max_points = DEFAULT_POINTS_TO_CAP +zone_scoring = false +draw_hud = true + +attackers = Team.kBlue +defenders = Team.kRed + +scoring_team = Team.kRed + +local teamdata = { + [Team.kBlue] = { skin = "0", beamcolour = "0 0 255" }, + [Team.kRed] = { skin = "1", beamcolour = "255 0 0" } +} + +-- stores ID's of attackers in the cap room +local zone_collection = Collection() + +-- stores if the player has touched the cap point (for 1 touch per death) +local playerTouchedTable = {} + +----------------------------------------------------------------------------- +-- functions that do sh... stuff +----------------------------------------------------------------------------- + +-- sounds, right? +function precache() + PrecacheSound("otherteam.flagstolen") -- doors open sound + PrecacheSound("otherteam.drop") -- warning sound + PrecacheSound("yourteam.flagreturn") -- scoring sound + PrecacheSound("misc.bloop") -- minutes remaining + PrecacheSound("misc.doop") -- attackers capping sound +end + +-- pretty standard setup, aside from scoring starting +function startup() + SetGameDescription( "Invade Defend the Zone" ) + + -- set up team limits on each team + SetPlayerLimit( Team.kBlue, 0 ) + SetPlayerLimit( Team.kRed, 0 ) + SetPlayerLimit( Team.kYellow, -1 ) + SetPlayerLimit( Team.kGreen, -1 ) + + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- Making the game not suck. + local team = GetTeam(attackers) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kSniper, 1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) + + + team = GetTeam(defenders) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, -1) + team:SetClassLimit(Player.kMedic, -1) + team:SetClassLimit(Player.kSniper, 1) + team:SetClassLimit(Player.kEngineer, 2) + team:SetClassLimit(Player.kDemoman, 2) + team:SetClassLimit(Player.kHwguy, 2) + team:SetClassLimit(Player.kPyro, 2) + + + AddSchedule( "round_start", INITIAL_ROUND_PERIOD, round_start) + if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_30SecWarning" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_10SecWarning" ) end + + -- sounds + if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_PERIOD - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_PERIOD - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_PERIOD - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_PERIOD - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_PERIOD - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_PERIOD - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_PERIOD - 1 , schedulecountdown, 1 ) end + + zone_max_points = zone1.pointstocap + + -- calculate defense period points + local total_points_to_reset = 1 + for i=1,NUMBER_OF_CAP_POINTS do + local t_points = getfield("zone"..i..".pointstocap") + total_points_to_reset = total_points_to_reset + t_points + end + local timelimit = GetConvar( "mp_timelimit" ) + -- convert mp_timelimit from minutes to seconds and divide by the number of rounds minus initial round period + POINTS_PER_DEFENSE_PERIOD = total_points_to_reset / (timelimit / (DEFENSE_PERIOD_TIME / 60)) + POINTS_PER_DEFENSE_PERIOD = math.ceil(POINTS_PER_DEFENSE_PERIOD) + + update_zone_all( ) + AddScheduleRepeating( "period_scoring_sched", PERIOD_TIME, period_scoring ) + AddScheduleRepeating( "defense_period_scoring_sched", DEFENSE_PERIOD_TIME, defenders_scoring ) +end + +----------------------------------------------------------------------------- +-- player_ functions +----------------------------------------------------------------------------- + +-- on player spawn +function player_spawn( player_entity ) + + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:RemoveAmmo( Ammo.kManCannon, 1 ) + + player:SetCloakable( true ) + player:SetDisguisable( true ) + + update_zone_player( player ) + + -- give demo 1 mirv, and only 1 mirv + if player:GetClass() == Player.kDemoman or player:GetClass() == Player.kEngineer then + player:RemoveAmmo( Ammo.kGren2, 4 ) + player:AddAmmo( Ammo.kGren2, 1 ) + end + + if player:GetTeamId() == attackers then + local attackers_objective = GetEntityByName( "zone"..phase ) + UpdateObjectiveIcon( player, attackers_objective ) + else + UpdateObjectiveIcon( player, nil ) + player:RemoveAmmo( Ammo.kDetpack, 1 ) + end + + -- wtf, scout or med on d? are you mental? + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + local classt = "Scout" + if player:GetClass() == Player.kMedic then classt = "Medic" end + local id = player:GetId() + AddSchedule("force_changemessage"..id, 2, schedulechangemessage, player, "No "..classt.."s on defense. Autoswitching to Soldier." ) + AddSchedule("force_change"..id, 2, forcechange, player) + end + + -- remove any players not on a team from playertouchedtable + for playerx, recordx in pairs(playerTouchedTable) do + if GetPlayerByID( playerx ) then + local playert = GetPlayerByID( playerx ) + if ( playert:GetTeamId() ~= attackers ) then + playerTouchedTable[playerx] = nil + end + end + end + + if player:GetTeamId() ~= attackers then return end + + -- add to table and reset touched to 0 + playerTouchedTable[player:GetId()] = {touched = false, allowed = true} + +end + +-- needed so that people who switch team are removed from the cap room collection properly. +function player_switchteam ( player, oldteam, newteam ) + if oldteam == attackers then + base_zone_trigger:onendtouch( player ) + end + + return true +end + +-- on player killed +function player_killed ( player, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + -- Entity that is attacking + local attacker = damageinfo:GetAttacker() + + -- If no attacker do nothing + if not attacker then return end + + local player_attacker = nil + + -- get the attacking player + if IsPlayer(attacker) then + attacker = CastToPlayer(attacker) + player_attacker = attacker + elseif IsSentrygun(attacker) then + attacker = CastToSentrygun(attacker) + player_attacker = attacker:GetOwner() + elseif IsDetpack(attacker) then + attacker = CastToDetpack(attacker) + player_attacker = attacker:GetOwner() + elseif IsDispenser(attacker) then + attacker = CastToDispenser(attacker) + player_attacker = attacker:GetOwner() + else + return + end + + -- if still no attacking player after all that, forget about it + if not player_attacker then return end + + -- If player killed self or teammate do nothing + if (player:GetId() == player_attacker:GetId()) or (player:GetTeamId() == player_attacker:GetTeamId()) then + return + end + + -- If player is an attacker, then do stuff + if player:GetTeamId() == attackers then + -- Check if he's in the cap point + for playerx in zone_collection.items do + playerx = CastToPlayer(playerx) + + if playerx:GetId() == player:GetId() then + player_attacker:AddFortPoints( FORT_POINTS_PER_DEFEND, "Defending the Point" ) + + -- for safety, remove player from collection + zone_collection:RemoveItem( player ) + -- also for safety, if no more players, reset the cap + if zone_collection:Count() == 0 then + update_zone_all( ) + zone_turnoff( phase ) + end + + return + end + end + + end + +end + +function player_ondamage ( player, damageinfo ) + + -- if no damageinfo do nothing + if not damageinfo then return end + + -- Get Damage Force + local damage = damageinfo:GetDamage() + + -- Entity that is attacking + local attacker = damageinfo:GetAttacker() + + -- If no attacker do nothing + if not attacker then return end + + local player_attacker = nil + + -- get the attacking player + if IsPlayer(attacker) then + attacker = CastToPlayer(attacker) + player_attacker = attacker + elseif IsSentrygun(attacker) then + attacker = CastToSentrygun(attacker) + player_attacker = attacker:GetOwner() + elseif IsDetpack(attacker) then + attacker = CastToDetpack(attacker) + player_attacker = attacker:GetOwner() + elseif IsDispenser(attacker) then + attacker = CastToDispenser(attacker) + player_attacker = attacker:GetOwner() + else + return + end + + -- if still no attacking player after all that, forget about it + if not player_attacker then return end + + -- If player killed self or teammate do nothing + if (player:GetId() == player_attacker:GetId()) or (player:GetTeamId() == player_attacker:GetTeamId()) then + return + end + + -- If player is an attacker, then do stuff + if player:GetTeamId() == attackers then + -- Check if he's in the cap point + for playerx in zone_collection.items do + playerx = CastToPlayer(playerx) + + if playerx:GetId() == player:GetId() then + if (damage > 100) then damage = 100 end + player_attacker:AddFortPoints( damage, "Protecting the Point" ) + return + end + end + + end + +end + +----------------------------------------------------------------------------- +-- on cap +----------------------------------------------------------------------------- + +function zone_cap( cap_phase ) + zone_collection:RemoveAllItems() + zone_turnoff( phase ) + + zone_points = 0 + + -- reset touches + for playerx, recordx in pairs(playerTouchedTable) do + if GetPlayerByID( playerx ) then + local playert = GetPlayerByID( playerx ) + if ( playert:GetTeamId() == attackers ) then + -- add to table and reset touched to 0 + playerTouchedTable[playert:GetId()] = {touched = false, allowed = true} + end + end + end + + draw_hud = false + + if phase == NUMBER_OF_CAP_POINTS then + onreset_outputs() + -- it's the last round. end and stuff + phase = 1 + -- run custom round reset stuff + AddSchedule( "onroundreset_sched", DELAY_BEFORE_TEAMSWITCH, onroundreset ) + else + oncap_outputs() + phase = phase + 1 + AddSchedule( "aftercap_sched", DELAY_AFTER_CAP, oncap_outputs_nextphase ) + + + AddSchedule( "aftercap_sched2", DELAY_AFTER_CAP, oncap_nextphase ) + end + + update_zone_all( ) + +end + + +----------------------------------------------------------------------------- +-- round functions +----------------------------------------------------------------------------- + +-- Opens the gates and schedules the round's end. +function round_start() + -- Opens the gates and all that lovely stuff + OpenDoor("frontgate") + BroadCastMessage( "#FF_AD_GATESOPEN" ) + BroadCastSound( "otherteam.flagstolen" ) + SpeakAll( "AD_GATESOPEN" ) + + openstartdoor() +end + +-- Checks to see if it's the first or second round, then either swaps teams, or ends the game. +function onroundreset() + + if attackers == Team.kBlue then + attackers = Team.kRed + defenders = Team.kBlue + + onswitch_bluetodef() + else + attackers = Team.kBlue + defenders = Team.kRed + + onswitch_redtodef() + end + + -- objective icon + UpdateTeamObjectiveIcon( GetTeam(attackers), nil ) + UpdateTeamObjectiveIcon( GetTeam(defenders), nil ) + + -- switch them team names + SetTeamName( attackers, "Attackers" ) + SetTeamName( defenders, "Defenders" ) + + -- reset them limits + team = GetTeam(defenders) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, -1) + team:SetClassLimit(Player.kMedic, -1) + + team = GetTeam(attackers) + team:SetClassLimit(Player.kCivilian, -1) + team:SetClassLimit(Player.kScout, 0) + team:SetClassLimit(Player.kMedic, 0) + + -- reset schedules + AddSchedule( "round_start", INITIAL_ROUND_PERIOD, round_start) + + -- reset player touched table + playerTouchedTable = {} + -- remove all leftovers from the cap point collection + zone_collection:RemoveAllItems() + -- respawn the players + RespawnAllPlayers() + + -- MORE scheduled message loveliness. + if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_30SecWarning" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_10SecWarning" ) end + + -- sounds + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_PERIOD - 30 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_PERIOD - 10 , schedulesound, "misc.bloop" ) end + if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_PERIOD - 5 , schedulecountdown, 5 ) end + if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_PERIOD - 4 , schedulecountdown, 4 ) end + if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_PERIOD - 3 , schedulecountdown, 3 ) end + if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_PERIOD - 2 , schedulecountdown, 2 ) end + if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_PERIOD - 1 , schedulecountdown, 1 ) end + + DeleteSchedule( "defense_period_scoring_sched" ) + AddScheduleRepeating( "defense_period_scoring_sched", DEFENSE_PERIOD_TIME, defenders_scoring ) + + draw_hud = true + update_zone_all( ) + + onswitch() +end + + +----------------------------------------------------------------------------- +-- zone functions +----------------------------------------------------------------------------- + +function zone_turnon( cp_num ) + zone_on_outputs() + + -- init scoring + AddSchedule( "period_init", DELAY_BEFORE_PERIOD_POINTS, init_scoring, team ) + AddSchedule( "period_init_alarm", DELAY_BEFORE_PERIOD_POINTS - 1, init_scoring_alarm ) +end +function zone_turnoff( cp_num ) + zone_off_outputs() + + -- stop scoring + zone_scoring = false +end +function oncap_nextphase() + draw_hud = true + update_zone_all( ) + + -- update objective icon + local attackers_objective = GetEntityByName( "zone"..phase ) + UpdateTeamObjectiveIcon( GetTeam(attackers), attackers_objective ) + UpdateTeamObjectiveIcon( GetTeam(defenders), nil ) +end + +----------------------------------------------------------------------------- +-- output functions +----------------------------------------------------------------------------- + +function zone_on_outputs() + return +end +function zone_off_outputs() + return +end +function onswitch_bluetodef() + return +end +function onswitch_redtodef() + return +end +function onswitch() + return +end +function openstartdoor() + return +end +function oncap_outputs() + return +end +function oncap_outputs_nextphase() + return +end +function onreset_outputs() + return +end + +----------------------------------------------------------------------------- +-- hud +----------------------------------------------------------------------------- + +function update_zone_all( ) + + RemoveHudItemFromAll( "Zone_Status" ) + RemoveHudItemFromAll( "Zone_Status_BG" ) + RemoveHudItemFromAll( "Zone_Status_Points" ) + RemoveHudItemFromAll( "Zone_Team"..attackers ) + RemoveHudItemFromAll( "Zone_Team"..defenders ) + RemoveHudItemFromAll( "Zone_Team_Text"..attackers ) + RemoveHudItemFromAll( "Zone_Team_Text"..defenders ) + + if draw_hud then + AddHudIconToAll( "hud_statusbar_256.vtf", "Zone_Status_BG", -64, 36, 128, 16, 3 ) + AddHudTextToTeam( GetTeam(attackers), "Zone_Team_Text"..attackers, "Attacking Zone "..phase, 33, 56, 4, 0 ) + AddHudTextToTeam( GetTeam(defenders), "Zone_Team_Text"..defenders, "Defending Zone "..phase, 33, 56, 4, 0 ) + AddHudTextToAll( "Zone_Status_Points", zone_points.." / "..zone_max_points, 40, 56, 2, 0 ) + + AddHudIconToTeam( GetTeam(attackers), "hud_offense.vtf", "Zone_Team"..attackers, -92, 38, 24, 24, 3 ) + AddHudIconToTeam( GetTeam(defenders), "hud_defense.vtf", "Zone_Team"..defenders, -92, 38, 24, 24, 3 ) + + local max_width = 124 + if zone_points > 0 then + + bar_width = zone_points / zone_max_points * max_width + + if zone_collection:Count() > 0 then + AddHudIconToAll( "hud_statusbar_"..ZONE_COLOR.."_active.vtf", "Zone_Status", -62, 36, bar_width, 16, 3 ) + else + AddHudIconToAll( "hud_statusbar_"..ZONE_COLOR..".vtf", "Zone_Status", -62, 36, bar_width, 16, 3 ) + end + + end + end +end + +function update_zone_player( player ) + RemoveHudItem( player, "Zone_Status" ) + RemoveHudItem( player, "Zone_Status_BG" ) + RemoveHudItem( player, "Zone_Status_Points" ) + RemoveHudItem( player, "Zone_Team"..attackers ) + RemoveHudItem( player, "Zone_Team"..defenders ) + RemoveHudItem( player, "Zone_Team_Text"..attackers ) + RemoveHudItem( player, "Zone_Team_Text"..defenders ) + + if draw_hud then + AddHudIcon( player, "hud_statusbar_256.vtf", "Zone_Status_BG", -64, 36, 128, 16, 3 ) + AddHudText( player, "Zone_Status_Points", zone_points.." / "..zone_max_points, 40, 56, 2, 0 ) + + if player:GetTeamId() == attackers then + AddHudIcon( player, "hud_offense.vtf", "Zone_Team"..attackers, -92, 38, 24, 24, 3 ) + AddHudText( player, "Zone_Team_Text"..attackers, "Attacking Zone "..phase, 33, 56, 4, 0 ) + else + AddHudIcon( player, "hud_defense.vtf", "Zone_Team"..defenders, -92, 38, 24, 24, 3 ) + AddHudText( player, "Zone_Team_Text"..defenders, "Defending Zone "..phase, 33, 56, 4, 0 ) + end + + local max_width = 124 + if zone_points > 0 then + + bar_width = zone_points / zone_max_points * max_width + + if zone_collection:Count() > 0 then + AddHudIcon( player, "hud_statusbar_"..ZONE_COLOR.."_active.vtf", "Zone_Status", -62, 36, bar_width, 16, 3 ) + else + AddHudIcon( player, "hud_statusbar_"..ZONE_COLOR..".vtf", "Zone_Status", -62, 36, bar_width, 16, 3 ) + end + + end + end +end + +----------------------------------------------------------------------------- +-- base_zone_trigger +----------------------------------------------------------------------------- + +-- capture room +base_zone_trigger = trigger_ff_script:new({ phase = 0, pointstocap = DEFAULT_POINTS_TO_CAP }) + +zone1 = base_zone_trigger:new({phase=1}) +zone2 = base_zone_trigger:new({phase=2}) +zone3 = base_zone_trigger:new({phase=3}) +zone4 = base_zone_trigger:new({phase=4}) +zone5 = base_zone_trigger:new({phase=5}) +zone6 = base_zone_trigger:new({phase=6}) +zone7 = base_zone_trigger:new({phase=7}) +zone8 = base_zone_trigger:new({phase=8}) + +-- registers attackers as they enter the cap room +function base_zone_trigger:ontouch( trigger_entity ) + if IsPlayer( trigger_entity ) then + + local player = CastToPlayer( trigger_entity ) + + if phase ~= self.phase then return end + if player:GetTeamId() == defenders then return end + + player:SetCloakable( false ) + player:SetDisguisable( false ) + + update_zone_all( ) + + local playerid = player:GetId() + zone_collection:AddItem( player ) + + local team = GetTeam(attackers) + -- if it's the first touch, give points and stuff + if playerTouchedTable[playerid].touched == false then + team:AddScore( POINTS_PER_INITIAL_TOUCH ) + player:AddFortPoints( FORT_POINTS_PER_INITIAL_TOUCH, "Initial Point Touch" ) + + zone_points = zone_points + POINTS_PER_INITIAL_TOUCH + update_zone_all( ) + + if zone_points >= self.pointstocap then + zone_cap( self.phase ) + return + end + + SmartTeamSound( GetTeam(defenders), "yourteam.flagreturn", "misc.doop" ) + + playerTouchedTable[playerid].touched = true + + elseif zone_collection:Count() == 1 then + SmartTeamSound( GetTeam(defenders), "otherteam.drop", nil ) + end + if zone_collection:Count() == 1 then + -- activate the cap point, bro + update_zone_all( ) + zone_turnon( self.phase ) + end + + end +end + +-- deregisters attackers as they enter the cap room. Checks to see if all attackers have left. +function base_zone_trigger:onendtouch( trigger_entity ) + + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + if player:GetTeamId() == defenders then return end + + player:SetCloakable( true ) + player:SetDisguisable( true ) + + zone_collection:RemoveItem( player ) + + local team = GetTeam(defenders) + if zone_collection:Count() == 0 then + update_zone_all( ) + zone_turnoff( self.phase ) + end + end +end + +-- empties the collection if no-one in in the room. Shouldn't really be nessecary. +function base_zone_trigger:oninactive() + -- Clear out the flags in the collection + DeleteSchedule( "period_scoring" ) + DeleteSchedule( "period_init" ) + DeleteSchedule( "period_init_alarm" ) + zone_collection:RemoveAllItems() + update_zone_status( false ) + zone_turnoff( self.phase ) +end + +----------------------------------------------------------------------------- +-- scoring +----------------------------------------------------------------------------- + +-- Adds points based on time inside cap room and number of attackers inside cap room +function period_scoring( ) + if zone_scoring then + local team = GetTeam( attackers ) + team:AddScore( POINTS_PER_PERIOD ) + zone_points = zone_points + POINTS_PER_PERIOD + update_zone_all( ) + SmartTeamSound( GetTeam(defenders), "yourteam.flagreturn", "misc.doop" ) + + for player in zone_collection.items do + player = CastToPlayer(player) + + if player ~= nil then + player:AddFortPoints( FORT_POINTS_PER_PERIOD, "Touching the Point" ) + else + ConsoleToAll("LUA ERROR: player_addfortpoints: Unable to find player") + end + end + end + -- cap zone if the points say to + if zone_points >= zone_max_points then + zone_cap( phase ) + end +end + +-- Initializes the period_scoring (allows for a delay after initial touch) +function init_scoring( team ) + if zone_collection:Count() > 0 then + zone_scoring = true + end +end + +-- Initializes the period_scoring (allows for a delay after initial touch) +function init_scoring_alarm( ) + if zone_collection:Count() > 0 then + SmartTeamSound( GetTeam(defenders), "otherteam.drop", nil ) + end +end + +-- Adds points based on time inside cap room and number of attackers inside cap room +function defenders_scoring( ) + local team = GetTeam( defenders ) + team:AddScore( POINTS_PER_DEFENSE_PERIOD ) +end + +----------------------------------------------------------------------------- +-- misc functions +----------------------------------------------------------------------------- + +-- Sends a message to all after the determined time +function schedulechangemessage( player, message ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + BroadCastMessageToPlayer( player, message ) + end +end + +-- reset everything +function RespawnAllPlayers() + ApplyToAll({ AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, AT.kStopPrimedGrens, AT.kReloadClips, AT.kAllowRespawn, AT.kReturnDroppedItems }) +end + +-- force a scout/med to switch to soli if they haven't +function forcechange( player ) + if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then + ApplyToPlayer( player, { AT.kChangeClassSoldier, AT.kRespawnPlayers } ) + end +end + +-- Sends a message to all after the determined time +function schedulemessagetoall( message ) + BroadCastMessage( message ) +end + +-- Plays a sound to all after the determined time +function schedulesound( sound ) + BroadCastSound( sound ) +end + + +function schedulecountdown( time ) + BroadCastMessage( ""..time.."" ) + SpeakAll( "AD_" .. time .. "SEC" ) +end + +----------------------------------------------------------------------------- +-- Entity definitions (flags/command points/backpacks etc.) +----------------------------------------------------------------------------- + +-- respawns +base_attacker_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player) + return player:GetTeamId() == attackers and phase == self.phase +end }) +base_defender_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player) + return player:GetTeamId() == defenders and phase == self.phase +end }) +zone1_attacker = base_attacker_spawn:new({phase=1}) +zone2_attacker = base_attacker_spawn:new({phase=2}) +zone3_attacker = base_attacker_spawn:new({phase=3}) +zone4_attacker = base_attacker_spawn:new({phase=4}) +zone5_attacker = base_attacker_spawn:new({phase=5}) +zone6_attacker = base_attacker_spawn:new({phase=6}) +zone7_attacker = base_attacker_spawn:new({phase=7}) +zone8_attacker = base_attacker_spawn:new({phase=8}) +zone1_defender = base_defender_spawn:new({phase=1}) +zone2_defender = base_defender_spawn:new({phase=2}) +zone3_defender = base_defender_spawn:new({phase=3}) +zone4_defender = base_defender_spawn:new({phase=4}) +zone5_defender = base_defender_spawn:new({phase=5}) +zone6_defender = base_defender_spawn:new({phase=6}) +zone7_defender = base_defender_spawn:new({phase=7}) +zone8_defender = base_defender_spawn:new({phase=8}) + +-- generic respawns +attacker_spawn = info_ff_teamspawn:new({ validspawn = function(self,player) + return player:GetTeamId() == attackers +end }) +defender_spawn = info_ff_teamspawn:new({ validspawn = function(self,player) + return player:GetTeamId() == defenders +end }) + +----------------------------------------------------------------------------- +-- Generic Backpack +----------------------------------------------------------------------------- +genericbackpack = info_ff_script:new({ + health = 0, + armor = 0, + grenades = 0, + shells = 0, + nails = 0, + rockets = 0, + cells = 0, + detpacks = 0, + mancannons = 0, + gren1 = 0, + gren2 = 0, + respawntime = 5, + model = "models/items/healthkit.mdl", + materializesound = "Item.Materialize", + touchsound = "HealthKit.Touch", + notallowedmsg = "#FF_NOTALLOWEDPACK", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen} +}) + +function genericbackpack:dropatspawn() return false end + +function genericbackpack:precache( ) + -- precache sounds + PrecacheSound(self.materializesound) + PrecacheSound(self.touchsound) + + -- precache models + PrecacheModel(self.model) +end + +function genericbackpack:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + + local dispensed = 0 + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then dispensed = dispensed + player:AddHealth( self.health ) end + if self.armor ~= nil and self.armor ~= 0 then dispensed = dispensed + player:AddArmor( self.armor ) end + + -- give player ammo + if self.nails ~= nil and self.nails ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren2, self.gren2) end + + -- if the player took ammo, then have the backpack respawn with a delay + if dispensed >= 1 then + local backpack = CastToInfoScript(entity); + if backpack then + backpack:EmitSound(self.touchsound); + backpack:Respawn(self.respawntime); + end + end + end +end + +function genericbackpack:materialize( ) + entity:EmitSound(self.materializesound) +end + +-- from http://www.lua.org/pil/14.1.html +function getfield (f) + local v = _G -- start with the table of globals + for w in string.gfind(f, "[%w_]+") do + v = v[w] + end + return v +end +function setfield (f, v) + local t = _G -- start with the table of globals + for w, d in string.gfind(f, "([%w_]+)(.?)") do + if d == "." then -- not last field? + t[w] = t[w] or {} -- create table if absent + t = t[w] -- get the table + else -- last field + t[w] = v -- do the assignment + end + end +end diff --git a/maps/includes/base_location.lua b/maps/includes/base_location.lua new file mode 100644 index 0000000..f62ff39 --- /dev/null +++ b/maps/includes/base_location.lua @@ -0,0 +1,222 @@ + +-- base_location.lua + +----------------------------------------------------------------------------- +-- Include this file to add base location functionality to your map +-- DO NOT ALTER THIS FILE +----------------------------------------------------------------------------- +location_info = trigger_ff_script:new({ text = "Unknown", team = Team.kUnassigned }) + +function location_info:ontouch( touch_entity ) + + -- set the location of the player + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + player:SetLocation(entity:GetId(), self.text, self.team) + end +end + +-- Locations were randomly screwing up when you move between them. I removed this and it appears to have completely fixed it. +-- I am not familiar with all this though, so someone who knows btr should check it over please (caesium). +--function location_info:onendtouch( touch_entity ) + -- remove the location from the player +-- if IsPlayer( touch_entity ) then +-- local player = CastToPlayer( touch_entity ) +-- player:RemoveLocation(entity:GetId()) +-- end +--end + +----------------------------------------------------------------------------- +-- Some common locations +-- PREFIX locations with the word "location_" (or just follow the same style as below!) +----------------------------------------------------------------------------- +location_attic = location_info:new({ text = "#FF_LOCATION_ATTIC", team = Team.kUnassigned }) +location_blue_attic = location_info:new({ text = "#FF_LOCATION_ATTIC", team = Team.kBlue }) +location_red_attic = location_info:new({ text = "#FF_LOCATION_ATTIC", team = Team.kRed }) +location_yellow_attic = location_info:new({ text = "#FF_LOCATION_ATTIC", team = Team.kYellow }) +location_green_attic = location_info:new({ text = "#FF_LOCATION_ATTIC", team = Team.kGreen }) + +location_base = location_info:new({ text = "#FF_LOCATION_BASE", team = Team.kUnassigned }) +location_blue_base = location_info:new({ text = "#FF_LOCATION_BASE", team = Team.kBlue }) +location_red_base = location_info:new({ text = "#FF_LOCATION_BASE", team = Team.kRed }) +location_yellow_base = location_info:new({ text = "#FF_LOCATION_BASE", team = Team.kYellow }) +location_green_base = location_info:new({ text = "#FF_LOCATION_BASE", team = Team.kGreen }) + +location_balcony = location_info:new({ text = "#FF_LOCATION_BALCONY", team = Team.kUnassigned }) +location_blue_balcony = location_info:new({ text = "#FF_LOCATION_BALCONY", team = Team.kBlue }) +location_red_balcony = location_info:new({ text = "#FF_LOCATION_BALCONY", team = Team.kRed }) +location_yellow_balcony = location_info:new({ text = "#FF_LOCATION_BALCONY", team = Team.kYellow }) +location_green_balcony = location_info:new({ text = "#FF_LOCATION_BALCONY", team = Team.kGreen }) + +location_battlements = location_info:new({ text = "#FF_LOCATION_BATTLEMENTS", team = Team.kUnassigned }) +location_blue_battlements = location_info:new({ text = "#FF_LOCATION_BATTLEMENTS", team = Team.kBlue }) +location_red_battlements = location_info:new({ text = "#FF_LOCATION_BATTLEMENTS", team = Team.kRed }) +location_yellow_battlements = location_info:new({ text = "#FF_LOCATION_BATTLEMENTS", team = Team.kYellow }) +location_green_battlements = location_info:new({ text = "#FF_LOCATION_BATTLEMENTS", team = Team.kGreen }) + +location_bunker = location_info:new({ text = "#FF_LOCATION_BUNKER", team = Team.kUnassigned }) +location_blue_bunker = location_info:new({ text = "#FF_LOCATION_BUNKER", team = Team.kBlue }) +location_red_bunker = location_info:new({ text = "#FF_LOCATION_BUNKER", team = Team.kRed }) +location_yellow_bunker = location_info:new({ text = "#FF_LOCATION_BUNKER", team = Team.kYellow }) +location_green_bunker = location_info:new({ text = "#FF_LOCATION_BUNKER", team = Team.kGreen }) + +location_button = location_info:new({ text = "#FF_LOCATION_BUTTON", team = Team.kUnassigned }) +location_blue_button = location_info:new({ text = "#FF_LOCATION_BUTTON", team = Team.kBlue }) +location_red_button = location_info:new({ text = "#FF_LOCATION_BUTTON", team = Team.kRed }) +location_yellow_button = location_info:new({ text = "#FF_LOCATION_BUTTON", team = Team.kYellow }) +location_green_button = location_info:new({ text = "#FF_LOCATION_BUTTON", team = Team.kGreen }) + +location_cappoint = location_info:new({ text = "#FF_LOCATION_CAPPOINT", team = Team.kUnassigned }) +location_blue_cappoint = location_info:new({ text = "#FF_LOCATION_CAPPOINT", team = Team.kBlue }) +location_red_cappoint = location_info:new({ text = "#FF_LOCATION_CAPPOINT", team = Team.kRed }) +location_yellow_cappoint = location_info:new({ text = "#FF_LOCATION_CAPPOINT", team = Team.kYellow }) +location_green_cappoint = location_info:new({ text = "#FF_LOCATION_CAPPOINT", team = Team.kGreen }) + +location_elevator = location_info:new({ text = "#FF_LOCATION_ELEVATOR", team = Team.kUnassigned }) +location_blue_elevator = location_info:new({ text = "#FF_LOCATION_ELEVATOR", team = Team.kBlue }) +location_red_elevator = location_info:new({ text = "#FF_LOCATION_ELEVATOR", team = Team.kRed }) +location_yellow_elevator = location_info:new({ text = "#FF_LOCATION_ELEVATOR", team = Team.kYellow }) +location_green_elevator = location_info:new({ text = "#FF_LOCATION_ELEVATOR", team = Team.kGreen }) + +location_flagroom = location_info:new({ text = "#FF_LOCATION_FLAGROOM", team = Team.kUnassigned }) +location_blue_flagroom = location_info:new({ text = "#FF_LOCATION_FLAGROOM", team = Team.kBlue }) +location_red_flagroom = location_info:new({ text = "#FF_LOCATION_FLAGROOM", team = Team.kRed }) +location_yellow_flagroom = location_info:new({ text = "#FF_LOCATION_FLAGROOM", team = Team.kYellow }) +location_green_flagroom = location_info:new({ text = "#FF_LOCATION_FLAGROOM", team = Team.kGreen }) + +location_frontdoor = location_info:new({ text = "#FF_LOCATION_FRONTDOOR", team = Team.kUnassigned }) +location_blue_frontdoor = location_info:new({ text = "#FF_LOCATION_FRONTDOOR", team = Team.kBlue }) +location_red_frontdoor = location_info:new({ text = "#FF_LOCATION_FRONTDOOR", team = Team.kRed }) +location_yellow_frontdoor = location_info:new({ text = "#FF_LOCATION_FRONTDOOR", team = Team.kYellow }) +location_green_frontdoor = location_info:new({ text = "#FF_LOCATION_FRONTDOOR", team = Team.kGreen }) + +location_lift = location_info:new({ text = "#FF_LOCATION_LIFT", team = Team.kUnassigned }) +location_blue_lift = location_info:new({ text = "#FF_LOCATION_LIFT", team = Team.kBlue }) +location_red_lift = location_info:new({ text = "#FF_LOCATION_LIFT", team = Team.kRed }) +location_yellow_lift = location_info:new({ text = "#FF_LOCATION_LIFT", team = Team.kYellow }) +location_green_lift = location_info:new({ text = "#FF_LOCATION_LIFT", team = Team.kGreen }) + +location_loft = location_info:new({ text = "#FF_LOCATION_LOFT", team = Team.kUnassigned }) +location_blue_loft = location_info:new({ text = "#FF_LOCATION_LOFT", team = Team.kBlue }) +location_red_loft = location_info:new({ text = "#FF_LOCATION_LOFT", team = Team.kRed }) +location_yellow_loft = location_info:new({ text = "#FF_LOCATION_LOFT", team = Team.kYellow }) +location_green_loft = location_info:new({ text = "#FF_LOCATION_LOFT", team = Team.kGreen }) + +location_pit = location_info:new({ text = "#FF_LOCATION_PIT", team = Team.kUnassigned }) +location_blue_pit = location_info:new({ text = "#FF_LOCATION_PIT", team = Team.kBlue }) +location_red_pit = location_info:new({ text = "#FF_LOCATION_PIT", team = Team.kRed }) +location_yellow_pit = location_info:new({ text = "#FF_LOCATION_PIT", team = Team.kYellow }) +location_green_pit = location_info:new({ text = "#FF_LOCATION_PIT", team = Team.kGreen }) + +location_plank = location_info:new({ text = "#FF_LOCATION_PLANK", team = Team.kUnassigned }) +location_blue_plank = location_info:new({ text = "#FF_LOCATION_PLANK", team = Team.kBlue }) +location_red_plank = location_info:new({ text = "#FF_LOCATION_PLANK", team = Team.kRed }) +location_yellow_plank = location_info:new({ text = "#FF_LOCATION_PLANK", team = Team.kYellow }) +location_green_plank = location_info:new({ text = "#FF_LOCATION_PLANK", team = Team.kGreen }) + +location_ramp = location_info:new({ text = "#FF_LOCATION_RAMP", team = Team.kUnassigned }) +location_blue_ramp = location_info:new({ text = "#FF_LOCATION_RAMP", team = Team.kBlue }) +location_red_ramp = location_info:new({ text = "#FF_LOCATION_RAMP", team = Team.kRed }) +location_yellow_ramp = location_info:new({ text = "#FF_LOCATION_RAMP", team = Team.kYellow }) +location_green_ramp = location_info:new({ text = "#FF_LOCATION_RAMP", team = Team.kGreen }) + +location_ramp_bottom = location_info:new({ text = "#FF_LOCATION_RAMP_BOTTOM", team = Team.kUnassigned }) +location_blue_ramp_bottom = location_info:new({ text = "#FF_LOCATION_RAMP_BOTTOM", team = Team.kBlue }) +location_red_ramp_bottom = location_info:new({ text = "#FF_LOCATION_RAMP_BOTTOM", team = Team.kRed }) +location_yellow_ramp_bottom = location_info:new({ text = "#FF_LOCATION_RAMP_BOTTOM", team = Team.kYellow }) +location_green_ramp_bottom = location_info:new({ text = "#FF_LOCATION_RAMP_BOTTOM", team = Team.kGreen }) + +location_ramp_top = location_info:new({ text = "#FF_LOCATION_RAMP_TOP", team = Team.kUnassigned }) +location_blue_ramp_top = location_info:new({ text = "#FF_LOCATION_RAMP_TOP", team = Team.kBlue }) +location_red_ramp_top = location_info:new({ text = "#FF_LOCATION_RAMP_TOP", team = Team.kRed }) +location_yellow_ramp_top = location_info:new({ text = "#FF_LOCATION_RAMP_TOP", team = Team.kYellow }) +location_green_ramp_top = location_info:new({ text = "#FF_LOCATION_RAMP_TOP", team = Team.kGreen }) + +location_ramproom = location_info:new({ text = "#FF_LOCATION_RAMPROOM", team = Team.kUnassigned }) +location_blue_ramproom = location_info:new({ text = "#FF_LOCATION_RAMPROOM", team = Team.kBlue }) +location_red_ramproom = location_info:new({ text = "#FF_LOCATION_RAMPROOM", team = Team.kRed }) +location_yellow_ramproom = location_info:new({ text = "#FF_LOCATION_RAMPROOM", team = Team.kYellow }) +location_green_ramproom = location_info:new({ text = "#FF_LOCATION_RAMPROOM", team = Team.kGreen }) + +location_respawn = location_info:new({ text = "#FF_LOCATION_RESPAWN", team = Team.kUnassigned }) +location_blue_respawn = location_info:new({ text = "#FF_LOCATION_RESPAWN", team = Team.kBlue }) +location_red_respawn = location_info:new({ text = "#FF_LOCATION_RESPAWN", team = Team.kRed }) +location_yellow_respawn = location_info:new({ text = "#FF_LOCATION_RESPAWN", team = Team.kYellow }) +location_green_respawn = location_info:new({ text = "#FF_LOCATION_RESPAWN", team = Team.kGreen }) + +location_roof = location_info:new({ text = "#FF_LOCATION_ROOF", team = Team.kUnassigned }) +location_blue_roof = location_info:new({ text = "#FF_LOCATION_ROOF", team = Team.kBlue }) +location_red_roof = location_info:new({ text = "#FF_LOCATION_ROOF", team = Team.kRed }) +location_yellow_roof = location_info:new({ text = "#FF_LOCATION_ROOF", team = Team.kYellow }) +location_green_roof = location_info:new({ text = "#FF_LOCATION_ROOF", team = Team.kGreen }) + +location_security = location_info:new({ text = "#FF_LOCATION_SECURITY", team = Team.kUnassigned }) +location_blue_security = location_info:new({ text = "#FF_LOCATION_SECURITY", team = Team.kBlue }) +location_red_security = location_info:new({ text = "#FF_LOCATION_SECURITY", team = Team.kRed }) +location_yellow_security = location_info:new({ text = "#FF_LOCATION_SECURITY", team = Team.kYellow }) +location_green_security = location_info:new({ text = "#FF_LOCATION_SECURITY", team = Team.kGreen }) + +location_sniper_perch = location_info:new({ text = "#FF_LOCATION_SNIPER_PERCH", team = Team.kUnassigned }) +location_blue_sniper_perch = location_info:new({ text = "#FF_LOCATION_SNIPER_PERCH", team = Team.kBlue }) +location_red_sniper_perch = location_info:new({ text = "#FF_LOCATION_SNIPER_PERCH", team = Team.kRed }) +location_yellow_sniper_perch = location_info:new({ text = "#FF_LOCATION_SNIPER_PERCH", team = Team.kYellow }) +location_green_sniper_perch = location_info:new({ text = "#FF_LOCATION_SNIPER_PERCH", team = Team.kGreen }) + +location_spiral = location_info:new({ text = "#FF_LOCATION_SPIRAL", team = Team.kUnassigned }) +location_blue_spiral = location_info:new({ text = "#FF_LOCATION_SPIRAL", team = Team.kBlue }) +location_red_spiral = location_info:new({ text = "#FF_LOCATION_SPIRAL", team = Team.kRed }) +location_yellow_spiral = location_info:new({ text = "#FF_LOCATION_SPIRAL", team = Team.kYellow }) +location_green_spiral = location_info:new({ text = "#FF_LOCATION_SPIRAL", team = Team.kGreen }) + +location_switch = location_info:new({ text = "#FF_LOCATION_SWITCH", team = Team.kUnassigned }) +location_blue_switch = location_info:new({ text = "#FF_LOCATION_SWITCH", team = Team.kBlue }) +location_red_switch = location_info:new({ text = "#FF_LOCATION_SWITCH", team = Team.kRed }) +location_yellow_switch = location_info:new({ text = "#FF_LOCATION_SWITCH", team = Team.kYellow }) +location_green_switch = location_info:new({ text = "#FF_LOCATION_SWITCH", team = Team.kGreen }) + +location_t = location_info:new({ text = "#FF_LOCATION_T", team = Team.kUnassigned }) +location_blue_t = location_info:new({ text = "#FF_LOCATION_T", team = Team.kBlue }) +location_red_t = location_info:new({ text = "#FF_LOCATION_T", team = Team.kRed }) +location_yellow_t = location_info:new({ text = "#FF_LOCATION_T", team = Team.kYellow }) +location_green_t = location_info:new({ text = "#FF_LOCATION_T", team = Team.kGreen }) + +location_train_tunnel = location_info:new({ text = "#FF_LOCATION_TRAIN_TUNNEL", team = Team.kUnassigned }) +location_blue_train_tunnel = location_info:new({ text = "#FF_LOCATION_TRAIN_TUNNEL", team = Team.kBlue }) +location_red_train_tunnel = location_info:new({ text = "#FF_LOCATION_TRAIN_TUNNEL", team = Team.kRed }) +location_yellow_train_tunnel = location_info:new({ text = "#FF_LOCATION_TRAIN_TUNNEL", team = Team.kYellow }) +location_green_train_tunnel = location_info:new({ text = "#FF_LOCATION_TRAIN_TUNNEL", team = Team.kGreen }) + +location_underground = location_info:new({ text = "#FF_LOCATION_UNDERGROUND", team = Team.kUnassigned }) +location_blue_underground = location_info:new({ text = "#FF_LOCATION_UNDERGROUND", team = Team.kBlue }) +location_red_underground = location_info:new({ text = "#FF_LOCATION_UNDERGROUND", team = Team.kRed }) +location_yellow_underground = location_info:new({ text = "#FF_LOCATION_UNDERGROUND", team = Team.kYellow }) +location_green_underground = location_info:new({ text = "#FF_LOCATION_UNDERGROUND", team = Team.kGreen }) + +location_waterroute = location_info:new({ text = "#FF_LOCATION_WATERROUTE", team = Team.kUnassigned }) +location_blue_waterroute = location_info:new({ text = "#FF_LOCATION_WATERROUTE", team = Team.kBlue }) +location_red_waterroute = location_info:new({ text = "#FF_LOCATION_WATERROUTE", team = Team.kRed }) +location_yellow_waterroute = location_info:new({ text = "#FF_LOCATION_WATERROUTE", team = Team.kYellow }) +location_green_waterroute = location_info:new({ text = "#FF_LOCATION_WATERROUTE", team = Team.kGreen }) + +location_yard = location_info:new({ text = "#FF_LOCATION_YARD", team = Team.kUnassigned }) +location_blue_yard = location_info:new({ text = "#FF_LOCATION_YARD", team = Team.kBlue }) +location_red_yard = location_info:new({ text = "#FF_LOCATION_YARD", team = Team.kRed }) +location_yellow_yard = location_info:new({ text = "#FF_LOCATION_YARD", team = Team.kYellow }) +location_green_yard = location_info:new({ text = "#FF_LOCATION_YARD", team = Team.kGreen }) + +-- Generic Invade/Defend Locations + +location_attackerspawn = location_info:new({ text = "#FF_LOCATION_ATTACKER_SPAWN", team = Team.kUnassigned }) + +location_defenderspawn = location_info:new({ text = "#FF_LOCATION_DEFENDER_SPAWN", team = Team.kUnassigned }) + +location_commandpointone = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_ONE", team = Team.kUnassigned }) + +location_commandpointtwo = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_TWO", team = Team.kUnassigned }) + +location_commandpointthree = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_THREE", team = Team.kUnassigned }) + +location_commandpointfour = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_FOUR", team = Team.kUnassigned }) + +location_detpack_hole = location_info:new({ text = "#FF_LOCATION_DETPACK_HOLE", team = Team.kUnassigned }) + diff --git a/maps/includes/base_push.lua b/maps/includes/base_push.lua new file mode 100644 index 0000000..5618433 --- /dev/null +++ b/maps/includes/base_push.lua @@ -0,0 +1,351 @@ +-- base_push.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base_teamplay"); +IncludeScript("base_location"); +IncludeScript("base_respawnturret"); + +BALL_THROW_SPEED = 512; +BALL_RETURN_TIME = 120; + +----------------------------------------------------------------------------- +-- Some Global Stuff! +----------------------------------------------------------------------------- +function startup() + SetGameDescription( "Push" ) + + -- set up team limits on each team + SetPlayerLimit(Team.kBlue, 0) + SetPlayerLimit(Team.kRed, 0) + SetPlayerLimit(Team.kYellow, -1) + SetPlayerLimit(Team.kGreen, -1) + + -- push maps generally don't have civilians, so override in map LUA file if you want 'em + local team = GetTeam( Team.kBlue ) + team:SetClassLimit( Player.kCivilian, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + + local team = GetTeam( Team.kRed ) + team:SetClassLimit( Player.kCivilian, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) +end + +-- Give everyone a full resupply, but strip grenades +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 100 ) + player:AddArmor( 300 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) + player:AddAmmo( Ammo.kDetpack, 1 ) + player:AddAmmo( Ammo.kManCannon, 1 ) + + player:RemoveAmmo( Ammo.kGren1, 4 ) + player:RemoveAmmo( Ammo.kGren2, 4 ) +end + +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- backpacks +----------------------------------------------------------------------------- +push_backpack = genericbackpack:new({ + health = 25, + armor = 50, + touchsound = "ArmorKit.Touch", + respawntime = 10, + model = "models/items/backpack/backpack.mdl", + botgoaltype = Bot.kBackPack_Health +}) + +function push_backpack:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- base_ball +----------------------------------------------------------------------------- +base_ball = info_ff_script:new({ + name = "base ball", + team = Team.kUnassigned, + model = "models/items/ball/ball.mdl", + modelskin = 0, + tosssound = "Flag.Toss", + dropnotouchtime = 2, + capnotouchtime = 2, + hudicon = "hud_ball", + hudx = 5, + hudy = 210, + hudwidth = 48, + hudheight = 48, + hudalign = 1, + hudstatusiconbluex = 60, + hudstatusiconbluey = 5, + hudstatusiconredx = 60, + hudstatusiconredy = 5, + hudstatusiconblue = "hud_ball.vtf", + hudstatusiconred = "hud_ball.vtf", + hudstatusiconw = 15, + hudstatusiconh = 15, + hudstatusiconbluealign = 2, + hudstatusiconredalign = 3, + + touchflags = {AllowFlags.kOnlyPlayers, AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen}, + botgoaltype = Bot.kFlag +}) + +function base_ball:hasanimation() return true end + +-- For when this object is carried, these offsets are used to place +-- the info_ff_script relative to the players feet +function base_ball:attachoffset() + -- x = forward/backward + -- y = left/right + -- z = up/down + local offset = Vector( 32, 0, 0 ) + return offset +end + +function base_ball:precache() + PrecacheSound(self.tosssound) + PrecacheSound("yourteam.flagstolen") + PrecacheSound("otherteam.flagstolen") + PrecacheSound("yourteam.drop") + PrecacheSound("otherteam.drop") + PrecacheSound("yourteam.flagreturn") + PrecacheSound("otherteam.flagreturn") + PrecacheSound("yourteam.flagcap") + PrecacheSound("otherteam.flagcap") + info_ff_script.precache(self) +end + +function base_ball:spawn() + self.notouch = { } + info_ff_script.spawn(self) +end + +function base_ball:addnotouch(player_id, duration) + self.notouch[player_id] = duration + AddSchedule(self.name .. "-" .. player_id, duration, self.removenotouch, self, player_id) +end + +function base_ball.removenotouch(self, player_id) + self.notouch[player_id] = nil +end + +function base_ball:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + -- pickup if they can + if self.notouch[player:GetId()] then return; end + + if player:GetTeamId() ~= self.team then + -- let the teams know that the ball was picked up + SmartSound(player, "yourteam.flagstolen", "yourteam.flagstolen", "otherteam.flagstolen") + SmartSpeak(player, "CTF_YOUHAVEBALL", "CTF_TEAMHASBALL", "CTF_ENEMYHASBALL") + SmartMessage(player, "#FF_YOUHAVEBALL", "#FF_TEAMHASBALL", "#FF_ENEMYHASBALL", Color.kGreen, Color.kGreen, Color.kRed) + + -- if the player is a spy, then force him to lose his disguise + player:SetDisguisable( false ) + -- if the player is a spy, then force him to lose his cloak + player:SetCloakable( false ) + + -- note: this seems a bit backwards (Pickup verb fits Player better) + local ball = CastToInfoScript(entity) + ball:Pickup(player) + AddHudIcon( player, self.hudicon, ball:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign ) + + + RemoveHudItemFromAll( "ball-icon-dropped" ) + local team = player:GetTeamId() + if (team == Team.kBlue) then + AddHudIconToAll( self.hudstatusiconblue, "ball-icon-blue", self.hudstatusiconbluex, self.hudstatusiconbluey, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconbluealign ) + elseif (team == Team.kRed) then + AddHudIconToAll( self.hudstatusiconred, "ball-icon-red", self.hudstatusiconredx, self.hudstatusiconredy, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconredalign ) + end + + end + end +end + +function base_ball:onownerdie( owner_entity ) + -- drop the ball + local ball = CastToInfoScript(entity) + ball:Drop(BALL_RETURN_TIME, 0.0) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, ball:GetName() ) + + local team = player:GetTeamId() + if (team == Team.kBlue) then + RemoveHudItemFromAll( "ball-icon-blue" ) + elseif (team == Team.kRed) then + RemoveHudItemFromAll( "ball-icon-red" ) + end + end +end +function base_ball:ownerfeign( owner_entity ) + -- drop the ball + local ball = CastToInfoScript(entity) + ball:Drop(BALL_RETURN_TIME, 0.0) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, ball:GetName() ) + local team = player:GetTeamId() + if (team == Team.kBlue) then + RemoveHudItemFromAll( "ball-icon-blue" ) + elseif (team == Team.kRed) then + RemoveHudItemFromAll( "ball-icon-red" ) + end + end +end +function base_ball:dropitemcmd( owner_entity ) + -- throw the ball + local ball = CastToInfoScript(entity) + ball:Drop(BALL_RETURN_TIME, BALL_THROW_SPEED) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, ball:GetName() ) + local team = player:GetTeamId() + if (team == Team.kBlue) then + RemoveHudItemFromAll( "ball-icon-blue" ) + elseif (team == Team.kRed) then + RemoveHudItemFromAll( "ball-icon-red" ) + end + end +end + +function base_ball:ondrop( owner_entity ) + if IsPlayer( owner_entity ) then + local player = CastToPlayer( owner_entity ) + -- let the teams know that the flag was dropped + SmartSound(player, "yourteam.drop", "yourteam.drop", "otherteam.drop") + SmartMessage(player, "#FF_YOUBALLDROP", "#FF_TEAMBALLDROP", "#FF_ENEMYBALLDROP", Color.kYellow, Color.kYellow, Color.kYellow) + end + + local ball = CastToInfoScript(entity) + ball:EmitSound(self.tosssound) +end + +function base_ball:onloseitem( owner_entity ) + if IsPlayer( owner_entity ) then + -- let the player that lost the ball put on a disguise + local player = CastToPlayer( owner_entity ) + player:SetDisguisable(true) + player:SetCloakable( true ) + + self:addnotouch(player:GetId(), self.capnotouchtime) + end +end + +function base_ball:onreturn( ) + -- let the teams know that the ball was returned + BroadCastMessage("#FF_BALLRETURN", Color.kYellow) + BroadCastSound ( "yourteam.flagreturn" ) + SpeakAll( "CTF_BALLRETURN" ) +end + +-- Define the ball +ball = base_ball:new({}) + +----------------------------------------------------------------------------- +-- Capture Points +----------------------------------------------------------------------------- +pushcap = trigger_ff_script:new({ + health = 100, + armor = 300, + grenades = 200, + nails = 200, + shells = 200, + rockets = 200, + cells = 200, + detpacks = 1, + mancannons = 1, + gren1 = 0, + gren2 = 0, + item = "", + team = Team.kUnassigned, + botgoaltype = Bot.kFlagCap +}) + +function pushcap:allowed ( allowed_entity ) + if IsPlayer( allowed_entity ) then + -- get the player and his team + local player = CastToPlayer( allowed_entity ) + + -- check if the player is on our team + if player:GetTeamId() ~= self.team then + return EVENT_DISALLOWED + end + + if player:HasItem( self.item ) then + return EVENT_ALLOWED + end + end + + return EVENT_DISALLOWED +end + +function pushcap:ontrigger( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- check if the player is carrying the ball + if player:HasItem( self.item ) then + + -- reward player for goal + player:AddFortPoints(FORTPOINTS_PER_CAPTURE, "#FF_FORTPOINTS_GOAL") + + -- reward player's team for capture + local team = player:GetTeam() + team:AddScore(POINTS_PER_CAPTURE) + + local ball = GetInfoScriptByName( "ball" ) + + -- return the ball + ball:Return() + + -- Remove any hud icons + RemoveHudItem( player, ball:GetName() ) + local team = player:GetTeamId() + if (team == Team.kBlue) then + RemoveHudItemFromAll( "ball-icon-blue" ) + elseif (team == Team.kRed) then + RemoveHudItemFromAll( "ball-icon-red" ) + end + + -- let the teams know that a capture occured + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") + SmartSpeak(player, "CTF_YOUSCORE", "CTF_TEAMSCORE", "CTF_THEYSCORE") + SmartMessage(player, "#FF_YOUSCORE", "#FF_TEAMSCORE", "#FF_ENEMYSCORE", Color.kGreen, Color.kGreen, Color.kRed) + + ApplyToAll({ AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, AT.kStopPrimedGrens, AT.kReloadClips }) + end + end +end + +-- declare the elements +red_cap = pushcap:new({ team = Team.kRed, item = "ball" }) +blue_cap = pushcap:new({ team = Team.kBlue, item = "ball" }) + +----------------------------------------------------------------------------- +-- Hurts +----------------------------------------------------------------------------- +hurt = trigger_ff_script:new({ team = Team.kUnassigned }) +function hurt:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + + return EVENT_DISALLOWED +end + +hurt_blue = hurt:new({ team = Team.kBlue }) +hurt_red = hurt:new({ team = Team.kRed }) diff --git a/maps/includes/base_respawnturret.lua b/maps/includes/base_respawnturret.lua new file mode 100644 index 0000000..54a0a22 --- /dev/null +++ b/maps/includes/base_respawnturret.lua @@ -0,0 +1,41 @@ + +-- base_turret handles some stuff for Respawn Turrets + +-- Custom target selection should be handled in your map's .lua +-- file and not this one (so please do not mess with this file)! + +---------------------------------------------------------------------------- +-- Team assigned Respawn Turrets target players, dispensers, and sentryguns +-- that are not on the Respawn Turrets team as well as players, dispensers, +-- and sentryguns that are not on a team that is allied to the Respawn +-- Turrets team +---------------------------------------------------------------------------- +base_respawnturret = baseclass:new({ team = Team.kUnassigned }) + +-- Note: GetObjectsTeam only works on players, dispensers, and sentryguns so +-- don't use it where an object could be anything except those 3 items + +-- Note: IsTeam1AlliedToTeam2 will return true if team1 is allied to team2 or +-- if team1 is the same as team2 + +function base_respawnturret:validtarget( target_entity ) + --local entity = GetEntity(ent_id) + return (AreTeamsAllied(self.team, target_entity:GetTeamId()) == false) +end + +-- Turrets, by default, have a 2 second delay after they +-- spot a target and before they're deployed (opened) +function base_respawnturret:deploydelay( target_entity ) return 2.0 end + +---------------------------------------------------------------------------- +-- Generic Respawn Turret assigned to no team. +---------------------------------------------------------------------------- +respawnturret = base_respawnturret:new({ team = Team.kUnassigned }) + +---------------------------------------------------------------------------- +-- Team assigned Respawn Turrets +---------------------------------------------------------------------------- +respawnturret_blue = base_respawnturret:new({ team = Team.kBlue }) +respawnturret_red = base_respawnturret:new({ team = Team.kRed }) +respawnturret_yellow = base_respawnturret:new({ team = Team.kYellow }) +respawnturret_green = base_respawnturret:new({ team = Team.kGreen }) diff --git a/maps/includes/base_shutdown.lua b/maps/includes/base_shutdown.lua new file mode 100644 index 0000000..0fe5510 --- /dev/null +++ b/maps/includes/base_shutdown.lua @@ -0,0 +1,193 @@ + +-- base_shutdown.lua + +----------------------------------------------------------------------------- +-- includes +----------------------------------------------------------------------------- +IncludeScript("base"); +IncludeScript("base_ctf"); +IncludeScript("base_teamplay"); +IncludeScript("base_location"); +IncludeScript("base_respawnturret"); + +----------------------------------------------------------------------------- +-- global overrides +----------------------------------------------------------------------------- +POINTS_PER_CAPTURE = 10; +FLAG_RETURN_TIME = 60; + +----------------------------------------------------------------------------- +-- Buttons +----------------------------------------------------------------------------- + +-- base button stuff (common functionality) +button_common = func_button:new({ team = Team.kUnassigned }) + +function button_common:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team and player:IsAlive() then + return EVENT_ALLOWED + end + end + + return EVENT_DISALLOWED +end + +-- TODO this doesn't work +function button_common:onfailuse( use_entity ) + if IsPlayer( use_entity ) then + local player = CastToPlayer( use_entity ) + BroadCastMessageToPlayer( player, "#FF_NOTALLOWEDBUTTON" ) + end +end + +----------------------------------------------------------------------------- +-- Button inputs (touch, use, damage etc.) +----------------------------------------------------------------------------- + +-- red button +--button_red = button_common:new({ team = Team.kBlue, sec_up = true }) + +button_red = button_common:new({ + team = Team.kBlue, + sec_up = true, + sec_down_icon = "hud_secdown.vtf", + sec_up_icon = "hud_secup_red.vtf", + iconx = 60, + icony = 30, + iconw = 16, + iconh = 16, + iconalign = 3 +}) + +----------------------------------------------------------------------------- +-- Button responses +----------------------------------------------------------------------------- +function button_red:onin() + BroadCastMessage( "#FF_RED_SECURITY_DEACTIVATED" ) + SpeakAll( "SD_REDDOWN" ) + + self.sec_up = false + + RemoveHudItemFromAll( "red-sec-up") + AddHudIconToAll( self.sec_down_icon, "red-sec-down", self.iconx, self.icony, self.iconw, self.iconh, self.iconalign ) + LogLuaEvent(0, 0, "security_down", "team", "red") + +end + +function button_red:onout() + BroadCastMessage( "#FF_RED_SECURITY_ACTIVATED" ) + SpeakAll( "SD_REDUP" ) + + self.sec_up = true + + RemoveHudItemFromAll( "red-sec-down" ) + AddHudIconToAll( self.sec_up_icon, "red-sec-up", self.iconx, self.icony, self.iconw, self.iconh, self.iconalign ) + LogLuaEvent(0, 0, "security_up", "team", "red") + +end + +----------------------------------------------------------------------------- +-- Button inputs (touch, use, damage etc.) +----------------------------------------------------------------------------- + +-- blue button +--button_blue = button_common:new({ team = Team.kRed, sec_up = true }) + +button_blue = button_common:new({ + team = Team.kRed, + sec_up = true, + sec_down_icon = "hud_secdown.vtf", + sec_up_icon = "hud_secup_blue.vtf", + iconx = 60, + icony = 30, + iconw = 16, + iconh = 16, + iconalign = 2 +}) + +----------------------------------------------------------------------------- +-- Button responses +----------------------------------------------------------------------------- +function button_blue:onin() + BroadCastMessage( "#FF_BLUE_SECURITY_DEACTIVATED" ) + SpeakAll( "SD_BLUEDOWN" ) + + self.sec_up = false + + RemoveHudItemFromAll( "blue-sec-up") + AddHudIconToAll( self.sec_down_icon, "blue-sec-down", self.iconx, self.icony, self.iconw, self.iconh, self.iconalign ) + LogLuaEvent(0, 0, "security_down", "team", "blue") + +end + +function button_blue:onout() + BroadCastMessage( "#FF_BLUE_SECURITY_ACTIVATED" ) + SpeakAll( "SD_BLUEUP" ) + + self.sec_up = true + + RemoveHudItemFromAll( "blue-sec-down") + AddHudIconToAll( self.sec_up_icon, "blue-sec-up", self.iconx, self.icony, self.iconw, self.iconh, self.iconalign ) + LogLuaEvent(0, 0, "security_up", "team", "blue") +end + +----------------------------------------------------------------------------- +-- Hurts +----------------------------------------------------------------------------- +hurt = trigger_ff_script:new({ team = Team.kUnassigned }) +function hurt:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + local player = CastToPlayer( allowed_entity ) + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + end + + return EVENT_DISALLOWED +end + +-- red lasers hurt blue and vice-versa + +red_laser_hurt = hurt:new({ team = Team.kBlue }) +blue_laser_hurt = hurt:new({ team = Team.kRed }) + +-- function precache() + -- precache sounds +-- PrecacheSound("vox.blueup") +-- PrecacheSound("vox.bluedown") +-- PrecacheSound("vox.redup") +-- PrecacheSound("vox.reddown") +-- end + + + +------------------------- +-- flaginfo +------------------------- + +--flaginfo runs whenever the player spawns or uses the flaginfo command. +--Right now it just refreshes the HUD items; this ensures that players who just joined the server have the right information +function flaginfo( player_entity ) + flaginfo_base(player_entity) --see base_teamplay.lua + + local player = CastToPlayer( player_entity ) + + RemoveHudItem( player, "red-sec-down" ) + RemoveHudItem( player, "blue-sec-down" ) + RemoveHudItem( player, "red-sec-up" ) + RemoveHudItem( player, "blue-sec-up" ) + + if button_blue.sec_up == true then + AddHudIcon( player, button_blue.sec_up_icon, "blue-sec-up", button_blue.iconx, button_blue.icony, button_blue.iconw, button_blue.iconh, button_blue.iconalign ) + else + AddHudIcon( player, button_blue.sec_down_icon, "blue-sec-down", button_blue.iconx, button_blue.icony, button_blue.iconw, button_blue.iconh, button_blue.iconalign ) + end + + if button_red.sec_up == true then + AddHudIcon( player, button_red.sec_up_icon, "red-sec-up", button_red.iconx, button_red.icony, button_red.iconw, button_red.iconh, button_red.iconalign ) + else + AddHudIcon( player, button_red.sec_down_icon, "red-sec-down", button_red.iconx, button_red.icony, button_red.iconw, button_red.iconh, button_red.iconalign ) + end +end \ No newline at end of file diff --git a/maps/includes/base_soldierarena.lua b/maps/includes/base_soldierarena.lua new file mode 100644 index 0000000..1864a64 --- /dev/null +++ b/maps/includes/base_soldierarena.lua @@ -0,0 +1,111 @@ + +-- base_soldierarena + +function startup() + + local team = GetTeam(Team.kBlue) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, -1 ) + team:SetClassLimit( Player.kSoldier, 0 ) + team:SetClassLimit( Player.kDemoman, 0 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + team = GetTeam(Team.kRed) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, -1 ) + team:SetClassLimit( Player.kSoldier, 0 ) + team:SetClassLimit( Player.kDemoman, 0 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + team = GetTeam(Team.kYellow) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, -1 ) + team:SetClassLimit( Player.kSoldier, 0 ) + team:SetClassLimit( Player.kDemoman, 0 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, -1 ) + + team = GetTeam(Team.kGreen) + team:SetClassLimit( Player.kScout, -1 ) + team:SetClassLimit( Player.kSniper, -1 ) + team:SetClassLimit( Player.kSoldier, 0 ) + team:SetClassLimit( Player.kDemoman, 0 ) + team:SetClassLimit( Player.kMedic, -1 ) + team:SetClassLimit( Player.kHwguy, -1 ) + team:SetClassLimit( Player.kPyro, -1 ) + team:SetClassLimit( Player.kSpy, -1 ) + team:SetClassLimit( Player.kEngineer, -1 ) + team:SetClassLimit( Player.kCivilian, -1 ) + +end + +function player_spawn( player_id ) + -- 400 for overkill. of course the values + -- get clamped in game code + local player = GetPlayer(player_id) + player:AddHealth( 400 ) + player:AddArmor( 400 ) + + player:RemoveAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:RemoveAmmo( Ammo.kCells, 400 ) + player:RemoveAmmo( Ammo.kDetpack, 1 ) + player:RemoveAmmo( Ammo.kManCannon, 1 ) + player:RemoveAmmo( Ammo.kGren1, 4 ) + player:RemoveAmmo( Ammo.kGren2, 4 ) + + -- Players get 1 gren1 + player:AddAmmo( Ammo.kGren1, 1 ) +end + +function player_ondamage( player, damageinfo ) + + if not player_entity then return end + if not damageinfo then return end + + local attackerPlayer = CastToPlayer(damageinfo:GetAttacker()) + if not attackerPlayer then return end + + local weapon = damageinfo:GetInflictor():GetClassName() + local player = CastToPlayer(player_entity) + + -- Don't take rocket, gl/pl damage from ourselves + if ( player:GetId() == attackerPlayer:GetId() ) then + + if ( weapon == "ff_projectile_rocket" ) then + damageinfo:SetDamage(0); + -- green pipes + elseif ( weapon == "ff_projectile_pl" ) then + damageinfo:SetDamage(0); + -- blue pipes + elseif ( weapon == "ff_projectile_gl" ) then + damageinfo:SetDamage(0); + end + end +end + +function player_killed( player_id ) + -- If you kill someone, give your team a point + local killer = GetPlayer(killer) + local victim = GetPlayer(player_id) + + if not (victim:GetTeamId() == killer:GetTeamId()) then + local killersTeam = killer:GetTeam() + killersTeam:AddScore(1) + end +end diff --git a/maps/includes/base_teamplay.lua b/maps/includes/base_teamplay.lua new file mode 100644 index 0000000..04f7b15 --- /dev/null +++ b/maps/includes/base_teamplay.lua @@ -0,0 +1,872 @@ + +-- base_teamplay.lua + +----------------------------------------------------------------------------- +-- base_teamplay handles stuff for "normal" maps so this stuff doesn't need +-- to be replicated all over the place (like standard teamspawns, +-- doors, bags, and such) +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Globals +----------------------------------------------------------------------------- +if POINTS_PER_CAPTURE == nil then POINTS_PER_CAPTURE = 10; end +if FORTPOINTS_PER_CAPTURE == nil then FORTPOINTS_PER_CAPTURE = 1000; end +if FORTPOINTS_PER_INITIALTOUCH == nil then FORTPOINTS_PER_INITIALTOUCH = 100; end +if FLAG_RETURN_TIME == nil then FLAG_RETURN_TIME = 60; end +if FLAG_THROW_SPEED == nil then FLAG_THROW_SPEED = 330; end + +redallowedmethod = function(self,player) return player:GetTeamId() == Team.kRed end +blueallowedmethod = function(self,player) return player:GetTeamId() == Team.kBlue end +yellowallowedmethod = function(self,player) return player:GetTeamId() == Team.kYellow end +greenallowedmethod = function(self,player) return player:GetTeamId() == Team.kGreen end + +-- things for flags +teamskins = {} +teamskins[Team.kBlue] = 0 +teamskins[Team.kRed] = 1 +teamskins[Team.kYellow] = 2 +teamskins[Team.kGreen] = 3 + +team_hudicons = {} +team_hudicons[Team.kBlue] = "hud_flag_blue_new.vtf" +team_hudicons[Team.kRed] = "hud_flag_red_new.vtf" +team_hudicons[Team.kGreen] = "hud_flag_green_new.vtf" +team_hudicons[Team.kYellow] = "hud_flag_yellow_new.vtf" + +----------------------------------------------------------------------------- +-- Player spawn: give full health, armor, and ammo +----------------------------------------------------------------------------- +function player_spawn( player_entity ) + local player = CastToPlayer( player_entity ) + + player:AddHealth( 400 ) + player:AddArmor( 400 ) + + player:AddAmmo( Ammo.kNails, 400 ) + player:AddAmmo( Ammo.kShells, 400 ) + player:AddAmmo( Ammo.kRockets, 400 ) + player:AddAmmo( Ammo.kCells, 400 ) +end + +----------------------------------------------------------------------------- +-- No builds: area where you can't build +----------------------------------------------------------------------------- +nobuild = trigger_ff_script:new({}) + +function nobuild:onbuild( build_entity ) + return EVENT_DISALLOWED +end + +no_build = nobuild + +----------------------------------------------------------------------------- +-- No grens: area where grens won't explode +----------------------------------------------------------------------------- +nogrens = trigger_ff_script:new({}) + +function nogrens:onexplode( explode_entity ) + if IsGrenade( explode_entity ) then + return EVENT_DISALLOWED + end + return EVENT_ALLOWED +end + +no_grens = nogrens + +----------------------------------------------------------------------------- +-- No Fucking Annoyances +----------------------------------------------------------------------------- +noannoyances = trigger_ff_script:new({}) + +function noannoyances:onbuild( build_entity ) + return EVENT_DISALLOWED +end + +function noannoyances:onexplode( explode_entity ) + if IsGrenade( explode_entity ) then + return EVENT_DISALLOWED + end + return EVENT_ALLOWED +end + +function noannoyances:oninfect( infect_entity ) + return EVENT_DISALLOWED +end + +no_annoyances = noannoyances +spawn_protection = noannoyances + +----------------------------------------------------------------------------- +-- Trigger_ff_clips +----------------------------------------------------------------------------- + +-- these block all players except the team the clip "belongs to" (clip_red blocks all players not on the red team) +clip_blue = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipPlayersByTeam, ClipFlags.kClipTeamRed, ClipFlags.kClipTeamYellow, ClipFlags.kClipTeamGreen, ClipFlags.kClipAllNonPlayers} }) +clip_red = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipPlayersByTeam, ClipFlags.kClipTeamBlue, ClipFlags.kClipTeamYellow, ClipFlags.kClipTeamGreen, ClipFlags.kClipAllNonPlayers} }) +clip_yellow = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipPlayersByTeam, ClipFlags.kClipTeamBlue, ClipFlags.kClipTeamRed, ClipFlags.kClipTeamGreen, ClipFlags.kClipAllNonPlayers} }) +clip_green = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipPlayersByTeam, ClipFlags.kClipTeamBlue, ClipFlags.kClipTeamRed, ClipFlags.kClipTeamYellow, ClipFlags.kClipAllNonPlayers} }) + +-- each of these block specific things +block_buildables = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllBuildables, ClipFlags.kClipAllBuildableWeapons} }) +block_buildablepathing = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllBuildables} }) +block_buildableweapons = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllBuildableWeapons} }) +block_spawnturrets = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllSpawnTurrets} }) +block_nonplayers = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllNonPlayers} }) +block_players = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllPlayers} }) +block_backpacks = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllBackpacks} }) +block_flags = trigger_ff_clip:new({ clipflags = {ClipFlags.kClipAllInfoScripts} }) + +----------------------------------------------------------------------------- +-- Generic Backpack +----------------------------------------------------------------------------- +genericbackpack = info_ff_script:new({ + health = 0, + armor = 0, + grenades = 0, + shells = 0, + nails = 0, + rockets = 0, + cells = 0, + detpacks = 0, + mancannons = 0, + gren1 = 0, + gren2 = 0, + respawntime = 5, + model = "models/items/healthkit.mdl", + materializesound = "Item.Materialize", + touchsound = "HealthKit.Touch", + notallowedmsg = "#FF_NOTALLOWEDPACK", + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen} +}) + +function genericbackpack:dropatspawn() return false end + +function genericbackpack:precache( ) + -- precache sounds + PrecacheSound(self.materializesound) + PrecacheSound(self.touchsound) + + -- precache models + PrecacheModel(self.model) +end + +function genericbackpack:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + + local dispensed = 0 + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then dispensed = dispensed + player:AddHealth( self.health ) end + if self.armor ~= nil and self.armor ~= 0 then dispensed = dispensed + player:AddArmor( self.armor ) end + + -- give player ammo + if self.nails ~= nil and self.nails ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren2, self.gren2) end + + -- if the player took ammo, then have the backpack respawn with a delay + if dispensed >= 1 then + local backpack = CastToInfoScript(entity); + if backpack then + backpack:EmitSound(self.touchsound); + backpack:Respawn(self.respawntime); + end + end + end +end + +function genericbackpack:materialize( ) + entity:EmitSound(self.materializesound) +end + +----------------------------------------------------------------------------- +-- Health Kit (backpack-based) +----------------------------------------------------------------------------- +healthkit = genericbackpack:new({ + health = 25, + model = "models/items/healthkit.mdl", + materializesound = "Item.Materialize", + respawntime = 20, + touchsound = "HealthKit.Touch", + botgoaltype = Bot.kBackPack_Health +}) + +function healthkit:dropatspawn() return true end + +----------------------------------------------------------------------------- +-- Armor Kit (backpack-based) +----------------------------------------------------------------------------- +armorkit = genericbackpack:new({ + armor = 200, + cells = 150, -- mirv: armour in 2fort/rock2/etc gives 150 cells too + model = "models/items/armour/armour.mdl", + materializesound = "Item.Materialize", + touchsound = "ArmorKit.Touch", + botgoaltype = Bot.kBackPack_Armor +}) + +function armorkit:dropatspawn() return true end + +----------------------------------------------------------------------------- +-- Ammo Kit (backpack-based) +----------------------------------------------------------------------------- +ammobackpack = genericbackpack:new({ + grenades = 20, + nails = 50, + shells = 100, + rockets = 15, + cells = 70, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +function ammobackpack:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- bigpack -- has a bit of everything (excluding grens) (backpack-based) +----------------------------------------------------------------------------- +bigpack = genericbackpack:new({ + health = 150, + armor = 200, + grenades = 50, + nails = 150, + shells = 200, + rockets = 100, + cells = 200, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Ammo +}) + +function bigpack:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- Grenade Backpack +----------------------------------------------------------------------------- +grenadebackpack = genericbackpack:new({ + mancannons = 1, + gren1 = 2, + gren2 = 2, + model = "models/items/backpack/backpack.mdl", + materializesound = "Item.Materialize", + respawntime = 30, + touchsound = "Backpack.Touch", + botgoaltype = Bot.kBackPack_Grenades +}) + +function grenadebackpack:dropatspawn() return false end + +----------------------------------------------------------------------------- +-- Door Triggers +----------------------------------------------------------------------------- +respawndoor = trigger_ff_script:new({ team = Team.kUnassigned, allowdisguised=false }) + +function respawndoor:allowed( allowed_entity ) + if IsPlayer( allowed_entity ) then + + local player = CastToPlayer( allowed_entity ) + + if player:GetTeamId() == self.team then + return EVENT_ALLOWED + end + + if self.allowdisguised then + if player:IsDisguised() and player:GetDisguisedTeam() == self.team then + return EVENT_ALLOWED + end + end + end + return EVENT_DISALLOWED +end + +function respawndoor:onfailtouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + BroadCastMessageToPlayer( player, "#FF_NOTALLOWEDDOOR" ) + end +end + +bluerespawndoor = respawndoor:new({ team = Team.kBlue }) +redrespawndoor = respawndoor:new({ team = Team.kRed }) +greenrespawndoor = respawndoor:new({ team = Team.kGreen }) +yellowrespawndoor = respawndoor:new({ team = Team.kYellow }) + +----------------------------------------------------------------------------- +-- Elevator Triggers +----------------------------------------------------------------------------- + +elevator_trigger = respawndoor:new( {} ) + +function elevator_trigger:onfailtouch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + BroadCastMessageToPlayer( player, "#FF_NOTALLOWEDELEVATOR" ) + end +end + +blue_elevator_trigger = elevator_trigger:new({ team = Team.kBlue }) +red_elevator_trigger = elevator_trigger:new({ team = Team.kRed }) +green_elevator_trigger = elevator_trigger:new({ team = Team.kGreen }) +yellow_elevator_trigger = elevator_trigger:new({ team = Team.kYellow }) + +----------------------------------------------------------------------------- +-- Spawn functions +----------------------------------------------------------------------------- +redspawn = { validspawn = redallowedmethod } +bluespawn = { validspawn = blueallowedmethod } +greenspawn = { validspawn = greenallowedmethod } +yellowspawn = { validspawn = yellowallowedmethod } + +-- aliases for people that like underscores +red_spawn = redspawn; blue_spawn = bluespawn; +green_spawn = greenspawn; yellow_spawn = yellowspawn +blue_respawndoor = bluerespawndoor; red_respawndoor = redrespawndoor; +green_respawndoor = greenrespawndoor; yellow_respawndoor = yellowrespawndoor + +----------------------------------------------------------------------------- +-- Capture Points +----------------------------------------------------------------------------- +basecap = trigger_ff_script:new({ + health = 100, + armor = 300, + grenades = 200, + shells = 200, + nails = 200, + rockets = 200, + cells = 200, + detpacks = 1, + mancannons = 1, + gren1 = 4, + gren2 = 4, + item = "", + team = 0, + -- teampoints and fortpoints are defined as functions here for backwards compatibility (to always get the current value of the global variable) + -- when defining capture points that inherit from basecap, teampoints and fortpoints can be set to numbers instead + teampoints = function(cap, team) return POINTS_PER_CAPTURE end, + fortpoints = function(cap, player) return FORTPOINTS_PER_CAPTURE end, + botgoaltype = Bot.kFlagCap, +}) + +bluerspawn = info_ff_script:new() + +function basecap:allowed ( allowed_entity ) + if IsPlayer( allowed_entity ) then + -- get the player and his team + local player = CastToPlayer( allowed_entity ) + local team = player:GetTeam() + + -- check if the player is on our team + if team:GetTeamId() ~= self.team then + return false + end + + -- check if the player has the flag + for i,v in ipairs(self.item) do + local flag = GetInfoScriptByName(v) + + -- Make sure flag isn't nil + if flag then + if player:HasItem(flag:GetName()) then + return true + end + end + end + end + + return false +end + +function basecap:ontrigger ( trigger_entity ) + if IsPlayer( trigger_entity ) then + local player = CastToPlayer( trigger_entity ) + + -- player should capture now + for i,v in ipairs( self.item ) do + + -- find the flag and cast it to an info_ff_script + local flag = GetInfoScriptByName(v) + + -- Make sure flag isn't nil + if flag then + + -- check if the player is carrying the flag + if player:HasItem(flag:GetName()) then + flag.status = 0 + + -- reward player for capture + local fortpoints = (type(self.fortpoints) == "function" and self.fortpoints(self, player) or self.fortpoints) + player:AddFortPoints(fortpoints, "#FF_FORTPOINTS_CAPTUREFLAG") + + -- reward player's team for capture + local team = player:GetTeam() + local teampoints = (type(self.teampoints) == "function" and self.teampoints(self, team) or self.teampoints) + team:AddScore(teampoints) + + LogLuaEvent(player:GetId(), 0, "flag_capture","flag_name",flag:GetName()) + -- show on the deathnotice board + ObjectiveNotice( player, "captured the flag" ) + + -- clear the objective icon + UpdateObjectiveIcon( player, nil ) + + -- Remove any hud icons + RemoveHudItem( player, flag:GetName() ) + + -- return the flag + flag:Return() + + --Cappin cures what ails ya + player:RemoveEffect(EF.kOnfire) + player:RemoveEffect(EF.kConc) + player:RemoveEffect(EF.kGas) + player:RemoveEffect(EF.kInfect) + player:RemoveEffect(EF.kRadiotag) + player:RemoveEffect(EF.kTranq) + player:RemoveEffect(EF.kLegshot) + player:RemoveEffect(EF.kRadiotag) + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then player:AddHealth(self.health) end + if self.armor ~= nil and self.armor ~= 0 then player:AddArmor(self.armor) end + + -- give the player some ammo + if self.nails ~= nil and self.nails ~= 0 then player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then player:AddAmmo(Ammo.kGren2, self.gren2) end + + self:oncapture( player, v ) + end + end + end + end +end + +function basecap:oncapture(player, item) + -- let the teams know that a capture occured + SmartSound(player, "yourteam.flagcap", "yourteam.flagcap", "otherteam.flagcap") + SmartSpeak(player, "CTF_YOUCAP", "CTF_TEAMCAP", "CTF_THEYCAP") + SmartMessage(player, "#FF_YOUCAP", "#FF_TEAMCAP", "#FF_OTHERTEAMCAP", Color.kGreen, Color.kGreen, Color.kRed) +end + +----------------------------------------------------------------------------- +-- Flag +-- status: 0 = home, 1 = carried, 2 = dropped +----------------------------------------------------------------------------- +baseflag = info_ff_script:new({ + name = "base flag", + team = 0, + model = "models/flag/flag.mdl", + tosssound = "Flag.Toss", + modelskin = 1, + dropnotouchtime = 2, + capnotouchtime = 2, + botgoaltype = Bot.kFlag, + status = 0, + hudicon = "", + hudx = 5, + hudy = 114, + hudalign = 1, + hudstatusiconalign = 2, + hudstatusicon = "", + hudstatusiconx = 0, + hudstatusicony = 0, + hudstatusiconw = 50, + hudstatusiconh = 50, + allowdrop = true, + droppedlocation = "", + carriedby = "", + flagtoss = false, + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen} +}) + +function baseflag:precache() + PrecacheSound(self.tosssound) + PrecacheSound("yourteam.flagstolen") + PrecacheSound("otherteam.flagstolen") + PrecacheSound("yourteam.drop") + PrecacheSound("otherteam.drop") + PrecacheSound("yourteam.flagreturn") + PrecacheSound("otherteam.flagreturn") + PrecacheSound("yourteam.flagcap") + PrecacheSound("otherteam.flagcap") + info_ff_script.precache(self) +end + +function baseflag:spawn() + self.notouch = { } + info_ff_script.spawn(self) + local flag = CastToInfoScript( entity ) + LogLuaEvent(0, 0, "flag_spawn","flag_name",flag:GetName()) + self.status = 0 + self:refreshStatusIcons(flag:GetName()) +end + +function baseflag:addnotouch(player_id, duration) + self.notouch[player_id] = duration + AddSchedule(self.name .. "-" .. player_id, duration, self.removenotouch, self, player_id) +end + +function baseflag.removenotouch(self, player_id) + self.notouch[player_id] = nil +end + +function baseflag:touch( touch_entity ) + local player = CastToPlayer( touch_entity ) + -- pickup if they can + if self.notouch[player:GetId()] then return; end + + if player:GetTeamId() ~= self.team then + -- let the teams know that the flag was picked up + SmartSound(player, "yourteam.flagstolen", "yourteam.flagstolen", "otherteam.flagstolen") + RandomFlagTouchSpeak( player ) + SmartMessage(player, "#FF_YOUPICKUP", "#FF_TEAMPICKUP", "#FF_OTHERTEAMPICKUP", Color.kGreen, Color.kGreen, Color.kRed) + + -- if the player is a spy, then force him to lose his disguise + player:SetDisguisable( false ) + -- if the player is a spy, then force him to lose his cloak + player:SetCloakable( false ) + + -- note: this seems a bit backwards (Pickup verb fits Player better) + local flag = CastToInfoScript(entity) + flag:Pickup(player) + AddHudIcon( player, self.hudicon, flag:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign ) + + -- show on the deathnotice board + --ObjectiveNotice( player, "grabbed the flag" ) + -- log action in stats + LogLuaEvent(player:GetId(), 0, "flag_touch", "flag_name", flag:GetName(), "player_origin", (string.format("%0.2f",player:GetOrigin().x) .. ", " .. string.format("%0.2f",player:GetOrigin().y) .. ", " .. string.format("%0.1f",player:GetOrigin().z) ), "player_health", "" .. player:GetHealth()); + + local team = nil + -- get team as a lowercase string + if player:GetTeamId() == Team.kBlue then team = "blue" end + if player:GetTeamId() == Team.kRed then team = "red" end + if player:GetTeamId() == Team.kGreen then team = "green" end + if player:GetTeamId() == Team.kYellow then team = "yellow" end + + -- objective icon pointing to the cap + UpdateObjectiveIcon( player, GetEntityByName( team.."_cap" ) ) + + -- 100 points for initial touch on flag + if self.status == 0 then player:AddFortPoints(FORTPOINTS_PER_INITIALTOUCH, "#FF_FORTPOINTS_INITIALTOUCH") end + self.status = 1 + self.carriedby = player:GetName() + self:refreshStatusIcons(flag:GetName()) + + end +end + +function baseflag:onownerdie( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, flag:GetName() ) + + self.status = 2 + self.carriedby = "" + self.droppedlocation = player:GetLocation() + self:refreshStatusIcons(flag:GetName()) + + -- clear the objective icon + UpdateObjectiveIcon( player, nil ) + +end + +function baseflag:ownercloak( owner_entity ) + -- drop the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, 0.0) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, flag:GetName() ) + + self.status = 2 + self.carriedby = "" + self.droppedlocation = player:GetLocation() + self:refreshStatusIcons(flag:GetName()) + + -- clear the objective icon + UpdateObjectiveIcon( player, nil ) +end + +function baseflag:dropitemcmd( owner_entity ) + if allowdrop == false then return end + + --Used by logging + self.flagtoss = true + + -- throw the flag + local flag = CastToInfoScript(entity) + flag:Drop(FLAG_RETURN_TIME, FLAG_THROW_SPEED) + + -- remove flag icon from hud + local player = CastToPlayer( owner_entity ) + RemoveHudItem( player, flag:GetName() ) + + self.status = 2 + self.carriedby = "" + self.droppedlocation = player:GetLocation() + self:refreshStatusIcons(flag:GetName()) + + -- clear the objective icon + UpdateObjectiveIcon( player, nil ) +end + +function baseflag:ondrop( owner_entity ) + local player = CastToPlayer( owner_entity ) + -- let the teams know that the flag was dropped + SmartSound(player, "yourteam.drop", "yourteam.drop", "otherteam.drop") + SmartMessage(player, "#FF_YOUDROP", "#FF_TEAMDROP", "#FF_OTHERTEAMDROP", Color.kYellow, Color.kYellow, Color.kYellow) + + local flag = CastToInfoScript(entity) + --Log a toss if drop was intentional. Otherwise, drop + if self.flagtoss == true then + LogLuaEvent(player:GetId(), 0, "flag_thrown","flag_name",flag:GetName(), "player_origin", (string.format("%0.2f",player:GetOrigin().x) .. ", " .. string.format("%0.2f",player:GetOrigin().y) .. ", " .. string.format("%0.1f",player:GetOrigin().z) ), "player_health", "" ..player:GetHealth()); + + self.flagtoss = false + else + LogLuaEvent(player:GetId(), 0, "flag_dropped", "flag_name", flag:GetName(), "player_origin", (string.format("%0.2f",player:GetOrigin().x) .. ", " .. string.format("%0.2f",player:GetOrigin().y) .. ", " .. string.format("%0.1f",player:GetOrigin().z) )); + + end + + flag:EmitSound(self.tosssound) +end + +function baseflag:onloseitem( owner_entity ) + local flag = CastToInfoScript( entity ) + -- let the player that lost the flag put on a disguise + local player = CastToPlayer( owner_entity ) + player:SetDisguisable(true) + -- let player cloak if he can + player:SetCloakable( true ) + + self.status = 0 --For some reason, the flag won't register as home when captured, unless I do this. + self.carriedby = "" + self:refreshStatusIcons(flag:GetName()) + self:addnotouch(player:GetId(), self.capnotouchtime) +end + +function baseflag:onownerforcerespawn( owner_entity ) + local flag = CastToInfoScript( entity ) + local player = CastToPlayer( owner_entity ) + player:SetDisguisable( true ) + player:SetCloakable( true ) + RemoveHudItem( player, flag:GetName() ) + flag:Drop(0, FLAG_THROW_SPEED) + + self.status = 2 + self.carriedby = "" + self.droppedlocation = player:GetLocation() + self:refreshStatusIcons(flag:GetName()) + + -- clear the objective icon + UpdateObjectiveIcon( player, nil ) +end + +function baseflag:onreturn( ) + -- let the teams know that the flag was returned + local team = GetTeam( self.team ) + SmartTeamMessage(team, "#FF_TEAMRETURN", "#FF_OTHERTEAMRETURN", Color.kYellow, Color.kYellow) + SmartTeamSound(team, "yourteam.flagreturn", "otherteam.flagreturn") + SmartTeamSpeak(team, "CTF_FLAGBACK", "CTF_EFLAGBACK") + local flag = CastToInfoScript( entity ) + + LogLuaEvent(0, 0, "flag_returned","flag_name",flag:GetName()); + + RemoveHudItemFromAll( flag:GetName() .. "location" ) + self.status = 0 + self.droppedlocation = "" + self:refreshStatusIcons(flag:GetName()) +end + +function baseflag:hasanimation() return true end + +function baseflag:gettouchsize( mins, maxs ) + mins.x = mins.x * 0.75 + mins.y = mins.y * 0.75 + maxs.x = maxs.x * 0.75 + maxs.y = maxs.y * 0.75 + mins.z = 0 + maxs.z = maxs.z * 0.5 +end + +function baseflag:getphysicssize( mins, maxs ) + mins.x = mins.x / 2 + mins.y = mins.y / 2 + maxs.x = maxs.x / 2 + maxs.y = maxs.y / 2 + mins.z = 0 + maxs.z = 1 +end + +function baseflag:getbloatsize() + return 0 +end + +--All your flag HUD status needs in a convenient package (sort of) +function baseflag:refreshStatusIcons(flagname) + RemoveHudItemFromAll( flagname .. "_status" ) + RemoveHudItemFromAll( flagname .. "location" ) + RemoveHudItemFromAll( flagname .. "carrier" ) + RemoveHudItemFromAll( flagname .. "timer" ) + + if self.status == 1 then + AddHudTextToAll( flagname .. "carrier", self.carriedby, self.hudstatusiconx, (self.hudstatusicony + self.hudstatusiconh), self.hudstatusiconalign ) + AddHudIconToAll( self.hudstatusiconcarried, ( flagname .. "_status" ), self.hudstatusiconx, self.hudstatusicony, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconalign ) + elseif self.status == 2 then + AddHudTextToAll( flagname .. "location", self.droppedlocation, self.hudstatusiconx + 24, (self.hudstatusicony + self.hudstatusiconh), self.hudstatusiconalign ) + AddHudTimerToAll( flagname .. "timer", FLAG_RETURN_TIME+1, -1, self.hudstatusiconx, (self.hudstatusicony + self.hudstatusiconh), self.hudstatusiconalign ) + AddHudIconToAll( self.hudstatusicondropped, ( flagname .. "_status" ), self.hudstatusiconx, self.hudstatusicony, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconalign ) + else + AddHudIconToAll( self.hudstatusiconhome, ( flagname .. "_status" ), self.hudstatusiconx, self.hudstatusicony, self.hudstatusiconw, self.hudstatusiconh, self.hudstatusiconalign ) + end +end + +----------------------------------------------------------------------------- +--flaginfo, basic version. If you override flaginfo in a map's lua, call this to get default functionality. +----------------------------------------------------------------------------- +function flaginfo_base( player_entity ) + local player = CastToPlayer( player_entity ) + + local flag = GetInfoScriptByName("blue_flag") + if flag then + local flagname = flag:GetName() + + RemoveHudItem( player, flagname .. "_status" ) + RemoveHudItem( player, "blue_flagcarrier" ) + RemoveHudItem( player, "blue_flaglocation" ) + + if flag:IsCarried() then + AddHudText( player, "blue_flagcarrier", blue_flag.carriedby, blue_flag.hudstatusiconx, (blue_flag.hudstatusicony + blue_flag.hudstatusiconh), blue_flag.hudstatusiconalign ) + AddHudIcon( player, blue_flag.hudstatusiconcarried, ( flagname .. "_status" ), blue_flag.hudstatusiconx, blue_flag.hudstatusicony, blue_flag.hudstatusiconw, blue_flag.hudstatusiconh, blue_flag.hudstatusiconalign ) + elseif flag:IsDropped() then + AddHudText( player, "blue_flaglocation", blue_flag.droppedlocation, blue_flag.hudstatusiconx + 24, (blue_flag.hudstatusicony + blue_flag.hudstatusiconh), blue_flag.hudstatusiconalign ) + AddHudIcon( player, blue_flag.hudstatusicondropped, ( flagname .. "_status" ), blue_flag.hudstatusiconx, blue_flag.hudstatusicony, blue_flag.hudstatusiconw, blue_flag.hudstatusiconh, blue_flag.hudstatusiconalign ) + else + AddHudIcon( player, blue_flag.hudstatusiconhome, ( flagname .. "_status" ), blue_flag.hudstatusiconx, blue_flag.hudstatusicony, blue_flag.hudstatusiconw, blue_flag.hudstatusiconh, blue_flag.hudstatusiconalign ) + end + end + local flag = GetInfoScriptByName("red_flag") + if flag then + local flagname = flag:GetName() + + RemoveHudItem( player, flagname .. "_status" ) + RemoveHudItem( player, "red_flagcarrier" ) + RemoveHudItem( player, "red_flaglocation" ) + + if flag:IsCarried() then + AddHudText( player, "red_flagcarrier", red_flag.carriedby, red_flag.hudstatusiconx, (red_flag.hudstatusicony + red_flag.hudstatusiconh), red_flag.hudstatusiconalign ) + AddHudIcon( player, red_flag.hudstatusiconcarried, ( flagname .. "_status" ), red_flag.hudstatusiconx, red_flag.hudstatusicony, red_flag.hudstatusiconw, red_flag.hudstatusiconh, red_flag.hudstatusiconalign ) + elseif flag:IsDropped() then + AddHudText( player, "red_flaglocation", red_flag.droppedlocation, red_flag.hudstatusiconx + 24, (red_flag.hudstatusicony + red_flag.hudstatusiconh), red_flag.hudstatusiconalign ) + AddHudIcon( player, red_flag.hudstatusicondropped, ( flagname .. "_status" ), red_flag.hudstatusiconx, red_flag.hudstatusicony, red_flag.hudstatusiconw, red_flag.hudstatusiconh, red_flag.hudstatusiconalign ) + else + AddHudIcon( player, red_flag.hudstatusiconhome, ( flagname .. "_status" ), red_flag.hudstatusiconx, red_flag.hudstatusicony, red_flag.hudstatusiconw, red_flag.hudstatusiconh, red_flag.hudstatusiconalign ) + end + end + local flag = GetInfoScriptByName("yellow_flag") + if flag then + local flagname = flag:GetName() + + RemoveHudItem( player, flagname .. "_status" ) + RemoveHudItem( player, "yellow_flagcarrier" ) + RemoveHudItem( player, "yellow_flaglocation" ) + + if flag:IsCarried() then + AddHudText( player, "yellow_flagcarrier", yellow_flag.carriedby, yellow_flag.hudstatusiconx, (yellow_flag.hudstatusicony + yellow_flag.hudstatusiconh), yellow_flag.hudstatusiconalign ) + AddHudIcon( player, yellow_flag.hudstatusiconcarried, ( flagname .. "_status" ), yellow_flag.hudstatusiconx, yellow_flag.hudstatusicony, yellow_flag.hudstatusiconw, yellow_flag.hudstatusiconh, yellow_flag.hudstatusiconalign ) + elseif flag:IsDropped() then + AddHudText( player, "yellow_flaglocation", yellow_flag.droppedlocation, yellow_flag.hudstatusiconx + 24, (yellow_flag.hudstatusicony + yellow_flag.hudstatusiconh), yellow_flag.hudstatusiconalign ) + AddHudIcon( player, yellow_flag.hudstatusicondropped, ( flagname .. "_status" ), yellow_flag.hudstatusiconx, yellow_flag.hudstatusicony, yellow_flag.hudstatusiconw, yellow_flag.hudstatusiconh, yellow_flag.hudstatusiconalign ) + else + AddHudIcon( player, yellow_flag.hudstatusiconhome, ( flagname .. "_status" ), yellow_flag.hudstatusiconx, yellow_flag.hudstatusicony, yellow_flag.hudstatusiconw, yellow_flag.hudstatusiconh, yellow_flag.hudstatusiconalign ) + end + end + local flag = GetInfoScriptByName("green_flag") + if flag then + local flagname = flag:GetName() + + RemoveHudItem( player, flagname .. "_status" ) + RemoveHudItem( player, "green_flagcarrier" ) + RemoveHudItem( player, "green_flaglocation" ) + + if flag:IsCarried() then + AddHudText( player, "green_flagcarrier", green_flag.carriedby, green_flag.hudstatusiconx, (green_flag.hudstatusicony + green_flag.hudstatusiconh), green_flag.hudstatusiconalign ) + AddHudIcon( player, green_flag.hudstatusiconcarried, ( flagname .. "_status" ), green_flag.hudstatusiconx, green_flag.hudstatusicony, green_flag.hudstatusiconw, green_flag.hudstatusiconh, green_flag.hudstatusiconalign ) + elseif flag:IsDropped() then + AddHudText( player, "green_flaglocation", green_flag.droppedlocation, green_flag.hudstatusiconx + 24, (green_flag.hudstatusicony + green_flag.hudstatusiconh), green_flag.hudstatusiconalign ) + AddHudIcon( player, green_flag.hudstatusicondropped, ( flagname .. "_status" ), green_flag.hudstatusiconx, green_flag.hudstatusicony, green_flag.hudstatusiconw, green_flag.hudstatusiconh, green_flag.hudstatusiconalign ) + else + AddHudIcon( player, green_flag.hudstatusiconhome, ( flagname .. "_status" ), green_flag.hudstatusiconx, green_flag.hudstatusicony, green_flag.hudstatusiconw, green_flag.hudstatusiconh, green_flag.hudstatusiconalign ) + end + end +end +----------------------------------------------------------------------------- +-- Dettable triggers. Use this to make triggers that respond to a detpack explosion. +----------------------------------------------------------------------------- + +detpack_trigger = trigger_ff_script:new({ team = Team.kUnassigned, team_name = "neutral" }) + +function detpack_trigger:onexplode( explosion_entity ) + if IsDetpack( explosion_entity ) then + local detpack = CastToDetpack( explosion_entity ) + + if detpack:GetTeamId() ~= self.team then + -- Generic 'trigger' output for use with logic_ entities. + OutputEvent( self.team_name .. "_det_relay", "trigger" ) + end + end + + return EVENT_ALLOWED +end + +red_detpack_trigger = detpack_trigger:new({ team = Team.kRed, team_name = "red" }) +blue_detpack_trigger = detpack_trigger:new({ team = Team.kBlue, team_name = "blue" }) +green_detpack_trigger = detpack_trigger:new({ team = Team.kGreen, team_name = "green" }) +yellow_detpack_trigger = detpack_trigger:new({ team = Team.kYellow, team_name = "yellow" }) + +----------------------------------------------------------------------------- +-- backpack entity setup +----------------------------------------------------------------------------- +function build_backpacks(tf) + return healthkit:new({touchflags = tf}), + armorkit:new({touchflags = tf}), + ammobackpack:new({touchflags = tf}), + bigpack:new({touchflags = tf}), + grenadebackpack:new({touchflags = tf}) +end + +blue_healthkit, blue_armorkit, blue_ammobackpack, blue_bigpack, blue_grenadebackpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kBlue}) +red_healthkit, red_armorkit, red_ammobackpack, red_bigpack ,red_grenadebackpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kRed}) +yellow_healthkit, yellow_armorkit, yellow_ammobackpack, yellow_bigpack, yellow_grenadebackpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kYellow}) +green_healthkit, green_armorkit, green_ammobackpack, green_bigpack, green_grenadebackpack = build_backpacks({AllowFlags.kOnlyPlayers,AllowFlags.kGreen}) + +----------------------------------------------------------------------------- +-- plays random flag touched sounds to avoid repetition +-- use instead of: SmartSpeak(player, "CTF_YOUGOTFLAG", "CTF_GOTFLAG", "CTF_LOSTFLAG") +----------------------------------------------------------------------------- +function RandomFlagTouchSpeak( player ) + local rnd = RandomInt(1,4) + if rnd == 1 then SmartSpeak(player, "CTF_YOUGOTFLAG", "CTF_GOTFLAG", "CTF_LOSTFLAG") + elseif rnd == 2 then SmartSpeak(player, "CTF_YOUGOTFLAG2", "CTF_GOTFLAG2", "CTF_LOSTFLAG2") + elseif rnd == 3 then SmartSpeak(player, "CTF_YOUGOTFLAG3", "CTF_GOTFLAG3", "CTF_LOSTFLAG3") + else SmartSpeak(player, "CTF_YOUGOTFLAG4", "CTF_GOTFLAG4", "CTF_LOSTFLAG4") end +end diff --git a/maps/includes/base_test.lua b/maps/includes/base_test.lua new file mode 100644 index 0000000..8dd5244 --- /dev/null +++ b/maps/includes/base_test.lua @@ -0,0 +1,5 @@ +ConsoleToAll("base_test loaded!"); + +function tick() + ConsoleToAll("Tick"); +end diff --git a/maps/includes/base_training.lua b/maps/includes/base_training.lua new file mode 100644 index 0000000..e5d7c56 --- /dev/null +++ b/maps/includes/base_training.lua @@ -0,0 +1,658 @@ +-- base_training.lua + +-- contains common useful functionality for maps that include training elements. + +IncludeScript("base_teamplay") +IncludeScript("base_respawnturret") + +----------------------------------------------------------------------------- +-- helper functions +----------------------------------------------------------------------------- + +function restoreEntityByName(name) + local e = GetInfoScriptByName(name) + if e ~= nil then e:Restore() end +end + +----------------------------------------------------------------------------- +-- glass +----------------------------------------------------------------------------- + +breakable_glass = info_ff_script:new({ }) + +function breakable_glass:spawn() end + +function breakable_glass:OnBreak() + if self.BotSignal ~= nil then + bot.signal(self.BotSignal.."_OnBreak") + end +end + +function breakable_glass:ondamage() end + +----------------------------------------------------------------------------- +-- Class specific trainer spawns +----------------------------------------------------------------------------- +training_spawn = info_ff_script:new({ + name="Trainer", + model="", + botteam=Team.kYellow, + botclass=0, + botgoaltype=Bot.kTrainerSpawn, +}) + +function training_spawn:spawn() + info_ff_script.spawn(self) + + local info = CastToInfoScript(entity) + info:SpawnBot(self.name, self.botteam, self.botclass); +end + +scout_trainer = training_spawn:new({ name="Scout Instructor", botclass=Player.kScout, }) +sniper_trainer = training_spawn:new({ name="Sniper Instructor", botclass=Player.kSniper, }) +soldier_trainer = training_spawn:new({ name="Soldier Instructor", botclass=Player.kSoldier, }) +demoman_trainer = training_spawn:new({ name="Demo-man Instructor", botclass=Player.kDemoman, }) +medic_trainer = training_spawn:new({ name="Medic Instructor", botclass=Player.kMedic, }) +hwguy_trainer = training_spawn:new({ name="HwGuy Instructor", botclass=Player.kHwguy, }) +pyro_trainer = training_spawn:new({ name="Pyro Instructor", botclass=Player.kPyro, }) +engineer_trainer = training_spawn:new({ name="Engineer Instructor", botclass=Player.kEngineer, }) +spy_trainer = training_spawn:new({ name="Spy Instructor", botclass=Player.kSpy, }) +civilian_trainer = training_spawn:new({ name="Civilian Instructor", botclass=Player.kCivilian, }) + +random_target = training_spawn:new({ name="Target", botclass=Player.kRandom, }) + +----------------------------------------------------------------------------- +-- Training buttons +----------------------------------------------------------------------------- + +train_button = func_button:new({}) +function train_button:allowed() return true end +function train_button:ondamage() end +function train_button:ontouch() end +function train_button:onuse() + + if self.restoreentity ~= nil then + local e = GetInfoScriptByName(self.restoreentity) + if e ~= nil then + e:Restore() + else + ConsoleToAll("Could not restore " .. self.restoreentity) + end + end + + bot.signal(entity:GetName()) + + ConsoleToAll(entity:GetName() .. " onuse") +end + +function train_button:onfailuse() + ConsoleToAll("button failuse") +end + +----------------------------------------------------------------------------- +-- Fake weapon pickups +----------------------------------------------------------------------------- + +fakeweapon_spawn = info_ff_script:new({ + model = "models/items/backpack/backpack.mdl", + weaponname = "ff_weapon_crowbar", + ammo = {}, + touchsound = "HealthKit.Touch", + materializesound = "Item.Materialize", + respawntime = 5, + removeOnSpawn = false, + touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen} +}) + +function fakeweapon_spawn:spawn() + + -- temporary override + --self.model = "models/items/backpack/backpack.mdl" + + info_ff_script.spawn(self) + + local info = CastToInfoScript(entity) + if self.removeOnSpawn then + info:Remove() + end +end + +function fakeweapon_spawn:precache( ) + PrecacheSound(self.materializesound) + PrecacheSound(self.touchsound) + --PrecacheModel(self.model) +end + +function fakeweapon_spawn:materialize( ) + entity:EmitSound(self.materializesound) +end + +function fakeweapon_spawn:touch( touch_entity ) + if IsPlayer( touch_entity ) then + local player = CastToPlayer( touch_entity ) + + local dispensed = 0 + + if self.weaponclass ~= nil and not player:OwnsWeaponType(self.weaponclass) then + player:GiveWeapon(self.weaponclass) + dispensed = dispensed + 1 + end + + if self.weaponclass2 ~= nil and not player:OwnsWeaponType(self.weaponclass2) then + player:GiveWeapon(self.weaponclass2) + dispensed = dispensed + 1 + end + + -- give player some health and armor + if self.health ~= nil and self.health ~= 0 then player:AddHealth(self.health) end + if self.armor ~= nil and self.armor ~= 0 then player:AddArmor(self.armor) end + + -- give the player some ammo + if self.nails ~= nil and self.nails ~= 0 then player:AddAmmo(Ammo.kNails, self.nails) end + if self.shells ~= nil and self.shells ~= 0 then player:AddAmmo(Ammo.kShells, self.shells) end + if self.rockets ~= nil and self.rockets ~= 0 then player:AddAmmo(Ammo.kRockets, self.rockets) end + if self.cells ~= nil and self.cells ~= 0 then player:AddAmmo(Ammo.kCells, self.cells) end + if self.detpacks ~= nil and self.detpacks ~= 0 then player:AddAmmo(Ammo.kDetpack, self.detpacks) end + if self.mancannons ~= nil and self.mancannons ~= 0 then player:AddAmmo(Ammo.kManCannon, self.mancannons) end + if self.gren1 ~= nil and self.gren1 ~= 0 then player:AddAmmo(Ammo.kGren1, self.gren1) end + if self.gren2 ~= nil and self.gren2 ~= 0 then player:AddAmmo(Ammo.kGren2, self.gren2) end + + if dispensed > 0 then + local item = CastToInfoScript(entity); + item:EmitSound(self.touchsound) + + -- Do this or don't call Respawn? + --item:SetStartOrigin(item:GetOrigin()) + --item:SetStartAngles(item:GetAngles()) + + --item:Remove() + --item:Respawn(self.respawntime); + end + + end +end + +function fakeweapon_spawn:add_weapon( weaponname ) + ConsoleToAll("fakeweapon_spawn:add_weapon " .. weaponname) + self.weaponclass2 = weaponname +end + +----------------------------------------------------------------------------- +-- Weapon pickup variations. +----------------------------------------------------------------------------- + +weapon_assaultcannon = fakeweapon_spawn:new({ model = "models/weapons/assaultcannon/w_assaultcannon.mdl", weaponclass = "ff_weapon_assaultcannon", shells = 400 }) +weapon_autorifle = fakeweapon_spawn:new({ model = "models/weapons/autorifle/w_autorifle.mdl", weaponclass = "ff_weapon_autorifle", shells = 400 }) +weapon_crowbar = fakeweapon_spawn:new({ model = "models/weapons/crowbar/w_crowbar.mdl", weaponclass = "ff_weapon_crowbar", }) +weapon_flamethrower = fakeweapon_spawn:new({ model = "models/weapons/flamethrower/w_flamethrower.mdl", weaponclass = "ff_weapon_flamethrower", cells = 400 }) +weapon_grenadelauncher = fakeweapon_spawn:new({ model = "models/weapons/grenadelauncher/w_grenadelauncher.mdl", weaponclass = "ff_weapon_grenadelauncher", rockets = 400 }) +weapon_incendiarycannon = fakeweapon_spawn:new({ model = "models/weapons/incendiarycannon/w_incendiarycannon.mdl", weaponclass = "ff_weapon_ic", rockets = 400 }) +weapon_knife = fakeweapon_spawn:new({ model = "models/weapons/knife/w_knife.mdl", weaponclass = "ff_weapon_knife" }) +weapon_medkit = fakeweapon_spawn:new({ model = "models/weapons/medkit/w_medkit.mdl", weaponclass = "ff_weapon_medkit" }) +weapon_nailgun = fakeweapon_spawn:new({ model = "models/weapons/nailgun/w_nailgun.mdl", weaponclass = "ff_weapon_nailgun", nails = 400 }) +weapon_pipelauncher = fakeweapon_spawn:new({ model = "models/weapons/pipelauncher/w_pipelauncher.mdl", weaponclass = "ff_weapon_pipelauncher", rockets = 400 }) +weapon_railgun = fakeweapon_spawn:new({ model = "models/weapons/railgun/w_railgun.mdl", weaponclass = "ff_weapon_railgun", nails = 400 }) +weapon_rpg = fakeweapon_spawn:new({ model = "models/weapons/rpg/w_rpg.mdl", weaponclass = "ff_weapon_rpg", rockets = 400 }) +weapon_shotgun = fakeweapon_spawn:new({ model = "models/weapons/shotgun/w_shotgun.mdl", weaponclass = "ff_weapon_shotgun", shells = 400 }) +weapon_sniperrifle = fakeweapon_spawn:new({ model = "models/weapons/sniperrifle/w_sniperrifle.mdl", weaponclass = "ff_weapon_sniperrifle", nails = 400 }) +weapon_spanner = fakeweapon_spawn:new({ model = "models/weapons/spanner/w_spanner.mdl", weaponclass = "ff_weapon_spanner" }) +weapon_supernailgun = fakeweapon_spawn:new({ model = "models/weapons/supernailgun/w_supernailgun.mdl", weaponclass = "ff_weapon_supernailgun", nails = 400 }) +weapon_supershotgun = fakeweapon_spawn:new({ model = "models/weapons/supershotgun/w_supershotgun.mdl", weaponclass = "ff_weapon_supershotgun", shells = 400 }) +weapon_tommygun = fakeweapon_spawn:new({ model = "models/weapons/tommygun/w_tommygun.mdl", weaponclass = "ff_weapon_tommygun", shells = 400 }) +weapon_tranq = fakeweapon_spawn:new({ model = "models/weapons/tranq/w_tranq.mdl", weaponclass = "ff_weapon_tranq", nails = 400 }) +weapon_umbrella = fakeweapon_spawn:new({ model = "models/weapons/umbrella/w_umbrella.mdl", weaponclass = "ff_weapon_umbrella" }) + +grenade_pack = fakeweapon_spawn:new({ model = "models/items/backpack/backpack.mdl", gren1 = 4, gren2 = 4 }) + +weapon_sentry = fakeweapon_spawn:new({ weaponclass = "ff_weapon_deploysentrygun" }) +weapon_dispenser = fakeweapon_spawn:new({ weaponclass = "ff_weapon_deploydispenser" }) + +----------------------------------------------------------------------------- +-- class scanner triggers +----------------------------------------------------------------------------- + +function perform_player_scan(player, expectedclass, respawnturret) + + if expectedclass ~= player:GetClass() then + BroadCastMessage("Wrong Class") + respawnturret.killplayer = true + else + --BroadCastMessage("Wrong Class") + end +end + +scanner_class = trigger_ff_script:new({ }) + +function scanner_class:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + AddSchedule("perform_player_scan", 0, perform_player_scan, p, self.class, self.turret) + end + end +end + +function scanner_class:onendtouch() + RemoveSchedule("perform_player_scan") +end + +scout_scanner = scanner_class:new({ class=Player.kScout, }) +sniper_scanner = scanner_class:new({ class=Player.kSniper, }) +soldier_scanner = scanner_class:new({ class=Player.kSoldier, }) +demoman_scanner = scanner_class:new({ class=Player.kDemoman, }) +medic_scanner = scanner_class:new({ class=Player.kMedic, }) +hwguy_scanner = scanner_class:new({ class=Player.kHwguy, }) +pyro_scanner = scanner_class:new({ class=Player.kPyro, }) +engineer_scanner = scanner_class:new({ class=Player.kEngineer, }) +spy_scanner = scanner_class:new({ class=Player.kSpy, }) +civilian_scanner = scanner_class:new({ class=Player.kCivilian, }) + +----------------------------------------------------------------------------- +-- class turrets +----------------------------------------------------------------------------- + +scanner_turret = respawnturret:new({ team = Team.kGreen }) +function scanner_turret:deploydelay( target_entity ) return 0.5 end + +function scanner_turret:validtarget( target_entity ) + --local entity = GetEntity(ent_id) + + if self.killplayer then + local player = CastToPlayer( target_entity ) + if player ~= nil and not player:IsBot() then + return true + end + end + + if not AreTeamsAllied(self.team, target_entity:GetTeamId()) then return true end + + return false +end + +scout_turret = scanner_turret:new({ class=Player.kScout, }) +sniper_turret = scanner_turret:new({ class=Player.kSniper, }) +soldier_turret = scanner_turret:new({ class=Player.kSoldier, }) +demoman_turret = scanner_turret:new({ class=Player.kDemoman, }) +medic_turret = scanner_turret:new({ class=Player.kMedic, }) +hwguy_turret = scanner_turret:new({ class=Player.kHwguy, }) +pyro_turret = scanner_turret:new({ class=Player.kPyro, }) +engineer_turret = scanner_turret:new({ class=Player.kEngineer, }) +spy_turret = scanner_turret:new({ class=Player.kSpy, }) +civilian_turret = scanner_turret:new({ class=Player.kCivilian, }) + +----------------------------------------------------------------------------- +-- class holograms +----------------------------------------------------------------------------- + +base_hologram = info_ff_script:new({ model = "models/player/pyro/pyro.mdl", renderfx = RenderFx.kHologram }) + +scout_hologram = base_hologram:new({ model = "models/player/scout/scout.mdl" }) +sniper_hologram = base_hologram:new({ model = "models/player/sniper/sniper.mdl" }) +soldier_hologram = base_hologram:new({ model = "models/player/soldier/soldier.mdl" }) +demoman_hologram = base_hologram:new({ model = "models/player/demoman/demoman.mdl" }) +medic_hologram = base_hologram:new({ model = "models/player/medic/medic.mdl" }) +hwguy_hologram = base_hologram:new({ model = "models/player/hwguy/hwguy.mdl" }) +pyro_hologram = base_hologram:new({ model = "models/player/pyro/pyro.mdl" }) +engineer_hologram = base_hologram:new({ model = "models/player/engineer/engineer.mdl" }) +spy_hologram = base_hologram:new({ model = "models/player/spy/spy.mdl" }) + +----------------------------------------------------------------------------- +-- Beams +----------------------------------------------------------------------------- + +base_beam = baseclass:new({ startstate="on",startcolor="0 255 0" }) +function base_beam:spawn() + + if startstate == "on" then + OutputEvent( entity:GetName(), "TurnOn" ) + else + OutputEvent( entity:GetName(), "TurnOff" ) + end + + if startstate ~= nil then + OutputEvent( entity:GetName(), "Color", startcolor ) + end + +end + +function base_beam:turnon() + OutputEvent( entity:GetName(), "TurnOn" ) +end + +function base_beam:turnoff() + OutputEvent( entity:GetName(), "TurnOff" ) +end + +function base_beam:setcolor(newcolor) + if newcolor ~= nil then + OutputEvent( entity:GetName(), "Color", newcolor ) + end +end + +----------------------------------------------------------------------------- +-- training room triggers +----------------------------------------------------------------------------- +training_room = trigger_ff_script:new({ }) + +function training_room:allowed() + +-- if self.restrictClass ~= nil then +-- entity:EmitSound(self.speakOnceOnEnter) +-- end + + return EVENT_ALLOWED +end + +function training_room:ontrigger() + --ConsoleToAll("training_room:ontrigger() ") +end + +function training_room:ontouch( touch_entity ) + if IsPlayer( touch_entity ) then + local p = CastToPlayer( touch_entity ) + if not p:IsBot() then + bot.signal(entity:GetName()) + end + end + + ------------------ + ConsoleToAll(entity:GetName() .. " ontouch") + ------------------ +end + +function training_room:onendtouch() + ------------------ + ConsoleToAll(entity:GetName() .. " onendtouch") + ------------------ +end + +function training_room:onfailtouch() +end + +function training_room:onexplode() + return EVENT_ALLOWED +end + +function training_room:onbuild() + return EVENT_ALLOWED +end + +function training_room:onfailuse() +end + +function training_room:onuse() + +end + +function training_room:onactive() +end + +function training_room:oninactive() +end + +function training_room:onremoved() + +end + +function training_room:onrestored() +end + +function training_room:spawn() + +end + +----------------------------------------------------------------------------- +-- current training status +----------------------------------------------------------------------------- + + +----------------------------------------------------------------------------- +-- bot helper functions +----------------------------------------------------------------------------- +function restore_entity(entname) + local info = GetInfoScriptByName(entname) + if info ~= nil then + info:Restore() + end +end + +function remove_entity(entname) + local info = GetInfoScriptByName(entname) + if info ~= nil then + info:Remove() + end +end + +function update_grenadecount(entname, g1, g2) + local info = GetInfoScriptByName(entname) + if info ~= nil then + info.gren1 = tonumber(g1) + info.gren2 = tonumber(g2) + end +end + +function vec_tostring(v) + return string.format("%f %f %f", v.x, v.y, v.z) +end + +bot = {} + +bot.spawnAtEntity = function(spawnent, name, team, class) + local info = GetInfoScriptByName(spawnent) + if info ~= nil then + info:SpawnBot(name, team, class); + end +end + +bot.sendMsg = function(botname, msg, d1, d2, d3) + local p = GetPlayerByName(botname) + if p ~= nil then + p:SendBotMessage(msg, d1, d2, d3) + else + ConsoleToAll("bot.sendMsg: player not found: " .. botname) + end +end + +bot.signal = function(signalname) + SendBotSignal(signalname) +end + +bot.moveTo = function(botname, targetentity) + local e = GetEntityByName(targetentity) + if e ~= nil then + local epos = e:GetOrigin() + local eface = e:GetAbsFacing() + -- convert epos to string + bot.sendMsg(botname, "run_to", vec_tostring(epos), vec_tostring(eface)) + end +end + +bot.setIdlePoint = function(botname, targetentity) + local e = GetEntityByName(targetentity) + if e ~= nil then + local epos = e:GetOrigin() + local eface = e:GetAbsFacing() + -- convert epos to string + bot.sendMsg(botname, "set_idle_position", vec_tostring(epos), vec_tostring(eface)) + end +end + +bot.leaveGame = function(botname) + bot.sendMsg(botname, "leave_game") +end + +-- teleportTo(botname, targetEntName) +-- local p = GetPlayerByName(botname) +-- local e = GetEntityByName(targetentity) +-- if p ~= nil and e ~= nil then +-- p:SetOrigin(e:GetOrigin()) +-- p:SetAngles(e:GetAngles()) +-- else +-- ConsoleToAll("teleportTo: player not found: " .. botname) +-- end +-- end + +function player_giveweapon(weaponname, as) + local c = Collection() + c:GetByFilter({ CF.kHumanPlayers }) + for temp in c.items do + local player = CastToPlayer( temp ) + local autoselect = false + if as == "true" then autoselect = true end + player:GiveWeapon(weaponname, autoselect) + end +end + +function player_giveammo(ammoname, amount) + local c = Collection() + c:GetByFilter({ CF.kHumanPlayers }) + for temp in c.items do + local player = CastToPlayer( temp ) + if ammoname == "nails" then player:AddAmmo(Ammo.kNails, tonumber(amount)) end + if ammoname == "shells" then player:AddAmmo(Ammo.kShells, tonumber(amount)) end + if ammoname == "rockets" then player:AddAmmo(Ammo.kRockets, tonumber(amount)) end + if ammoname == "cells" then player:AddAmmo(Ammo.kCells, tonumber(amount)) end + if ammoname == "detpack" then player:AddAmmo(Ammo.kDetpack, tonumber(amount)) end + if ammoname == "mancannon" then player:AddAmmo(Ammo.kManCannon, tonumber(amount)) end + if ammoname == "gren1" then player:AddAmmo(Ammo.kGren1, tonumber(amount)) end + if ammoname == "gren2" then player:AddAmmo(Ammo.kGren2, tonumber(amount)) end + end +end +function player_removeweapon(weaponname) + local c = Collection() + c:GetByFilter({ CF.kHumanPlayers }) + for temp in c.items do + local player = CastToPlayer( temp ) + player:RemoveWeapon(weaponname) + end +end + +function player_givedetpack() + local c = Collection() + c:GetByFilter({ CF.kHumanPlayers }) + for temp in c.items do + local player = CastToPlayer( temp ) + player:AddAmmo(Ammo.kDetpack, 1) + end +end + +function player_givemancannon() + local c = Collection() + c:GetByFilter({ CF.kHumanPlayers }) + for temp in c.items do + local player = CastToPlayer( temp ) + player:AddAmmo(Ammo.kManCannon, 1) + end +end + +function player_givegren1() + local c = Collection() + c:GetByFilter({ CF.kHumanPlayers }) + for temp in c.items do + local player = CastToPlayer( temp ) + player:AddAmmo(Ammo.kGren1, 4) + end +end + +function player_givegren2() + local c = Collection() + c:GetByFilter({ CF.kHumanPlayers }) + for temp in c.items do + local player = CastToPlayer( temp ) + player:AddAmmo(Ammo.kGren2, 4) + end +end + +function player_removehealth(playername, amt) + p = GetPlayerByName(playername) + if p ~= nil then + p:AddHealth(-tonumber(amt)) + else + ConsoleToAll("player_removehealth: Unable to find " .. playername) + end +end + +function player_removearmor(playername, amt) + p = GetPlayerByName(playername) + if p ~= nil then + p:RemoveArmor(tonumber(amt)) + else + ConsoleToAll("player_removehealth: Unable to find " .. playername) + end +end + +function player_forcerespawn(playername, amt) + p = GetPlayerByName(playername) + if p ~= nil then + ApplyToPlayer(p, { AT.kRespawnPlayers }) + else + ConsoleToAll("player_forcerespawn: Unable to find " .. playername) + end +end + +function broadcast_message(message) + BroadCastMessage(message) +end + +function training_intro(classname) + if classname == "Scout" then + BroadCastSound("training.fem_scout_ovr") + elseif classname == "Sniper" then + BroadCastSound("training.fem_sniper_ovr") + elseif classname == "Soldier" then + BroadCastSound("training.fem_soldier_ovr") + elseif classname == "Demoman" then + BroadCastSound("training.fem_demo_ovr") + elseif classname == "Medic" then + BroadCastSound("training.fem_medic_ovr") + elseif classname == "HwGuy" then + BroadCastSound("training.fem_hwguy_ovr") + elseif classname == "Pyro" then + BroadCastSound("training.fem_pyro_ovr") + elseif classname == "Spy" then + BroadCastSound("training.fem_spy_ovr") + elseif classname == "Engineer" then + BroadCastSound("training.fem_engy_ovr") + end +end + +function section_complete(sectionname, room) + BroadCastSound("training.section_complete") +end + +function training_complete(classname) + if classname == "Scout" then + BroadCastSound("training.fem_scout_comp") + elseif classname == "Sniper" then + BroadCastSound("training.fem_sniper_comp") + elseif classname == "Soldier" then + BroadCastSound("training.fem_soldier_comp") + elseif classname == "Demoman" then + BroadCastSound("training.fem_demo_comp") + elseif classname == "Medic" then + BroadCastSound("training.fem_medic_comp") + elseif classname == "HwGuy" then + BroadCastSound("training.fem_hwguy_comp") + elseif classname == "Pyro" then + BroadCastSound("training.fem_pyro_comp") + elseif classname == "Spy" then + BroadCastSound("training.fem_spy_comp") + elseif classname == "Engineer" then + BroadCastSound("training.fem_engy_comp") + end +end + +function training_classname(classId) + if classId == Player.kScout then return "Scout" end + if classId == Player.kSniper then return "Sniper" end + if classId == Player.kSoldier then return "Soldier" end + if classId == Player.kDemoman then return "Demoman" end + if classId == Player.kMedic then return "Medic" end + if classId == Player.kHwguy then return "HwGuy" end + if classId == Player.kPyro then return "Pyro" end + if classId == Player.kSpy then return "Spy" end + if classId == Player.kEngineer then return "Engineer" end + if classId == Player.kCivilian then return "Civilian" end +end + + diff --git a/motd.txt b/motd.txt new file mode 100644 index 0000000..afe91e0 --- /dev/null +++ b/motd.txt @@ -0,0 +1 @@ +Welcome to Fortress-Forever. \ No newline at end of file diff --git a/pure_server_whitelist.txt b/pure_server_whitelist.txt new file mode 100644 index 0000000..ef660db --- /dev/null +++ b/pure_server_whitelist.txt @@ -0,0 +1,60 @@ +whitelist +{ + // + // 3 modifiers are allowed on file specifications: + // + // from_steam - only check the Steam cache for the file (ignore anything on disk) + // allow_from_disk - allow the file to come from disk + // check_crc - used with allow_from_disk - server does CRC checks on the client's file to make sure it matches + // + // The default modifier on all files is allow_from_disk. Thus, all files can come from disk and don't need CRC checks unless + // allow_from_disk can be set at the same time as check_crc. Use the + character in between them to signify this: allow_from_disk+check_crc. + + + // + // Three types of file specifications: + // + // 1. directory/*.* - refers to all files under the directory + // 2. directory/... - refers to all files under the directory and all directories under that (recursively) + // 3. directory/filename - refers to a single file + + + // + // By default, when in pure server mode, most content file types are only allowed to come from Steam. + // + materials/... allow_from_disk + materials/effects/... allow_from_disk+check_crc + models/... allow_from_disk + models/player/... allow_from_disk+check_crc + models/grenades/... allow_from_disk+check_crc + models/projectiles/... allow_from_disk+check_crc + models/flag/... allow_from_disk+check_crc + shaders/... allow_from_disk+check_crc + sound/... allow_from_disk + sound/sound/player/footsteps/... allow_from_disk+check_crc + sound/buildable/sentry/sg_scan1 allow_from_disk+check_crc + sound/buildable/sentry/sg_scan2 allow_from_disk+check_crc + + // + // Allow custom player models. Don't do CRC checks on them because the clients may all + // have different custom models and the server won't have them all. + // + //models/player/... allow_from_disk + //materials/models/player/... allow_from_disk + + // + // Allow custom spray decals. + // + materials/temp/... allow_from_disk + materials/vgui/logos/... allow_from_disk + materials/vgui/logos/ui/... allow_from_disk + + + // + // (Uncomment and edit these for mods). + // Allow mod resources to come from disk. + // + // materials/mymod/... allow_from_disk+check_crc + // models/mymod/... allow_from_disk+check_crc + // sound/mymod/... allow_from_disk+check_crc +} \ No newline at end of file diff --git a/resource/ClientScheme.res b/resource/ClientScheme.res new file mode 100644 index 0000000..b64c19c --- /dev/null +++ b/resource/ClientScheme.res @@ -0,0 +1,2814 @@ +/////////////////////////////////////////////////////////// +// Fortress Forever scheme resource file +// +// sections: +// Colors - All the colors used by the scheme +// BaseSettings - contains settings for app to use to draw controls +// Fonts - list of all the fonts used by app +// Borders - description of all the borders +// CustomFontFiles - defines fonts to be loaded which are not part of the system +// +// P.S. Advise you turn off wordwrap xP +/////////////////////////////////////////////////////////// +Scheme +{ + /////////////////////////// COLORS /////////////////////////// + Colors + { + /////////////// HUD Colours /////////////// + "HUD_Tone_Bright" "225 235 255 235" + "HUD_Tone_Default" "199 219 255 215" + "HUD_Tone_Dim" "199 219 255 120" + + "HUD_BG_Bright" "109 124 142 185" + "HUD_BG_Default" "109 124 142 115" + "HUD_BG_Dim" "109 124 142 50" + + "HUD_Surface_Bright" "82 92 104 210" + "HUD_Surface_Default" "75 85 95 200" + "HUD_Surface_Dim" "75 85 95 50" + + "HUD_Border_Bright" "255 255 255 255" + "HUD_Border_Default" "245 245 245 230" + "HUD_Border_Dim" "245 245 245 50" + + "Hud_Status_Bright" "255 255 255 255" + "Hud_status_Default" "109 124 142 200" + "Hud_Status_Dim" "109 124 142 100" + + "ArmorIncColor" "255 220 0 255" + "ArmorLowColor" "255 0 0 255" + "ArmorDmgColor" "255 0 0 255" + + "HealthIncColor" "255 220 0 255" + "HealthIncAbove100Color" "0 255 0 255" + "HealthLowColor" "255 0 0 255" + "HealthDmgColor" "255 0 0 255" + + /////////////// VGUI Colours /////////////// + "UI_Tone_Default" "199 219 255 255" + "UI_Tone_Dim" "109 124 142 115" + "UI_Tone_Dark" "75 85 95 115" + + "UI_BG_Highlight" "225 235 255 45" + "UI_BG_Dim" "0 0 0 165" + "UI_BG_Dark" "0 0 0 90" + + //"UI_Slider_Text" "127 140 127 255" + "UI_Slider_Text" "0 255 0 255" + "UI_Slider_Nob" "108 108 108 255" + "UI_Slider_Track" "31 31 31 255" + "UI_Slider_DisabledText1" "117 117 117 255" + "UI_Slider_DisabledText2" "30 30 30 255" + + /////////////// Team Colours /////////////// + "BlueTeamColor" "56 100 171 196" + "RedTeamColor" "188 0 0 196" + "YellowTeamColor" "202 173 33 196" + "GreenTeamColor" "68 144 65 196" + + /////////////// Misc. Colours /////////////// + "Red" "255 0 0 255" + "Yellow" "255 255 0 255" + "Blue" "0 255 0 255" + "Cyan" "0 255 255 255" + "Green" "0 255 0 255" + "Magenta" "255 0 255 255" + + "White" "255 255 255 255" + "Black" "0 0 0 255" + + "Blank" "0 0 0 0" + + "Normal" "109 124 142 115" + "Dark" "50 50 50 180" + } + + /////////////////////////// BASE SETTINGS /////////////////////////// + BaseSettings + { + HudItem.Foreground "HUD_Tone_Default" + HudItem.Background "HUD_BG_Default" + + "TeamColorHud.BackgroundAlpha" "0 0 0 150" + + "FgColor" "HUD_Tone_Default" + "BgColor" "Blank" + + "Panel.FgColor" "HUD_Tone_Default" + "Panel.BgColor" "Blank" + + "BrightFg" "HUD_Tone_Bright" + + "DamagedBg" "Blank" + "DamagedFg" "Red" + "BrightDamagedFg" "Red" + + "ZoomReticleColor" "Green" + + /////////////// Weapon Selection Colours /////////////// + "SelectionNumberFg" "HUD_Tone_Bright" + "SelectionTextFg" "HUD_Tone_Bright" + "SelectionEmptyBoxBg" "HUD_BG_Dim" + "SelectionBoxBg" "HUD_BG_Dim" + "SelectionSelectedBoxBg" "HUD_BG_Dim" + + /////////////// VGUI Colour Specification /////////////// + Border.Bright "UI_Tone_Dark" // the lit side of a control + Border.Dark "UI_Tone_Dark" // the dark/unlit side of a control + Border.Selection "Blank" // the additional border color for displaying the default/selected button + + Button.TextColor "UI_Tone_Default" + Button.BgColor "Blank" + Button.ArmedTextColor "UI_Tone_Default" + Button.ArmedBgColor "UI_BG_Highlight" + Button.DepressedTextColor "UI_Tone_Default" + Button.DepressedBgColor "UI_BG_Highlight" + + CheckButton.TextColor "UI_Tone_Default" + CheckButton.SelectedTextColor "UI_Tone_Default" + CheckButton.BgColor "UI_BG_Dim" + CheckButton.Border1 "Border.Dark" // the left checkbutton border + CheckButton.Border2 "Border.Bright" // the right checkbutton border + CheckButton.Check "UI_Tone_Default" // color of the check itself + + ComboBoxButton.ArrowColor "UI_Tone_Default" + ComboBoxButton.ArmedArrowColor "UI_Tone_Default" + ComboBoxButton.BgColor "UI_BG_Dim" + ComboBoxButton.DisabledBgColor "Blank" + + Frame.BgColor "Blank" + Frame.OutOfFocusBgColor "Blank" + Frame.FocusTransitionEffectTime "0.0" // time it takes for a window to fade in/out on focus/out of focus + Frame.TransitionEffectTime "0.0" // time it takes for a window to fade in/out on open/close + Frame.AutoSnapRange "0" + FrameGrip.Color1 "Blank" + FrameGrip.Color2 "Blank" + FrameTitleButton.FgColor "Blank" + FrameTitleButton.BgColor "Blank" + FrameTitleButton.DisabledFgColor "Blank" + FrameTitleButton.DisabledBgColor "Blank" + FrameSystemButton.FgColor "Blank" + FrameSystemButton.BgColor "Blank" + FrameSystemButton.Icon "" + FrameSystemButton.DisabledIcon "" + FrameTitleBar.TextColor "UI_Tone_Default" + FrameTitleBar.BgColor "Blank" + FrameTitleBar.DisabledTextColor "UI_Tone_Default" + FrameTitleBar.DisabledBgColor "Blank" + + GraphPanel.FgColor "UI_Tone_Default" + GraphPanel.BgColor "UI_BG_Dim" + + Label.TextDullColor "UI_Tone_Default" + Label.TextColor "UI_Tone_Default" + Label.TextBrightColor "UI_Tone_Default" + Label.SelectedTextColor "UI_Tone_Default" + Label.BgColor "Blank" + Label.DisabledFgColor1 "Blank" + Label.DisabledFgColor2 "UI_Tone_Dark" + + ListPanel.TextColor "UI_Tone_Default" + ListPanel.BgColor "UI_BG_Dim" + ListPanel.SelectedTextColor "Black" + ListPanel.SelectedBgColor "UI_BG_Highlight" + ListPanel.SelectedOutOfFocusBgColor "UI_BG_Highlight" + ListPanel.EmptyListInfoTextColor "UI_Tone_Default" + + Menu.TextColor "UI_Tone_Default" + Menu.BgColor "UI_BG_Dim" + Menu.ArmedTextColor "UI_Tone_Default" + Menu.ArmedBgColor "UI_BG_Highlight" + Menu.TextInset "6" + + Chat.TypingText "UI_Tone_Default" + + Panel.FgColor "UI_Tone_Dim" + Panel.BgColor "blank" + + HTML.BgColor "0 0 0 255" + + ProgressBar.FgColor "UI_Tone_Default" + ProgressBar.BgColor "UI_BG_Dim" + + PropertySheet.TextColor "UI_Tone_Default" + PropertySheet.SelectedTextColor "UI_Tone_Default" + PropertySheet.TransitionEffectTime "0.25" // time to change from one tab to another + + RadioButton.TextColor "UI_Tone_Default" + RadioButton.SelectedTextColor "UI_Tone_Default" + + RichText.TextColor "UI_Tone_Default" + RichText.BgColor "Blank" + RichText.SelectedTextColor "UI_Tone_Default" + RichText.SelectedBgColor "Blank" + + ScrollBarButton.FgColor "UI_Tone_Default" + ScrollBarButton.BgColor "Blank" + ScrollBarButton.ArmedFgColor "UI_Tone_Default" + ScrollBarButton.ArmedBgColor "Blank" + ScrollBarButton.DepressedFgColor "UI_Tone_Default" + ScrollBarButton.DepressedBgColor "Blank" + + ScrollBarSlider.FgColor "Blank" // nob color + ScrollBarSlider.BgColor "Blank" // slider background color + + SectionedListPanel.HeaderTextColor "UI_Tone_Default" + SectionedListPanel.HeaderBgColor "Blank" + SectionedListPanel.DividerColor "Black" + SectionedListPanel.TextColor "UI_Tone_Default" + SectionedListPanel.BrightTextColor "UI_Tone_Default" + SectionedListPanel.BgColor "UI_BG_Dark" + SectionedListPanel.SelectedTextColor "Black" + SectionedListPanel.SelectedBgColor "UI_BG_Highlight" + SectionedListPanel.OutOfFocusSelectedTextColor "Black" + SectionedListPanel.OutOfFocusSelectedBgColor "UI_BG_Highlight" + + Slider.TextColor "UI_Slider_Text" + Slider.NobColor "UI_Slider_Nob" + Slider.TrackColor "UI_Slider_Track" + Slider.DisabledTextColor1 "UI_Slider_DisabledText1" + Slider.DisabledTextColor2 "UI_Slider_DisabledText1" + + TextEntry.TextColor "UI_Tone_Default" + TextEntry.BgColor "UI_BG_Dim" + TextEntry.CursorColor "UI_Tone_Default" + TextEntry.DisabledTextColor "UI_Tone_Default" + TextEntry.DisabledBgColor "Blank" + TextEntry.SelectedTextColor "Black" + TextEntry.SelectedBgColor "UI_BG_Highlight" + TextEntry.OutOfFocusSelectedBgColor "UI_BG_Highlight" + TextEntry.FocusEdgeColor "UI_BG_Dim" + + ToggleButton.SelectedTextColor "UI_Tone_Default" + + Tooltip.TextColor "UI_BG_Dim" + Tooltip.BgColor "UI_BG_Highlight" + + TreeView.BgColor "UI_BG_Dim" + + WizardSubPanel.BgColor "Blank" + + // Top-left corner of the main screen title + "Main.Title1.X" "76" //76 + "Main.Title1.Y" "194" //184 + "Main.Title1.Color" "White" + + // Top-left corner of the menu on the main screen + "Main.Menu.X" "76" + "Main.Menu.Y" "250" //240 + + // Blank space to leave beneath the menu on the main screen + "Main.BottomBorder" "40" + + "FFButton.BgColor" "HUD_Surface_Default" + "FFButton.BgColorArmed" "HUD_Surface_Bright" + "FFButton.BgColorPressed" "HUD_Surface_Bright" + "FFButton.BgColorDisabled" "HUD_Surface_Dim" + + "FFButton.FgColor" "HUD_Border_Default" + "FFButton.FgColorArmed" "HUD_Border_Bright" + "FFButton.FgColorPressed" "HUD_Border_Bright" + "FFButton.FgColorDisabled" "HUD_Border_Dim" + } + + /////////////////////////// FONTS /////////////////////////// + Fonts + { + // fonts are used in order that they are listed + "DebugFixed" + { + "1" + { + "name" "Courier New" + "tall" "14" + "weight" "400" + "antialias" "1" + } + } + // fonts are used in order that they are listed + "DebugFixedSmall" + { + "1" + { + "name" "Courier New" + "tall" "14" + "weight" "400" + "antialias" "1" + } + } + // fonts listed later in the order will only be used if they fulfill a range not already filled + // if a font fails to load then the subsequent fonts will replace + + "Default" // death messages, not sure bout what else + { + "1" + { + "name" "Verdana" + "tall" "9" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + } + "2" + { + "name" "Verdana" + "tall" "12" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + } + } + + "Default_Shadow" // death messages, not sure bout what else + { + "1" + { + "name" "Verdana" + "tall" "9" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "12" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + "dropshadow" "1" + } + } + + "DefaultBG" // used for testing shoks crosshair thing + { + "1" + { + "name" "Verdana" + "tall" "9" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "blur" "3" + "additive" "0" + } + "2" + { + "name" "Verdana" + "tall" "12" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "blur" "3" + "additive" "0" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "blur" "3" + "additive" "0" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "blur" "3" + "additive" "0" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "blur" "3" + "additive" "0" + } + } + + HudQuickmenu + { + "1" + { + "name" "FortressForever - HUD Glyphs" + "custom" "1" + "tall" "16" + "weight" "0" + "antialias" "1" + "yres" "1 599" + } + "2" + { + "name" "FortressForever - HUD Glyphs" + "custom" "1" + "tall" "18" + "weight" "0" + "antialias" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Glyphs" + "custom" "1" + "tall" "24" + "weight" "0" + "antialias" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Glyphs" + "custom" "1" + "tall" "32" + "weight" "0" + "antialias" "1" + "yres" "1024 1199" + } + "5" + { + "name" "FortressForever - HUD Glyphs" + "custom" "1" + "tall" "40" + "weight" "0" + "antialias" "1" + "yres" "1200 10000" + } + } + HudNumbers2 + { + "1" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "32" + "weight" "0" + "antialias" "1" + "yres" "1 599" + } + "2" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "35" + "weight" "0" + "antialias" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "37" + "weight" "0" + "antialias" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "43" + "weight" "0" + "antialias" "1" + "yres" "1024 1199" + } + "5" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "47" + "weight" "0" + "antialias" "1" + "yres" "1200 10000" + "additive" "1" + } + } + "DefaultSmall" // doesn't appear to be used + { + "1" + { + "name" "Verdana" + "tall" "12" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "480 599" + } + "2" + { + "name" "Verdana" + "tall" "13" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "600 767" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "768 1023" + "antialias" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "1024 1199" + "antialias" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "1200 6000" + "antialias" "1" + } + "6" + { + "name" "Arial" + "tall" "12" + "range" "0x0000 0x00FF" + "weight" "0" + } + } + "DefaultSmall_Shadow" // doesn't appear to be used + { + "1" + { + "name" "Verdana" + "tall" "12" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "480 599" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "13" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "600 767" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "768 1023" + "antialias" "1" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "1024 1199" + "antialias" "1" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "0" + "range" "0x0000 0x017F" + "yres" "1200 6000" + "antialias" "1" + "dropshadow" "1" + } + "6" + { + "name" "Arial" + "tall" "12" + "range" "0x0000 0x00FF" + "weight" "0" + "dropshadow" "1" + } + } + "DefaultVerySmall" // doesn't appear to be used + { + "1" + { + "name" "Verdana" + "tall" "12" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "480 599" + } + "2" + { + "name" "Verdana" + "tall" "13" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "600 767" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "768 1023" + "antialias" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "1024 1199" + "antialias" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "1200 6000" + "antialias" "1" + } + "6" + { + "name" "Verdana" + "tall" "12" + "range" "0x0000 0x00FF" + "weight" "0" + } + "7" + { + "name" "Arial" + "tall" "11" + "range" "0x0000 0x00FF" + "weight" "0" + } + } + "DefaultVerySmall_Shadow" // doesn't appear to be used + { + "1" + { + "name" "Verdana" + "tall" "12" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "480 599" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "13" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "600 767" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "768 1023" + "antialias" "1" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "1024 1199" + "antialias" "1" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "0" + "range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A + "yres" "1200 6000" + "antialias" "1" + "dropshadow" "1" + } + "6" + { + "name" "Verdana" + "tall" "12" + "range" "0x0000 0x00FF" + "weight" "0" + "dropshadow" "1" + } + "7" + { + "name" "Arial" + "tall" "11" + "range" "0x0000 0x00FF" + "weight" "0" + "dropshadow" "1" + } + } + Crosshairs + { + "1" + { + "name" "HalfLife2" + "tall" "40" + "weight" "0" + "antialias" "0" + "additive" "1" + "custom" "1" + "yres" "1 10000" + } + } + QuickInfo + { + "1" + { + "name" "HL2cross" + "tall" "28" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + HudNumbers + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "32" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + HudNumbersGlow + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "32" + "weight" "0" + "blur" "4" + "scanlines" "2" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + HudNumbersSmall + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "16" + "weight" "1000" + "additive" "1" + "antialias" "1" + "custom" "1" + } + } + HudSelectionNumbers + { + "1" + { + "name" "Verdana" + "tall" "11" + "weight" "700" + "antialias" "1" + "additive" "1" + } + } + + "HudHintCenterIcon" + { + "1" + { + "name" "FortressForever - Hud Glyphs" + "tall" "32" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + + "HudHintCenterIconGlow" + { + "1" + { + "name" "FortressForever - Hud Glyphs" + "tall" "32" + "weight" "0" + "blur" "4" + "scanlines" "2" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + + HudAddHealth + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "16" + "weight" "0" + "antialias" "1" + "additive" "0" + "dropshadow" "1" + } + } + + HudTeamScore + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "14" + "weight" "0" + "antialias" "1" + "additive" "0" + "dropshadow" "1" + } + } + + HudPlayerScore + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "16" + "weight" "0" + "antialias" "1" + "additive" "0" + "dropshadow" "1" + } + } + HudPlayerScoreDesc + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "12" + "weight" "0" + "antialias" "1" + "additive" "0" + "dropshadow" "1" + } + } + + HudPlayerScoreBG + { + "1" + { + "name" "Verdana" + "tall" "18" + "weight" "1000" + "antialias" "1" + "blur" "5" + "additive" "0" + } + } + + HudPlayerScoreDescBG + { + "1" + { + "name" "Verdana" + "tall" "12" + "weight" "1000" + "antialias" "1" + "blur" "5" + "additive" "0" + } + } + + HudBonusScore + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "12" + "weight" "0" + "antialias" "1" + "additive" "0" + "dropshadow" "1" + } + } + + HudBonusScoreDesc + { + "1" + { + "name" "FortressForever - HUD Font CAPS" + "tall" "10" + "weight" "0" + "antialias" "1" + "additive" "0" + "dropshadow" "1" + } + } + HudHintTextLarge + { + "1" + { + "name" "Verdana" + "tall" "14" + "weight" "1000" + "antialias" "1" + "additive" "1" + } + } + HudHintTextSmall + { + "1" + { + "name" "Verdana" + "tall" "11" + "weight" "0" + "antialias" "1" + "additive" "1" + } + } + + BudgetLabel + { + "1" + { + "name" "Courier New" + "tall" "14" + "weight" "400" + "outline" "1" + } + } + DebugOverlay + { + "1" + { + "name" "Courier New" + "tall" "14" + "weight" "400" + "outline" "1" + } + } + "CloseCaption_Normal" + { + "1" + { + "name" "Tahoma" + "tall" "26" + "weight" "500" + "dropshadow" "1" + } + } + "CloseCaption_Italic" + { + "1" + { + "name" "Tahoma" + "tall" "26" + "weight" "500" + "italic" "1" + "dropshadow" "1" + } + } + "CloseCaption_Bold" + { + "1" + { + "name" "Tahoma" + "tall" "26" + "weight" "900" + "dropshadow" "1" + } + } + "CloseCaption_BoldItalic" + { + "1" + { + "name" "Tahoma" + "tall" "26" + "weight" "900" + "italic" "1" + "dropshadow" "1" + } + } + + // this is the symbol font + "Marlett" + { + "1" + { + "name" "Marlett" + "tall" "14" + "weight" "0" + "symbol" "1" + } + } + "Trebuchet24" + { + "1" + { + "name" "Trebuchet MS" + "tall" "24" + "weight" "900" + "range" "0x0000 0x007F" // Basic Latin + "antialias" "1" + "additive" "1" + } + } + "Trebuchet18" + { + "1" + { + "name" "Trebuchet MS" + "tall" "18" + "weight" "900" + } + } + "ClientTitleFont" // Main Title above resume game etc.. + { + "1" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "24" + "weight" "0" + "additive" "0" + "antialias" "1" + "yres" "480 599" + } + + "2" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "40" + "weight" "0" + "additive" "0" + "antialias" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "48" + "weight" "0" + "additive" "0" + "antialias" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "80" + "weight" "0" + "yres" "1024 1199" + "antialias" "1" + } + "5" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "96" + "weight" "0" + "yres" "1200 6000" + "antialias" "1" + } + } + CreditsLogo + { + "1" + { + "name" "HalfLife2" + "tall" "128" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + CreditsText + { + "1" + { + "name" "Trebuchet MS" + "tall" "20" + "weight" "900" + "antialias" "1" + "additive" "1" + } + } + CreditsOutroLogos + { + "1" + { + "name" "HalfLife2" + "tall" "48" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + CreditsOutroText + { + "1" + { + "name" "Verdana" + "tall" "9" + "weight" "900" + "antialias" "1" + } + } + CenterPrintText + { + // note that this scales with the screen resolution + "1" + { + "name" "Trebuchet MS" + "tall" "18" + "weight" "900" + "antialias" "1" + "additive" "1" + } + } + "ChatFont" + { + "1" + { + "name" "Verdana" + "tall" "12" + "weight" "700" + "yres" "480 599" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "13" + "weight" "700" + "yres" "600 767" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "700" + "yres" "768 1023" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "700" + "yres" "1024 1199" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "700" + "yres" "1200 10000" + "dropshadow" "1" + } + } + ///////////////////////////NEW STUFF///////////////////////////// + + + + HudSelectionText //Text below weapon selection glyphs + { + "1" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "9" + "weight" "500" + "antialias" "1" + "yres" "1 599" + } + "2" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "11" + "weight" "500" + "antialias" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "13" + "weight" "600" + "antialias" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "16" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + } + "5" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "17" + "weight" "1000" + "antialias" "1" + "yres" "1200 10000" + } + } + "MenuTitle" // class menu title, flythrough title etc + { + + "1" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "18" + "weight" "500" + "antialias" "1" + "yres" "1 599" + } + "2" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "18" + "weight" "500" + "antialias" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "24" + "weight" "600" + "antialias" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "36" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + } + "5" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "48" + "weight" "1000" + "antialias" "1" + "yres" "1200 10000" + } + } + ClassMenu // class selection text + { + "1" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "10" + "weight" "300" + "antialias" "1" + "yres" "1 599" + } + "2" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "12" + "weight" "500" + "antialias" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "14" + "weight" "500" + "antialias" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "20" + "weight" "1000" + "antialias" "1" + "yres" "1024 1199" + } + "5" + { + "name" "FortressForever - HUD Font" + "custom" "1" + "tall" "24" + "weight" "1000" + "antialias" "1" + "yres" "1200 10000" + } + } + "HUD_BackGround" // hud shape glyphs + { + "1" + { + "name" "FortressForever - HUD Glyphs" + "tall" "31" + "custom" "1" + "antialias" "1" + } + } + "HUD_ForeGround" // hud shape glyphs + { + "1" + { + "name" "FortressForever - HUD Glyphs" + "tall" "31" + "custom" "1" + "antialias" "1" + } + } + "HUD_NumSmall" + { + "1" + { + "name" "FortressForever - HUD Glyphs" + "tall" "10" + "custom" "1" + "antialias" "1" + + } + } + "HUD_NumLarge" + { + "1" + { + "name" "FortressForever - HUD Glyphs" + "tall" "20" + "custom" "1" + "antialias" "1" + + } + } + "HUD_TextSmall" // font used when you disguise + { + "1" + { + "name" "FortressForever - HUD Font" // Tahoma + "tall" "10" + "antialias" "1" + } + } + "HUD_TextSmall_Shadow" // font used when you disguise + { + "1" + { + "name" "FortressForever - HUD Font" // Tahoma + "tall" "10" + "antialias" "1" + "dropshadow" "1" + } + } + "HUD_TextRoundInfo" + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "12" + "custom" "1" + "antialias" "1" + "additive" "0" + } + } + "WeaponIcons" + { + "1" + { + "name" "FortressForever - Item Glyphs" + "tall" "64" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "WeaponIconsSelected" + { + "1" + { + "name" "FortressForever - Item Glyphs" + "tall" "64" + "weight" "0" + "antialias" "1" + "blur" "5" + "scanlines" "2" + "additive" "1" + "custom" "1" + } + } + "WeaponIconsClassSelect" + { + "1" + { + "name" "FortressForever - Item Glyphs" + "tall" "50" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "WeaponIconsHUD" + { + "1" + { + "name" "FortressForever - Item Glyphs" + "tall" "38" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "WeaponIconsSmall" + { + "1" + { + "name" "FortressForever - Item Glyphs" + "tall" "28" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "AmmoIconsSmall" + { + "1" + { + "name" "FortressForever - Item Glyphs" + "tall" "16" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "StatusGlyphs" + { + "1" + { + "name" "FortressForever - Status Glyphs" + "tall" "48" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "StatusGlyphsSmall" + { + "1" + { + "name" "FortressForever - Status Glyphs" + "tall" "20" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "GrenadeIcons" + { + "1" + { + "name" "FortressForever - Status Glyphs" + "tall" "18" + "weight" "0" + "antialias" "1" + //"dropshadow" "1" + } + } + "GrenadeAmmoIcons" + { + "1" + { + "name" "FortressForever - Status Glyphs" + "tall" "28" + "weight" "0" + "antialias" "1" + "additive" "1" + "custom" "1" + } + } + "ClassGlyphs" // icons on hud when you disguise and such + { + "1" + { + "name" "FortressForever - Hud Glyphs" + "tall" "26" + "weight" "0" + "antialias" "1" + "additive" "0" + "custom" "1" + } + } + + "TeamMenuTitles_small" + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "8" // 6 + "weight" "0" + "antialias" "1" + } + } + "TeamMenuTitles" + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "10" // 6 + "weight" "0" + "antialias" "1" + } + } + + "TeamMenuTitles_large" + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "12" // 6 + "weight" "0" + "antialias" "1" + } + } + + "TeamMenuTitles_small" + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "8" // 6 + "weight" "0" + "antialias" "1" + } + } + + "Tahoma8" // after you've joined server-map information titles and shit, now replaced + { + "1" + { + "name" "Tahoma" + "tall" "8" // 6 + "weight" "0" + "antialias" "1" + } + } + "Tahoma12" + { + "1" + { + "name" "Tahoma" + "tall" "12" // 6 + "weight" "0" + "antialias" "1" + } + + } + "Tahoma16" // Scoreboard listing of map and server name? + { + "1" + { + "name" "Tahoma" + "tall" "16" // 12 + "weight" "700" + "antialias" "1" + } + } + "Scoreboard" // Column titles and player list + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "10" + "weight" "0" + "dropshadow" "1" + "antialias" "1" + "yres" "1 599" + } + + "2" + { + "name" "FortressForever - HUD Font" + "tall" "12" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Font" + "tall" "14" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Font" + "tall" "20" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "1024 1199" + } + "5" + { + "name" "FortressForever - HUD Font" + "tall" "24" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "1200 9999" + } + } + "Scoreboard_Header" // Main Scoreboard titles + { + "1" + { + "name" "FortressForever - HUD Font" + "tall" "14" + "weight" "0" + "dropshadow" "1" + "antialias" "1" + "yres" "1 599" + } + "2" + { + "name" "FortressForever - HUD Font" + "tall" "16" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "600 767" + } + "3" + { + "name" "FortressForever - HUD Font" + "tall" "18" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "768 1023" + } + "4" + { + "name" "FortressForever - HUD Font" + "tall" "24" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "1024 1199" + } + "5" + { + "name" "FortressForever - HUD Font" + "tall" "32" + "weight" "0" + "antialias" "1" + "dropshadow" "1" + "yres" "1200 9999" + } + } + + "LuaText_Default" // used for Lua hud timers, text, etc + { + "1" + { + "name" "Verdana" + "tall" "9" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "12" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + "dropshadow" "1" + } + } + "LuaText1" + { + "1" + { + "name" "Verdana" + "tall" "9" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "12" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "14" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "20" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "24" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + "dropshadow" "1" + } + } + "LuaText2" + { + "1" + { + "name" "Verdana" + "tall" "12" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "14" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "20" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "24" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "30" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + "dropshadow" "1" + } + } + "LuaText3" + { + "1" + { + "name" "Verdana" + "tall" "14" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "20" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "24" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "30" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "36" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + "dropshadow" "1" + } + } + "LuaText4" + { + "1" + { + "name" "Verdana" + "tall" "20" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "24" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "30" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "36" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "40" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + "dropshadow" "1" + } + } + "LuaText5" + { + "1" + { + "name" "Verdana" + "tall" "24" + "weight" "700" + "antialias" "1" + "yres" "1 599" + "additive" "0" + "dropshadow" "1" + } + "2" + { + "name" "Verdana" + "tall" "30" + "weight" "700" + "antialias" "1" + "yres" "600 767" + "additive" "0" + "dropshadow" "1" + } + "3" + { + "name" "Verdana" + "tall" "36" + "weight" "900" + "antialias" "1" + "yres" "768 1023" + "additive" "0" + "dropshadow" "1" + } + "4" + { + "name" "Verdana" + "tall" "40" + "weight" "900" + "antialias" "1" + "yres" "1024 1199" + "additive" "0" + "dropshadow" "1" + } + "5" + { + "name" "Verdana" + "tall" "48" + "weight" "900" + "antialias" "1" + "yres" "1200 10000" + "additive" "0" + "dropshadow" "1" + } + } + } + + /////////////////////////// BORDERS /////////////////////////// + Borders + { + BaseBorder + { + "inset" "0 0 1 1" + Left + { + "1" + { + "color" "Border.Dark" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Bright" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + } + + TitleButtonBorder + { + "inset" "0 0 1 1" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + } + + TitleButtonDisabledBorder + { + "inset" "0 0 1 1" + Left + { + "1" + { + "color" "BgColor" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "BgColor" + "offset" "1 0" + } + } + Top + { + "1" + { + "color" "BgColor" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "BgColor" + "offset" "0 0" + } + } + } + + TitleButtonDepressedBorder + { + "inset" "1 1 1 1" + Left + { + "1" + { + "color" "Border.Dark" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Bright" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + } + + ScrollBarButtonBorder + { + "inset" "1 0 0 0" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + } + + ScrollBarButtonDepressedBorder + { + "inset" "2 2 0 0" + Left + { + "1" + { + "color" "Border.Dark" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Bright" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + } + + ButtonBorder + { + "inset" "0 0 0 0" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "1 1" + } + } + + Bottom + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + } + + ScoreBoardItemBorder + { + "inset" "0 0 0 0" + Left + { + "1" + { + "color" "White" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "White" + "offset" "0 0" + } + } + + Top + { + "1" + { + "color" "White" + "offset" "1 1" + } + } + + Bottom + { + "1" + { + "color" "White" + "offset" "0 0" + } + } + } + + FrameBorder + { + "inset" "0 0 1 1" + Left + { + "1" + { + "color" "ControlBG" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "ControlBG" + "offset" "0 0" + } + } + + Top + { + "1" + { + "color" "ControlBG" + "offset" "0 1" + } + } + + Bottom + { + "1" + { + "color" "ControlBG" + "offset" "0 0" + } + } + } + + TabBorder + { + "inset" "0 0 1 1" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + } + + TabActiveBorder + { + "inset" "0 0 1 0" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "ControlBG" + "offset" "6 2" + } + } + } + + + ToolTipBorder + { + "inset" "0 0 1 0" + Left + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + } + + // this is the border used for default buttons (the button that gets pressed when you hit enter) + ButtonKeyFocusBorder + { + "inset" "0 0 0 0" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "1 1" + } + } + + Bottom + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + } + + ButtonDepressedBorder + { + "inset" "0 0 0 0" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "1 1" + } + } + + Bottom + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + } + + ComboBoxBorder + { + "inset" "0 0 1 1" + Left + { + "1" + { + "color" "Border.Dark" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Bright" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + } + + MenuBorder + { + "inset" "1 1 1 1" + Left + { + "1" + { + "color" "Border.Bright" + "offset" "0 1" + } + } + + Right + { + "1" + { + "color" "Border.Dark" + "offset" "1 0" + } + } + + Top + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + } + BrowserBorder + { + "inset" "0 0 0 0" + Left + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Right + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + + Top + { + "1" + { + "color" "Border.Dark" + "offset" "0 0" + } + } + + Bottom + { + "1" + { + "color" "Border.Bright" + "offset" "0 0" + } + } + } + } + + /////////////////////////// CUSTOM FONT FILES /////////////////////////// + CustomFontFiles + { + "1" "resource/HUDGlyphs.ttf" + "2" "resource/ItemGlyphs.ttf" + "3" "resource/StatusGlyphs.ttf" + "4" "resource/Crosshairs.ttf" + "5" "resource/HALFLIFE2.ttf" + "6" "resource/HL2crosshairs.ttf" + "7" "resource/HUDfont.ttf" + "8" "resource/HUDfont_caps.ttf" + } +} diff --git a/resource/CrosshairScheme.res b/resource/CrosshairScheme.res new file mode 100644 index 0000000..88d0d0a --- /dev/null +++ b/resource/CrosshairScheme.res @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////// +// Crosshair scheme resource file +// +// Here you can apply a number of additional effects which aren't available in +// the main option screen (some of which will work better than others). You're +// advised to leave the 'tall' values alone, the crosshair font was specifically +// engineered for these values and other ones may cause certain glyphs to +// misalign. Likewise, keep anti-aliasing set to 1 for best results. +// +// Additional switches; +// additive, blur, dropshadow, outline, scanlines, weight +// +// Peace out, +// ~~~Fooley^Cooley. B) +/////////////////////////////////////////////////////////// +Scheme +{ + Fonts + { + "PrimaryCrosshairs1" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "12" //20 + "custom" "1" + "antialias" "0" + } + } + "PrimaryCrosshairs2" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "16" //30 + "custom" "1" + "antialias" "1" + } + } + "PrimaryCrosshairs3" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "20" //40 + "custom" "1" + "antialias" "1" + } + } + "PrimaryCrosshairs4" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "30" //52 + "custom" "1" + "antialias" "1" + } + } + "PrimaryCrosshairs5" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "40" //60 + "custom" "1" + "antialias" "1" + } + } + + "SecondaryCrosshairs1" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "30" //52 + "custom" "1" + "antialias" "1" + } + } + "SecondaryCrosshairs2" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "40" //72 + "custom" "1" + "antialias" "1" + } + } + "SecondaryCrosshairs3" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "52" //80 + "custom" "1" + "antialias" "1" + } + } + "SecondaryCrosshairs4" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "64" //100 + "custom" "1" + "antialias" "1" + } + } + "SecondaryCrosshairs5" + { + "1" + { + "name" "FontressForever - Crosshairs" + "tall" "72" //114 + "custom" "1" + "antialias" "1" + } + } + } + + CustomFontFiles + { + "1" "resource/Crosshairs.ttf" + } +} \ No newline at end of file diff --git a/resource/Crosshairs.ttf b/resource/Crosshairs.ttf new file mode 100644 index 0000000000000000000000000000000000000000..eb2bfe2b441ac5fe758d708c13149e7b547a307c GIT binary patch literal 18160 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 literal 0 HcmV?d00001 diff --git a/resource/Font Layouts.txt b/resource/Font Layouts.txt new file mode 100644 index 0000000..e6e7394 --- /dev/null +++ b/resource/Font Layouts.txt @@ -0,0 +1,222 @@ +This is a temp file which basically just shows what +glyphs are planned and what characters they correspond +to. Glyphs with * have been completed. + +Characters to avoid (so far): + + "& + +************************************************** +ItemGlyphs.ttf +************************************************** + +Ammo glyphs + +1 * Shells (Shotgun) +2 * Shells (SuperShotgun) +3 * Shells (SniperRifle) +4 * Shells (Assault Cannon/AutoRifle) +5 * Nails (Nailgun/SuperNailgun) +6 * Nails (Railgun) +7 * Nails (Tranq/RadioTag) +8 * Rockets (RPG) +9 * Rockets (IC) +0 * Rockets (GL/PL) +- Fuel (Spanner) += Fuel (Flamethrower) + +Weapon Selection glyphs + +a * Crowbar +b * Knife +c Medkit +d * Spanner +e Umbrella +f Flag +g Shotgun +h * SuperShotgun +i * Nailgun +j * SuperNailgun +k SniperRifle +l AutoRifle +m * GrenadeLauncher +n * PipeLauncher +o * Flamethrower +p Incendiary Cannon +q * RPG +r * Assault Cannon +s * Tranq +t * Railgun + +A Detpack +B Dispenser +C SentryGun + +Grenade glyphs + +\ Frag Grenade +, Nail Grenade +. EMP Grenade +/ MIRV Grenade +| Napalm Grenade +< Caltrops +> Gas Grenade +? Conc Grenade + +************************************************** +StatusGlyphs +************************************************** + +Status effect glyphs + +1 * Conc +2 * Plague +3 * Leg Injury (Sniped) +4 * Leg Injury (Caltrop) +5 * Tranq +6 * Hallucinations +7 * Fire +8 * Drowning +9 * Radiation +0 * Cold +- Toxic + +Weapon Death glyphs + +a * Crowbar +b * Knife +c Medkit +d * Spanner +e Umbrella +f Flag +g Shotgun +h * SuperShotgun +i * Nailgun +j * SuperNailgun +k SniperRifle +l AutoRifle +m * GrenadeLauncher +n * PipeLauncher +o * Flamethrower +p Incendiary Cannon +q * RPG +r * Assault Cannon +s * Tranq +t * Railgun + +A Detpack +B Dispenser +C SentryGun Level 1 +D SentryGun Level 2 +E SentryGun Level 3 +F Plagued +G Headshot + +Environmental Death glyphs + +M * Fall death +N * Crushed (Lifts etc.) +O * Physics death +P * Respawn Turret +Q * Lasered +R Burned +S Drowned +T Radiation +U Froze + +Grenade Death glyphs + +\ Frag Grenade +, Nail Grenade +. EMP Grenade +/ MIRV Grenade +| Napalm Grenade +< Caltrops +> Gas Grenade + +************************************************** +HUDGlyphs +************************************************** + +Numerics + +1 * 1 +2 * 2 +3 * 3 +4 * 4 +5 * 5 +6 * 6 +7 * 7 +8 * 8 +9 * 9 +0 * 0 +- * - += Infinity symbol +: * Colon + +Class glyphs + +! * Scout +@ * Sniper +# * Soldier +$ * Demoman +% * Medic +^ * HWGuy +? * Pyro +* * Spy +( * Engineer +) * Civilian +_ * Random + +HUD elements + +a * Location Box (Background) +b * Location Box (Foreground) +c * Health Box (Background) +d * Health Box (Foreground) +e * Armour Box (Background) +f * Armour Box (Foreground) +g * Weapon Box (Background) +h * Weapon Box (Foreground) +i * Ammo Carried Box (Background) +j * Ammo Carried Box (Foreground) +k * Ammo Loaded Box (Background) +l * Ammo Loaded Box (Foreground) +m * Primary Gren Box (Background) +n * Primary Gren Box (Foreground) +o * Secondary Gren Box (Background) +p * Secondary Gren Box (Foreground) + +Structure Glyphs + +[ SentryGun Level 1 +] SentryGun Level 2 +{ SentryGun Level 3 +} Dispenser + +Logos + +, Blue Team +. Red Team +< Yellow Team +> Green Team +/ FF Logo + +Goal item glyphs + + Flag + Keycard + Ball + Gasmask + Lasers + Detpack destructible terrain + +Misc glyphs + + Simple flag glyph + Capture point glyph + Healme + Repairme + DON'T SHOOT ME I'M A SPY + In 'nobuild' area + In 'nogrens' area \ No newline at end of file diff --git a/resource/FortressForever_english.txt b/resource/FortressForever_english.txt new file mode 100644 index 0000000000000000000000000000000000000000..693db90cf414bd4c203e09f81390d016cd6d457d GIT binary patch literal 92038 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 ZP|W}Ma#m?^t@SkW;r}t!mh>;U{~y&|;#vRz literal 0 HcmV?d00001 diff --git a/resource/GameMenu.res b/resource/GameMenu.res new file mode 100644 index 0000000..f9843e7 --- /dev/null +++ b/resource/GameMenu.res @@ -0,0 +1,62 @@ +"GameMenu" +{ + "1" + { + "label" "#GameUI_GameMenu_ResumeGame" + "command" "ResumeGame" + "OnlyInGame" "1" + } + "2" + { + "label" "#GameUI_GameMenu_Disconnect" + "command" "Disconnect" + "OnlyInGame" "1" + } + "3" + { + "label" "#GameUI_GameMenu_PlayerList" + "command" "OpenPlayerListDialog" + "OnlyInGame" "1" + } + "4" + { + "label" "#GameUI_GameMenu_FindServers" + "command" "OpenServerBrowser" + } + "5" + { + "label" "#GameUI_GameMenu_CreateServer" + "command" "OpenCreateMultiplayerGameDialog" + } + "6" + { + "label" "#GameUI_GameMenu_Training" + "command" "engine ff_training" + } + "7" + { + "label" "#GameUI_GameMenu_Friends" + "command" "OpenFriendsDialog" + } + "8" + { + "label" "#GameUI_GameMenu_Options" + "command" "OpenOptionsDialog" + } + "9" + { + "label" "#GameUI_GameMenu_FFOptions" + "command" "engine ff_options" + } +// "10" +// { +// "label" "#GameUI_GameMenu_MP3Player" +// "command" "engine mp3" +// } + "11" + { + "label" "#GameUI_GameMenu_Quit" + "command" "Quit" + } +} + diff --git a/resource/HUDGlyphs.ttf b/resource/HUDGlyphs.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8682a967fce9bd0a8030e5b226e421012475c556 GIT binary patch literal 30612 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 literal 0 HcmV?d00001 diff --git a/resource/HUDfont.ttf b/resource/HUDfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f6693c07ac34b4f6b03021afc6cc51f423e4558f GIT binary patch literal 11144 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 literal 0 HcmV?d00001 diff --git a/resource/ItemGlyphs.ttf b/resource/ItemGlyphs.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e54fa5234532d39b71cfcd3d15a83c89bd529772 GIT binary patch literal 51256 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%0DjdI|@s8=J)mkbV9jF4F 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 A`v3p{ literal 0 HcmV?d00001 diff --git a/resource/LoadingDialogNoBanner.res b/resource/LoadingDialogNoBanner.res new file mode 100644 index 0000000..8308901 --- /dev/null +++ b/resource/LoadingDialogNoBanner.res @@ -0,0 +1,85 @@ +"Resource/LoadingDialog.res" //credit to dystopia mod team for optimal locations +{ + "LoadingDialog" + { + "ControlName" "Frame" + "fieldName" "LoadingDialog" + "xpos" "322" + "ypos" "249" + "wide" "800" + "tall" "600" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ImagePanel" + { + "ControlName" "ImagePanel" + "fieldName" "ImagePanelLogo" + "xpos" "20" + "ypos" "24" + "wide" "760" + "tall" "540" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "image" "loading_screen_map" + "scaleImage" "1" + } + "InfoLabel" + { + "ControlName" "Label" + "fieldName" "InfoLabel" + "xpos" "470" + "ypos" "570" + "wide" "250" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "" + "textAlignment" "west" + "dulltext" "1" + "brighttext" "0" + } + "progress" + { + "ControlName" "ProgressBar" + "fieldName" "Progress" + "xpos" "60" + "ypos" "570" + "wide" "400" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "720" + "ypos" "570" + "wide" "72" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "Cancel" + "Default" "0" + } +} diff --git a/resource/LoadingDialogNoBannerSingle.res b/resource/LoadingDialogNoBannerSingle.res new file mode 100644 index 0000000..1a630d0 --- /dev/null +++ b/resource/LoadingDialogNoBannerSingle.res @@ -0,0 +1,85 @@ +"Resource/LoadingDialog.res" //credit to dystopia mod for optimal locations! +{ + "LoadingDialog" + { + "ControlName" "Frame" + "fieldName" "LoadingDialog" + "xpos" "322" + "ypos" "249" + "wide" "800" + "tall" "600" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ImagePanel" + { + "ControlName" "ImagePanel" + "fieldName" "ImagePanelLogo" + "xpos" "20" + "ypos" "24" + "wide" "760" + "tall" "540" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "image" "loading_screen_map" + "scaleImage" "1" + } + "InfoLabel" + { + "ControlName" "Label" + "fieldName" "InfoLabel" + "xpos" "470" + "ypos" "570" + "wide" "250" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "" + "textAlignment" "west" + "dulltext" "1" + "brighttext" "0" + } + "progress" + { + "ControlName" "ProgressBar" + "fieldName" "Progress" + "xpos" "60" + "ypos" "570" + "wide" "400" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "720" + "ypos" "570" + "wide" "72" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "Cancel" + "Default" "0" + } +} diff --git a/resource/LoadingDialogVAC.res b/resource/LoadingDialogVAC.res new file mode 100644 index 0000000..e235f8f --- /dev/null +++ b/resource/LoadingDialogVAC.res @@ -0,0 +1,101 @@ +"Resource/LoadingDialog.res" //credit to dystopia mod for optimal locations! +{ + "LoadingDialog" + { + "ControlName" "Frame" + "fieldName" "LoadingDialog" + "xpos" "322" + "ypos" "249" + "wide" "800" + "tall" "600" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ImagePanel" + { + "ControlName" "ImagePanel" + "fieldName" "ImagePanelLogo" + "xpos" "20" + "ypos" "24" + "wide" "760" + "tall" "540" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "image" "loading_screen_map" + "scaleImage" "1" + } + "InfoLabel" + { + "ControlName" "Label" + "fieldName" "InfoLabel" + "xpos" "470" + "ypos" "570" + "wide" "250" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "" + "textAlignment" "west" + "dulltext" "1" + "brighttext" "0" + } + "VACImage" + { + "ControlName" "ImagePanel" + "fieldName" "VACImage" + "xpos" "20" + "ypos" "565" + "wide" "64" + "tall" "64" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "border" "" + "scaleimage" "1" + "image" "resource/icon_vac" + } + "progress" + { + "ControlName" "ProgressBar" + "fieldName" "Progress" + "xpos" "60" + "ypos" "570" + "wide" "400" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "720" + "ypos" "570" + "wide" "72" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "Cancel" + "Default" "0" + } +} diff --git a/resource/ModEvents.res b/resource/ModEvents.res new file mode 100644 index 0000000..c9c7334 --- /dev/null +++ b/resource/ModEvents.res @@ -0,0 +1,222 @@ +//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +//============================================================================= + +// No spaces in event names, max length 32 +// All strings are case sensitive +// +// valid data key types are: +// string : a zero terminated string +// bool : unsigned int, 1 bit +// byte : unsigned int, 8 bit +// short : signed int, 16 bit +// long : signed int, 32 bit +// float : float, 32 bit +// local : any data, but not networked to clients +// +// following key names are reserved: +// local : if set to 1, event is not networked to clients +// unreliable : networked, but unreliable +// suppress : never fire this event +// time : firing server time +// eventid : holds the event ID + +"ffevents" +{ + "player_sayteam" + { + "userid" "short" + "text" "string" + } + "player_death" // a game event, name may be 32 charaters long + { + // this extents the original player_death by a new + // field "headshot", all other fields remains the same + "userid" "short" + "attacker" "short" + "weapon" "string" // weapon name killer used + "damagetype" "long" // damage type + "killersglevel" "short" + } + + // From here down are events necessary for bot support. + "player_changeclass" + { + "userid" "short" + "oldclass" "short" + "newclass" "short" + } + + "build_dispenser" + { + "userid" "short" // who built it + } + + "build_sentrygun" + { + "userid" "short" + } + + "build_detpack" + { + "userid" "short" + } + + "build_mancannon" + { + "userid" "short" + } + + "detpack_detonated" + { + "userid" "short" + } + + "sentrygun_killed" + { + "userid" "short" // owner + "attacker" "short" + "weapon" "string" + "attackerpos" "string" + "killedsglevel" "short" + "killersglevel" "short" + } + + "dispenser_killed" + { + "userid" "short" // owner + "attacker" "short" + "weapon" "string" + "killersglevel" "short" + } + + "mancannon_detonated" + { + "userid" "short" // owner + } + + "mancannon_killed" + { + "userid" "short" // owner + "attacker" "short" + "weapon" "string" + "killersglevel" "short" + } + + "sentrygun_upgraded" + { + "userid" "short" // upgrader + "sgownerid" "short" // owner + "level" "short" + } + + "disguised" + { + "userid" "short" + "team" "short" + "class" "short" + } + + "disguise_lost" + { + "userid" "short" + "attackerid" "short" + } + + "cloak_lost" + { + "userid" "short" + "attackerid" "short" + } + + "uncloaked" + { + "userid" "short" + } + + "cloaked" + { + "userid" "short" + } + + "dispenser_enemyused" + { + "userid" "short" // owner + "enemyid" "short" + } + + "dispenser_detonated" + { + "userid" "short" + } + + "dispenser_dismantled" + { + "userid" "short" + } + + "dispenser_sabotaged" + { + "userid" "short" // owner + "saboteur" "short" // who done it? + } + + "sentry_detonated" + { + "userid" "short" + "level" "short" + } + + "sentry_dismantled" + { + "userid" "short" + "level" "short" + } + + "sentry_sabotaged" + { + "userid" "short" // owner + "saboteur" "short" // who done it? + } + "player_additem" + { + "userid" "short" + "item" "string" + } + "player_removeitem" + { + "userid" "short" + "item" "string" + } + "player_removeallitems" + { + "userid" "short" + } + "ff_restartround" + { + } + "objective_event" + { + "userid" "short" // entity index of the player + //"eventname" "string" + "eventtext" "string" + } + "luaevent" + { + "userid" "short" // entity index of the first player + "userid2" "short" // entity index of the 2nd player + "eventname" "string" // name for the event - like flag_cap, flag_drop, etc - something stats programs could use + + // These next ones are just brainstorming... + "key0" "string" + "value0" "string" + "key1" "string" + "value1" "string" + "key2" "string" + "value2" "string" + } +} diff --git a/resource/MultiplayerAdvancedDialog.res b/resource/MultiplayerAdvancedDialog.res new file mode 100644 index 0000000..b01cb46 --- /dev/null +++ b/resource/MultiplayerAdvancedDialog.res @@ -0,0 +1,83 @@ +"Resource\MultiplayerAdvancedDia" +{ + "MultiplayerAdvancedDialog" + { + "ControlName" "Frame" + "fieldName" "MultiplayerAdvancedDialog" + "xpos" "60" + "ypos" "108" + "wide" "472" + "tall" "376" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "Cancel" + { + "ControlName" "Button" + "fieldName" "Cancel" + "xpos" "396" + "ypos" "338" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "2" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "command" "Close" + "default" "0" + } + "OK" + { + "ControlName" "Button" + "fieldName" "OK" + "xpos" "328" + "ypos" "338" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "labelText" "#GameUI_OK" + "textAlignment" "west" + "dulltext" "0" + "command" "Ok" + "default" "1" + } + "PanelListPanel" + { + "ControlName" "CPanelListPanel" + "fieldName" "PanelListPanel" + "xpos" "16" + "ypos" "56" + "wide" "442" + "tall" "274" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "BuildDialog" + { + "ControlName" "BuildModeDialog" + "fieldName" "BuildDialog" + "xpos" "532" + "ypos" "108" + "wide" "285" + "tall" "640" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } +} diff --git a/resource/Options1.vdf b/resource/Options1.vdf new file mode 100644 index 0000000..1129ccb --- /dev/null +++ b/resource/Options1.vdf @@ -0,0 +1,28 @@ +"Options" +{ + "heading" + { + "caption" "#GameUI_GameplayHeading" + } + + "hints" + { + "caption" "#GameUI_ShowHelpfulHints" + "cvar" "cl_hints" + } + "autoreload" + { + "caption" "#GameUI_AutoReloadGuns" + "cvar" "cl_autoreload" + } + "changeclass" + { + "caption" "#GameUI_InstantClassChange" + "cvar" "cl_classautokill" + } + "ragdolldeath" + { + "caption" "#GameUI_RagdollDeathView" + "cvar" "cl_ragdoll_deathview" + } +} diff --git a/resource/Options2.vdf b/resource/Options2.vdf new file mode 100644 index 0000000..a11b4a9 --- /dev/null +++ b/resource/Options2.vdf @@ -0,0 +1,67 @@ +"Options" +{ + "heading" + { + "caption" "#GameUI_GraphicalEffectsHeading" + } + + "mblur" + { + "caption" "#GameUI_EnableBlurredVision" + "cvar" "cl_dynamicblur" + } + "mfov" + { + "caption" "#GameUI_EnableDynamicFOV" + "cvar" "cl_dynamicfov" + } + "gtarget" + { + "caption" "#GameUI_DrawGrenadeTargets" + "cvar" "cl_grenadetargets" + } + "gtrail" + { + "caption" "#GameUI_DrawGrenadeTrails" + "cvar" "cl_grenadetrails" + } + "cl_nail_trail" + { + "caption" "#GameUI_DrawNailTrails" + "cvar" "cl_nail_trail" + } + "cl_conc_refract" + { + "caption" "#GameUI_UseConcRefractSphere" + "cvar" "cl_conc_refract" + } + "effectdetail" + { + "caption" "#GameUI_LevelOfEffectsDetail" + "cvar" "cl_effectsdetail" + "type" "discrete" + "values" + { + "2" "#GameUI_High" + "1" "#GameUI_Medium" + "0" "#GameUI_None" + } + } + "default_fov" + { + "caption" "#GameUI_FOV" + "cvar" "default_fov" + "type" "slider" + "minval" "80" + "maxval" "120" + } + "viewmodel_fov" + { + "caption" "#GameUI_ViewModelFOV" + "cvar" "viewmodel_fov" + "type" "slider" + "minval" "74" + "maxval" "120" + } +} + \ No newline at end of file diff --git a/resource/Options3.vdf b/resource/Options3.vdf new file mode 100644 index 0000000..f245810 --- /dev/null +++ b/resource/Options3.vdf @@ -0,0 +1,85 @@ +"Options" +{ + "heading" + { + "caption" "#GameUI_HeadsUpDisplayHeading" + } + + "tchud" + { + "caption" "#GameUI_TeamColorHUD" + "cvar" "cl_teamcolourhud" + } + "hud_centerid" + { + "caption" "#GameUI_CenterPlayerInfo" + "cvar" "hud_centerid" + } + "hud_takesshots" + { + "caption" "#GameUI_TakeEndRoundScreenshots" + "cvar" "hud_takesshots" + } + "hud_speedometer" + { + "caption" "#GameUI_ShowSpeedometer" + "cvar" "hud_speedometer" + } + "hud_speedometer_avg" + { + "caption" "#GameUI_ShowAverageSpeedometer" + "cvar" "hud_speedometer_avg" + } + + "heading" + { + "caption" "#GameUI_InGameMenusHeading" + } + "usemouse" + { + "caption" "#GameUI_UseMouseIngameMenus" + "cvar" "cl_cmusemouse" + } + + "heading" + { + "caption" "#GameUI_ObjectiveIconHeading" + } + "cl_objectiveicon" + { + "caption" "#GameUI_ObjectiveIcon" + "cvar" "cl_objectiveicon" + "type" "discrete" + "values" + { + "1" "#GameUI_On" + "2" "#GameUI_HideArrow" + "0" "#GameUI_Off" + } + } + + "cl_objectiveicon_teamcolor" + { + "caption" "#GameUI_ObjectiveTeamColoredIcon" + "cvar" "cl_objectiveicon_teamcolor" + "type" "discrete" + "values" + { + "1" "#GameUI_On" + "0" "#GameUI_Off" + } + } + + "cl_objectiveicon_arrow_teamcolor" + { + "caption" "#GameUI_ObjectiveTeamColoredArrow" + "cvar" "cl_objectiveicon_arrow_teamcolor" + "type" "discrete" + "values" + { + "1" "#GameUI_On" + "0" "#GameUI_Off" + } + } +} + \ No newline at end of file diff --git a/resource/Options4.vdf b/resource/Options4.vdf new file mode 100644 index 0000000..6bdf437 --- /dev/null +++ b/resource/Options4.vdf @@ -0,0 +1,90 @@ +"Options" +{ + "heading" + { + "caption" "#GameUI_OptimisationsHeading" + } + + //"ragdolls1" + //{ + // "caption" "#GameUI_RagdollLifetime" + // "cvar" "cl_ragdolltime" + // "type" "discrete" + // "values" + // { + // "20.0" "#GameUI_Normal" + // "5.0" "#GameUI_Quick" + // "0" "#GameUI_None" + // } + //} + + "ragdolls2" + { + "caption" "#GameUI_RagdollSleepAfterTime" + "cvar" "ragdoll_sleepaftertime" + "type" "discrete" + "values" + { + "3.5" "#GameUI_Normal" + "0.5" "#GameUI_Quick" + "0" "#GameUI_Instant" + } + } + + "gibs" + { + "caption" "#GameUI_GibCount" + "cvar" "cl_gib_count" + "type" "discrete" + "values" + { + "6" "#GameUI_Normal" + "12" "#GameUI_Many" + "24" "#GameUI_Lots" + "0" "#GameUI_None" + } + } + + "r_dynamic_ff" + { + "caption" "#GameUI_DynamicLights" + "cvar" "r_dynamic_ff" + } + + "cl_phys_props_enable" + { + "caption" "#GameUI_DisablePhysicsProps" + "cvar" "cl_phys_props_enable" + } + + "cl_reduced_explosions" + { + "caption" "#GameUI_HigherFPSExplosions" + "cvar" "cl_reduced_explosions" + } + + "r_WaterDrawReflection" + { + "caption" "#GameUI_WaterReflections" + "cvar" "r_WaterDrawReflection" + } + + "r_WaterDrawRefraction" + { + "caption" "#GameUI_WaterRefraction" + "cvar" "r_WaterDrawRefraction" + } + + "r_3dsky" + { + "caption" "#GameUI_Draw3DSkyBox" + "cvar" "r_3dsky" + } + + "r_drawflecks" + { + "caption" "#GameUI_DrawFlecks" + "cvar" "r_drawflecks" + } +} + \ No newline at end of file diff --git a/resource/OptionsSubMultiplayer.res b/resource/OptionsSubMultiplayer.res new file mode 100644 index 0000000..0231736 --- /dev/null +++ b/resource/OptionsSubMultiplayer.res @@ -0,0 +1,552 @@ +"Resource/OptionsSubMultiplayer.res" +{ + "Cancel" + { + "ControlName" "Button" + "fieldName" "Cancel" + "xpos" "378" + "ypos" "322" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "3" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Close" + "Default" "0" + } + "ok" + { + "ControlName" "Button" + "fieldName" "OK" + "xpos" "308" + "ypos" "322" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "3" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_OK" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Ok" + "Default" "0" + } + "Apply" + { + "ControlName" "Button" + "fieldName" "Apply" + "xpos" "448" + "ypos" "322" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "3" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Apply" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Apply" + "Default" "0" + } + "Advanced" + { + "ControlName" "Button" + "fieldName" "Advanced" + "xpos" "40" + "ypos" "260" + "wide" "120" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "9" + "labelText" "#GameUI_AdvancedEllipsis" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Advanced" + "Default" "1" + } + "ImportSprayImage" + { + "ControlName" "Button" + "fieldName" "ImportSprayImage" + "xpos" "112" + "ypos" "160" + "wide" "124" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_ImportSprayEllipsis" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "1" + } + "NameLabel" + { + "ControlName" "Label" + "fieldName" "NameLabel" + "xpos" "40" + "ypos" "28" + "wide" "150" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_PlayerName" + "textAlignment" "west" + "associate" "NameEntry" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "NameEntry" + { + "ControlName" "CCvarTextEntry" + "fieldName" "NameEntry" + "xpos" "40" + "ypos" "52" + "wide" "196" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "editable" "1" + "maxchars" "63" + "NumericInputOnly" "0" + "unicode" "1" + } + "Primary Color Slider" + { + "ControlName" "CCvarSlider" + "fieldName" "Primary Color Slider" + "xpos" "20" + "ypos" "188" + "wide" "140" + "tall" "39" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "3" + "leftText" " " + "rightText" " " + } + "Secondary Color Slider" + { + "ControlName" "CCvarSlider" + "fieldName" "Secondary Color Slider" + "xpos" "20" + "ypos" "223" + "wide" "140" + "tall" "42" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "4" + "leftText" " " + "rightText" " " + } + "High Quality Models" + { + "ControlName" "CCvarToggleCheckButton" + "fieldName" "High Quality Models" + "xpos" "190" + "ypos" "259" + "wide" "174" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "5" + "labelText" "#GameUI_HighModels" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "Player model" + { + "ControlName" "CLabeledCommandComboBox" + "fieldName" "Player model" + "xpos" "40" + "ypos" "122" + "wide" "140" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "2" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "SpraypaintList" + { + "ControlName" "CLabeledCommandComboBox" + "fieldName" "SpraypaintList" + "xpos" "112" + "ypos" "120" + "wide" "124" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "2" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "ModelImage" + { + "ControlName" "Panel" + "fieldName" "ModelImage" + "xpos" "176" + "ypos" "36" + "wide" "164" + "tall" "200" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + } + "LogoImage" + { + "ControlName" "ImagePanel" + "fieldName" "LogoImage" + "xpos" "40" + "ypos" "120" + "wide" "64" + "tall" "64" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "image" "" + "border" "InsetBorder" + "scaleImage" "1" + } + "CrosshairColorComboBox" + { + "ControlName" "ComboBox" + "fieldName" "CrosshairColorComboBox" + "xpos" "354" + "ypos" "160" + "wide" "108" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "8" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "CrosshairSizeComboBox" + { + "ControlName" "CLabeledCommandComboBox" + "fieldName" "CrosshairSizeComboBox" + "xpos" "354" + "ypos" "120" + "wide" "108" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "6" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "CrosshairTranslucencyCheckbox" + { + "ControlName" "CCvarToggleCheckButton" + "fieldName" "CrosshairTranslucencyCheckbox" + "xpos" "281" + "ypos" "188" + "wide" "181" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Translucent" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "LockRadarRotationCheckbox" + { + "ControlName" "CCvarToggleCheckButton" + "fieldName" "LockRadarRotationCheckbox" + "xpos" "281" + "ypos" "214" + "wide" "181" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#Cstrike_RadarLocked" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + "cvar_name" "cl_radar_locked" + "cvar_value" "0" + } + "CrosshairLabel" + { + "ControlName" "Label" + "fieldName" "CrosshairLabel" + "xpos" "281" + "ypos" "94" + "wide" "181" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_CrosshairDescription" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "CrosshairImage" + { + "ControlName" "ImagePanel" + "fieldName" "CrosshairImage" + "xpos" "281" + "ypos" "120" + "wide" "64" + "tall" "64" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "image" "gfx/vgui/crosshair" + "border" "InsetBorder" + "scaleImage" "1" + } + "SysMenu" + { + "ControlName" "Menu" + "fieldName" "SysMenu" + "xpos" "0" + "ypos" "0" + "zpos" "1" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + } + "topHorizLeft" + { + "ControlName" "Label" + "fieldName" "topHorizLeft" + "xpos" "186" + "ypos" "120" + "wide" "21" + "tall" "16" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "392" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "topVertLeft" + { + "ControlName" "Label" + "fieldName" "topVertLeft" + "xpos" "374" + "ypos" "58" + "wide" "21" + "tall" "16" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "133" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "bottomHorizRight" + { + "ControlName" "Label" + "fieldName" "bottomHorizRight" + "xpos" "508" + "ypos" "176" + "wide" "21" + "tall" "16" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "133" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "bottomVertRight" + { + "ControlName" "Label" + "fieldName" "bottomVertRight" + "xpos" "496" + "ypos" "260" + "wide" "21" + "tall" "16" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "133" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Colors" + { + "ControlName" "Label" + "fieldName" "Colors" + "xpos" "20" + "ypos" "164" + "wide" "88" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_ColorSliders" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label1" + { + "ControlName" "Label" + "fieldName" "Label1" + "xpos" "40" + "ypos" "98" + "wide" "152" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_PlayerModel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label2" + { + "ControlName" "Label" + "fieldName" "Label2" + "xpos" "40" + "ypos" "94" + "wide" "150" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_SpraypaintImage" + "textAlignment" "west" + "associate" "SpraypaintList" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label3" + { + "ControlName" "Label" + "fieldName" "Label3" + "xpos" "40" + "ypos" "187" + "wide" "196" + "tall" "64" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_SpraypaintServerNote" + "textAlignment" "west" + "dulltext" "1" + "brighttext" "0" + "wrap" "1" + } +} + diff --git a/resource/PlayerListDialog.res b/resource/PlayerListDialog.res new file mode 100644 index 0000000..b4aff0e --- /dev/null +++ b/resource/PlayerListDialog.res @@ -0,0 +1,72 @@ +"Resource/PlayerListDialog.res" +{ + "PlayerListDialog" + { + "ControlName" "CPlayerListDialog" + "fieldName" "PlayerListDialog" + "xpos" "168" + "ypos" "55" + "wide" "467" + "tall" "388" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + } + "MuteButton" + { + "ControlName" "Button" + "fieldName" "MuteButton" + "xpos" "173" + "ypos" "326" + "wide" "144" + "tall" "24" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "labelText" "#GameUI_MuteIngameVoice" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "Mute" + "Default" "1" + } + "PlayerList" + { + "ControlName" "ListPanel" + "fieldName" "PlayerList" + "xpos" "28" + "ypos" "38" + "wide" "410" + "tall" "279" + "autoResize" "3" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + } + "Button1" + { + "ControlName" "Button" + "fieldName" "Button1" + "xpos" "352" + "ypos" "352" + "wide" "86" + "tall" "24" + "autoResize" "0" + "pinCorner" "3" + "visible" "1" + "enabled" "1" + "tabPosition" "4" + "labelText" "#GameUI_Close" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "Close" + "Default" "0" + } +} diff --git a/resource/RedOctoberff.ttf b/resource/RedOctoberff.ttf new file mode 100644 index 0000000000000000000000000000000000000000..36e53f343a4eb9cf84062af5bb2e875ba9325912 GIT binary patch literal 18400 zcmeHv34B%6x$heGc*dOhWIoABasq@*CnpC;n8V~ikXck9Ko}&D5F!o*MD3s!L51?v z(yEA54O--+j%c;N4pgOATdvhU(Kysv>$BENeU_4a?tkrl0z{C~`+Dztzx#Sl*4b;X z{jG0()B4u8zqNM=C4|_?Cc;Veq-o7F-d=R*2|`9bK!~lrc}7+3vR(iC4}{QRfLgeC zRZGV^mu*@}h_o4P#cG8(N||y;;J6pWZ&e%43E0Mv+0d_Omw^~Q~ z6H-gLMx+ym8_u;sk$kc{F$zks z$3r-(I6jA?OelL5b%Em<;5vfiwhY|E>0|6Yoc{v6|1VNNK{I(V{cCz>`ZMru;vX>f z572hDv2Vw9F*YnwjLqIYW$f>!51%$Rtjrwycj?c_J*1rc4*cAf{wrHYis?(FlKhlJ zO&(u?OxHu^f`?^*fvkiM$WPLrvEyVgUrOxkF^gw#LWIu5xquh)frTA6W%O>k*OXHR z506`L5^RyRrPG3Tvj|y2wx%q_QSc+=_B;yoVCn$0^OsPE40#)l;`|YqP-WWSdr=p- z1pJ7!A+-ay;1#&eIzIFu-XeMFr_)cQpHDxHvwPD!j;}tx z^7xYD3y#n4J+F5XA-!XIlO~Oo7^MQ`weh+{ zeRA0F5e)@1~X$Jsu9c=s|gf?Q5+COza;@)-@%Iy#xoqzh>q zT~8mOFEGLevkTZYY#)1#m-G3&gI~{g@Q3&T{;ITFdQN&@`ds$P<#MAuQ*M*5k#Cmw z$UX84@;mZpibE+^CMxrl4&{1fyRuh#L3u|xrrOjTwL%@EPE{{gZ&i1x2h?Ax@2iFu z)Jn8EZJIV;Tc>T&c4<#&hqX_2o1Ujv>SOe|`a1nq{Q><)`Y-ek^y9X$t=`sTTWGt= zw%zuW?FHLA_8fb;%W#iy&v$P$zq{N|xet2Y^BnbNc`Llry^FjXz1zJ9ysvsc@wt41 zePevHeXD)f`*!&D`kwW@?EBE4<*)QN`RDmN{5Sh|`+wwr&Hrh@8>kLk5Lh1A68LW5 zsldyD&x77zd9W$CFt{$bIk-FcMDV5HJHewNB@_uw3@r&=6S_6DC-hwCH=)nNu5fvH za(HQYWBAtaJ?8g7_(1s8@T*uGN5kwM!}`OCN=T8X$m5H9qVzH2rcuX^@yPLB_D&zH zgqiB=>4%FaqJeB0_w@Aiq*64O$$ftnFj4w0UBnJpxP0+sG=wsxu58n9QRus`zy7*F z!-!bH{s_2SQbH? zoO7*XrsK$^b1r=u9~_PxIYNienImRVdAgf^$UVeIh_5J66o?1niMXdIQIv>+@Mt-$ zFb>~;)&0g{T7d%%ZrU+x7TtRdeg%Cp`X6RL#(F1YVh6PX4Q(GrD%%c_+Pd;zZ-$sB3d$(3L6@mY_os*vspLgG&WASY|Wa>CNzx95#9y;Wvjm@81Sos`Xs)I zx>y;$=-t>LdN(#Sv2nA0_S4xn<&12wx;HlF2)WuYEBAm07dTKuYA6{>#*#4=dX8p) zYr(kLbH**$o_(7{6+J&`b|NQ5lTrb*%J#~|Z&2|%> zb$6pZ{aX4keaO@y(V;B5)aZnU*e87&6oNhpbS&io^eX~*)Dx$5qof8}zylt?OBzCp zE2RXz?chOUH`P5w@zP(#hvi6C^ zRxn^s-6)nUHEqQtvbI3Vr+ybxe@t79Ebb{Tq|RS$rJ5&FQ}U~l>WD|9OtI-Syy*@) z$d;WQR4?DUbxO3MHkRXZ<-}?mqF2jyyA7i3A1gre34t9#E8@2(Ag~v3F^UvT&`S>; zf*d|!Sw)3~MOn-e!yUV~_uTg9?4hwjyS=ciBAjn=pOI|@vSq}JArh)D5iPD{BPl!v z>^wj(-M;;y@K97@cT`kR%v@vl3${Q}u#rA#OuGFA=+vUC1Tuh!ppckJiKP`Wo8hP+ z7`h`jULF>FSC{;FF`hgUv9CRmmF3WYfa?8N;#K-B6@7ONvMd-c+ z^c4vS1G^j#RYOPJ?Vpi;yk}o)e9PGGFrEIr*Y%Z!GrX5cQ8LcTYIo#Tt(2* zI&HP2@SVGjCwlt%i18romlQ>Pqj&;V5QT)nQy`DJs7hzv^__*9w_?jaG8(iv`}sk9 zwhz>yY1IRp`uTi4Wyn3#!b8gks@Jsi{BT8?Xf7Yxul0=0_siCA$<~KiBuHWnLdxdM z61*oo@bLTm(cHipL~9(Pafr6T9m*4;9WricMzopfW#4%>oea@JkD_$51&|8XE*M!r zlx}=zPj|O56^;Nf>5tC>a}%5kP5%|XX(Jm>5RcJ>9FP;Gbfd9>-e7!A-?;4I^B%se z9YX<^jl4&9)85Q@fg->bC2aIAV=29h_RgEPYu-G-!B3K{^cEHu_>zIrL}@^_0oews zePm+00=UwB0DO}d5uG>@{1yd-7O_SNeRA6H?4D-VJXuA{qQ$D>W@7D#*A}wC zRoUh7M2T1sp^5Z2PQor`H~JJM4FOa(!~otj1piT_wNuRObxNTRPH_UE?k}-(TpJ z202ToRC)c?E60{qxV4%wTD~V|P*udSH5Tx>W^dPbwYdHMAwPwhS^6W~ajoEmmOgz^ zcqlCHYLt4Se9HzlH}!GJ6ZD0SX{;@Ey!XZ%DJF!08!xzE^y@PFxkQ{nJ!;6K3irmN zFs@hYzPPk ziNZRKvGj)kOc@hX!iELRlYmiRrGy5!pi@RH!k)a(NSsg8MtTb`O!aMJt5WD9OwPi) z7JaaGn|R?J#h0x$#?bl3F8Z9n|CQ9{)G4sA))TOv6ObmH@q7kur-c*4o5W)ADPlYO zmav^hh}J(%S6gJ?3A!yBHdyeGDWWG#7zl`MNEyFJ3>xBv$9w6`#yTE(_gw*>gZsZj zfQN)bfIXA~vg5rLKe!jAkMfAf;|#)rjJ5w!W5!>4QfyU*UkK`2T*u6$z9^4o#)^BG zZRUZQ-^Os+DZ1I{5`{HE$? zQ>XZO0Pv`A>(MzcaQ%z_O;_^V8?fFaUFYNyP#t$da{ge1L*YLdk#^jC;VP6^9 znSKqL%E*rjJHB?s0W;S2j|d%x#>wu!AWEjWX7g9TFqIl|IC zDH`4n*==WSra@TaW?%+U0K|Q9`mix0)v@adz+oy3)E~x*slq1UYI&qzgMfUcx0h8N z?-e>s9|LVmc&@OaA})l$qdpGAKDOlcZ#;I{(D^_3#w49$4$i*gfomnaqUDIh~`b@V03?Iojb z|M0`KB{lY6O!$KIzmX65Fd?@P)*BH&6udNK$V<-Y?B401{k8O`^dT;y4I(EIp)74e z@a!^gWJLe;uhYLL_wh>6p9h3(#yx}3omWopTQHqZFkwEUx6}I|cQ{8H2lsIwy>Rxv z3-`_5gbQ1YPFe;qA=mWR>CyBP=2)Pb9yJ{F=;T^lW2UbXbKbP2fj)KDKYePy_x=Cd zr(y=0{z6Ru%$LVg+f!dp3Eu}l@E4}`Z39ro7yP|`^+9wU=vN<18PEJD_|=5zSC8$_ z_|^TBPjRdN#eVfLCf`i(eX3ub`Nq%x=YJ!=O3ieTSPigJUJD=jqEXjF!y<}EbWw(`k6b z2pX6!>=L;la+R4kBk-o4tERC7eNCos+)Dmr;qt)8B55RCZ8GLD@l2h{4o^4!Fk*!9 z!F1X(emtEIT-eXaraNe_sk@k!qM`XeT-;Rm+~SFJb;?0yw=Kpi94D= zc}2yjQ5E=zUrPIHI2WtaKQc}S!_$e@RS|a~QlDMmtQA7p^ z_qKoRroZV%mJ5GW4UwCJm%@S%RicV%rDDe8XcL0CS-^` zu({+>?Bjt_jufEn+mRjY-YNC72}T`^oy5nuLh|S!T1hXY7tY(oW zxF6}$;+P*71WZV+MNTwXn^ZA$A;p;S+JH!}q8>0CYLgfv4nlCOj|by|M866wZW>Ag zO+XDM)L_0CCtg&Gn>Uf9t&hj*;(_`GK{61ARAF?nvS>0Scn}c4R}AWFLm)m;hdVk6q76>xRQLRyQ|Z>T;IjDmjic06FFg27K5Sd(h87&xKUK>}z~ z0&2XpSoOziaZiuQ9y1%&IOK&6wF!!$kOf9pK!&_->c>D(L##NU0u;HVXmO%gh=~yW#$ z`1YH$n^FVARJKW55YWDQ)jgS_E<%gt}C*xs!W%-BuTQ&1MYwisSbvx z2V~9_yIp6DX?{vw;dc$QwWp+(cRZq5-vzBo-)$M1B%xw%i zvs`n*g!1%Ih2~L$!Rr(-4;h4VjazL_S>djT&6cAokcOJ=pfw!4O_4a4?TSRHdZnr( zUGAXF#&L#CJN&q{N=cC!weyHvkW>o_Sd!ap%w|7d1L3Ly9#s(PlKl?965_I|saZ}g zD_SHQm$WR&CfRgbG5Ay<6vfMIDz{5I*id9DQ_)?c5FoQVDucFMa67qv*wO-7mW@xD z^epE$2juVSNU|dpo-b!GID9E;!;CG8;r`b14N<{3T|QMvft|njmxsj!BJAJQ*k+^d>@P2?Q9R@ z4#-c2pmgK2>o ziUQMfbFi#A99bYpciW@@tjsN8x=EP5kT=&DQ_)G|n4>~es+Wq>VjK8mPF$?;xklzV zqESbLGvn7l$LaOJf6&EXxR_2lcjz2FVF=+IiD^EM4XVY2SF+qZSIvhlsk{s(E@N^- zR~)=>`hJd!W1fIEXi?Rndf9!zZ7XKVU`63sF2E=;#vGvYyFi9nA|V#Cryu17?DwPu z8J?JMc|7J5em5o(#8_Y8&#{WC^>Bn@p$oCYi!WJq@r5_F|LUUVSZRkmD2>g!^paby8#2v|Z$vDG zr?WD9t0(e=2qtMJ&S71~XfwC?ys@*JKGofyVdSebQBUUCDfR&H^zYM>{@jqp2Sa|63)Q0o z;u$ydhsqGt6<4t`2tW{BrlKYyC)Er`)DTz#>awWY3Wp#tfglJ_3EoN=~<|IrN+`9KIB( zQ#~Gdt=w!~b^0jvx|~kcX`@cH&dD7)jCryos=>ix5-VJVtI(X9+r{7tbz0Bt=8~;C zotGzUEa-&u7+!JFlo_{OoEveMmlc=h#GG(5vJzo##`<w3bB` zO2>MAZkFwHXpU@d&kN>qPmV1MzQlWhs;V^WPc`fvK}gv1Hs}Vht288iUteq+#bX-UC;o^6vPz@A|y@K z{rLqn%aQA4^|6Z4AdzFi4iA~a_BbZwy8=m3?w`db;+YgNvfVG_F@5*H7rANc0l2Fo6D0W zqhr9)$R&>=IVwwiMRZQpWN+|-h|eeKMY>!)eRL%M!qBL~NS;U59hKY{j+WR#&~!Iq zIkE5~no^{&qI>-sLN6r?vB~xkb#@&r*d4BHN%v@)gV|;8a3NUL`Q%W>b?6k!7FKv0 zw(0>0ngm_62+JwQLh%di@XO4pZnE2O3s1%Kb!XYrVCi1?+{@0KOTGTfbE(#Sx!9l5 zhyx>7TT|E^#|=O0GB>5L2jnt7rGGNqrjItB-z;ul{|oPzEgFx2M)PhN34Ek7kZ#7# z8@v7dzUal*P{;LCcwyf*u@%#|EwddW{C4J^9{1R%u0bc)p8i$Gg2mHjg(L(iWcD;f zN?+_kVdGX553iebVAhnLDfnHNI@oite~)M_y+!O5(QR+zV~DK|+(YBTN`Vh~BH0ra z+k8bT(lFR1Dc!fP?>BVXLx+r8DDAy<-=kaiZQL*Vh>rdHLf{VjLSppN1Y3<=A#6%% zVv##_XUNQ}n0=beH4gea*-OP5d7@{9xj>%m+qiIHX1xE0Nxe7&)=$Jj}i^w1@JA3Vx}k3Pzpn|X0_bKmXsX=8#Y;P?N0AL~z$tJrN6 znK`5ik(qlk^|d~CYQK;xa`a}(%bH&%pMV9B0EB{(k;RT@9WNC5SlD(z( zju$}8R~t9-!lOqs`~N5D>)+FbXBD20!f9dK_h{}by@JCBGbM&d9WkC;f&L<&oeo)S~|zKfXSc<)7)zM=GX zz6!8-O7s+Hj^!rPqZ*4%e;;-LD@|rjpZ3fJ>}%jN7u)GKjVtKpf3DIfmnA{F7bGWbyJ0h!D_AO z2Xs$GF*(Ms9q-Lpbq0J>Gj&b^WLBmwodP412;Q`@;Kfsb3o~^U?=kh`5i7kb({2Zz z$1-)tDfO&VaC*#f@z$1v_>Jr&FG8lGPRS^`EK_I1MeonlIT=h-nYu(8Pr%4z3_X%* zS59eH$y}D7Y1c^(-rKYA+sR;dMW*gJrS2s`mOs9|ZKShxZENSc)+LpZfppg}8BQ24x&Xy&ut6Dl&M%tGSq^$A_!&Y@&-O*Y_#*=o^L9Qm9WCdA~eM$`#Rgn9$_!DH`zz*7}t0)ujZrp1$-&*!h3bQ z`F?(wzr#P_hUAcPq;jcVnkg-kI;4%#W@(qSPkL5*NqSTINIE9_GDFn zcXy+_L*6a#m!Fe=A-^GiD1WYal?r8qGFh3eEKxd@P0AK!r}B{U1m41XP5D$Ms!PpN z>(wT8p1NFJr+!tvUEQnxR6VS|qke+7@f=!?R<6}+P1quX*51^P z>P*kl3-n=-qbKbm{`B1>JH6LDbK~rOoIQ-Es$F=Ws1&6PC5BRtQi)Q9QjJoJG8SbV zN)yTil!+*lP%cDiM!5)O2}&IIQ|pNBz@!Gs?;_UUIQ<$bnm>S=lq@}Gh^^mpsP_z<*NRst*d zf(~Y+#S>MhO7(1K18we9x$ilH+=aGIaw}|UJpSjy-=d$wCSEgXIyae~VH9KEmyB|f zn$x*F+qHoLUc9aof7(rEc-cS5+Av8~s*igMH9zg^i# zh#dQ6U*(sKFPdY0zaN$_BfQu6!fE*fZhsg=h$fy8V|_thPVU)0#nITu`V$JULD7jD zj<~$A9#T+LUg_3b%VT{DrmqW&$K_1AQt*%vbqe<1E6S-Xf#KkdeMwk1P0A_Cd+9;$ z9vu2TAvCU}xUAfnOb}PNiS?J1=9Mh^I;j--xrOz7!sf=(^5{{cJyP!CJif*nsdb!v zj^&4E4DaH+;LPW&Tntt@LRl+bIEIUH=HqiI_TS{JA{MDndQKNxrjryL#V$&e#7@*$ zI!RWFErgcC%S29q?x!zd%VH^q4@n$|V`LK8Z=PKX%gYd#$>fPVbY`58)yUEvlEy&6 z50f3!Da7*?38P05A{bM9WMVr4+#q2v9Q!bF-Xsv=lCUifd5L2==SRlS5yXZPwXs}G zLopxjO4+V9tOL$RObk~r86)CFy7U~SI7u!$-;*$`6m(_L07G}l%L`EVoS6~ikaWhSxPAAsUQk+ibwMG;U z*2D`GEhTJZ_*yKxrI}f{Os?RSDz!%I=I-ICYoqrvc>DMo{o48m1O}PR!IqHFu<(d> z?K?z9MaOiEjkCtv5)zX-bxux6?UH8in%=E@MrMz!p1pead8%)}{sRUM8a!m^)5D$_ zK4N6{sL^9`S}2i8Ev1Ri7EBnMKfc&i&vWIuET2qDST>H3B9{Nbh2H&#SK;GcJCMkV z4AV|7G{cfp;A<%u(>=-_pwoGJdU&|IySZt#8jV`5QYn=jM=3DrEvyIUix~yo|K!gh zmt~R;4qk!JT{0Pt+NDt7lMrXJ^FGzl_sI(KB6)>WlX>K6^u(QT7}DT6Rqx#d^*`3k?`y96 zX2G1|l(w@LOh_28?8~|uOX9`ZNxPoT_~Js(s;io_*|FP|zl`XxkIv3M+K_wd(;?|M ze=MD4{EyxGf$P8TGUknKp^nhmUKjF1_Rd%_Y~}ksbGG$->C4f7^PVy9?Aq!<QuP?37 zj=HmF(o=n9JI24#aPfzv%Mjje>Q(vhMTb+Lt&DvUPp87nVQ+Z!HwS1%eS z%mPTE_QUA8L9v1Y7U%`Gj2=o#n-B4y9KP+8=0TiqkF^p z+y6Y*xr2P#khGgsj4>Y;q_m{47qe)Zf_rP=H=lB z6Gz;v-uh=}{c}HIF`^@!kLucCEewtIQpf^t5`}NoAJkPJ9t>yUoHz)a|2CkZwQr*AcQeXO0^sATs20T2!YMAB#39L*G0amOHPu`taEDZ?1iMYRm-UwPSDR?9C0` zk8PQJ%yZnF@7pbFNFH(Gg}`rz{Ji{wP5OJ|jvi2~RL*%|PM$w~O-!%q)TAXv86SkK znCmt#ZSsrR^&d@m^N8x+(Sy5!a*e8wHnf|l@^Efg*H5$f$LH5iOt@Wp%57?d@za`$ z$bc=)17C1-ynOEIj9cHWdrlen-XUf5i0F;cOM|W##~*ZCpS9#?`;ynDEsx23)m*g1 z{KATYr#nr(o>cSNSoia7XWc5^+s|B8Stz=t$GoL>5aZoysc>Sl7~he5M_ZF63msqPfB?PTVZbDlGs{O26DP5M-x zHT!yG<LFR$&|Gcs+_Pp@__3Qc+O)t8o( z7LWY+#GK6&m3@wVc<`>DLp|iRWd*g`%$h4B%J1L&;*FAwZ})uq>(r?~dM$6P7^Jr~ z>@)Q{_EE&-0Yh#!RhM)MdZ!^P;`F8HcBFFTY_Dq0c*5a}LHN*~>`$r@5e?t>?oAR0PDAD9WN;S4lUf7*-AqFd;FE}FA*1Gz$O7Ppey zkN0PsAoG;9m)T{5WreaAWJ_fmWDT-Yvg@*ka!+}fJY7CUUMYV`zDB-7epG&4E-1Ve z9Tj%PFud~>6^f;bdc{e_bwv~J&WG_`_&)qdzLKxz*YSJ#lYArpQ0b?PQ+8JlRTd~` zDc33Mm1mUSD(|a2@lID2sy5?&P9>=Q)t%LS)T7jIsV{2$HDfdjH1*m*@$RLq(AH=# zYjJObt7#gpt9x;0#u1(jwVObxw5upDlLJx6SoI+wdLeGMC5v8(cLC#M5z+p+c#CM6(c_`@_tIn(owdyQsFjY9#)WpR+ zJex*$BkefnJ#q>6U|Qlyh~8jHrSS>L5ElTP)nK`_#bQiI*s^5{#CKfXZI97nw+mw% zM4rRo1vrG`~`8dkuIQ#Uhb4X0y%;wrwa}OxATiZsWZifoDb<}(kX!|)GF|u zwG!H?jYe;N;^M_UEy;1=e(vsm;c>~9X>#1qq1akz8At#jR-4(zv}LxL4GeoA$Ee6q zfFnh5EV{`G({BrI8S`Mc;+9p%qwA!Z;^`Kez)AgI6DN_uz3B0S4hJ zXk&+@T4YKdJ~4!tf;@P4jbe41j)S_oTY@d_XswU!mM6(*AIK%+lxHRq&84)z`q`!DH%gH(Oa}qq767H9VU9K zxrDyV671hEMDBkQ_n(O4;+h4kajj@W@H9t{9-j=7>Z%<*GLJ)A7*PYWFn z8|Tf#g&|JBLj(*7PA4rF$GHgXV>_?9M45@$pW= zc?l=_r3!BYXVM7m7mT=W&B9|Nd`m=JrHBi)V_*)8iIxgo;UEG!giJ>ZpYI}!f}IJ0 zfn$8i%{nW6ccWnI4Nk$ihzoKwFQY{c9Kz-%;Vr{4xH^k?(OcO~%LF@&5;njghW|Oo z0!J%YRV!HCBS;ZWIP8L3BjH5yBC{9_&2&w3E?pz|K*BzlB(c2;`IdNK@?|>&jP1xa z#x}E!&Tt6dI2_=^1wCwpmxKz=bnP00_rnv2(+H0e_CeUw4n+2_QJN2~ZLo_ovGuAQ zE)cjD?Ggq(sB=*96(4D#psKK+?H}|O&f=nF)lv1}{exdcaz+O%5XxENOjoZ8;;X$h zuA786mRYEUb`we*46WFQr+KCp{uxeob5=)K7)rFYlU|>Q}fy}qF(W_72!qSj79l`W1?Ff!T|>BfcHdY(noWXqotBi zGj5N}JW8Kd3GohEnS|}QYMArq=4iLbqw?eHj$WgMP9^ud(Tskzlc(drj zd1e=hKB(2Y%U2wZE0^mK@@!)xjd|F3<_z-IguLZ)ZJ8aJIVJ?oqUR8?p5`u{yEi*( z)SkJ^_D+Z@fF)?TAAwD%5Q-s1I3mgceYvW|-X%dW&S@3O;3FZv4t$x#JIdjKun#hr zTAz>|vp-v?C_6dIE*?(dxKl#>?oJmV$IS`&Z2U{}*#ZFxFkbJt})AXKT)dojc*Akc3hAiM{lninnU~3WVD{ z+=nFC-9f9hkNw z-LheH_fgpy86&b;+%BULFq6KAF};)B17tG094CMuF#)KH2%a%PbaV?DN@T6c$V4){ zB@t$>E6S(uEnSMkc^U_!@tYpo-}JKwi04{}QI2)|TqNfe_@zWHW2ahj7Y(137@yxB zXvu%)K#QH3@R(rq+_`7x&ZTi>Wo2w0X7Hm?un}pd+I8YQC`a)F7o*}jI*XBJ@^~&N z&EL#Lj~gE|)q>yr`M7QY@g)L$3A6rfyzJ$`7vH{T&z9E11IXJFI!)TIfh7@NKy=nn zS5B8?XJ?PvC)^Y>*f)CgXyJzRWNYaYWA#?vU`^CnLS<-PlvCk1P`N_Jj%|UeC~l5Gp}-Sd8OLl-_SnKxU~aVXi1MNG zNK4NAD%y2=Djpx4{I z2p$!C@|35FHg1FiULu;7f)UL=E2B0QM4BqZXEp~4!M2vZGX!YkUT zGSyV6wWR3_3=tZ-e{oby2YK5z@ljEtOdg<23TbI8-ylrPzY%q7z5br4*~) zQ7<%;aPlEFp&lRm^8XBPDB`6ifrkelPG+_rjtUCKb6^cwY40J$Qzg}?QB_2vVY*bS z)SQyT6DB2URHahOWGanXqg1N!7#{zd0dkp~Qci(q@}N-h96Zu4i!7p2k4Or}r=;Xo zb<~0=i0H=}|82w$<-_^##PCF)L?50852)QfV8@RBwYB}W_wToTd%qpqvE09w%?0=F zq=70>Mrn5aZ|vM<=TTJ7~Ju!CwFZj`7nc^FYsp(X1qQL!P9gaoj~_OC5}|l{ z^>lPUwzLf#h*QDKz(~5T3i6t(1VqdJWh7pdxI?h3%(ZHlwJNiP_B9s_F5Wm+d@IBj zJ0__N#2x?6AeC`l#U825k@lpAt1N2;BPYT5F9-=nf$y@*&^|zh?;3>hDU~HYrLx4Q zRF?RZ$`YSaS>jVFi+pw~E}2$3VSGWkX{#x=Q>TPT_DnRTmmbW`D;+y!Qm$!Gaen#K zoYK5#Q`f>mlL%X8D$Og)E3L@OjUJdceoA3Z=~Fr5N{fr~awp`NGK(jb7mqK^DJjS+ zHN{8Anz~`bgh^AT6q(YC3v>Sn(iW2t(<$K*JOd}Oq?34?@QaU$^h603;~z*SkQ{uP zNTygTCuO8F)(S{D-X&O$!Mlj$VH%6iQtXc=l?YpmEzu&5B7~Um1h)J~xMIj4ELUKE d9^xB_&+%jmDMXs3D1BTM*yT)O|1{Cu#9aCwsF8V#sUKmBW>&dtDf0L$o4z$o%hc9fA5`drP}&+g97mQTbpE0>3)Y(-woT+XzKY{$!=ei|MYsz5 zr&mFV}HqUIwMCa-d?_B z!QvtBMi%!0Ty8l6T)R!>D6bUHrOVfB+R`;HUWw-y;TEr6w`jq*Gj}cosR6`4v1Y-R z_4FPCi|fO4WbJ}AOYVLA&u?%f^FHc0YyG;7o8GK=Bh1@+lY4B7ozLt#f_M{8y>1n)&8!(l&THB|Qs39?cu_M3OOIgePj= zrpB;X_A^5XnZbLxyz>}jIHlLP4d;Y$nvI-KdX*$}3%F@;tF;ZpC=Dv<-a>Cl zIz4wA@=Rj+bnCbaQT_}3Z@4wmn_LDX_g!fuhcS*m+s7@H9^tYm|9lpQ^dsP0ERN;H z59WsAg2fT=78~sd3vvSYl;T?vV&tM+lB?kwxmIo@Hxhyw@o61e&9GsV%%vEz~P^snWxC|$f`JfQt9#W`q zDjn`0P!cePMNYzO(s6pufVLKXEQ)t_IgMNs*UYt`m2F%*TH48Vaot=GdSn#W%k^>n z+-PnLcOEwuImf}VdU2ee3!t4Lw6p{@igGb7jy5OIpDFZNIk-Gd_2%91XM(U_^QaL z$N9vlNdxg2k^PbV{fqZUMn#q{Sp2w#@J=~rQ>4PfajONU^p4yn>b$f+K6QO!;CYtJ3Eja$VGCG=93Kv z8V8yxn(u9y-THRNXI+PTxKVriF6jSkOx?JJ6U-AHpE5A@mZ`T4R1F-N8Jl$j`#0xz z^G6r|-Ll}h;eU%RU2I=6d)Zwp=*mY|zO_bNTesoO4R3CVY-`y*Wk>175AJ$u*Hc$~ zyzl)h{a1Uh-GAV!16Lhf%TZxG8Pv@YgWzi(@EtTJje!lPOAmt6={V75ZyW@dEuflO zBJm{Q;E6*=9C?QMl!w<4hbUb&iL4|)Y<-$!`%iyQu6=Lo!XJ?*>FMlq*R{zedF_B` zyF(r$e{utvL@t%@lwOT#b3@{q4*oQ z9g43*Q(1Tdf`IuH;Tx4^T8pSt!~G12{s>3sbOz9P4}^;c%-91F=K&-4U;*UeR={nA z+Xr_u+yih=!o37%nsb!fXgx|6y?vC7czciwlSO2NQc6`3DWzmkN@lo}3`)tMlnhGA zpp*@c-ATh3kguD*Y<~m5d>$s(G7r*IAEpy|2OH#g9hMHKVSD(D4WzkI*S!37vs9twqmX zuC!@O5f$1z>$Rg~76#Ea{+pw&mv>LY0N zk>OS!L936T)r08ALM;Zl7m7%sd>oXIgYt1uJ`T#qLHRf+9|z^*pnM#ZkAw1YP(BXI z$A>8&2j%01*C}#mK;;amoB@?HpmGLO&Vb4pP&orCXF%l)sGI?nGoW&2n93PYIiu9? z$Hc*%QCj|95n(i;XFhs+km!c%PK?DjGf4a@3aPR2;gLs@!|#jKt0-TLRo)J1!kcTt z8*9PH?E&sd50Y_3N*K!sU4_t9>7!&a{K<%&rj|2*cpj0ZMRb%)AjgKcxuZmfEP1#P zTpZc@Nqb@P5giFB4YaB#tfDFvjaJc=B05Ui(Gd$UL>6F(tX1Q;sOX@IZdcKLq@DB^ zhLVb&RAXOI(T`R1-Y_CY75P<^R8hT(#;ItUislcOMwS*4cxf`__Jnzt(@Z5%%H`Ym zY<)HL{KHTpdTeo9HHpVWN%Xklwp_j%$=hh&3<7SC+tWreb#4!+5Jn|cr0Z6*xtt8< zQVI>;8K$0Uq*MqA}sAe$Xn`{ssg@86SOJvoz^ygI+<{%beX%BMZGEneaX zROZ9BvY6X%vAZn^voU3MIjlZ+JZTFyRQVj?Qrqb4WR^!DD<~zrpy8jf`NF2kPHRb- z%M|w6A||)jP+C({YVf*ELx0UqU)Q+r;h)~$w|`An*P8u(_y6?aeU0m;XMZ-LcTNo| zc1dHQVvU!uip}XA!N0O;R;s@_9&heX&DyjPxG5HE0^T^|*>$52^xU;QyJSL5&4eY{ z?RWJY7`^V<8MB^U+kc?@j*IG-j<2m9zqJ0MJGu|_uYJ~R3nbj`M9^jnGCyF`yUW7% zt}0WB-)i-jl*ZHPxWVHxnOq*tU(O$sUQ)67_UE^6d;a!Kl}plN&QEVW_}J2Aj~(1< zSkOLVc520y53OAJ(Eb&v*(2H(R<642&bjmMylmCb1zNqlnLed47&M}Gh|DXs>Ky)L zFfbzO(&${_icq-9WH<1H@CLi7Djcc^yL1{?bVMMS^gDFcQu%ITC}y5SuGDL_MkDoj z<9>(MkgrDN9g@!Fk9k~SuR}D{rBby<$?l2BE0&^SX;$gVO}9V4ZTs`LZ>|`w^s>3A zSmnYtR_Xn$(pR!dw=ZCoKK;8%tE<=Tx_vyfIUOlPsG-15*^m06FP4rey-c+;w z+I#2DyYISfHJc_^_9iU3csyq*#B96nzIk)+y>@#c#+ns=?oI`4wm{15D)jU$$${>! z&KtB2f86Vd`CWpsHkGO~hz@Vq<&1cs+|Yu(a@x&O3ziPe*rzVwzQzr59}|&$Gzb}Q zQCQyx+@BTyUGA5P|2p@E;=jPXsQ8z27s5ZvS-|EvusOCg`v6z~7Sf8G@+>1y#fRqEs#qcIzmir>C7%oBE zUQp5>RMCAZwI|gY{1WNkL%#QlZT)L5?y%B% zz1aD)#a%U?Z&0c=6{3hjXi=p6998Kgl>59;brmfure+I~LO!P>F_+8+4)8O(RusNxkcbvtq!C`F~S2fQVtLXM9F(Sc3s*Ptn zkfkp$YDcOK^1{p~n2=~AV9Kc^P&Q*LFvwv(Ul$e$I48J2SU6*+siKF%-C*(_M?pS- z`w~?oK$3hZ5{eJm`XpqGONjxoT>c#POgrZW9>2;o|JJoFX{|{w)-AYpZf0IzWjNno zw#+wc$H7VcyO(wFg2QU@*mbGyX)~tx){whmW4aq{rMBj|SInM!#oQ))(%R57CTeX? zCYnDpU-`}8T)t)9tvs)@do5O{AapF<(>Lkh#j||N%lh&qRekd^bFW!cC+f|TrlxoL zjA`Ae)B6ne3F|KJON~x=T6_9pU6*a0UlLld^|G#5-^dnsVsxtSvh@?}`c6aC?u;1C zrbKsODxso=$$~Y6P+lW|Ymv1?BZwM8rv$qarYCKoGPgSww%fxgx4SH4pRJi| zTXxMiNTa_p-Bdp9?tQDG{{DsA$9Jxt(I1kZf2{Aq$)zTJ$BL__H4ck;sxnWv=IRrP`kZyTxvDD0M}omq@6WAy_OLMa8`mtm+T7aH;Vd6$oOacU z4!x;#@`Zhmk>*hUjMbgvw=eAXM_28;ds=x@y3#K>6D`v&xJ`b^+O>9k6(J_G#beVY zJEo@7Q#+D6o5x}{5mGgNZI_kbL0JolHsFx2CmxMXrxA5Sb>t3%R%`u!f@}FfH}m=ip<4)PPNr4!bf7bXIOKjv)BVN>V!rHPl39 znlUvOn{GL5*O<@LR*ZK|z@*S)BIq$S4M;mdnQ%^^as|1OuUkPLHO!}m1&cY3ayih+ zfKCRJD-VoyD%TCa1AY(u!p@~o-dKcNDbY2h&et$)C zB-&Kv7hl+L>RS&zG?kRUBfmXWzWMlzL%$`u`Nq}qOY2BUth1>zL%d~6_yv^bsX&Zn zp`l-sy+*xcHcNWrsdwmno6%sm8;rI`>H6Vdc?%7P%8cYYv8GC|x3Vb~E%+FUTnXub zR{AN7#Y%AXEY|?->NpILDUh!-xjEc?ZV}$<3T`#Gjys>*%x&Sea~DJ4TnbsdpSv0x z$FD&eKFIxekUIp00$-^}&_fu{haf=@Vdx%$1U-b2eF$_8L4qEF1U-a2haf=@L4qEF z1U)n?K@UNK9#SOeY*0I-457Iynx~@0Dq5$ajViiOMO#(0T}3;J2;=r5jN83%H(>1E z%iX3-uG=uEwHV-9CS|~@+xUFWT|)96O)3V@fu*)vl-Mdi&r1#|#a9yxNhLfOYk3Sh zN#jaLVaig}=NP~cB5hRTk@8X+qtcVgC;kbR{z>@R>B+f+vcy^DwAbdF0`-eWB#wsU z_bMHH>`H^{oPQYo2D5kV# zQ3Njs$JU+tmjjJAZVzQ*x12oCNCMa6A)JXF`tbTj;<~=^&_&@)>CGQr*YN%8^9L^q z*2ix?d7yy=uWPvRqEM#vmcOu6ctDoYTTfo!IJDaxuMGrhO5N_#nn0j7?$+Gzt~MLo z7CkTOEC=hBjk(+TVzb;Dv71dEp7)r{HqzWFC+wHf%gqk`hoi=p%HQt`%AFKP(QhGV9G_|2mT3Ow5?>+fx0RAnUgOHJ@`+s z=ntZPsBbV(Tk3L^*5Z(dgfKVW#oQ>voLGfXe~`P0dxrZ9;mLOgxs%)%!{hxV#`{T( z_mdd!Co$enV!WTkct45peiGyTB*yzmjIfg!?TYC3?ij^rjGd=lzA6ZM#?O#Kxq!a1R$vN_7# zjFfkwR;)G;BgezY@fce6gwlCu5c*?;{uneF{t56;fIkKPGw`3;tTtoCM^bE;ofqB8 zYLV@qi6@qf=aR~VPasJynZ@)E^B!!kbM6c#eN0T{s;QEIRFk|rmv>{;m~-dDM2fd4 ztb%RD5tebqlUN_dl3)W^Jr=`aNvu2bNimgm=cJ58P^1ePlBFyd|4}LY$HForhN)67 zlE`Zil+4yM6$I9exx7Y7u(c#x;kq-$2iNdJ>Kyh!kM>^IN%j2VDT%)JIy1G3#1%?9 zMl|i(&g=ONzqwG<>G?ou+S@>@M(!C&q=nBd&+G;eR~+|~)Pwe0z28ps-v_a)Nq zoO};2kmz}3qQw`|dCI+b`Z`YoB|*_!mlSjkhuAQiH#nV=IjYAjaiv|fk^@xNd2)LcmvZ<9~lOm+O6r{^wyegQ9Pdk@@j;}}5{i71p*H-&po*UM?1 ztisw78(}K(8a|vSuj=I^dYx#Z#3X6;{65przghG;E4Ap1CaN=?o_oYyS{Dk|CEf01 zT`*Kv>K5yWfd(@HNyNTDO9P!@DN>g9HT3X8ti4oI(&ZLIm9?J6PNJdybkLyJ>wKY* zq3eP!Dux>a0&!L(O7x<;B^V~NXW zHR&lY8W41s$)?w9ojmbc^a3whsQBbzAxK0mAL@xnc3s)1WXFYFR1iwWx_Ln-S`+c8 zL5z;b`#Zm=bFZ-*JbIhWQt9zlSnTFGoz<&iglHv!k~#b8vDQXk@%8&>eJfDMbQN`h zU>#Q2sXDe-7VztHDG#YWz%4}&ny@GuAglQh_R7SpO!x!bEsC$f^8sbT8C7H}qW`WP zahXavt)hArb*iXOMH5xDQbpTTv{OZgib&D?-vZ75Enujqwhq7tR}R+**AF)XZUx*{ zxP5Rp!#x1^B-~4ICTOn@tCSyB(Gx0qN=2`$=vONGKt-PcDH;H%CyKp``96%)mXj&P zFz|S6rPs36^fK_P7HD&qlez5mz%bw=k#Bh>mi*!HHi0Cw>8Z`*rRk z!Xf@B;Sl-`Lf=8?uhje>sQEur^M8btr=X}8hvU$J#r_~+71f`ep0q$i(E=U$Ty$|K za3^{gbjT>+QRr!Q2*Y|5vLOe~TP=uEn1{ANV%)indKhn}VC%qPLfmHPn9UT9#Gzye zQ^uAd9>NL}2kQo_)_}JQkpv`68{sodkBk8Pcjr88aR@O2-L1rw5-5-@D4~*trlP23 zPBKlc2Z>lUnD_yL$0UFo;wO`X78tSugxVm8fMaIr0(DkhR1>Hg>IyTo-Vj1c9U${q zFiTDffvh%4LI@g?J!>n(Bo7NKHo%ZILIcMkW9TPM=g`DW})K4m{G^Hl}+aJ89%#_;lMO&^I zxBfdLM=c4Yt~vJM70VvGsEdCdGF8xkgHthTcX_*KTCL`CXhqC6^URUUpg&>Eof!M4 zPyNglO$P&MwirzZg6XJ>&amOIdO_>r(Up2%#M^Y<%xue=@f8}~&IRLkP4Zx&tqVl0 zyeAn>W&*scQobr#XSbJ>q+L39>sXTPnbR<8e#%u-GvKbZTMSg}OWDIN$m#5Wque4e zv9H%k4)NRZV>YcR>edBBkxKfCOwLo1tq5tObJL~0OFK-4cw;;}Inesxj@oH`t)Bd@ z=>xZ4&@YJfl@)y>wC)+Vtg1H~N>b^dtJ08}+vajhAwy*yp+=q>jQY&vu-+ksOSRsB z&tF|(EC~fOV``+ZQ|Hu%q^3p9j@iAzOwwD?GY`$1TrYGiA5%$p>^c2e?c@@BVUA2kS)tBN_hBYzi^H_S2 z8pwN!qAV8bC&V4SdpV=G~dPHoiW~SQO7#Nv;|vS7FBSs+pb@+^UV% zE5L&jEViCCQ>?QYyHr-ug*4!o9=2pQgF~{cIMiYUB{9q+VZFlMQjBGVX&d-1WGF$L zP$&iA8MA4OUaKn`#XvK@0T}*8QTzCXo1hvctpD;wdp z)?})+KBp$=HG0iPN;D>;a{gzvTPUyNwN_mysZh?GnYbe5XTQ0O}%2J=`~ zDr~cbQ!aOc`3d12ZS(l)ed%CTE}fKoZSC#8fLZ5DrpCrx`TDdea9&s3YOiZ(s;@Lw ztXi|O+*LiI)~_io^+>jolBnHZlTQ1CT_ZbuW{<|^t(r7xQkAQ;H02FcrIJo>Ng(77 z=IiVIu1r-(py|d|o3*;G#$|Ik{cclzYpz5Hl}w*EJ<_;78*FZA3{3nTMG6(bh5y4fF%T($dZ4DI^Tl=c2a%=spW|zI9 zuC~2F-#UIud(f(}xdS$LBvKZ3xAk;oLNpk%3(kPn<5iJFOMSXJ z6E?baT8q0nUFGsuRgdtylaa8wcIEloyDU+QCEB^OK9(O53wsULV5~Cah}v-!;Bp77 zk=h2FMz^=OMhqU0*I+ROLXyrGi96zigkn)0Us6>jMB{<5FP!!fyS1sk+3D-)>-Kp< z{%BB}s3`XcHm}bd3I&WhtKDTZ_|r9}@=Vm@4*SH4mNAni#Hz-R?(S&s=q@dZ7_*&q#KV`yTgwMVvgr{fpw?h66#SaAGRgYoXF{VFTd8()^Df(}E@njukKoZU)?aa8F<-G8?;SrWrfIy`uOM&MjM*9OML$GUC+IQVbb{4(;r? z7~)c238_HHh_8gypo+6Wr?Kc`H^OZ|GhRX14Zt@rT@_OhiP&mjJN8QXI%dRvuo0M6PKBF(b~4u_~{O*Vf?^^2FbLzue80cM3kDw&m7;N)ijNpF|JW# zS=v|Lk`AAKCRQp4soFB0cgb5F4j$)rRzXWf`NEWh5+R;gUb2$=JPtygevf?I zT;cXsnC;g2-K(%3mv{{7D=@A_jYh!e-cJRlYT;Lnnrr#Jv$Qr8s7*SZ$=X1uw$v## zRdvtR2(w2;8!LSSJGc>}2{;GHrTZzu> z$&HMcj;ik;@QrAU<$7WyI;tK)G&ZV!^Z@aVXc!X1o@gl_Ewu$li8i0d;&j%4%Xxyt z7ce>d4OY=)oh&)bb|-Ij_#aW0w$xQE=g4fyWRfJ~>B}iK>Gfu_UT+$b`E5q25H5d* z{A;y~-hyVhTxdqHsOZ*lzu|bTN6IO7q3gIk(5L<%?p3D0qozUbWtjgL)DX`plVCQE zh1jGRk8?`q_Yhw3AHp=j`46-5JOM4tiD50w320$XKnrsMT9^~i!kmB><^;4bC!mEn z0WHi4Xkku33v&Wmm=n;#oM2iQBEWx$O*I0m4A4ZtAK?m`9RMF(Ib0)LKimws6>wYO z_QBl@_W<0Ja4*3z%TW$iqf9}~CfX=W@j1Zrf#+lW%M=hxftMEXa^U4fyb_agJmS|Q zY<)4`HsEaqdy$u+{eKzS|Cgcte;L~Um!bWC8QTAsq5Xdu{O@IG|6hjo|7B?ZUj{FH zd06}ZGPM6ME873-(Z??z zL?o>3C1A9V7~bXvVSOPfuf@fESMl%Q-dFr5z?B)(-3%hlAkd6V6nH%F_#&PSJR1eE zG&|90EPn6X;6_*%;XF%#Rha;b3ITct0jo*iHiT6R{4lG)Zon4L7T28rjyVL*UBRgS zj#*%dj&e#>z$>>@nioy^QH54#at0*Q*0C1lomy0+YZ{7*Y~e(=Nlwsv-Iz3+z~ z?A-aM z%+kO1nyK@8@18#W?%sJ*u36h}d4?C_opXjrS8hvJ*OqK|&n;7?+;Zd8%8|8xD(uzp z@wNflerI`C+AqGt3p}hv%r?io`i<=!8#D7Z-d{Va za%z4?Ta3RAEiAOQ&~mgEz3{^i=x6O44?p+bwsRVOcw_s}#gzRJ$zzkB`$*8~pgJ46 zku1g`x4|GuI{7xbQW6W{zacF)k3?2EV_u8J8*{Q&qZdwJd-JrpbEn@lV#B2e#`$Y~ zfkofG{gU*9WtA1>52i1<{o9KIzFPmdukG2u|7}Y+8Vy~TDlb3v;_BFxMQfU!Nr%&0 z;~RbT#cPP~Un7&|t!zk@MuHwkOh{?%TAlX6Fn%5cuxnF7%;5<}90|vUXS!a}%7@9^ zZ~AJyPJ7DPyk^nV=$gtk7hlcJ#GNFDbHAVB+%J!tMT>Fry$xsHyTPii!5Q&)!QbBJ zKH)xxV%J7o7)n!xYX?a;EOr?;w7}q>amz6GHeogxM@bkHDTUd(1e0nBa0u8B9LJQ3@}?3)Lzj4U7(O7jRcGehT6Tu&|hgQY|QL5JqvsXcf1F zD;NQ9E`}9s(6%7|mLjbkz&n7;KzDfcWC7lV@LdRJWnTi!jKHq=3YEPGWk=^M#XjJD zMT%DgUtOel4e&L{d4rmB3R2&Q`W`CQ?I_1WZb7;&@SlY~G95$=S=Y#S{dazUwp>oi9biC3vsAP|MXQjvSLyoAD%zpOvNQ4m zl`B-VPeuDxbhV0ZP|+b3-L9g$RCKS39#+v~DtbaiXl1bmPpRmbie6OFakchus^}*w z`UQ|iY2~lfu-~ZY&nlI_sOTdVeXOF-RP@C#B1A=kiX;{3Rb)_+NktYFIaL%_(YPXF zrx;k=Guil`HB3Bb(e99N)GVd)o-A`2S018LV!sKbW=xDDRD^X3&du4uMT(^IE=?-y zfmMu@%4A^{lXsO6_TY+VK_;6);*=-ufhCMXa!I)5B=MOn0zCT-Gbc4jjp;So6#9v5ik5eZs(+&Xqi**wZi#?%p3VHn9Bu@lC$kwLVKNybc6-EVGL?1)CPQ_iXi-)|u0yI96e@y7qapm1 zK<}mbWeBNzIMFrbONm@K8b@uAL&1F}06i zn$KxM5Q9F3sjWvW{*tWdprZ)Q6%J8yMO1c`CPodpQw{&z* z@{$JoUoIp&?eg<0U$e_kkY>Al$%TKh%P*4V?v5=>yXlnWja`J6E(@=`+Wy+9%4pkb zj;mLOmnUd9d6eEJs2I-8QMaeSUZMZ9|XC@<-%RO?kRZ zGs|ca1YyQM__+XQ8fIga@EFeN@dF!4zeB#2SeYsT2JR!t0fUxpLSQ4gmVQ?&7Q$tj zEOGdEyOYe=o}Je#KAApbu?*F{f6+~~%eP;!h|=0aTYp2TydYd}Cy&-nwJoiEl-TRT z4*Ti8+DjHrn6U5?`RBES{MhaOaqW|?m4|>AZ@FlB?M*9w*_vzJNA0h+$S>i*hwK>n zfrHd$CU;(n+9&%+xpFK4y|7V;0VSnF9c}(dj$E$X_4+SN9w#ctKK4=(~a`aVZ5kRlataB`tr*eqWvo8fOJ5YyIB~>aGIi=V# z)xsigG_3KaVav4xE08O2Ywr*>3}Po$uB z2s{y@WKuCDGvyhkIp-_67qQ&Pu^9eh34YG?_BiWHOh?{wK zrJ5xwimIqoMF|y^si;ClBUFTY>qUAkD(X_vNEMx@qKPV+q@tNBnxmpcD%zx?ohsU` zqCG0QTt$0Tbft=}Q_ePvaa#tK!r7<`7xxK!hHs0qUq}*VzYq_8 z+71;G@qmM8*|ADeOkoR#6K4msHdzNRN}deU6k*@wz&T9{=gLqt;T971boh@=9XKNX zJEADUh61DP7pny;la-Cb-FEr-kA^;YT|VB`+S*0xUZ>6@33@`_;a$k zm57f$CV$aNK7LOA1q<{ZdzWwJ7o~dnWu|VD$ zXunVLRkudcC8oNluBIX=c+J|l!B8m()%NBK=97Z(_ao|hjns9tw|B_LUpw^%s|BjlPLq$ye{0cv)&fE_ z(O%3c9;>_NOx>kp`?jZcwr*KFJ0utcr#oVw^vvmRL9g%SC!YF3l1{}XpCpC!HA5qeDMyN3XE%5k{cS?Iu=d z@Pr_T5d+iFdYH4A@nwS;zFJTVJwpqoYcHnc1gzTzz#TS0nX()5|4!~6ETNx-mEud> z?{Tv?E(MsS;=RhA#LWF%@k3m-!adF?YE4CB^9nRJuMBH!UV+Bu6>ykWz-L~8#^x1h zY+ixJ<`oq33bsM7Kx6X?G&ZlGpjS}PD~jC=2fuKulBkHPh*yzDMPd=*0;BaP(Sm>d z3OfLaXt`f06I`nz9apVfXk^w%u=jAoCE;>#qu{2&Erq)P?sB*r;qHa|Hrx;33iomW zehY_txx|d}a01HZP@aW&xSUd+mHRm{E67$viuKcf*}Ah}$N4vu_d3e6bARJrS4wfH z$fY7TGZR%}J!+U&MLrezRTNNb9aK?BZBtlHSE8bbT1He2D;<6pirM5JQP<~D*93;e z^Ga=!>RU^xsI2%_a5F)DQxz(zRMS-r(`N4(iln1lEjW8E7wxRno(lL%#9zIhNv zufuP-SFL})+FxVT*s*F$#;NHhsp%%G>87c%18UezHEfoO=Ba3*iWaMAiHeqT)m)v@ z=gZX6maAxmidL#S8-9A`5aa$1(OJ(BB~<3h;Y_{m$C|j zOyD+ftI*)WGR1+CG&nnQC|w|``6Lx-RismqMMYK>*;M2#mN1C#*$mgsts;+#yhQ{h z1M2n;>gGe6-%)DfS5pPh&R3PNU=bZ9elQdR25$%hE`%0@)ifn4il`K#D%F^Z;wmat zQ9{j;Ji83FjK6_pWe<5nRSf#Q=MN3t*OhwC!sE~Ula<2qs zMsW@B8sLq<>wveyUk{%>Z^2Ub5tYVw)OJ6uj)518u~z^U8n~8 z%M?ExF@mUJBnvyfN^Gq&ArepJ@*Zp=-E4zeLa>94=U}Vt#x^#Gt!OHNt+6|ejbj}9 zW^8$p*p;!6I2LMb(=5du`3yGaQYuF>X~OYwSDZoxmC5B38aImYz`mPBN>E$7Nj;u% z(OgQx$R*D<^-_{&6%a{1o?-lv!uehC`jS(LRxHK~h9QiO2eDi{#(@aSoJ!iPTr|Sj ztV${TznfQcu;z5jXYxHQvfLs6ZA^tX;ep>NpJ|cr`Ky2c&y; ziyE^?Qql#BO$+4B<1J&?Iah0Hcit_1;}TJ05r(9BlkEd!`9$mF)s8i?e&y>o-}vUr z&PmejzD>Wo=f2-<8aY)v_U%XId;j(~`JP9Y?+IVA<{7dbYF<0J=$Q@IxOP8TyRdiE z!didCQJw6$V!^^IdSVs6FkjQwlU+TwVM6Uie-o&d%w0qsI6bIB3n1~sebx&{VkPKn&sb4ZJIQtWuWbRGICUAN@dU2HtSlnlQwUj zq;J!0szy8tBKPR)~dp`gC(d8Aj=`~LiGqIA3<=yg0`QxY0 zA5mXH4%dzvwQ%96QMCbMn=RQhf5G0p3+DI4Y|YANy##y-jA)l=hH&ivXXs08WWyjn zbM~YnEZBh<6B;MDA1VH?xObS3!^gtW`x7{hWbrGI{wam&u0zTb3fhdcg_Yt~ob&Mr zQ`WM3Almi}uVwduh3~;yb`RFFd$5+>gSG4)P}>8cwFhh2Jy^@`!CH0?=%u9XgURG|DDq8MRj@Aj5cfveX8%JZEb!SuoJf4m zeW-NCO+|E+dlT_5favG&{{a6Fg*z|I1Py0*FjZ#TKWycgd0EO0Gd1ky6pOuFlI`&d zMsP4cgH2tInH!vKi`tLDn!~N?P7~WNaWy8c;5<_R(MD^4Q<-FD< zhzT8UBIRPp{1p?o=-jic*=h@RYvzAsv=;T}?4%~wly=leI?=1slqUNt&#SPGv^bYr z{T-F2@S*KzTaS%l7Gs)qy=KMaOVdtr-C?(`rD)YL`8`y)m`Pvry6p#v%1bQ;L7jVbC#u6UBM>H`VS4V zO3O2Kt4CC5uM}Y68*1+ix5ac5%0tquTxZ>m;1hS+mbUfEUz}|l#WQ=T6=fIoD)vlW zeZBpQ!WF@VMT;e;Wm_WC@v5G}pohw;?#JA$J1bj<8$d z--j^v`~dtr;6DiecKA=iXYt=-r~a!+kJ6Oe$n6TxxP)A;JRc#73V;icd&v={vfYTe zL}}y^WS#^fuzn&~rxEZL!opwoF=9spLxQjNtIS+UTv*<0_?N0cUFHLm`m=a@R z|5uvdx}sPT;u}5fB#Sj5v#V$(Fsul%d%n`R|Ez7U`5a^1mSMx&f5^aAl-W8*>FSB; zY%^PY(%}}xu(tb4yV`8_n!hus&BJ=O>Z?|>u!{XBHnYOHCbMhmGXGNyVC#ujzJNCc zyeIBEpNM8(Ds*2c>BB0MV38&K;y-I1n>xoD);(IcT zNqHBAkb!eY&6aLRxsM>_K1vVY zazUXeSc3{^5XLafK&Tt{WBO?eZAX5{L$l`p-Gcd_e+woHy$nnOqBuNbf;Y@F0W8GN z5ArTT@qMKKcRA*N<>eSFpZTxsviM`fdHAsW0ohND0k1cJi&2uVXFGdEuH-?2wM<=(pcf@?QE>nJVp>9oFZ+~En;B!dn;)+&kuO=^@HVHAtJ##3prgZH*Bs`BD`EHbks2m zf%aMnLrL)%bl2H>JmxZ*I()>$?ea*Ox_qXNWsIegagq7iI5hHcXB_HnJk;k?aS=rz zS1Jy>FZlTksKC>pXt9!jsz%D-6kUT@MbQlv6+YN>c0!$^~h&`CK!0 ze91IP!qzQ{%*dfo$v~rqt|%e(NL4_rZ=4pSOrn(%nvZvk*NZm0GIcHw>o~UyB}uU~ z!4?u5$Pzvk2WEZLPBI?;4zhs+iCKP2eqVmfBY#8w{pzy4Z;_PTNa^K5ouC(n1f%d7 z{FM8=oSQb7`N0nerM5=ZNBbQ2Y;0iiwQ!kOejqXLUJY&e}+s$f?4Ph_V2n^ z{^`~7`94YCrY)OBr`0SM1))N~m7EU2IWFfG+%zmi@UfQ`QD3@Sm{x8fJ0s4R`N2|w zYR!Wo9mt4U5vfGlBRHLAu>)2exZAi^2;xp^0}2)@sQf}q>(vG{61~?*cZvE_(}c^< z%dWX$#k^ZbQz6Le&Z>w~OIND((+l)L78(|WuvZYg5n;n4E2ouBKUC@6FN~sQwe3Tv z1RB-~!U@5TA}a(cQX|aj#XG*Pb8Zs!73*J|Nrfq|J10z;BKAFM7*V#++I5>3ru~0y z5VTgSAY5RlxExDIiD>t1k@|U)Nb&KPr1mMDZk$vS5!~C>(|Vg`3tfG<#Tgi3#4RNM zhQv3@M6adf;j;Oq)|t~KzQX$M* zGu+-nTlK;jw7FWiX4HtW>#AnYe2{+k8ayJ{TzIvtTUZvq;1}Ei{obz#T~RgkE4Nlp z4VorO+w4=kNv$|e5d0$5LJI;`Z#}ubPAJp+zkI_+!LP+|VIzaRHSg$BQMf^% zKaspnt@Q~??ZOLMjl14S>HC7&wOQ-wbz_X^F{)zJW}>BnNNI%Dh`EXwH40ig#YNgF z%V&3({Xe5+9s|DBlfR9+V>g*;1wF|qTd{jIgC}!RnN)@|jnS~pIfe`N^`wPtA`ga!H-B5~GQ(jrTdsRgXqf=1A3f|im=DZvYA zfZL<6T%?17U~%G`+|E!yxE5S#&Yhjw@|4DGis@IBJ`{qnv?lOsR6jRtUvNu#C*F_N zug6CiVqUV~|7ayG3Vw$YFNld$Dw98ve=lDnUn&3Q3@76)Z#I(iNy+KcH-A+ioZb3r zVUMn{qIW{?jBz)Pv(tC3f*hr2wmL4p6bpi%iG_CvSz7s8O;|c8Bt_wM2t$#g7s7&H ze_3#4G6p^@^wB~(uXKM|^3qLZfYrq1t}Xi7L%1(K*^vq2L?TJ|b2_aK*$SA-bh@z<&J z;?Jc7EWexad0zYhI<}H?N?-?A%GKvJU=4i2nR*fhTVS^@NULj2Uc1Fxs@av+Tt+*epDCSe-WKLptiZf_k2dq^GaO}Pv zU-`zj8u8us?{Tl;Cf#pgpYtgZl$&%x633A(`>S@Dhz5)I5V67A_+WTufxNTMZ-2O1^$}Vz`iA$fRzjSDUoqO@;E)%NyH$p*qXZ#z)WBm??wQ6 z97(WHkAZz71Yd&0u7OFiL=LQ1VfuV3>%e`IEXjg-i&$CP^C^#u$0e3LJP84LN4>^_ z`!JB3%)SO5BT68Hg67wI1!1o+6r?v-9iGnfyM%{t&^zh1n#0pY;59@4roBX~ z>ApbFT=-F^k@O6;8JY!so}90=O3Hn7MayqKtdQT7Pi~Gr@rzA$eNe(G-97PLMu#;My99re=@DmMqY8|~}zhSB<-%5RSi7>HjS!CmqvD23{8YWz|`06?HT57*&7tNIJG0CckX`xVF zH*(&p9rL!mx$U{_o)L7Sc3REct1i7O&uTs1v~+Kak4_Ex#`kX895hW6$s(Ljjpj1i zE5*OyZ!lKi&fz3*M0O&~bG(REGP)Wl1y<#9I_wVUPokMfHV2qbl|~~lVsyk4S)M5t z5?GZc_yk+;X{m;x(&n4OSJa`ks(KzMRrqc7F2@$4bo? z5`&&>SozTJx9O>T->E+ieG=y{rA{iJuKf8tN_2V~l~>-{7JcR zh7(-)lEz=CQClj1?et&e@`RBZFC{;qkCB_56k33U92mMr?i{Oiy-kkN4zi(^*Efjt zZ@)f7>1KoG4XUNTr}$v@`qv2mTRi+r49bb?^apUB&qNC0wvg?nUd?BaCl=U8jfCM8 zEMf7zVOVp9sf!IBtjtBm%%OE*xA*e6$x@B=wV4>HgfCvlQ|u2pB(c)ZVX%fFbaPc= zE??(1VPIW6X5-_`ukV z25Y)J(yXC(!Fp*qxq&uY9w*Hwq>@CM57jRyne8VA;*_!MIA ztaaO3e=5IEsWVVw6ihCs9e)@{6dUI6y7ti37td{#@R!oK6zMiys`270I=2xQyQVuG zhgxVk`+m(-xaqJE+lKG6Gt01Tu=vu!;*0&AISazJDQ8?R75P*YP*F@pDHWBgs9Hr? z6*a4Mo*!)$Rn;hFuS1_P+zb14TR=n0;Y_g)=*0e1b#4g$rQ?yd2^91c%Zp zb|s9pZgL!(pjB z5`c3tW+!MM^b6ZWY}c^0{i>7Lvke>8j0gYN@2@(HIU?c@I}xE2=4~nQ&CWxEej-(B zj6tHSHO7f4BSm<?+N!U#VkNA1#I0J~CekMyhKOL+S9@ZD*<4{VlvuxW-q@WN zr_(F9T~&Sh>+(sR^rWy@IP49Wml_-O%gpuWCGb}ov-(Age<@rc2>XP07B4Vn&CB&! z^D2GLxJ=)uU#<7~AFz6o({VD6MjnkkrN^YYbDlM~@x;Pp?2S-MiMJFpS;Y6ecT0!G?_!*mfWyt>R^kj@&%R_Z3PTw$ z)y`JJS&~mv?78vj5Vkc3A&-Wn ziI@U&@JJ;TJkgWKu05HBb#y)@F?EP1?-3rK)!y#6PnAzD2>MKZSL%sP6DCAGtL1yP zmqx77KrOvyU~FHh+e)P>i{Nqet?gP}qYXTu^LGqk>mWR!O^uIgurglCFUp3OOk0t? zl?b2lMH;g^8E`E2cnm!_9YKSFB7uPfyHYkXS!_J>XG?94fZ9z zSvxK`sbQ*XpmoLR)4M(Fo%rbb3uNC4gZ(z^ElayD-EL_q_XySI9NTC1^wfIob7z?@ zU-kISt}Wl1yU3(BoTf(Na5H9EICtuTVORPs)mtx*UcO?Pkc^%j*q_=Hy&`#D*`5%! zsS>UB=t|$Dd3q zwM&1pNH0}_8U!B*ppKzVNnpabi@JV%kzA@N<4L8xsa!J}Yc$iuYiSZ7d*{$sX@^Kk zCFo1wX)@Q6r5L66duzwJ`<=dSr?<=J9k4rR4UTv{T^?7r-QDdfx2P?3`imuNuUne$ zZGTbt{ilX)_Zt7CzQ?UTbNsvsofjL8YwIp%tcg3sugB7DmN?NqF?Miapqca5&tPKy zDd}eE0Xq1bh0kw@4+UL)Tx_yEFerZ@-YiPdi(YV;1e+O^RIpoRo5!NwYqltQtHL|X zl3ls%scJagf_4 zLspxC6&Q0-aaQ2FZN>;|7aSlld_8i>L2iyF;tQsW3x+K)c^=Yw1zQPa5J#Iv9!9QX zvAso9ST+nJ3|${`87Re%E1~HnG^2!Ome6Pk%`Tz2B{Z*uPADR6b3<)&tBttcrqZ2l zE2TW6gm#qBnI*Klh^PTUVH3#xPZ_L>y=D0IpdZjm88!AYj&xj*Jz|`d!J%ji%mizh zgg-3ez#bh|te%7`0@2D~6_AnPh+oD!4<|T<#sbYtMs|A9kQ7^xG(4=Qb4gk+BBvRb zNegMX05S;`$>dMeclKTMZh0_ZHm(~Oa+fz@LyW=9s`6z^&R=i0<|>n4e4skiry6Hq zSp5h78Q)Ap$K<9H=byK8@EXt7)Z8=F56$Yilh|3zXi%rH`~KupUuGf8>SGV{lbjj# z+*{e%an;0(m3M^H<=lbgtvjpF%&lnMUVX;R_4_(b?YOYvg7$Uo@LGR@%57rbt7=t4 zhgnZei~14Uy6s7IzWR>(wR*q$&^qC_mtVZ^$h2hg$CoWzQC8*O7v99pyUi6`X$lHv ze|(v(DruQ;SFo%}RNs>-bF1uESi*It6KzW!{lnou){p;bdB#~)##J5iJn%sDz6qJo zifg|e$^ZVA2-}}}dTr(Irjwg?R_<&%xlw&*ZO^$4=X9UaeRkv7YHiusXVtF%?1DPe zim%tQVBo|Br>&?`KcTkCh_e2=azOm6t{W2HWUPgsRcfVHK^!D6cKBpyW1^TFkz`1? z=rLprzB3|(KuEwX-h!!ll(qD5m=DareiTw4d4XaX^d96|0$qI=rU+QP+lC`_T4##13Yu`PA1h%`ur`tG@h^*r5K>WD*R_r{@ilcg}#G&6lKH z>@TgNxtnc!d1X(REz{6Gs{YhDC8>`YqMTFkiRy-N!P>#p7jMZHZ_N6cV7Nl?iwfuG z#|u6o#{3*SrM666Ion~LB>Ua2^bR9-1xp&uiA;VAd}FOE?LBB;B*le*V1WeD!{KO z^5LpSS5?F{z%{^hje20Bji6Yzs$DCGYmpbnwqh98)S55JO-MHiJX*|W8}K%~kDX}Q za$1YKTi2|M0~PM^LXu`NP1K~#K*XWu%H~KVsOfk}BuyruNTRNF>=#qxA|}b>P`p71 zqKO3z4@r+j^X{6CD}@;a%o;#UrM3#c{{?uO(y&2Bq4#)6bdn)#wa{F%Bu%Yf|Iu}N zeuvFuo{jz`As>nL(Lid>E&m!rt#C~`T9T#h1_qsZkbayg1zjv|+%$mQr*E=Q5e zQRIR)h1!m(s0*~i7_|)_V9hU49`XxOAKp08UtnWQq8#Es&}xbgk2KaI5Z2@I^vLZs z;C;a7qc#>s!3FnZg9yWmq0WRj6VlN+7GMkT`M_3SYT?cTwgKCKKLBVB&2A-B{#p0^U?iyBTk5>_09w)_qy~xE(WG|a0%!o_=;Czhpffg*CFmfa1R#Gx*3?RdJE_+ z;L#hu6PR-RHYmm24|;zw?t8!#cNmo79tVBA821b?#XS#7aW8lOA@KW$z2c@_C zb}{^Jk$zm{|4wUTF z@6cY5v;tiNb_nTVaA;Xdfw`c6i$y#FD_)Yi2)gtbl^~b=Fd-^!2bI%}w?sltVVSHv81nbcuL5!5eY6E9uaW9czo>gY@I@o?e7bmu7o8c_*F_C3v&j?njELfS zX45mq$4zFl%Y$8*Y_4d6nJcW(pwDZv+gqf_#OBuU^)p99$>|N#t~z;O)uct+X35)n zoVK>gOs4Vzy93U;ia(Z!%@(oz&T9RmO^N$`tRZZ(>zBBU6_eRpg}DFvAF0_Tl+)M& zUF~AF#QYcWSLiFQ(LDfrkeRekXFZy%!qBM<#jXrRw892)0+>XKdf-~%+9GZQZloRC zrh!2Yl=egZqBd_AM&U#^Vf;2GH_6nxAp->`DM+seHUpb+o(1Ra*J>fv5!D*p}<5(r1MDDw^)M>;vA(rTsI4cXBMSd-%6k)`4fZGA?f)bamvI<<1b5?^= zm|7*G)UpttS``^|59l78eO2jfx~Bu+61^7mTEyO3ilsar1NSk_3$~m@Ey7wURLmrl z4qmsF(=>B1vWq9WVCqKo7L``3wq${VUkf7}6HJ=LWf$r#w0rnV&_UHT3%xMS0m7gV zftFko{;(EHGr}W*3y_)y?LTHInzB8x*~nq)E!RZaL0IHuvLXyzB$pREJi>g%jYX~S zugx;eWlkuY;e{5eWo<(rrZg)CM@NXQR<8;Tp3jlKEGg}h4$J=$R&*}ySpfLAhp&*@ddiBe^vE#h;BptGosalqXvxtr5g` z)(M+kkGiZFvj`{Abdqe2y1gAi{_sy?hXmnJ>?em8>xYK)E4r{dL3x#-tV~f>1|w2W zCf59ZwGtfgxSQ?Rfc%Xh*J$*1#xb{)Y^sFi1k5@F3*TiPV3vVXgmr>?PMs)N>wM1` zLbd*2waXc_CEc7SZgXYW%c3ln{%G7MK&M@Ao*)My4|uUL*9}ZO4CTMJxDi9aL2Xl6 z_npPCM4&-?qs={Fm zHwy@Z62$i*9Z?c1Xg@|e=W5`qi`O_rYfug#ki|icYOrq?EOkeZyGz_2L@ zmGZ(L>}yFWmy4rvc)W28Oz1#=hFValA7$PwS?7A3xG}?ro-aRc$6RLAnshRyeZka0 z=`$t;#B8|lJGK$AS`ezmJ%QXxqfl;{i^-w^3pPdWSYdU@;ehkl;c##;Ve^%rFuFOJ zWQK0_Lcz%;b~vq`Ue0 z-#B&^zxv~JpvP{Je6#J2ruwv%n^)T^cr4EdaISZH6eH}v>%^GQ5^5KZ?G}XcYGGjM z;Jd;>pRtCQyCkW$J0rf=+ll=s>Xf~Qr?#FFV`kwjA!t6QCuAxg?)GIAyV--E6x8$v zgQbOCX>~B}*i&?A(x=*4xA~XCJovFOLwYTTbGz^J29%V-`1r8yT$E}m8Ji*f5*?2( zPwhL8FHPfOn%fb888D5F3GW6T8xx<4u!N$y8B_+J#>0f~03MTuDLf_x-vLZxWn(ej zm?TVT3VjF81-2kh2hv%9vDQhW0rV76+~;Pk1n)-7dZbDqHi6v6Bb)@Lku_l|-RnWe zN;csq!7HZ&X*v)dlaVFh+rhsb{3hgC=yeMD75Te>>5H8WdNz23&oA;wj;3=j!SmBKFGu)t-2as* zA?IpuoMNv6_bQx8Igd3z#HZeqS|8#c1SXlA_}2knSL9z0e0`CBBk+wy{vqH)xYDiP zco(;UdmBwU--*<-93!B2*x$t3GyPVgt$8$Cu2?FrJMDis=IDFFZPs8n2wFhB0i_j z$5oC9UmR6j?&_b<_86iIF%>@7cCk$e)WOIMrkCe-+WhuTpCP7i07DRF#jbM2trWQa z62q$eDm{08%x+s|wn~B3%i=fR?wgg~kkWT4Bfgthxn6ze?(mrKibl&YC|Ct{VJxPw zjqXzr(bwu$uUG%9=G?xUHuEpRtg;Da&5ClW#T=xcT2T;VISVt3-mM0|+reVxS&P9j z2kZ(_kNGUoYm>)WfFaWO;4>V^`#@o03o>}9qP(}04-5fTksAvuVlkSNyP zZ>YtC6@JWV1FXgk2D50v1{ygF=Df#=&I+tyvFM&MKgs_Iy}A)|NC9{;tb$co56a#H za0K%rd+0E_%4@Wy@H9+fP*Zps3e2e}Fhtjb(xCWs;7!0Z&?QV2l<0PJofqKz^;(4~ z6f?B8G+w6haX(7=4Vc-YmUc4cw}|#Z#wMymc(QidWMsr4L()GI7J+X79cxdCN9`u@ zte~VZAfB_x^MaCeO}t={7X>A40i83}N)jHE0rmqoBTX~XEC!x{8rO?3xvZmnhJlBR z=T8NmTEx?VX;z)`ngu)yn9g4Wyr_tm0+Vib3HT=ipIqcG118>bP&#K#F}xO(?x)b| z(F;9I*RQ=9x=Nw7z#RhLf|R#VJuXAdNn^-L#?Pp57(|0&VEYeB;z-Jui1#TJ3Q9zkU}!RG&Bowt!a?ssNb%n9o0FGN^X~rujR=M z6rN;&4f97}SjS;&Bx*oVb#n;}t}%Z|KCYVn3I8)+|CuD_SMh@mBR2PKvzTPJzQv81 zA-T=NV?=Q$Tugmm;Qz+dw`F!sBloRNsOla4Hevfc>vXGHw^>)3!JY@1eW(wHlDwF=4!FH4WyY~D+z0c%uv+tkt z`o1bltKNj^TazhQqzy&N?~p{3(@a0KodU?%KP+ky1lwJ2m}XC}cHfW=gsfE|wrxB& zj)|h#CbtRO+|DyjmRwfbco{z~LwHDCp^wiyeXjc&yOHY{ALX!j6@7DvujmUfu(QWuQV(xKP=jCyRqPEQ!@?*7tH^Nd%{V2->Fo;|!SlG>fflXgPUcdo8-D%hVyw1%YFTOw0t zFejU+J{t%`t+k7m)VYG5z@#Y)6Vs;4g45w~1!p?1UBC1tTiP%&cG5C=5=%MF>NBQT zI=f+=>DKF&b60d(`3ZsDol^{Z_e!B4zhFdgp1etk?q12W^PLx1Y=Q9V6R<4c=$>wREwQ2lD$xcBORaBh zG8g-q3bo;e2K7(%v6k;Y(a`Yt3%Ovu*=)>8eHFs=4FjGN=5yTYX}`GHX_#y5TjGqR zlv8I_DOSbEgmMSh`>XFq1V@zvJKVvyy1)%80q1~{IK^zJS^uZ<$(ro(EDYpoS&H2Az-AA#rPv@Ri^Abw6BFTH9- zq5OSSd%60A$CYWUK0{TvC(Wk#c4poj?Wi?fKKjBeY3=`crIYK-XSlbhaA7S${@21i z>H#meaJtv)Xsq2dW8CVx8n4wq8++NmTv>^7$FYkoo5cr!!nzd3nAMm`9D*IlYTY@k zm-|fjC{rN!d&!Jn)zVM0_56zQ`AV1z_Tn zWJEKwlwJa+nOPn1m`0MY1$>%cq4aiOdlCDA{l#+wz=0y4B&J}IKc={$b0gqKiu@FC zs+c|vOf$H24`sllQK9r1VA7}%e{9T2{IM}7@hg#rHrpY76)>q}iC+y|4S!c2;5y(s z@cr-#5`uVHj}6B{nl!W*vF9W9e8dvo2TZD=>wzx;Cf*gGR}|xE>_)t?u^Qo_Jz1pYSgw}FZO5b#4q{@7^jZtx!g{}J#B zKL$+sJ`PHADa3mcn7-8WMfxJ>i-@CZ{sQV>YXTaq0kgjzMK3DL@nGe*5z1aPwH;ubwO-PA5XDx_r z!5M^Gi@Xl-I>5u5XFb}iPQkw_MuC~MTN?@DzwE($IvOw0jrHY?G;RdMA-R)e@R3G; z4hf>5tA$B$Ejs-F4-Scu-Aqfv%1C%1eR8G+isLLyf+DoxaRv+My;v&Q3<;yTsS$3t zj}PQ9^n}O*wkG$Gc_OLP5P~R#JEYNNBM`|eux^BY8ROXuE=P)N$Qh8ZLEMmavG|W9 zW!MB@(jIHcaSt9%@PTb4#;O^<3jjq{@cL)FmB-u!g+*lt_7%RFdSpAykIkHFc5C@Kbi1j@&` zk_iAD$fzc6I?u^-M6-b#;q*vi1ZA??TkCI%&Tn9PXP42EuH7vfr%%XsKkagIKb5WJ z7EH>^mNKjC_3159C1~akblLljoa_li#B%G}Id2UsJr)lYPW&6m&;|o4r447 zlWmb19frW18o6n7yuBe|hQ&EI zs?2!T!E+TgMny5!*lZdt^Ag2QYSxg?6|~xHio@Y7w~n`nHY4t;#g8R9QsPk0vGo02WW<=D3CT6Q|ri0DYp#z5W- zdMU(yGdhy9QI&0|m^67#xDS|22G2zNrCP&j1NS^MX6N82G@yrd7Z+n`%BzqLI46i(3L@V& z49HMrR>oVNye4(J@*+fLwlz@$+mJRf*I@;#w+=E>lm2rki6 zK*?7%<#1||H`ag9*%yF!0nWY{dJ-CM)2k?;!gRwy+IJBn3fMWrz7WF-G;TPu85xt( z85rThUn^Q3Y>|kGV}c~EL7k704#w6!oY#pp$&JJ$zNYV&U;^EQbvtN$;Juo2qalC~ zYYpPeLNW-5BWX*_)d{E>RmRA;)VK&<80V5 zRk7HtRYARn)%%Sehd$|-z1Q+F?@lwjlbd4olrO=~~e?b|Hx&7WV zHU}0nz1O>o|2%YTgukDAG3GEPy(jBOjGp1ID~;(tpTRl!TzQpuF8|1(bUHQ^wzf_f zsaUjrrXcVl1Y_ZpUOrP z7Jx#XNd^u0g9)Uz_K^Ar>Kn8mhRRs80JRBrzDJ)yV`peV%d*b0Tpi|4;|S1_hA5f3 zVi^lfDP;_oMf5JO*r0H~n`j};NGLSzlgW)+Djyph;LV?!C(RT*a@Cv*r+hSi|oBC{=!!h)il<*bL)Wa#g{X&1aAlznga;ApCfF%H5CVO3;Dvx*alnDWg zYrXltlPa(^`Gf^kVPkxa7#f)^Hz|n_3spJ!CC!npMy{%HAo7!APm2?M+(29h{UKvd zTegckG4_%n|5~Ai@S~>3H7n;DZP%m@Xcq@Gi_z(@O`5M;2%D}Ix>Iz=geyr1hI$cJ-vfk`MefF?kVpd^?Qy&seWQ!_9L zr54a~P#0)5D4kOaN@?ps?+0xFrSy%Ul)f31(zk=sbvr>ji`OO9AmuR#N_h-{QXb<$ zDUS)Dl*c4cihme_>l8fe!&>`GxlY66$Ltb^o`o7U%JT$JI)|Dq%5xzo#alrso;o^`z3%{}?L6(EG{Omh z=Kyv9)A>$dI^P9K=et4ad@4*7PxYGOA^U3KASjK3h&NWxBftspsqQC1DNKcn!kJ>2 zMl=+z0;O|naZiUq>kzI5Z3Lw-Nz)XDG_8f(is8;;n0mT7w!*Y`FDMnXe$a8CeV|m} zh(7_8_!B{iPX&(nQ$UG76_ohXis2E^k>b0b0Xzek;%5WT2BvFL0VKMpNS7ArN>F;& z+d;`v?GE5GfX@J?@45?k7ciyS3%nQQ&W?Cn1^1YU7NVS z2KU$CeuA>RTI15WN5MT>n%5^ysHP1iis^O=i8ARU|0xFiLKyMhQmTJWK{NFj?m!Xx z%@fgcBS)A9W4Hi!S!7*YG;zUL#f|2lNDkwHMr_-N3^9g*0*Ex}5E76lrPeg{h4VBU zgE313Xx`DsXj*$*gai}}Tr?ei1}4j}Er9zfGSWf1!li+l$vs$3ykV-|v`n4<4)x6DWsXqHCs3r5=l>%;;;1^*{}11atwwnYfIc8 za_pUBi!U7a#b3P^m=ni^O>j>nW-<^Urp|P;R3hCgNWU;G-!jB6dTV)wVB)S8Ul-V! z!jSN=um^Mg!dY|xJ`9$6w(z>B*1(%mFm$oFcDJg&+M0jNZL$uVka3(mJiz=#k_6$6 z{CBt$&*;&9f+>)U&DOi3_;Y>+KMptkja#Mtbk?j|*W|QYlLeb=hMSk7tr4SbnnAER$(@8=PyYq=n2@1=|6tX?Z3+y79G%jz zEcmi60dBQ~xgG5l!fcP%;hQ5sBtf_LxX!HnNxZz&pE_ZETLr7L^L1a6)y)E}5oIW@ z5{j#YLTmz$X%);`Le3(>!cL^5rp}EDLbxElpiQS)_L(?+1J?UddtFg9=rJL@p_ttm za+Y{;-OS>SHK`&(D}ijOb*n>eb4uI|;8J@*9TTP4iFWW5gh~G1iSRbyZN<2=fN6%F z((MM`UBr8U_fU;Q1%Q#)Hx3w{HDxucGP2mjj5DMy5|&_(CPSM*V|OSY5}719l%VCL zNiq<{BsR7nz%+mipB3IR7}Sv8x-!gGLvAlrDyo^J1%O6EW7IHvjaGZI8E(9%BhVY{ z^*38WW?AMoc-)biN^6fvA2%K9spnsFHUCFQGHe?)Off!O7f%J!vPp@)qzZZ#_lPl1 zTT-2Tx}IdhcN>7C)` znm|pkBijGNkpw^ElZ8Fq-Q!&LuKm+Gr6A7-W!V>3cE;fp#b)5t8#x2~8 zUE1UkU(}t73E*v*NxB9bY#hcuc0Y%h_DkJ+x({`qaQkU+^srVMNvCi)6Au|#jt?AFl};IePwvhU-zjG$zL69?~C2$Q^FLil}zN#;<1 ze+5i(hq;)}4otEIokQ}3vxvtk81V}gtdPc!G^AlY5B#;b#$tpQBfJ{nlYwcw&E>e~ zLLWq_#(L9Rfa%2%?|e|wa1y?-$Q$cDDIL93in|*0>SDSBzz2%>+G70mpk#eQY3~BQ ztBCIbCc6^i-v^=eVclE0_wiB-oW~IR7-H$!o&kOa_zmFKfJqlg_)TDZf{#wut4NIyr13vB?@ZE!_U7?mLkOOHuuNNodJg)}CoX`xOIM;4RT znA^mNtQp!sEIgw|03N?EKu3@3Mk4BbJtATxEY87yG3kbO5$zKK$qZex5RSt(rWwM* z7zawl5(kDhwEq+K{X`1Ui!-&R3>JW1tQ5knQB#&f6Nf4L!r=s^iFw0=Ie)TcoivW) zPUXr?*@=x;MotM_5nk)55V}lWGo0GHnX}n@=5M`%=yb^Xn3J`#GIca*_eY&`9GqKm zi>`p*Z4TQl$}K%z*i}9 zv=~mk(Q}8TR_rsr$_wfNyW8654R|^OLjGk_#A{|Z#67W$&8pZZnJsqPq0YF>UFKWm zR~voH{A!)=B>%SqqX9a^yPXzOd@iRx$cdG;VVX>bW`Z}kLi00GJr}JAdZKCUz!Gby zGmf^#2VNfEXfXR1t&CeQkJgr3vq@Vp6-xwD@^nR9X9}A2Hl7a*);moh&U%L!v08cp zdQ(h^@!Vf{r)>RHQ4|e2`M+>H;a>%nA{P7=6`m^7PdUEI&GaF4TgW0=$D<^`wAnpX ztlY%Ka5jF_?ergQB$myyspf;w9n3`E2;VF)a)`r_B1d{-Dh*T$$V39AE|cUjNe(wr zByzztnXIHBfx+MzN?{Vhs3az2#cxKR z&El~$MC&;bN2|hLDe^Ay%Grl}PR0B!>!cGxW&B7aJFqpqE6)aNxvTxBa3`%3#g*I( z$=wyv%@)zTOpH3}MXOglO|@&r@;>1Z?YPqu0;)%c{ zbtikl@wmvw89PMrQBnQ5U7wBG{Yn(CLT6)=&Y;|h{z8JBLbeANWAD=k;Z^E+c$In= ztBF3wE>M5aeTDZFmsy6T|6i%An4o~&ftbbu*tFpW9&sYDy|lS5|0TOyICWwECZ5|GV+;Sg*6#d6(q)_MH@tD)@b0UBJ668^TKWDL@(?U) z@+jZ`k90zed`e(xJ=E4289LfDdO4QV$Nw)W)~sE9MLg&6MenkKnt>NDiP*TsTsFS| z6*zx!*MHxBOI7z?_IUQP56+#k$K8IB?-%@SvBbh-1}fv&)LEC1Ba$04C#x}0bOmJo z>vV_U9q{|y2n1ya(Xji}rhc~Tp3&$7kiE@Seb@yWZN3Lb8IBelLpWyRSdL>ej`MI_ zh2wS{594?qM{#ZJc9^4W*Ve{vhgfHaj?{{Ya69M9t@UI9WQ0<`+}QCwjH#M>3cd=KmPme3U?bg+c3E22ITz1Z#O z!EQ%3xETY0A4dg_HXIXi%)>!Th_~Um5XS)=cj0&p$B%HBas3By{pU!VIvJ8H*+`V* zAlru~i~>3!MbNz38ax+KAHE0CE3n>%=rvFj6LsM05S@UYmgo(*98oL66EvCKfy;O> z*608Yy;4|qLzoohWW7New0dA4XcuS~c!Ya^J)pgylt(`(&HhaQo(@blu2%q$0*?Yy zo+kpI2)qb*Y^+adt^=QJ-Y*0`1bnD??vubzlB|w}E|LsGa+);bF`dSXn9`CVH+$R+ zA{0%0kqiaVDN&Y5$CJ7w>hCFY8rT_gvlUQ*pRsa#C)2qgC3v>jhNhnDZD7daxo4bqyBM50t10= z1mO%+!e)yw&UC9E#x8B>NWEbA{_q_lb5&SoM}IJD4wGgFqg_ea6dQDSLS6GB>VK*i zJJj#F_Vx8Itk}+6Ehpc&=Zj!P$1CEc!}m6NP8ea_eCC>9umoA9&1`ahJyHGh4ZWVh zo7p7xEjDiOhW2~a7xVW7YZFdqqBa<;BU;DLFdOw2_%hckL8C0`1^9O}7$>|YzU=Y5 zVisOAyf#5r3^J395T{MFtjzS)+pdJc>N5J0Nug)Lu+t+r96_PRzePVV$BCai-A=Isyh;i&T7BEx-*gJs16*gh+0E#b8R$QL2Z-?b4x)KitSjX zej2LUe%)=TWcNYRd=4Ylce$EEJ9Q=MHC2h1A%LQNqT0I`wRi7W?cIyoyBD>0FKX{z z)ZV?Qy?ar6_ae)^s7`xPd-o#ay{Nr=QG1aaYVTeY<$_v3%kf#{`0QAY&mzZXk>j(- z@mb{fEOLAnIX;UVpGA((BFATu%ZOLXOWO$3>{9g-Uc7Zk_h(7HKWtxj==9 z^!+7tZ7KG)61u;H9xS55?xyckD>HyPM;2Wn98~W!Xl2Z>5T;jiJ=$!Vy_awcI@C#; ziy_Pbb44rwla*Np{2JV*9bwXaP&f!ob0dVqz+vD7a0=KAO6^NMc!V3#8 z-;VhEOXojWil_5mLHsM!230Yw0fHWp8XmXv_;#m`Y3)v7oaW6U9?cHl!$TX8%{X&W zcyY`{Ik=>0qRD$NDdXX}4qF>C{u@n@6RwHSu4uFUuH##t|0x&J6$C1p=I`N-Yrwq6 zg<-UhEn)u(bJz=QGhOX|eNDyd*Z*OfFWeC_$l)%#%iS^J|6KjHO?}mQ*48=cbzis4 z{^_2L?XKCi@o#lIe)yMUbkj;fnS+J-z`l#F zJ>0M(F4>iidq}A*^@R=(CgC{q<#Db%px0;I1$mmJpqScbUV5mn|kanBW_|ypB~cBsSql{ z{>rv^46PPgu~@vV(%4)%ee>I%x&sd z*DS3c-Fk8A)pv}UK`%GUkX8S{ZRlyKmZJ?#%KAm)x}80ocw+wS?<+%f9gzt`CRcuw zUFeox;y*g}4m)z&0YSuiJXs&uoQ#nihKKBJ?$8r0w+aIb~ zoDR!UolTe^!j|YQyaOI*Ic$~=qZEvVVAq$((6WIfM|LloKW%U{r#Nu23{mv_UPHheHwF(;$|IH-ef<_vaHa7x%!1$Gi}tbiKDWw6v6ln3$P zT5=f=C(Ir%?Qm0;!TW@%UbYeWz*nmb|IDBuIoR~kt-)GQc$=LPtAk_hZ-p8>Tsd=P zz3SUF8{bbf@E=ASjy)po{Av%|Y?~x7I1g|4%9H=Y+#TlIo!$vyZkh~tp}P#TzvNh- z;^u`nu2pY#az=LXdd_$VK5x$xIq4xd)8}62g!9$uGuRtHbk zxoP~o{eqO`*f_C&kLnh_CHsVoXMLbnE<01^pWh%QEvMgYXSXoD{-NDA?tQ`0%S$G| z_`7`L5IoVp-HshGJ)`+w^S(-MydS=#Cr|RT!{hw<@6<~#IJa21X3p>*RyJYAu-?-a zG0ZgUC;8a49dcNVm}c!Y*cWmSV>R3y?moEqS3l;Mg7qNkA-1L)n|Ca<3hCd?^r=5_ zbK-wuqk#N*20PmX%Q$trVCT-^xWDS1de*(9Ga~VEPT%{IQHC>Br~u&{f2=oc z)1S~^?}!PNm5NlINKHshyDQV~lOoOGC)ZFeYAz2snr6u(0W7<10fpf#P#Ns8j2 zeBznM?Hf~4r1GNt6^bPJB&kx8tOu%`Nu^%u>>N;2vjQGvYJ()Ks4`>6Vri;kj5$({ zlq9)?O4+C0ytZXlt}nH|NpiQ@Csl7ar&C!reW|C?wWnd8a*EU?U3B6?Wqh>UJ+ab! z+F9RTF=>%+eOWpek#705;#kPFMEdc#j?UCL_nmhsl3kXh`p$Ysi{g~}JMo?>YYd7* zawzpa+?TKN`tok6DlA1tBTE12(i(GROTE$;yK_`pdyW!Xx^}tJ=}U(vcBZDL9lqh` zusw&bO6i)QwjhsOy$?i5#PH}!D!t)qhvINek(89w)FUmIe7;E3)+E&i%%U`V!>F?A zUZo`-H!HJXLEYk0l&<%r%a=(56PG)%O%6+IZMsyNS5Bh$$?4!B#S9Zinj{m820RR+ zHiZq^R`-y4Av9G(03_NB;i;Ltqv#-Er7<2Si=H$h#w5OS%?i#A3)jMtCdzwqP8dRC zu*Rn{XdgT|gVsSDx2lVOWoSq}Hf|i385+tfpznXkOdl^$_lx>Vh96h|^YrgbyM#Bg z(~jMvHOr%+TqM#Gj z(iLxV48h7+SFZ64rC1Bj3uuo}j?0YAcsg(k5rjRsEScd^+}NzA6W9lS7&KH&mq0j# za1tYdvSN;h@rK9pjw5a&(vFp(ZiG8YWh`WLu-5wn(&<>1I1VH_uP@v3PeZ*&Syc z(qGl}>J@D5()@JpnA&{ptGSKL(e?QJe3pAz{ki(fjSSWx8#h1sIlBRwL{M~d$S3-k zdN!*uo7JDQZ5dhLl}L2y$^9exOL!62e<=4sR`lXc#Ze}!pcCqb5#e;KpI!<*(5t#n z*^`I0Ej{4rj>fqi7?pO6jY>Pv<#u3H+JRAN2S%kG7?pNlRN8@2X$MB79T=5%U{uxH%L)WAggLDa17g0g!Q-jY@Lv6q%_&x`5P+L%kwuGw5b67`CbQ)~c ziF)8Gy-?D8NKvO{94zr-C6vH<&lN8_hRRE^)uq_}B7!{|O2!1-$^=|};y1X3s&W`! z(8h9_UP7}=Xh8{`R6?f|uLwmQa^Ha5H{kis0N#bNySH>d*Obyx+}%ibH}2wl#e53) z_9D)Bvy_hVqgm{aknWRWI+SS0u1;)qQRc-zUdr$}>}`?;2Yzj_Y?U`-tp+q)PKX3h zlO12KF>r-H?JUU`m_bZq+b*vw%EO8nf3nw=!3;HaB!Re;#VQxgivt99*c?L;p^Y6O zGeanXD1jxo@Vx+$8PW>Y<{~o)QIL`$Re(iaFX3JZSAhrvp#*|+2C`R%66Lbq7{m%&BKGouu*xx$x&pn!5@XqWfS@f~|L*G$9 ze~{^ISAAf5vx?oUZsR9%RekwScclO0^xX~18}>0@s<$lFmrnMk)BVT(Alao@%Wpcw z6OVb=Gond~2So>l+_K3ivX0??kCdNiirH)ucd_W{6h-V~Xj0OF6cxjMrr6anL|y)XD^dlO**;ICA}FcTJ0*Uq6uZO=zYj{(*?pN+X^G7?85>462d$?_!6!P! z#kP*>70bKBQg!y`9|z-;O+!_tR3_#Y;|=vjV@%YW@59L*!4o8LQmfeVrt5OJsR}yr zVDK0rSsfw0(r)umJ7i{x?iBe{SuV*9PP9i=nnm|~cq>_nJs?gv4ENUsZ%`qaep9ti zK{y~rwnoh)b0^6&JWJR5I!?qQK;$fp8ps=`eB~r!@*wiwNegh$FMr zLC{fDu|=gcOMwc@0;x|u1!>6CjD(X-z?-PWih+^BEwG}oxel`(ben!Odql^N4GQ?N&*r%WpuMDOy*n0_%RcPUG(e}XIf-w>PvG~W}6^kTcM zbt|4+y|{mtWu0xUZT3*LqE;Bo+@5ler^4;7@bIkGP^CWhMTM`-F79|V`b83+8EpsE zzq6sX6a5R@_`|{GaHu&HYKlafWw}bN>XbU?N-?8ZF)IeM8~$E%=tEQa6nj*iz#UPK zu(i1-J-;*Coe3BITnVR3Vji29ZTKDMPF94y15eLh|6#~$_9Sk&lINR$l>b`n?G@<~ zV}B^aq|ewX{ZY0;pJ9h|7ljnk4smWGzVjTcMp%Zvb_aXxFgmDK?ejNb`7RZMD$RTh z6EyfB0zM9@L+gP>U=g3sh;-Cf77WSjP#ii+96F~P<+BHQR%vCpuNX(B^MckD!ekPu z#=4ni;BClxTS2}idrF!cDq4);a^=O+DWbP6^r^-YG8Iul8Y>idQ~=zP1v5jZXgA;} zrS_C~{t^ly_k#SFDxyLuufi=+Y0u$dI!bAJN~o`d`b%iAgr=9!Na^aMB{a8$7M0MF z5?WS5%S&ig39T(6)DaAhwf++QT>+%2`=Lu&xJzMZZsXSu%q z<-VGOmkK`?e`5c!aOthd{JI@G`xd&+w(hnq?c3VWF|MKI)O_osS6bhB7!M)8;LxUwO*-PkR&7Q{{<~kwkf98ukV0Rp+xA$L`};{_p%u z_1oyPN1Hu7i=2#Z{5( z?F(JP9T0UBblF6#8!LZE0r;lw57MR5VhkbO#ZiZha%#d#AS$2uGEI$65dwMEnStES z-|S4z;g;lA=l}Xwhbr5-K521&&Z~*J`B&}SCL3G$A>>{NJYh)@pTYW|%~r|-d)@*j0yup3Fd`;}HpkHEnR)m954sIRf0u!<=762ca(c1oy3BDgY& zvJ6bq0EOPDfE6^6)T_XQYOt(>c;W~UBdf^u!0o@|e3qdcWu^Q~*AX&;-=uOTEvvBxA>){|Z zW;N%CP)tGVt(i1Jc7;3%zKpfgN$Av?T#zZzDM9@WdD4S`9hx;5&o$R^$cy}cLO6z6 z7zzcFU7L9#mQQ4`ctVCxGeqMelo83i zNjOAm%GNP*gO-JdGLHz6mA1yE&8tZ1j*PGq1@0f)3z8%(+P!f7NVkbpxD)tI)5Pcu zA7JTycUlr2OXU*F9joN(^5o`&p)Il;lFea@+j7WanKSY72H6sl-HzuiJ(l4qa;0pk z82rT{x20u+++&|BTP#m3aj&=hz%ne?Tkdo(dC4sgFF7{6Z7^&zYo1vX*n1g zZLoaoevd0}IM;pC9kQu;iF;jg=4j-0ME*7VPd;xBH;w$x2*1itUjs$&lM3%a#7JfH!0bdN6Dm z`q~l*f0DGkcZX%=aI)cY_sg%kDi>q_zY|7>Lm_6X<}3GwMneZ>%Tm|+bKMs8Z>^QX z?pIGRv*_q(>-)jVAM9(ebaYx>7TMA|+_U9S{acpz-J9ieUQ$2zcgTiML(jQJ)k&LSz1GC-pzdf83@aVLL2$feV&S_-LevD4m~VdR_Kj#81h~WG63yk zav8kJe;4f)*>cx6I2jsx52o`xkhZ*5UfUptcB(*GWLSj@V!)BZj#hAORQLx#%Lrsz zUEpoWVJ{P$4pp%yr_JqQzbm<=j`P5q5fVt5GO#81_Rp2cP-T0e;6^uv|4}$6LU~6O zpb)GRP#is8*f3y%(UXI}1qPgDEl~~*b1}OQ?w`5$7jJggS4N(j5PaMkF*qC(^OlG1 zO_dv@^2Oy`B4y71Nny@PF5Og9+CufytdlaP zC3CZ;KsY^XnNRGkUvuvhAR zlDd8V{K~eaR)t+?bsRYMg4ASXi+DrC9c+>$b-%;f#8W?Lz^*^zqz|M|vC{3&Fi9C= zKV$D>2XZs#V#~-T0rO?=pv+bBTdxxm5oqfRmN}UXQ2Ocywq1zc` z@32ka9M;V&BG@{Czl3elylGsPvpqBOi1{?1#wb z)l&S=z7dbrd+c@iDftX(-vE9CY5y>m7Sp1IcZS{u^$jLP&@C*_M*@k~2-9oNgEZhLyG%O0VWeV`8ht`5jnefDLq4rM!va!-)k`^Az%<+mSnRXj!f@E^S z_m2QQ4c(v?LzkgP?SZcY?XmH&oX1OMS-2VItrM*98rOpl(8FP-58W>;vA}W5Y3=c# zV=7!s%SFUn#<~jW14Yuy4x>Rjkcx-9JnpW(F1Kgqf;s-c$n2?JZ)>i}Zg21g!fX6` z__pNDW|Q9}M^a^0(PFhqoCGrgm<(V$ZmZp)=dJL|Ct@pW+1}XFbz+kMpMtsg(IB?Lu2oR?pn#;EU_VMB^vb%Sv&m$|)@W45PLH2a@bT}oetT%9?Y%8xUx5^H^ z(IE016D6z7E^}6xXCNap$K%C|d)hDOm1IS=yJ5|eX&!rRL%k!txYpX#+1F8TiH!># zSk`;~b&p>-&oQ*?JC9#A@sHQNG~3X;a?9>h+m+tlJy~Ja83!)k)!VDSS`iP`aa1oC?n(TLZ-t{rZyJpPnqof`_W|xL(3b=Qw7vIbHBH(U8kJd|5+dReFNW)|{<1D$$S!(b&mJ4kc1n z*&j>V%WK`<)Vrc56bU#v4&@BDV0L(2SgaDRsH=)grtV~UeRq?mGUXGbXhm&BL=YWb zpUcb`%B3XnoF|q_1f}?da3WDx7H{W&Wp%<&hBa`8V<;Rfyg-ZD zAVL`Mey1|-E#g#~H+=U{Cdg8K4{zO?>%oLiEzREgtpvq7?W!|Epa;bUdGCndq zkn45wiLSmGwOtEl_f|=v-kCFcpX81DSRfEW-I7ekcpwlIrSlXMrsQC90@ceF-G2Rl zN`He=gI^KvW6imdt2JmYf9OhF@$aNz+U2T457v^Vnjm^*Of=I9n`q5pOpVRb1}F$OYn{0T_g_HP5^@!hKkG;M1i z*=cXZ^K8ZQY{m0z#q(^%^K8ZQY{m0z#q(^%^K8ZQY{m0z#q(?(d!DU$o~^iXIN!$g z$q8F0uC-OWepd-~m(aM<^@mDmd17#9qCtU=^Q1VtAxCz zSRe8)=*0r1*kBRC|2SSptM)p^^6e_6>Mo()Qf_@E)L+VXpo9iXXk6*sp%NNjLX%2p zN(oIb5W|h$VQqBuXyrrdcmlY94Kzxp2^F*(ciP(KUoncOdF>jA4DdzGBO^qp% z8&X)2hQ*WL3^O^$NL%K{PS@mgRnB4DX{@nZ$`S*S~X{+IyyW6?h>b1XD{qwjzhgfqycsE=`EPrg} z%Ey+kcw*VICsyqE;LI~W*s=51XPohC_Mb`OnstsdJ~8V(eDe6eZj!4XUBc_)PiuOlEvJz%~D)y(^E8qR97Ceat=!?8#$( z6GS3IDuy%+=@>FIWM?Rfp=gF;7>Z-a!;qJuM23p<5X`z|diae$LP@7`iirs4SUkP0=wc;*L|7 z8`$yD5ae_dI)o7{qFX?19V6ocVsZE|wuQ1565YZoNInMH6ND;$0-03>Pels03J`E$ zL=1s6imN~bidq;lBM+rO4vJn5WLaS80HSijT%P#A!~k1H2apd#Y4yKq?~al_nXzdy zTq$gmUi`9IwfU+`yPPl@OfX4*&`5WTCR4d)`_9OVX$5CX*IPf07ZTf~dCgGOAVpVq%z`RewC^A~hQFLE5RY|-qRBYk=8F=D=5`g{!( zE5|wRa6G?u`&#L#=ws0zmft$!>(qzU{BQ4jMcUx}PNv#G_USbw#vbpI-diC}INeyd^C?MRDfCX(OxGBs zeQ!j*TKb0h&Ajub*SKOSZItxkbK^AIo|&7(PPR35wInolcysM#g@xsOi8t4ml;Rhb#8-Ny-%Ls!OCm>ls*=Yi z2JW9y+BDi%H?b^hEZ3ae7+316c1943x{X9h&q`gcs5onGTp6(yIE&WB73R+=^w#3b zlB@8mma7ExjHy@*SqQzHb)_n%h-3GAkGl0qiSoaygy3YW33}D@70P8*j zSoawSulo#O-Df~v_Za|>^`JWo`|IUT*Y#-4fQ;5Mv^R7V{gT?0rXgh@QB5WqL9QGc zS9FbL7WzHi?t*XC(bOD-w6)^S5J07?NxCJz?!FM>Q z4Kf-TqvirYZ_YETcWQS4=9_k|Gpv_J*4c83qa;B#nyrJfS z$mYycprq z@EV8ZXPIg6E?m=CNS=H(`8Cy}er^|{Fj}R1Rb;sInm~%9E}cD@^zfP}uQ$r+^{RyR zquYIYO`JP1x}i-!FI`L(yvoc+r()gxdgVxOq~5Jmj)$S!pdMChRcSidqwf_Hau4Xz zPLgSt4@*DeUD+l*Y2c(sTtc0e+|IrCg|tycuKT1!nJjd!pOP;JFoPLOjcU#k8? zRaa?=CDi&n3q_LgE~6K~jz#X^1+mK8B3whd&&h7<5!VEj1Q4LBx*V_wECSQ~@I|8e zI^^q+Zw8J4jsT{%C*hA`E9e%< z`_KOfg+8n=L)NEi9Ik%^)`TBFvRRD4BNX}9>B-4;i3u~8Fe(OU9- z83wV+<&1GA=D3V0kr{3LC#N42@3H+{uRG+3-V+CzGqI2SNm?&$M*B( zQ8m_yQdQtW-pVTg(pjbx}E zH8;pLMu+kcDgljbMkAZSX*w%8gQ1xW%?AH&x%L8v7P6z)GurD|-bRMDGITRTyBXTU z&;f?}89K<&VTO(}bax1yR!qT}oWPl!z;&beB=AY9{RA}$d}Z>e=9}ya5ymAj9;LAe zApD1l5?1dcI3J=Mczu3+q%d_+BKR>KqKSS4_Qhe$Yw)-rlpy_taq@&Iw;%%Q0WfgE zTgTEX^JDZ;Xz}S?&_EuhDqzK2Q{Bq zq)2aCnhPotohtYl*bbGHTOy@Rk9;Bq9*gLWwDl=tIUD&#?XgO4#FrSj2w?+}DxTz? znyK9A;zyE|#)bORt`+W@sPA6RA&2vp_^lY+otvXqHI@;XCSCdMg^wH&_J5StLtn)Z|)6zq}n^Q8$+#}O_0(LjK@WC0f zDn>f@kv4+&d?dZcC)wv&eMvp4BwnqK^*IY|sb+7PDKXl5eMzY@@v6x3(wXmW-0XJ` z^SyIuVngbUdq^dV>chnYctJqz-gsjgg_fF4hc4j08eo3y)-H=RT+)>L5xPr0?v5!Z^TM`ef zvn#Vj)5e{P+SjOCip%er6*YrgG!%BYKtc9Q{bhB-u~ zx*)!fZ=?_J{|tCK$b%|;siG2Q8g%|M1u;YxLn^fyW5C0BLqI7N{#wr~K2&^76tF{g zl0=e)ICyoWiOe7!WEI&!c97f1o#Z5Wm^=d+@4JxlUVui`MfI^WaNtl)A9mQ@jFY#` zL^kapZDg*zzmU*are{buStDcM@m8(j#P^@326?}3Z#uldytMGokBW`6qFSMypKd> z#XizSf~xvSS5j^U9Vhbt zOF!DuA8t!O+R`t#r3Bs#f{t4%LzE#x#Z?`J*U+e8GM6%NDFc@>a47?qGH@vamojiE z1D7&zDFc@>a47?qvM`r2a4Dnn6;cL@A)8rJ4ICU9$<*sXy&lx-LA@T->p{I9)ayaL z9@OhWy&lx-LA@T->%-LRLA_q4UJr`F3CL+O4w!0gBiJix25tv#2c}=O1;7h}=hOzS zZQ$Alu5IAj2Ci-3+6Jy|;MxYRZQ$Alu5I87t$JCP0N{NjdQNSi7_t^2bAeZa`bu!3 z^S{-=tAV?K*8{H)a_t7!ZgA}e*KTm_2G?$I?FLtPc1GHRbOh-X(pjVs*KTm_mbrF= z;ucWc0_tmkw*zkvQttuv9#HQA^&U{~0rehG?*a85Q11ct9#HQA^&U{~2~+O@^&Xje z4=C;i#oeI34fp`?fgtrhQ11ivK2Yxi^*&JV1NA;o?*sKdQ11ivK2Yxi^}aCmK2YzI zsrP~6?VyMNZ)7jDTz_d3#2mBl` z?M*KOzYI)!)9b*m1JmC0E-+jo%l+UZ;E#Z5KllvzGho^ez5)IQnD&E9z?Xn=2MK}t zBmu@9Br0IoK@ePfVgNP(f17`!{d`ST?ru&#N2H%hJTa%nc?pfr%4As^r>AMK(p~2&4$omZanW2l}+H{sf zF40+q4I>r-B-RmG=Yy;uvd#yoC6)3^Iv#c?g8Z8EF_gqm3PWiOWiXVZu4COJD z&rk_Nr3_UvRK-wD2%RSDa3ZsD86XEB^Ut3qV}Qp1H)3I>mW&~da@*@!&C#qTUHn^y z+qsOE2EGyaM&L@|;9A9LLd)z#{!U6A_*URsL*)+w9|T^3`~lzr;4#2=0pA6TmMM+{ z9|xv&PXV6-UJU#Q@FT#q?i0XI08?Hs0KWiC+w&IiTcP|9fZ?56rvE2ksPD*Sz6Aaf zn9~0i_*-DwehF9t27MynieMf{%Mh#x5v&NwSIq=$3YD<~!|wor?hSDR!^4?e22)#t zsV!|Y$pp>}l_>@;2B!3<08ar1UostddZ>IaaBrymeqeYQBM*e{19^y{M;UsVq1VY` zvO@0A@3XuM4E>p*iy?%Ob^#)MIp|O~4uj-K9?^fP<_wRqwhtEEu=N%(5ru<9gaU)* z3=akT0v?P1BCjF^Dj2N!Fp3r(B;RL+>m;~Sg7+v`wEXYk|7(0MP9igUzRL9BZu*7jN--lmHl)+uXgouc+;lLe4@nK|BIzMSo(gfn!x5r)&sgBFE zGb!-FteY?2Y#C-Z3cYr_DfZ-{T>s^Z+yO_RexWc>TRJsh`#$DeBx&^OI_Hy%4>-t6 zfki?zKdoo>L5|yFSfcv&GZkMQFdH-)qYvi&in4}4&0m$qu^_Y2VNf5g))>yYf^?`bxCSY*>VfKTHO7q{YX~3uJ56f{ zGyCfk3S64GBuh+~|B6+w8n%Bc_i>3*6K&%wFMqY;uuu?)T)V$STexEz_wDkcy}K)- z>~WQQcU9EgW!*1*V$xh*JSIW>T2mthFr!VIlHZvzL5zy+h>th>#R#1^&Bd9dRni5| zxPI&PWc-6fVRJ?)wK3@n(z{5VxLZ27V0+cK&P&yg6)lsRq_-Eq!PN=rh?7)Dk=7>Z zc&hYT`<>5T|Hq@>cs{ZHQ9AeLXY$oF8dE~sq|i1&zFtP7H?;4kTjV8#_I;sk>X73P z$omFE_;_;Yc$iK&|G!J`kx=~~)I(mleTnoq+9lHiP7Jj>oG+i(703B}w>sBhw;tFs zthLtLu=nf=>0W`fT>tE$vGHWo&IFhy|2+QjP(mxk1{Iq$<3-n@ge98=R%p5Mw_dHgyU+&nWHlK)sS!;Bww6? zDY7UJ6UJgXO6PPXSmUJIZKy)GtysXK+n7-3vSBD6^yQPwP+kZj%p^WtBk<`Ofk861B!dlB8o$U1Vs$+VLHa5t7+7uiycxYx;SUY0Spr5 z7%2OJ&A?_HhYfmY1uZv(;0*@Hi*US1KE?3yX{_W7(6q~AoLMYyE<=kLTFlT=hL$n3 zf}!ge+Qd+A2tiH*uPI4z`i4-Pe!PTfOvMT@j*k$rf`#QIQa}yx%y@BQKufURiv=hu zna7fp=zui~*VS|MC5ifHgPYDUzOiUN~*Tq-G5_!+_*iD z-L<L=1c~7(@Z@NRRw)0#fAue7><2jF@$`nZ~QJUO((XG-M6OCMy(i*EnZ&2#vBe)o% zG5Ynm9T9MT>J|sfiWhYF8*kjcBk%IZlB71=-6CGi&A0`EN<(X#j_JsXe#ks$!bm-HLW92QOLc>*&e^HvE zQ)2T*eQAt~w&C0PQ7Sj(7GVc5Ib04CA$pkBqlC)u|*ltczc*+S^Pb!mj6l?FZa3=nExLLO8n+R)=mXl>#5)z+pz5YN@@8O zl5tF#uaJr({3hO(R5DJhda!azw>uykr`s-gV5P#t9eA@w;LS>9UKU^*Fr5vT11A6v zm6qoqKM(mHY%8&?L|KZffN7npu%(i8TCN!`1jb|Ag1oRq{aENNouLRKDq9aCDq9aC zDq9aCDq9aCDq9aCDq9btn;7a1A-FF9zgyr@WH&oTCGElT`*7|%Wd284-hB)mXXt*0 zPBQdB2>nE)^q4wV zUICE>eMlo|KnrXi$0vwxuZ&@V!IV7iI*kq=j6M;}q3-0u=oW_dGjv-B(KSgBwj(7W z4M(a)nuIh5X$8_oq&-MSkWL|;MGD!WJr4by$FU}P2AK%mCO=fqFdo!ZWH9e}miIyk zVe@;uAO5R272)_4;dm6`xD`X=Rs59WR8TM1^A%?KqCE+1hTqHREX(^1{4oY)$j@ND zLH&f$h=bvB|Hjbsti}r=gtwDykp0t(fT1B!L50XRj_RY*MJuGAd{7L2B6&ji?)yJw z9Te`$=8uz&-QT^qu3p$f($zoJcp1`aiM;&P!$n1RL}u|fkzXF%a?W$tMsAb6U1x#f_DVpbLX)`-)ld1WR25`Pw|$7^Z?3&L0kx2C=ZW5Rh-8Ic3N>B zCFmfgYM5+M`=i9+C=A8n=!VSq??vPYAN>U@cZ{L?8G4hUw-|bdp$`xZB*^0ug0bM|F|CXUHiA5nQ$m4o@^7{q(~ zl|sT7-2`6>tI1jN9GA%Da`;#f4^c##h!CIP@xjAQ88KNDP`r|TumwG_UHL1AEzSSo zZvmomPDHE_Npti#w;SfzuTVrW;}WQA&f0b-^i zo&!RFsAzBxxF$}3A7sRdkOM5(;olTl(7HwmdD)NZYC~@`hCovr{}CVo5m)61t@&_o zLn$KwID8p{APvJR?-#(a8=M)_U=i>emxNk~12H_mfZFsRZUmNZ@P`FK+R`7Mubd;( zki)&g+a0AJA3pEk*@u6r3nKZC62S@5-z(~h4xAKPf&de7oS$AGtWQA`4@JDtJ4MQM zpivHbI}l3(cAP3Njaux0=N`1nn-4YAr2K+-`6Rudj-VEBkcZVS#32Sz+9;f%4eO*~ z?R9!@a$o}mHCJ#^d56K7UIMD20lAJOc5@mk;0J+9e9+3!)aRr zzaJ9OXkvg``A5=myYvg`!w&!ESBOt4;kb=LwxAU*3wq%jZ0CCf!Q&PLw_OnIu>!|+ zoto9&?W{?vv9i-Ok9IUSga3x(h-q)PjgZqA{Cnr|#uq~-2cbC>oC8^`2#?7H@v{SBPprfsK9 zOcaE~`K*0ffjdfb5ep^ODF{xFu;iX=C;KPwNpo%$MuK1X+yeoDi-oh9L}hA@p@rKg zM5(HE5k%Od_pVQFuS3ZsxFtJKx!Ks3FC#w7T4#{(dj@bL7(4PGoAw#~3;uXuwrh zyRF%xRV$D+ZaoLrN*ouPDe_vW1h+$#BYg#1nXS?q>5Z?x@2r3O&n}XO1@KXqZ{;{4 zmY!bt0t8PU;camdGKAjR^s$|3SGNvwr+cxBY-8|V)9Xa5xC9q2I`{b7gv?8qREh3n zL0hHa8^;Qk^_l}T%y~p6k@lg3tacA^H%U3q4utL4P$#W_N<*7cWLt`}Tt4vbcHb6;?R*M7*P zEEV$ZG`rMF;WT=eFnpC!CED{X+#m61dM60Vih2(BNjcsvz@ovVg+pa9K!4>pv)U@S z=jOos(JMlhS#9QuZ{h6rpBuSkLH(YvPe2j7kyh60Iit(7QOKh&a0hYGjr{LtVF3S} zYv!I7c*H^RfHyo%IrIzB@QfRGr;V+!i zj#ZU*L#Zft)GXzV%#xGy9+!!6^l?d8yvE#I~R8^y>{-rWu8G#PFB`%Pi^PY zWlP(;x+rL0(Z1Bv)ZVr*(=(!@!_!F1b$J@wyV{qoXrG~02FulUc6PLPPp_6YfAg{rqR~J0CI9;u zIpYTx_{z&m>viICx8s6Oms=m+gKdiZ?|VNy%s~ zgl=>TgwazWCZ0xJ>60kPexlKPQ)QRr8R!GU(1){eVX3R~eDr4Oy1WSer34z*Wf1n7 zA%uv)!sKME8v4=qVZAP1lbMyBMSru3 + +Civilian + + + +
+
+ff +
+
CIVILIAN +civilian +There are "" on your team + +STATS +Max health: 50 +Max armor: None +Max speed: Medium + +WEAPONS +Crowbar + +GRENADES +None + +ABILITIES +None + +
+
+ + \ No newline at end of file diff --git a/resource/classes/civilian.jpg b/resource/classes/civilian.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e4bf3e58aa0f597950f7b5213d9e9f30548452ac GIT binary patch literal 22843 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 literal 0 HcmV?d00001 diff --git a/resource/classes/default.html b/resource/classes/default.html new file mode 100644 index 0000000..25d6e00 --- /dev/null +++ b/resource/classes/default.html @@ -0,0 +1,41 @@ + + + +Default + + + +
+
+ff +Default class html file thing! +
+
+ + \ No newline at end of file diff --git a/resource/classes/demoman.html b/resource/classes/demoman.html new file mode 100644 index 0000000..4840aea --- /dev/null +++ b/resource/classes/demoman.html @@ -0,0 +1,57 @@ + + +Demoman + + + +
+
+ff +
+
DEMOMAN +demoman +There are "" on your team + +STATS +Max health: 90 +Max armor: 120 Medium Armor +Max speed: Medium + +WEAPONS +Grenade + Pipebomb Launcher, Single-Barrel Shotgun, Crowbar + +GRENADES +Hand Grenades, MIRV Grenades + +ABILITIES +Can set large explosive devices. +
+
+ + \ No newline at end of file diff --git a/resource/classes/demoman.jpg b/resource/classes/demoman.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2065e23fa031495eb290bea43d82ec2fb28a9cc GIT binary patch literal 37831 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%0D;hYZn?=ETItZu>p?R|c+uf% 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 literal 0 HcmV?d00001 diff --git a/resource/classes/engineer.html b/resource/classes/engineer.html new file mode 100644 index 0000000..cd76e87 --- /dev/null +++ b/resource/classes/engineer.html @@ -0,0 +1,60 @@ + + +Engineer + + + +
+
+ff +
+
ENGINEER +engineer +There are "" on your team + +STATS +Max health: 90 +Max armor: 50 Medium Armor +Max speed: Medium + +WEAPONS +Railgun, Double-Barrel Shotgun, Wrench + +GRENADES +Hand Grenades, EMP Grenades + +ABILITIES +Can build automatic sentryguns. +Can build ammunition dispensers. +Can repair teammates armor. +Can create ammunition. +
+
+ + \ No newline at end of file diff --git a/resource/classes/engineer.jpg b/resource/classes/engineer.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6fca13546a04cfc4ae2f94f00124a30fea60b185 GIT binary patch literal 36677 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
    Xnt{U?W=DV8V$WRd}uE} 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 A8UO$Q literal 0 HcmV?d00001 diff --git a/resource/classes/ffheader.jpg b/resource/classes/ffheader.jpg new file mode 100644 index 0000000000000000000000000000000000000000..696e4163f4c5fa96b3f7ca8c35f192576c2cf5f7 GIT binary patch literal 12450 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 literal 0 HcmV?d00001 diff --git a/resource/classes/hwguy.html b/resource/classes/hwguy.html new file mode 100644 index 0000000..bc7028c --- /dev/null +++ b/resource/classes/hwguy.html @@ -0,0 +1,57 @@ + + +HWGuy + + + +
    +
    +ff +
    +
    HEAVY WEAPONS GUY +hwguy +There are "" on your team + +STATS +Max health: 100 +Max armor: 300 Heavy Armor +Max speed: Very Slow + +WEAPONS +Assault Cannon, Single-Barrel Shotgun, Double-Barrel Shotgun, Crowbar + +GRENADES +Hand Grenades, MIRV Grenades + +ABILITIES +Heavy, isn't pushed by explosions. +
    +
    + + \ No newline at end of file diff --git a/resource/classes/hwguy.jpg b/resource/classes/hwguy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5ca557d398bc26abf13b3103ec052da3e797ae52 GIT binary patch literal 40490 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 literal 0 HcmV?d00001 diff --git a/resource/classes/medic.html b/resource/classes/medic.html new file mode 100644 index 0000000..8cb2d9e --- /dev/null +++ b/resource/classes/medic.html @@ -0,0 +1,58 @@ + + +Medic + + + +
    +
    +ff +
    +
    MEDIC +medic +There are "" on your team + +STATS +Max health: 90 +Max armor: 100 Medium Armor +Max speed: Fast + +WEAPONS +Medikit, Super Nail Gun, Single-Barrel Shotgun, Double-Barrel Shotgun + +GRENADES +Hand Grenades, Concussion Grenades + +ABILITIES +Can heal teammates with Medikit. +Automatically regenerates health. +
    +
    + + \ No newline at end of file diff --git a/resource/classes/medic.jpg b/resource/classes/medic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d9f47071513d3470a2f9760309e0505a1cfe0147 GIT binary patch literal 43782 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�dQvRq2r4q`HemhY&}rL{VkT;3j2Xc> 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 literal 0 HcmV?d00001 diff --git a/resource/classes/pyro.html b/resource/classes/pyro.html new file mode 100644 index 0000000..70cde9f --- /dev/null +++ b/resource/classes/pyro.html @@ -0,0 +1,57 @@ + + +Pyro + + + +

    +
    +ff +
    +
    PYRO +pyro +There are "" on your team + +STATS +Max health: 100 +Max armor: 150 Medium Armor +Max speed: Medium + +WEAPONS +Flam-Thrower, Incendiary Cannon, Single-Barrel Shotgun, Crowbar + +GRENADES +Hand Grenades, Napalm Grenades + +ABILITIES +Flame resistant. +
    +
    + + \ No newline at end of file diff --git a/resource/classes/pyro.jpg b/resource/classes/pyro.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbb037790184fd507014a491278f61b6e6b6fb41 GIT binary patch literal 40794 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 literal 0 HcmV?d00001 diff --git a/resource/classes/random.html b/resource/classes/random.html new file mode 100644 index 0000000..198ec0c --- /dev/null +++ b/resource/classes/random.html @@ -0,0 +1,45 @@ + + +Random + + + +
    +
    +ff +
    +
    RANDOM +randompc +There are "" on your team + +Every time you die, RandomPC will randomly pick one of the other classes to become. +
    +
    + + \ No newline at end of file diff --git a/resource/classes/randompc.jpg b/resource/classes/randompc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b268456fbb7a78ad4da1896a4c953d61140ad85d GIT binary patch literal 16003 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 + +Scout + + + +
    +
    +ff +
    +
    SCOUT +scout +There are "" on your team + +STATS +Max health: 75 +Max armor: 50 Light Armor +Max speed: Very Fast + +WEAPONS +Single-Barrel Shotgun, Nail Gun, Crowbar + +GRENADES +Caltrop Canisters, Concussion Grenades + +ABILITIES +Can remove an enemy Spy's disguise. +Can disarm Demomen's detpacks. + +
    +
    + + \ No newline at end of file diff --git a/resource/classes/scout.jpg b/resource/classes/scout.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8b7191673b380bc35ad19d98800c904acf36178a GIT binary patch literal 55366 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 b!TO3ia_`&3_u#nTe}GJl!u$V8(B}RhmrmdQ literal 0 HcmV?d00001 diff --git a/resource/classes/sniper.html b/resource/classes/sniper.html new file mode 100644 index 0000000..c1d0734 --- /dev/null +++ b/resource/classes/sniper.html @@ -0,0 +1,55 @@ + + +Sniper + + + +
    +
    +ff +
    +
    SNIPER +sniper +There are "" on your team + +STATS +Max health: 90 +Max armor: 50 Light Armor +Max speed: Medium + +WEAPONS +Sniper Rifle (with automatic fire), Nail Gun, Crowbar + +GRENADES +Hand Grenades + +
    +
    + + \ No newline at end of file diff --git a/resource/classes/sniper.jpg b/resource/classes/sniper.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7d37fbb9fdc7799cdf581b795168089bb2b61485 GIT binary patch literal 49507 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 + +Soldier + + + +
    +
    +ff +
    +
    SOLDIER +soldier +There are "" on your team + +STATS +Max health: 100 +Max armor: 200 Heavy Armor +Max speed: Slow + +WEAPONS +Rocket Launcher, Single-Barrel Shotgun, Double-Barrel Shotgun, Crowbar + +GRENADES +Hand Grenades, Nail grenades + +
    +
    + + \ No newline at end of file diff --git a/resource/classes/soldier.jpg b/resource/classes/soldier.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4ff7e2d2afb255c32e9c6557970df653a4a7aed2 GIT binary patch literal 37785 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 ZRhW_(*NVnnd<}7(n5&lHrw{xu|JlpA7d8L@ literal 0 HcmV?d00001 diff --git a/resource/classes/spy.html b/resource/classes/spy.html new file mode 100644 index 0000000..7e053df --- /dev/null +++ b/resource/classes/spy.html @@ -0,0 +1,60 @@ + + +Spy + + + +
    +
    +ff +
    +
    SPY +spy +There are "" on your team + +STATS +Max health: 90 +Max armor: 100 Light Armor +Max speed: Medium + +WEAPONS +Tranquilizer, Double-Barrel Shotgun, Nail Gun, Knife + +GRENADES +Hand Grenades, Hallucination Grenades + +ABILITIES +Can disguise to look like and enemy. +Can feign death. +Can remove an enemy Spy's disguise. +Can backstab for and instant kill. +
    +
    + + \ No newline at end of file diff --git a/resource/classes/spy.jpg b/resource/classes/spy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4b5e8f10eaf89cf39bf1841b00c91e45f6151d66 GIT binary patch literal 47288 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 literal 0 HcmV?d00001 diff --git a/resource/ff_version_client.txt b/resource/ff_version_client.txt new file mode 100644 index 0000000..b888de8 --- /dev/null +++ b/resource/ff_version_client.txt @@ -0,0 +1,13 @@ +2.46.1 + +CLIENT version: +- only the first line of this file matters +- this determines the version of the CLIENT +- it can only be up to 15 characters long + +// Okay the server and client are versioned separately so that we can do a +// client- or server- only update if required. +// The client version is checked when FF is loaded +// The client + server versions are checked when a server is joined +// It is the discretion of the web-based version check script whether or not +// to tell the client to upgrade or that the server they are joining is out of date. \ No newline at end of file diff --git a/resource/ff_version_server.txt b/resource/ff_version_server.txt new file mode 100644 index 0000000..52d98b7 --- /dev/null +++ b/resource/ff_version_server.txt @@ -0,0 +1,13 @@ +2.46 + +SERVER version: +- only the first line of this file matters +- this determines the version of the SERVER +- it can only be up to 15 characters long + +// Okay the server and client are versioned separately so that we can do a +// client- or server- only update if required. +// The client version is checked when FF is loaded +// The client + server versions are checked when a server is joined +// It is the discretion of the web-based version check script whether or not +// to tell the client to upgrade or that the server they are joining is out of date. \ No newline at end of file diff --git a/resource/game_menu.tga b/resource/game_menu.tga new file mode 100644 index 0000000000000000000000000000000000000000..f75ead13ad954d499a8b8163661ab82167665b2e GIT binary patch literal 25132 zcmeHND{K`(6n(UmmO@emj!;t+)D%U6DJjWI`2SKt0t!O{7z_rF0F42QLZiTt;J{%) zVL{*@dr0r@VRC1;^V_%d-6orvo!z-}?wNCTXZCe8nj6XA$IwGzMm!fyrbt z>l9f2#z4)0`Jtx5D#pOb{9qz51{wy;4-FSqGX~5LrU7H1VZi**aA7rL!2DnuFa{b1 z#1Hew&Tbw!^W-TG)SEk+8s9Uwa(u11(p{6-DBJojoV@1v1YgOLF$&LG8H%6dhW16i zh5b-Jr?gz9Ed+O8e%N{T{}PONM}R9nmhXJ}BG+S{CG3X~4!U%js)?@nIj#>i_riWi zdUt8O_vHtSy*PgPO7z}UR%^Z!8s4_Hp=zQHbFOQpJe$gCVL#OGhg{FUKK(F%bbX`C z2e`g;<;~j|outm4Z_HA0vCrf8qts*Oc1Hd1U%wxqH(nF*e%aUV)2P;7O1Gu72Hk7V z2lztEudQvUx$lMd1NOVnfP0`_<}cRfmzAaDo19%k9xNPg+c8#%V^Ahr%RmRcQOQOxT zGS&~gug14k;8@tW|4_yPPl7G9WZlN%)5c`p1t*snSL@f+1}=cpJ!0mOF_y|bCNBGd zIpca4PrmD%Gsly94Bo!|fZXt25X@LJRcocsavq}v;S0KyI5AvE9JlP^9oOAHeV-T1 zJ&Du3;0NC`nsZCh8~TcFS!LR2 ze(>Su+)_E`y@+@tb{#Hx74$=qwYlKVQI^mKaHVp}n(^r>Hh(AQEc?Z2`Jvh~JQ5$E zl)XeOH_F^);b$i<`ypH0lw94usk(LJ$$4tr!hT3v%Sn!0PRkG2OR^uT->aW9u9&*> zya@gl;v19W;=3?3vUA`Y9O{3+#rgg(%NI9iJ8%e}sqb#al^U1*;C#0f-lPoPgE2Pj zL2+Ik|I7*6s^7g%b53pbY54(|@QqC7Fl8St`GE_Gmst~aT#2uh;9juwT^7te$!F{b zjWccw<&1OYIBq>e3)A!iZ~}WS9Wg&49CXbC$91{p^IUm!;nA)$#!|V*#4YTH+N(Sd zZaoCI_(9{ik2YYf-VMS3tJDWJ8)Nnun6@8gk8#U*$PAbthCDllt#1a*4}CLk;|-Ys z^TUv5$FTLyfcc?s#%;VIGhlug^6VJ4z8Nq-^v$@9H)ICb4>zve+`2WsKE8bE)b{!D Ig{}3`A9$LZSO5S3 literal 0 HcmV?d00001 diff --git a/resource/game_menu_mouseover.tga b/resource/game_menu_mouseover.tga new file mode 100644 index 0000000000000000000000000000000000000000..0dc5fe4bd0ae9dca444401a58e639e9f13378d6e GIT binary patch literal 25132 zcmeHOOK#La5FN2%nGO5dzz!6N3q+tGMM4n1VhJZ;Za_`|IRWGb4SVL|QZU8qJ z>RBoKsnu=w$33=~vSd}e++FqRRh7r>D2v6dg&sc^%f<4xUYRrocAbIEX0z)QSp3F7 z%YgMmON9-Lfra&h6@f9(F<|}BabY84!1}>zz!>Nluzu*cu#quf{a`g<40H@=KO7t! zJUTf!`GgbWZbmoaIm_kpUUz4Bq_!bt?cLCd_j2gm5RRC&YQrb{{QGP(rqs1Qdo^^7 z(HFDoQt`9h)U}9{YbG_HLp(7yjn5}jaBDxnj*OcFV;>ftlN#IQ<>mUu{O0uZ^s~?Y z-rnAwzjElj^VI5m9v9}l%t4|94$0@$qZcgl6GoiXl z!NYTF0tF5G9o{6>6%JwC6lu6}9#Lhr-dr{kJP#g||=>G|4c zcg%YgV_$1dayaFh$;oLSM>S&JRzD!Fv$M0W%I%O$dFNBk9DYWt+gf%N_ZU(zu9efA zx(#6{wOhF#IOb9EEgUvf#Ng&RIh^nB??2R>^~v+|^Y5Yj^y!_tjsA`7vx$4P?4swv zse9&dTUxgv4oYL^n!z~aCr4i+=7N66>PLPj;{CGde`=4gK82?m{J?)LyQq7OnPpDh z2*&nZI;WpPJeS7)KlFoacdx+%IOY?2&08+#ysyUl6Y_xPq}qj#P;Q3wz^Zm~@%em! z3$-hlzahtbA|~IuA>GLR&|<6=dyZZ12jqu&)A0~bq5GU~UtUmGp|v5sJQ4eNx&JUSLb@wi18$>SwRJE2Y?6 zFm8;y8QqBIjPac0eRat`S`n7!PVKmo?Q##hW6X2cZtI#cj*%P1Eq06gjBCc_%e_{g zv65qUZSi#qAF{4-&$zeM55NiBW7QG!lfuCe|7@3ecE@AIF@(o=UwjwUtE U`1a`4(er2b-#s~cdiY@R4}|W00{{R3 literal 0 HcmV?d00001 diff --git a/resource/gameui_english.txt b/resource/gameui_english.txt new file mode 100644 index 0000000000000000000000000000000000000000..05f8b8f82e1bb5fc4ef3cd555a9eaefdc3eeda30 GIT binary patch literal 50944 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 M4;p;sW&M-?1E%Bzr2qf` literal 0 HcmV?d00001 diff --git a/resource/icon_ff.tga b/resource/icon_ff.tga new file mode 100644 index 0000000000000000000000000000000000000000..657077d0871900a3e2663910316017d661e7433f GIT binary patch literal 1068 zcmXw3TTfJH6x}6#=pzqCYYeTJP+CF}s-TDrAj4&Fm>K4N=A1cmzi=5CW|%>t6eS~0 z5fChwDn$gj4+vOmYc-WpMgl^ybN= zOgj9IT@=V6*^w7o_Xb^*)!KJaT%jm0Wg# zB*8?oXd$O$y{I@KSZm1NeTE$AhWQ=)*! zLE*OGPDNQUs>)AdXLA)_elddC>l0YK^%cra9K#1kvd~ah{faqcI+=5tha{M(+2^9p z_SPJSX#TsnC?9o71s;5}h1AMCu1}8R?p6w#h8koY+{f4oVbp6I9ITbas3VI>&-3Lp z_P*Nca@Hx2YwNJSvViG{tC*Xa#&0j4!!29!{-OQI%RPeXO2tjy2O0Gmp3nNr_Ds9Y z@`tjj3|FrV;x=<$nxDngwGo~_hKJwY!^X;Oj1ON%QNf3(C@=k!b=+^|9Y{7Sg<6{> z_67u#4*k7xj14ETy}6EQ?!S3s5-)%G2}`$bAQB2dS#=txN{V36HHMs$KyA(bw;B86 zldO5YvI05Thj6~D15Y16!sPe}CdY>H?CB4Pb++QbzRbNn=H+ICJ@v%zb!M~#yye}| zj{iREi6fb~fSKuQyz?b|&6+JQ%wlvXvFCx&p-VhJ$k+xE?Fd3qR`QS2E|vzp?m@Fb z%k`Vs+F0dX&tvz|1HAn8XKbu4uzpi`@$3n{zrTa~cQ;=9g0U=!1!u}9X}vzvUc?#QBWhwtl_-{VRJe4dtp3;mQB7@$}* zLP5We`ulomD0!J9NyAr$D0wNt-!D>M&pC=k!qgq>qIg%7;+(rh_JXO#tTL#y NnvbouDs@c({SPTu+5rFn literal 0 HcmV?d00001 diff --git a/resource/overviews/ff_hunted_a08.txt b/resource/overviews/ff_hunted_a08.txt new file mode 100644 index 0000000..40771a8 --- /dev/null +++ b/resource/overviews/ff_hunted_a08.txt @@ -0,0 +1,9 @@ +"ff_hunted_a08" +{ + "material" "overviews/ff_hunted_a08" // texture file + "pos_x" "3998" // X coordinate, + "pos_y" "3463" // Y coordinate, + "scale" "7.0" // and used scale used when taking the screenshot + "rotate" "0" // map was rotated by 90 degress in image editor + "zoom" "1.3" // optimal zoom factor if map is shown in full size +} \ No newline at end of file diff --git a/resource/spectatormenu.res b/resource/spectatormenu.res new file mode 100644 index 0000000..b6bb677 --- /dev/null +++ b/resource/spectatormenu.res @@ -0,0 +1,130 @@ + // Command Menu Definition +// +// "filename.res" +// { +// "menuitem1" +// { +// "label" "#GoToB" // lable name shown in game, # = localized string +// "command" "echo hallo" // a command string +// "toggle" "sv_cheats" // a 0/1 toggle cvar +// "rule" "map" // visibility rules : "none", "team", "map","class" +// "ruledata" "de_dust" // rule data, eg map name or team number +// } +// +// "menuitem2" +// { +// ... +// } +// +// ... +// +// } +// +//-------------------------------------------------------- +// Everything below here is editable + +"spectatormenu.res" +{ + "menuitem1" + { + "label" "#Valve_Close" // name shown in game + "command" "spec_menu 0" // type data + } + + "menuitem2" + { + "label" "#Valve_Settings" + + "menuitem21" + { + "label" "#Valve_Chat_Messages" + "toggle" "hud_saytext" + } + + "menuitem22" + { + "label" "#Valve_Show_Status" + "toggle" "spec_drawstatus" + } + + "menuitem23" + { + "label" "#Valve_Overview_Locked" + "toggle" "overview_locked" + } + + "menuitem24" + { + "label" "#Valve_Overview_Names" + "toggle" "overview_names" + } + + "menuitem25" + { + "label" "#Valve_Overview_Health" + "toggle" "overview_health" + } + + "menuitem26" + { + "label" "#Valve_Overview_Tracks" + "toggle" "overview_tracks" + } + } + + "menuitem3" + { + "label" "#Valve_Overview" + + "menuitem31" + { + "label" "#Valve_Overview_Off" + "command" "overview_mode 0" + } + + "menuitem32" + { + "label" "#Valve_Overview_Small" + "command" "overview_mode 1" + } + + "menuitem33" + { + "label" "#Valve_Overview_Large" + "command" "overview_mode 2" + } + + "menuitem34" + { + "label" "#Valve_Overview_ZoomIn" + "command" "overview_zoomrel 1.1" + } + + "menuitem35" + { + "label" "#Valve_Overview_ZoomOut" + "command" "overview_zoomrel 0.9" + } + } + + "menuitem4" + { + "label" "#Valve_Auto_Director" + "toggle" "spec_autodirector" + } + + "menuitem5" + { + "label" "#Valve_Show_Scores" + "command" "togglescores" + } +} + +// Here are the rest of the buttons and submenus +// You can change these safely if you want. + + + + + + diff --git a/resource/spectatormodes.res b/resource/spectatormodes.res new file mode 100644 index 0000000..955bc48 --- /dev/null +++ b/resource/spectatormodes.res @@ -0,0 +1,53 @@ +// Command Menu Definition +// +// "filename.res" +// { +// "menuitem1" +// { +// "label" "#GoToB" // lable name shown in game, # = localized string +// "toggle" "sv_cheats" // a 0/1 toggle cvar +// "command" "say_team Go 2 B" // your type specific data, a client command or cvar etc. +// "rule" "map" // visibility rules : "none", "team", "map","class" +// "ruledata" "de_dust" // rule data, eg map name or team number +// } +// +// "menuitem2" +// { +// ... +// } +// +// ... +// +// } +// +//-------------------------------------------------------- +// Everything below here is editable + +"spectatormodes.res" +{ + "type" "menu" + + "menuitem1" + { + "label" "#Spec_Mode3" // name shown in game + "command" "spec_mode 3" // type data + } + + "menuitem2" + { + "label" "#Spec_Mode4" + "command" "spec_mode 4" + } + + "menuitem3" + { + "label" "#Spec_Mode5" + "command" "spec_mode 5" + } +} + + + + + + diff --git a/resource/ui/BottomSpectator.res b/resource/ui/BottomSpectator.res new file mode 100644 index 0000000..5f9d3c7 --- /dev/null +++ b/resource/ui/BottomSpectator.res @@ -0,0 +1,105 @@ +"Resource/UI/BottomSpectator.res" +{ + "specmenu" + { + "ControlName" "Frame" + "fieldName" "specmenu" + "xpos" "0" + "ypos" "428" + "wide" "640" + "tall" "55" + "visible" "1" + "enabled" "0" + "tabPosition" "0" + } + "settingscombo" + { + "ControlName" "ComboBox" + "fieldName" "settingscombo" + "xpos" "15" + "ypos" "14" + "wide" "140" + "tall" "22" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "textAlignment" "west" + } + "playercombo" + { + "ControlName" "ComboBox" + "fieldName" "playercombo" + "xpos" "c-108" + "ypos" "14" + "wide" "216" + "tall" "22" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "textAlignment" "center" + } + "viewcombo" + { + "ControlName" "ComboBox" + "fieldName" "viewcombo" + "xpos" "r155" + "ypos" "14" + "wide" "140" + "tall" "22" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "textAlignment" "west" + } + "specprev" + { + "ControlName" "Button" + "fieldName" "specprev" + "xpos" "c-140" + "ypos" "14" + "wide" "25" + "tall" "22" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "command" "specprev" + } + "specnext" + { + "ControlName" "Button" + "fieldName" "specnext" + "xpos" "c115" + "ypos" "14" + "wide" "25" + "tall" "22" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "command" "specnext" + } + +} diff --git a/resource/ui/ClassMenu.res b/resource/ui/ClassMenu.res new file mode 100644 index 0000000..a24df3e --- /dev/null +++ b/resource/ui/ClassMenu.res @@ -0,0 +1,602 @@ +"Resource/UI/ClassMenu.res" +{ + "class" + { + "ControlName" "CClassMenu" + "fieldName" "classmenu" + "xpos" "c-320" //0 + "ypos" "0" + "wide" "640" //640 + "tall" "480" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "SysMenu" + { + "ControlName" "Menu" + "fieldName" "SysMenu" + "xpos" "0" + "ypos" "0" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "0" + "tabPosition" "0" + } + "ClassPreview" + { + "ControlName" "ModelPanel" + "fieldName" "ClassPreview" + "xpos" "c" + "ypos" "60" + "wide" "316" + "tall" "350" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FullSection" + { + "ControlName" "Section" + "fieldName" "FullSection" + "xpos" "0" //12 + "ypos" "0" + "wide" "640" //616 + "tall" "480"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles_small" + "titleText" "" + } + "ChangeClassSection" + { + "ControlName" "Section" + "fieldName" "ChangeClassSection" + "xpos" "62" //12 + "ypos" "73" + "wide" "180" //616 + "tall" "270"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles_small" + "titleText" "" + } + "WeaponsSection" + { + "ControlName" "Section" + "fieldName" "WeaponsSection" + "xpos" "246" //12 + "ypos" "73" + "wide" "125" //616 + "tall" "270"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "MenuTitle" + "titleText" "Weapons" + } + "WepSlot1" + { + "ControlName" "LoadoutLabel" + "fieldName" "WepSlot1" + "xpos" "246" //12 + "ypos" "93" + "wide" "125" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "WepSlot2" + { + "ControlName" "LoadoutLabel" + "fieldName" "WepSlot2" + "xpos" "246" //12 + "ypos" "133" + "wide" "125" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "WepSlot3" + { + "ControlName" "LoadoutLabel" + "fieldName" "WepSlot3" + "xpos" "246" //12 + "ypos" "173" + "wide" "125" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "WepSlot4" + { + "ControlName" "LoadoutLabel" + "fieldName" "WepSlot4" + "xpos" "246" //12 + "ypos" "213" + "wide" "125" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "WepSlot5" + { + "ControlName" "LoadoutLabel" + "fieldName" "WepSlot5" + "xpos" "246" //12 + "ypos" "253" + "wide" "125" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "WepSlot6" + { + "ControlName" "LoadoutLabel" + "fieldName" "WepSlot6" + "xpos" "246" //12 + "ypos" "293" + "wide" "125" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "WepSlot7" + { + "ControlName" "LoadoutLabel" + "fieldName" "WepSlot6" + "xpos" "246" //12 + "ypos" "333" + "wide" "125" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "GrenadesSection" + { + "ControlName" "Section" + "fieldName" "GrenadesSection" + "xpos" "375" //12 + "ypos" "73" + "wide" "175" //616 + "tall" "80"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "MenuTitle" + "titleText" "Grenades" + } + "PrimaryGren" + { + "ControlName" "LoadoutLabel" + "fieldName" "PrimaryGren" + "xpos" "385" //12 + "ypos" "103" + "wide" "70" //616 + "tall" "40"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "SecondaryGren" + { + "ControlName" "LoadoutLabel" + "fieldName" "SecondaryGren" + "xpos" "465" //12 + "ypos" "103" + "wide" "70" //616 + "tall" "40"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ClassInfoSection" + { + "ControlName" "Section" + "fieldName" "ClassInfoSection" + "xpos" "62" //12 + "ypos" "347" + "wide" "309" //616 + "tall" "80"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "ClassMenu" + "titleText" "Class Information" + } + "ClassInfo" + { + "ControlName" "RichText" + "fieldName" "ClassInfo" + "xpos" "232" //12 + "ypos" "367" + "wide" "130" //616 + "tall" "52"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "text" "Special Abilities: Test +Second Line: Test word wrap word wrap word wrap word wrap" + "border" "0" + } + "SpeedLabel" + { + "ControlName" "ClassPropertiesLabel" + "fieldName" "SpeedLabel" + "xpos" "72" //12 + "ypos" "367" + "wide" "150" //616 + "tall" "16"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FirepowerLabel" + { + "ControlName" "ClassPropertiesLabel" + "fieldName" "FirepowerLabel" + "xpos" "72" //12 + "ypos" "385" + "wide" "150" //616 + "tall" "16"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "HealthLabel" + { + "ControlName" "ClassPropertiesLabel" + "fieldName" "HealthLabel" + "xpos" "72" //12 + "ypos" "403" + "wide" "150" //616 + "tall" "16"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ClassRoleSection" + { + "ControlName" "Section" + "fieldName" "ClassRoleSection" + "xpos" "375" //12 + "ypos" "397" + "wide" "175" //616 + "tall" "30"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ClassRole" + { + "ControlName" "Label" + "fieldName" "ClassRole" + "xpos" "375" + "ypos" "397" + "wide" "175" + "tall" "30" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "font" "MenuTitle" + } + + "changeclass" + { + "ControlName" "Label" + "fieldName" "changeclass" + "xpos" "76" + "ypos" "70" + "wide" "450" + "tall" "48" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "labelText" "#FF_CHANGECLASS" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "font" "MenuTitle" + } + "ScoutButton" + { + "ControlName" "MouseOverButton" + "fieldName" "ScoutButton" + "xpos" "76" + "ypos" "116" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "labelText" "#FF_MENU_SCOUT" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "scout" + } + "SniperButton" + { + "ControlName" "MouseOverButton" + "fieldName" "SniperButton" + "xpos" "156" + "ypos" "116" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "4" + "labelText" "#FF_MENU_SNIPER" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "sniper" + } + + "SoldierButton" + { + "ControlName" "MouseOverButton" + "fieldName" "SoldierButton" + "xpos" "76" + "ypos" "148" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "5" + "labelText" "#FF_MENU_SOLDIER" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "soldier" + } + + "DemomanButton" + { + "ControlName" "MouseOverButton" + "fieldName" "DemomanButton" + "xpos" "156" + "ypos" "148" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "labelText" "#FF_MENU_DEMOMAN" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "demoman" + } + "MedicButton" + { + "ControlName" "MouseOverButton" + "fieldName" "MedicButton" + "xpos" "76" + "ypos" "180" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "2" + "labelText" "#FF_MENU_MEDIC" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "medic" + } + "HwguyButton" + { + "ControlName" "MouseOverButton" + "fieldName" "HwguyButton" + "xpos" "156" + "ypos" "180" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_HWGUY" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "hwguy" + } + "PyroButton" + { + "ControlName" "MouseOverButton" + "fieldName" "PyroButton" + "xpos" "76" + "ypos" "212" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_PYRO" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "pyro" + } + "SpyButton" + { + "ControlName" "MouseOverButton" + "fieldName" "SpyButton" + "xpos" "156" + "ypos" "212" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_SPY" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "spy" + } + "EngineerButton" + { + "ControlName" "MouseOverButton" + "fieldName" "EngineerButton" + "xpos" "76" + "ypos" "244" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_ENGINEER" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "engineer" + } + "CivilianButton" + { + "ControlName" "MouseOverButton" + "fieldName" "CivilianButton" + "xpos" "156" + "ypos" "244" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_CIVILIAN" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "civilian" + } + "RandomButton" + { + "ControlName" "MouseOverButton" + "fieldName" "RandomButton" + "xpos" "76" + "ypos" "276" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_RANDOM" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "randompc" + } + "CancelButton" + { + "ControlName" "FFButton" + "fieldName" "CancelButton" + "xpos" "76" + "ypos" "308" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_CANCEL" + "font" "ClassMenu" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "cancel" + } +} \ No newline at end of file diff --git a/resource/ui/FFGameModes.res b/resource/ui/FFGameModes.res new file mode 100644 index 0000000..01eb6d2 --- /dev/null +++ b/resource/ui/FFGameModes.res @@ -0,0 +1,65 @@ +"Resource/UI/FFGameModes.res" +{ + "FFGameModesPanel" + { + "ControlName" "CFFGameModesPanel" + "fieldName" "FFGameModesPanel" + "xpos" "212" + "ypos" "106" + "wide" "512" + "tall" "406" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#GameUI_FortressGameModes" + } + "PlayButton" + { + "ControlName" "Button" + "fieldName" "PlayButton" + "xpos" "344" + "ypos" "372" + "wide" "72" + "tall" "24" + "labelText" "#GameUI_Play" + "Command" "OK" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "424" + "ypos" "372" + "wide" "72" + "tall" "24" + "labelText" "#GameUI_Cancel" + "Command" "Cancel" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "GameModesPages" + { + "ControlName" "CFFGameModesPages" + "fieldName" "GameModesPages" + "xpos" "8" + "ypos" "26" + "wide" "496" + "tall" "342" + "autoResize" "1" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } +} \ No newline at end of file diff --git a/resource/ui/FFGameModesScenario.res b/resource/ui/FFGameModesScenario.res new file mode 100644 index 0000000..e400ed1 --- /dev/null +++ b/resource/ui/FFGameModesScenario.res @@ -0,0 +1,409 @@ +"resource/ui/FFGameModesScenario.res" +{ + "ScenarioGameMode" + { + "ControlName" "CFFScenarioGameMode" + "fieldName" "ScenarioGameMode" + "xpos" "0" + "ypos" "28" + "wide" "496" + "tall" "314" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "AllowedClass" + { + "ControlName" "CFFAllowedClasses" + "fieldName" "AllowedClass" + "xpos" "243" + "ypos" "230" + "wide" "313" + "tall" "140" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Untitled" + } + "BlueTeamNumbers" + { + "ControlName" "ComboBox" + "fieldName" "BlueTeamNumbers" + "xpos" "82" + "ypos" "108" + "wide" "80" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "BlueTeamAllowed" + { + "ControlName" "Button" + "fieldName" "BlueTeamAllowed" + "xpos" "32" + "ypos" "138" + "wide" "116" + "tall" "23" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_AllowedClasses" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "BlueTeamTitle" + { + "ControlName" "Label" + "fieldName" "BlueTeamTitle" + "xpos" "14" + "ypos" "74" + "wide" "185" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Blue Team - Offence" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "BlueTeamBotsLabel" + { + "ControlName" "Label" + "fieldName" "BlueTeamBotsLabel" + "xpos" "10" + "ypos" "108" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Bots" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "RedTeamNumbers" + { + "ControlName" "ComboBox" + "fieldName" "RedTeamNumbers" + "xpos" "82" + "ypos" "220" + "wide" "80" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "RedTeamAllowed" + { + "ControlName" "Button" + "fieldName" "RedTeamAllowed" + "xpos" "32" + "ypos" "250" + "wide" "118" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_AllowedClasses" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "RedTeamTitle" + { + "ControlName" "Label" + "fieldName" "RedTeamTitle" + "xpos" "14" + "ypos" "191" + "wide" "185" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Red Team - Offence" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "RedTeamBotsLabel" + { + "ControlName" "Label" + "fieldName" "RedTeamBotsLabel" + "xpos" "9" + "ypos" "220" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Bots" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "YellowTeamNumbers" + { + "ControlName" "ComboBox" + "fieldName" "YellowTeamNumbers" + "xpos" "330" + "ypos" "108" + "wide" "80" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "YellowTeamAllowed" + { + "ControlName" "Button" + "fieldName" "YellowTeamAllowed" + "xpos" "278" + "ypos" "138" + "wide" "116" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_AllowedClasses" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "YellowTeamTitle" + { + "ControlName" "Label" + "fieldName" "YellowTeamTitle" + "xpos" "262" + "ypos" "74" + "wide" "185" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Yellow team" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "YellowTeamBotsLabel" + { + "ControlName" "Label" + "fieldName" "YellowTeamBotsLabel" + "xpos" "258" + "ypos" "105" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Bots" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "GreenTeamNumbers" + { + "ControlName" "ComboBox" + "fieldName" "GreenTeamNumbers" + "xpos" "330" + "ypos" "220" + "wide" "80" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "GreenTeamAllowed" + { + "ControlName" "Button" + "fieldName" "GreenTeamAllowed" + "xpos" "278" + "ypos" "250" + "wide" "116" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_AllowedClasses" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "GreenTeamTitle" + { + "ControlName" "Label" + "fieldName" "GreenTeamTitle" + "xpos" "262" + "ypos" "191" + "wide" "185" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Green team" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "GreenTeamBotsLabel" + { + "ControlName" "Label" + "fieldName" "GreenTeamBotsLabel" + "xpos" "258" + "ypos" "220" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Bots" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "MapCombo" + { + "ControlName" "ComboBox" + "fieldName" "MapCombo" + "xpos" "194" + "ypos" "17" + "wide" "115" + "tall" "25" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "Label2" + { + "ControlName" "Label" + "fieldName" "Label2" + "xpos" "147" + "ypos" "18" + "wide" "37" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Map" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Divider1" + { + "ControlName" "Divider" + "fieldName" "Divider1" + "xpos" "246" + "ypos" "63" + "wide" "2" + "tall" "239" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "BuildModeDialog" + { + "ControlName" "BuildModeDialog" + "fieldName" "BuildModeDialog" + "xpos" "0" + "ypos" "0" + "wide" "304" + "tall" "577" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Untitled" + } +} diff --git a/resource/ui/FFGamemodesScenarioAllowedClasses.res b/resource/ui/FFGamemodesScenarioAllowedClasses.res new file mode 100644 index 0000000..6392960 --- /dev/null +++ b/resource/ui/FFGamemodesScenarioAllowedClasses.res @@ -0,0 +1,483 @@ +"resource/ui/FFGameModesScenarioAllowedClasses.res" +{ + "AllowedClass" + { + "ControlName" "CFFAllowedClasses" + "fieldName" "AllowedClass" + "xpos" "243" + "ypos" "230" + "wide" "313" + "tall" "140" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#GameUI_AllowedClasses" + } + "frame_topGrip" + { + "ControlName" "Panel" + "fieldName" "frame_topGrip" + "xpos" "8" + "ypos" "0" + "wide" "297" + "tall" "5" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_bottomGrip" + { + "ControlName" "Panel" + "fieldName" "frame_bottomGrip" + "xpos" "8" + "ypos" "135" + "wide" "287" + "tall" "5" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_leftGrip" + { + "ControlName" "Panel" + "fieldName" "frame_leftGrip" + "xpos" "0" + "ypos" "8" + "wide" "5" + "tall" "124" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_rightGrip" + { + "ControlName" "Panel" + "fieldName" "frame_rightGrip" + "xpos" "308" + "ypos" "8" + "wide" "5" + "tall" "114" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_tlGrip" + { + "ControlName" "Panel" + "fieldName" "frame_tlGrip" + "xpos" "0" + "ypos" "0" + "wide" "8" + "tall" "8" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_trGrip" + { + "ControlName" "Panel" + "fieldName" "frame_trGrip" + "xpos" "305" + "ypos" "0" + "wide" "8" + "tall" "8" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_blGrip" + { + "ControlName" "Panel" + "fieldName" "frame_blGrip" + "xpos" "0" + "ypos" "132" + "wide" "8" + "tall" "8" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_brGrip" + { + "ControlName" "Panel" + "fieldName" "frame_brGrip" + "xpos" "295" + "ypos" "122" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_caption" + { + "ControlName" "Panel" + "fieldName" "frame_caption" + "xpos" "0" + "ypos" "0" + "wide" "303" + "tall" "23" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_minimize" + { + "ControlName" "Button" + "fieldName" "frame_minimize" + "xpos" "0" + "ypos" "0" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "0" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "frame_maximize" + { + "ControlName" "Button" + "fieldName" "frame_maximize" + "xpos" "0" + "ypos" "0" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "1" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "frame_mintosystray" + { + "ControlName" "Button" + "fieldName" "frame_mintosystray" + "xpos" "0" + "ypos" "0" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "o" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "MinimizeToSysTray" + "Default" "0" + } + "frame_close" + { + "ControlName" "Button" + "fieldName" "frame_close" + "xpos" "288" + "ypos" "8" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "r" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "frame_menu" + { + "ControlName" "FrameSystemButton" + "fieldName" "frame_menu" + "xpos" "7" + "ypos" "8" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "ScoutChk" + { + "ControlName" "CheckButton" + "fieldName" "ScoutChk" + "xpos" "10" + "ypos" "28" + "wide" "96" + "tall" "23" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_SCOUT" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "SniperChk" + { + "ControlName" "CheckButton" + "fieldName" "SniperChk" + "xpos" "10" + "ypos" "52" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_SNIPER" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "SoldierChk" + { + "ControlName" "CheckButton" + "fieldName" "SoldierChk" + "xpos" "10" + "ypos" "76" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_SOLDIER" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "DemomanChk" + { + "ControlName" "CheckButton" + "fieldName" "DemomanChk" + "xpos" "106" + "ypos" "28" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_DEMOMAN" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "MedicChk" + { + "ControlName" "CheckButton" + "fieldName" "MedicChk" + "xpos" "106" + "ypos" "52" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_MEDIC" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "HwguyChk" + { + "ControlName" "CheckButton" + "fieldName" "HwguyChk" + "xpos" "106" + "ypos" "76" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_HWGUY" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "PyroChk" + { + "ControlName" "CheckButton" + "fieldName" "PyroChk" + "xpos" "202" + "ypos" "28" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_PYRO" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "SpyChk" + { + "ControlName" "CheckButton" + "fieldName" "SpyChk" + "xpos" "202" + "ypos" "52" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_SPY" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "EngineerChk" + { + "ControlName" "CheckButton" + "fieldName" "EngineerChk" + "xpos" "202" + "ypos" "76" + "wide" "96" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_PLAYER_ENGINEER" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "OKButton" + { + "ControlName" "Button" + "fieldName" "OKButton" + "xpos" "154" + "ypos" "107" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_OK" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "OK" + "Default" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "224" + "ypos" "107" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Cancel" + "Default" "0" + } + "BuildModeDialog" + { + "ControlName" "BuildModeDialog" + "fieldName" "BuildModeDialog" + "xpos" "0" + "ypos" "0" + "wide" "304" + "tall" "577" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Untitled" + } +} diff --git a/resource/ui/FFGamemodesTraining.res b/resource/ui/FFGamemodesTraining.res new file mode 100644 index 0000000..07bc733 --- /dev/null +++ b/resource/ui/FFGamemodesTraining.res @@ -0,0 +1,91 @@ +"resource/ui/FFGameModesTraining.res" +{ + "TrainingGameMode" + { + "ControlName" "CFFTrainingGameMode" + "fieldName" "TrainingGameMode" + "xpos" "0" + "ypos" "28" + "wide" "496" + "tall" "314" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "TrainingTitle" + { + "ControlName" "Label" + "fieldName" "TrainingTitle" + "xpos" "24" + "ypos" "52" + "wide" "348" + "tall" "26" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#Training_AvD" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "font" "Trebuchet24" + "wrap" "0" + } + "TrainingDescription" + { + "ControlName" "Label" + "fieldName" "TrainingDescription" + "xpos" "24" + "ypos" "78" + "wide" "282" + "tall" "175" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#Training_AvD_Desc" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "1" + } + "TrainingScriptsCombo" + { + "ControlName" "ComboBox" + "fieldName" "TrainingScriptsCombo" + "xpos" "24" + "ypos" "21" + "wide" "208" + "tall" "23" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "BuildModeDialog" + { + "ControlName" "BuildModeDialog" + "fieldName" "BuildModeDialog" + "xpos" "470" + "ypos" "21" + "wide" "304" + "tall" "577" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Untitled" + } +} diff --git a/resource/ui/FFOptions.res b/resource/ui/FFOptions.res new file mode 100644 index 0000000..dd5b2ff --- /dev/null +++ b/resource/ui/FFOptions.res @@ -0,0 +1,81 @@ +"Resource/UI/FFOptions.res" +{ + "FFOptionsPanel" + { + "ControlName" "CFFOptionsPanel" + "fieldName" "FFOptionsPanel" + "xpos" "212" + "ypos" "106" + "wide" "512" + "tall" "406" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#GameUI_FortressOptions" + } + "OKButton" + { + "ControlName" "Button" + "fieldName" "OKButton" + "xpos" "264" + "ypos" "372" + "wide" "72" + "tall" "24" + "labelText" "#GameUI_OK" + "Command" "OK" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "344" + "ypos" "372" + "wide" "72" + "tall" "24" + "labelText" "#GameUI_Cancel" + "Command" "Cancel" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ApplyButton" + { + "ControlName" "Button" + "fieldName" "ApplyButton" + "xpos" "424" + "ypos" "372" + "wide" "72" + "tall" "24" + "labelText" "#GameUI_Apply" + "Command" "Apply" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "OptionsPages" + { + "ControlName" "CFFOptionsPages" + "fieldName" "OptionsPages" + "xpos" "8" + "ypos" "26" + "wide" "496" + "tall" "342" + "autoResize" "1" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } +} \ No newline at end of file diff --git a/resource/ui/FFOptionsSubCrosshairs.res b/resource/ui/FFOptionsSubCrosshairs.res new file mode 100644 index 0000000..25e043d --- /dev/null +++ b/resource/ui/FFOptionsSubCrosshairs.res @@ -0,0 +1,804 @@ +"resource/ui/FFOptionsSubCrosshairs.res" +{ + "CrosshairOptions" + { + "ControlName" "CFFCrosshairOptions" + "fieldName" "CrosshairOptions" + "xpos" "0" + "ypos" "28" + "wide" "496" + "tall" "314" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "InnerCharacter" + { + "ControlName" "ComboBox" + "fieldName" "InnerCharacter" + "xpos" "78" + "ypos" "28" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "OuterCharacter" + { + "ControlName" "ComboBox" + "fieldName" "OuterCharacter" + "xpos" "78" + "ypos" "181" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "7" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "InnerScale" + { + "ControlName" "CInputSlider" + "fieldName" "InnerScale" + "xpos" "78" + "ypos" "52" + "wide" "126" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "InnerScaleInput" + { + "ControlName" "TextEntry" + "fieldName" "InnerScaleInput" + "xpos" "211" + "ypos" "52" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "2" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "outerScale" + { + "ControlName" "CInputSlider" + "fieldName" "OuterScale" + "xpos" "78" + "ypos" "205" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "OuterScaleInput" + { + "ControlName" "TextEntry" + "fieldName" "OuterScaleInput" + "xpos" "211" + "ypos" "205" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "8" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "InnerRed" + { + "ControlName" "CInputSlider" + "fieldName" "InnerRed" + "xpos" "78" + "ypos" "73" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "InnerRedInput" + { + "ControlName" "TextEntry" + "fieldName" "InnerRedInput" + "xpos" "211" + "ypos" "73" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "OuterRed" + { + "ControlName" "CInputSlider" + "fieldName" "OuterRed" + "xpos" "78" + "ypos" "226" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "OuterRedInput" + { + "ControlName" "TextEntry" + "fieldName" "OuterRedInput" + "xpos" "211" + "ypos" "226" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "9" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "InnerGreen" + { + "ControlName" "CInputSlider" + "fieldName" "InnerGreen" + "xpos" "78" + "ypos" "94" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "InnerGreenInput" + { + "ControlName" "TextEntry" + "fieldName" "InnerGreenInput" + "xpos" "211" + "ypos" "94" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "4" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "OuterGreen" + { + "ControlName" "CInputSlider" + "fieldName" "OuterGreen" + "xpos" "78" + "ypos" "247" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "OuterGreenInput" + { + "ControlName" "TextEntry" + "fieldName" "OuterGreenInput" + "xpos" "211" + "ypos" "247" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "10" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "InnerBlue" + { + "ControlName" "CInputSlider" + "fieldName" "InnerBlue" + "xpos" "78" + "ypos" "115" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "InnerBlueInput" + { + "ControlName" "TextEntry" + "fieldName" "InnerBlueInput" + "xpos" "211" + "ypos" "115" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "5" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "OuterBlue" + { + "ControlName" "CInputSlider" + "fieldName" "OuterBlue" + "xpos" "78" + "ypos" "268" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "OuterBlueInput" + { + "ControlName" "TextEntry" + "fieldName" "OuterBlueInput" + "xpos" "211" + "ypos" "268" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "11" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "InnerAlpha" + { + "ControlName" "CInputSlider" + "fieldName" "InnerAlpha" + "xpos" "78" + "ypos" "136" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "InnerAlphaInput" + { + "ControlName" "TextEntry" + "fieldName" "InnerAlphaInput" + "xpos" "210" + "ypos" "136" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "6" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "OuterAlpha" + { + "ControlName" "CInputSlider" + "fieldName" "OuterAlpha" + "xpos" "78" + "ypos" "289" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "OuterAlphaInput" + { + "ControlName" "TextEntry" + "fieldName" "OuterAlphaInput" + "xpos" "211" + "ypos" "289" + "wide" "32" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "12" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "InnerUseGlobal" + { + "ControlName" "CheckButton" + "fieldName" "InnerUseGlobal" + "xpos" "130" + "ypos" "5" + "wide" "133" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "0" + "tabPosition" "0" + "labelText" "#GameUI_UseGlobal" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "outerUseGlobal" + { + "ControlName" "CheckButton" + "fieldName" "OuterUseGlobal" + "xpos" "130" + "ypos" "158" + "wide" "134" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "0" + "tabPosition" "0" + "labelText" "#GameUI_UseGlobal" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "UseGlobal" + { + "ControlName" "CheckButton" + "fieldName" "UseGlobal" + "xpos" "275" + "ypos" "49" + "wide" "185" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_UseGlobalAll" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "innerDisplay" + { + "ControlName" "Label" + "fieldName" "innerDisplay" + "xpos" "280" + "ypos" "100" + "zpos" "2" + "wide" "190" + "tall" "190" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "0" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "font" "Crosshairs1" + "wrap" "0" + } + "outerDisplay" + { + "ControlName" "Label" + "fieldName" "outerDisplay" + "xpos" "280" + "ypos" "100" + "zpos" "1" + "wide" "190" + "tall" "190" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "F" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "CrosshairBackground" + { + "ControlName" "ImagePanel" + "fieldName" "CrosshairBackground" + "xpos" "280" + "ypos" "100" + "zpos" "-1" + "wide" "190" + "tall" "190" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "border" "DepressedBorder" + "scaleImage" "1" + } + "weapon" + { + "ControlName" "ComboBox" + "fieldName" "Weapon" + "xpos" "292" + "ypos" "23" + "wide" "150" + "tall" "23" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "13" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "Label1" + { + "ControlName" "Label" + "fieldName" "Label1" + "xpos" "8" + "ypos" "28" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Shape" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label2" + { + "ControlName" "Label" + "fieldName" "Label2" + "xpos" "6" + "ypos" "73" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Red" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label3" + { + "ControlName" "Label" + "fieldName" "Label3" + "xpos" "7" + "ypos" "52" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Size" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label4" + { + "ControlName" "Label" + "fieldName" "Label4" + "xpos" "7" + "ypos" "94" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Green" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label5" + { + "ControlName" "Label" + "fieldName" "Label5" + "xpos" "6" + "ypos" "115" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Blue" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label6" + { + "ControlName" "Label" + "fieldName" "Label6" + "xpos" "7" + "ypos" "136" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Alpha" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label7" + { + "ControlName" "Label" + "fieldName" "Label7" + "xpos" "10" + "ypos" "5" + "wide" "113" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_PrimaryCrosshair" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label8" + { + "ControlName" "Label" + "fieldName" "Label8" + "xpos" "10" + "ypos" "158" + "wide" "121" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_SecondaryCrosshair" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label9" + { + "ControlName" "Label" + "fieldName" "Label9" + "xpos" "8" + "ypos" "181" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Shape" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label10" + { + "ControlName" "Label" + "fieldName" "Label10" + "xpos" "8" + "ypos" "205" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Size" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label11" + { + "ControlName" "Label" + "fieldName" "Label11" + "xpos" "8" + "ypos" "226" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Red" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label12" + { + "ControlName" "Label" + "fieldName" "Label12" + "xpos" "8" + "ypos" "247" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Green" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label13" + { + "ControlName" "Label" + "fieldName" "Label13" + "xpos" "8" + "ypos" "268" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Blue" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label14" + { + "ControlName" "Label" + "fieldName" "Label14" + "xpos" "8" + "ypos" "289" + "wide" "64" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Alpha" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "BuildModeDialog" + { + "ControlName" "BuildModeDialog" + "fieldName" "BuildModeDialog" + "xpos" "0" + "ypos" "0" + "wide" "304" + "tall" "577" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Untitled" + } +} diff --git a/resource/ui/FFOptionsSubDLights.res b/resource/ui/FFOptionsSubDLights.res new file mode 100644 index 0000000..45ec9a7 --- /dev/null +++ b/resource/ui/FFOptionsSubDLights.res @@ -0,0 +1,679 @@ +"resource/ui/FFOptionsSubDLights.res" +{ + "DLightOptions" + { + "ControlName" "CFFDLightOptions" + "fieldName" "DLightOptions" + "xpos" "0" + "ypos" "28" + "wide" "496" + "tall" "314" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightMax" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightMax" + "xpos" "130" + "ypos" "20" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightMaxInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightMaxInput" + "xpos" "430" + "ypos" "20" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightExplosion" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightExplosion" + "xpos" "130" + "ypos" "60" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightExplosionInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightExplosionInput" + "xpos" "430" + "ypos" "60" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "2" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightMuzzle" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightMuzzle" + "xpos" "130" + "ypos" "82" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightMuzzleInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightMuzzleInput" + "xpos" "430" + "ypos" "82" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightFlamethrower" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightFlamethrower" + "xpos" "130" + "ypos" "104" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightFlamethrowerInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightFlamethrowerInput" + "xpos" "430" + "ypos" "104" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "4" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightIgnited" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightIgnited" + "xpos" "130" + "ypos" "126" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightIgnitedInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightIgnitedInput" + "xpos" "430" + "ypos" "126" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "5" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightNapalm" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightNapalm" + "xpos" "130" + "ypos" "148" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightNapalmInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightNapalmInput" + "xpos" "430" + "ypos" "148" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "6" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightIC" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightIC" + "xpos" "130" + "ypos" "170" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightICInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightICInput" + "xpos" "430" + "ypos" "170" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "7" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightRocket" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightRocket" + "xpos" "130" + "ypos" "192" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightRocketInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightRocketInput" + "xpos" "430" + "ypos" "192" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "8" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightRail" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightRail" + "xpos" "130" + "ypos" "214" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightRailInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightRailInput" + "xpos" "430" + "ypos" "214" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "9" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightConc" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightConc" + "xpos" "130" + "ypos" "236" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightConcInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightConcInput" + "xpos" "430" + "ypos" "236" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "10" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightFlashlight" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightFlashlight" + "xpos" "130" + "ypos" "258" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightFlashlightInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightFlashlightInput" + "xpos" "430" + "ypos" "258" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "11" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "FFDLightGeneric" + { + "ControlName" "CInputSlider" + "fieldName" "FFDLightGeneric" + "xpos" "130" + "ypos" "280" + "wide" "300" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "FFDLightGenericInput" + { + "ControlName" "TextEntry" + "fieldName" "FFDLightGenericInput" + "xpos" "430" + "ypos" "280" + "wide" "40" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "12" + "textHidden" "0" + "editable" "1" + "maxchars" "-1" + "NumericInputOnly" "1" + "unicode" "0" + } + "Label1" + { + "ControlName" "Label" + "fieldName" "Label1" + "xpos" "0" + "ypos" "0" + "wide" "496" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DLightOptions" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label2" + { + "ControlName" "Label" + "fieldName" "Label2" + "xpos" "0" + "ypos" "20" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_MaxDLights" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label3" + { + "ControlName" "Label" + "fieldName" "Label3" + "xpos" "0" + "ypos" "60" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Explosion" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label4" + { + "ControlName" "Label" + "fieldName" "Label4" + "xpos" "0" + "ypos" "82" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_MFlash" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label5" + { + "ControlName" "Label" + "fieldName" "Label5" + "xpos" "0" + "ypos" "104" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Flamer" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label6" + { + "ControlName" "Label" + "fieldName" "Label6" + "xpos" "0" + "ypos" "126" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_PlayerBurn" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label7" + { + "ControlName" "Label" + "fieldName" "Label7" + "xpos" "0" + "ypos" "148" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Napalm" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label8" + { + "ControlName" "Label" + "fieldName" "Label8" + "xpos" "0" + "ypos" "170" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_IC" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label9" + { + "ControlName" "Label" + "fieldName" "Label9" + "xpos" "0" + "ypos" "192" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Rocket" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label10" + { + "ControlName" "Label" + "fieldName" "Label10" + "xpos" "0" + "ypos" "214" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Rail" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label11" + { + "ControlName" "Label" + "fieldName" "Label11" + "xpos" "0" + "ypos" "236" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Conc" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label12" + { + "ControlName" "Label" + "fieldName" "Label12" + "xpos" "0" + "ypos" "258" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Flashlight" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label13" + { + "ControlName" "Label" + "fieldName" "Label13" + "xpos" "0" + "ypos" "280" + "wide" "120" + "tall" "20" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Generic" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "Label14" + { + "ControlName" "Label" + "fieldName" "Label14" + "xpos" "0" + "ypos" "40" + "wide" "496" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_DL_Scale" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } +} diff --git a/resource/ui/FFOptionsSubMisc.res b/resource/ui/FFOptionsSubMisc.res new file mode 100644 index 0000000..a4360aa --- /dev/null +++ b/resource/ui/FFOptionsSubMisc.res @@ -0,0 +1,17 @@ +"resource/ui/FFOptionsSubMisc.res" +{ + "MiscOptions" + { + "ControlName" "CFFMiscOptions" + "fieldName" "MiscOptions" + "xpos" "0" + "ypos" "28" + "wide" "496" + "tall" "314" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } +} diff --git a/resource/ui/FFOptionsSubTimer.res b/resource/ui/FFOptionsSubTimer.res new file mode 100644 index 0000000..6ce5233 --- /dev/null +++ b/resource/ui/FFOptionsSubTimer.res @@ -0,0 +1,151 @@ +"resource/ui/FFOptionsSubTimer.res" +{ + "TimerOptions" + { + "ControlName" "CFFTimerOptions" + "fieldName" "TimerOptions" + "xpos" "0" + "ypos" "28" + "wide" "496" + "tall" "314" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "TimerList" + { + "ControlName" "ComboBox" + "fieldName" "TimerList" + "xpos" "31" + "ypos" "30" + "wide" "145" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "PlayButton" + { + "ControlName" "Button" + "fieldName" "PlayButton" + "xpos" "183" + "ypos" "30" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Play" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Play" + "Default" "0" + } + "Label1" + { + "ControlName" "Label" + "fieldName" "Label1" + "xpos" "31" + "ypos" "66" + "wide" "188" + "tall" "112" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_TimerHelp" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "1" + } + "BeepList" + { + "ControlName" "ComboBox" + "fieldName" "BeepList" + "xpos" "280" + "ypos" "30" + "wide" "145" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + "unicode" "0" + } + "PlayButton2" + { + "ControlName" "Button" + "fieldName" "PlayButton2" + "xpos" "432" + "ypos" "30" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Play" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Play2" + "Default" "0" + } + "Label2" + { + "ControlName" "Label" + "fieldName" "Label2" + "xpos" "280" + "ypos" "66" + "wide" "188" + "tall" "112" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_KillBeepHelp" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "1" + } + "BuildModeDialog" + { + "ControlName" "BuildModeDialog" + "fieldName" "BuildModeDialog" + "xpos" "0" + "ypos" "0" + "wide" "304" + "tall" "577" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Untitled" + } +} diff --git a/resource/ui/FFSplash.res b/resource/ui/FFSplash.res new file mode 100644 index 0000000..a8972f1 --- /dev/null +++ b/resource/ui/FFSplash.res @@ -0,0 +1,275 @@ +"resource/ui/FFSplash.res" +{ + "FFSplashPanel" + { + "ControlName" "CFFSplashPanel" + "fieldName" "FFSplashPanel" + "xpos" "100" + "ypos" "100" + "wide" "440" + "tall" "320" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Splash" + } + "frame_topGrip" + { + "ControlName" "Panel" + "fieldName" "frame_topGrip" + "xpos" "8" + "ypos" "0" + "wide" "424" + "tall" "5" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_bottomGrip" + { + "ControlName" "Panel" + "fieldName" "frame_bottomGrip" + "xpos" "8" + "ypos" "315" + "wide" "414" + "tall" "5" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_leftGrip" + { + "ControlName" "Panel" + "fieldName" "frame_leftGrip" + "xpos" "0" + "ypos" "8" + "wide" "5" + "tall" "304" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_rightGrip" + { + "ControlName" "Panel" + "fieldName" "frame_rightGrip" + "xpos" "435" + "ypos" "8" + "wide" "5" + "tall" "294" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_tlGrip" + { + "ControlName" "Panel" + "fieldName" "frame_tlGrip" + "xpos" "0" + "ypos" "0" + "wide" "8" + "tall" "8" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_trGrip" + { + "ControlName" "Panel" + "fieldName" "frame_trGrip" + "xpos" "432" + "ypos" "0" + "wide" "8" + "tall" "8" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_blGrip" + { + "ControlName" "Panel" + "fieldName" "frame_blGrip" + "xpos" "0" + "ypos" "312" + "wide" "8" + "tall" "8" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_brGrip" + { + "ControlName" "Panel" + "fieldName" "frame_brGrip" + "xpos" "422" + "ypos" "302" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_caption" + { + "ControlName" "Panel" + "fieldName" "frame_caption" + "xpos" "0" + "ypos" "0" + "wide" "430" + "tall" "23" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "frame_minimize" + { + "ControlName" "Button" + "fieldName" "frame_minimize" + "xpos" "0" + "ypos" "0" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "0" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "frame_maximize" + { + "ControlName" "Button" + "fieldName" "frame_maximize" + "xpos" "0" + "ypos" "0" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "1" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "frame_mintosystray" + { + "ControlName" "Button" + "fieldName" "frame_mintosystray" + "xpos" "0" + "ypos" "0" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "labelText" "o" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "MinimizeToSysTray" + "Default" "0" + } + "frame_close" + { + "ControlName" "Button" + "fieldName" "frame_close" + "xpos" "415" + "ypos" "8" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "r" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "frame_menu" + { + "ControlName" "FrameSystemButton" + "fieldName" "frame_menu" + "xpos" "7" + "ypos" "8" + "wide" "18" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Default" "0" + } + "FFSplashPanelHTML" + { + "ControlName" "SplashHTML" + "fieldName" "FFSplashPanelHTML" + "xpos" "20" + "ypos" "30" + "wide" "390" + "tall" "270" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "BuildModeDialog" + { + "ControlName" "BuildModeDialog" + "fieldName" "BuildModeDialog" + "xpos" "500" + "ypos" "75" + "wide" "300" + "tall" "420" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#Frame_Untitled" + } +} diff --git a/resource/ui/FFTraining.res b/resource/ui/FFTraining.res new file mode 100644 index 0000000..c7f91fb --- /dev/null +++ b/resource/ui/FFTraining.res @@ -0,0 +1,119 @@ +"Resource/UI/FFTraining.res" +{ + "FFTrainingPanel" + { + "ControlName" "CFFTrainingPanel" + "fieldName" "FFTrainingPanel" + "xpos" "212" + "ypos" "106" + "wide" "512" + "tall" "406" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "#GameUI_Training" + } + "TrainingTitle" + { + "ControlName" "Label" + "fieldName" "TrainingTitle" + "xpos" "24" + "ypos" "52" + "wide" "348" + "tall" "26" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#Training_Title" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "font" "Trebuchet24" + "wrap" "0" + } + "TrainingDescription" + { + "ControlName" "Label" + "fieldName" "TrainingDescription" + "xpos" "24" + "ypos" "78" + "wide" "282" + "tall" "175" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#Training_Desc" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "1" + } + "StatusLabel" + { + "ControlName" "Label" + "fieldName" "StatusLabel" + "xpos" "40" + "ypos" "78" + "wide" "150" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + } + "OKButton" + { + "ControlName" "Button" + "fieldName" "OKButton" + "xpos" "330" + "ypos" "372" + "wide" "88" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Start" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "OK" + "Default" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "424" + "ypos" "372" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Cancel" + "Default" "0" + } +} diff --git a/resource/ui/FFUpdates.res b/resource/ui/FFUpdates.res new file mode 100644 index 0000000..ed97789 --- /dev/null +++ b/resource/ui/FFUpdates.res @@ -0,0 +1,100 @@ +"Resource/UI/FFUpdates.res" +{ + "ff_update_info" + { + "ControlName" "CFFUpdateInfo" + "fieldName" "ff_update_info" + "xpos" "212" + "ypos" "106" + "wide" "512" + "tall" "206" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "settitlebarvisible" "1" + "title" "Fortress Forever Updater" + } + "UpdateTitle" + { + "ControlName" "Label" + "fieldName" "UpdateTitle" + "xpos" "24" + "ypos" "25" + "wide" "480" + "tall" "50" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_UPDATE_TITLE_OUTOFDATE" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "font" "Trebuchet24" + "wrap" "0" + } + "UpdateDescription" + { + "ControlName" "Label" + "fieldName" "UpdateDescription" + "xpos" "24" + "ypos" "78" + "wide" "480" + "tall" "75" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_UPDATE_TEXT_OUTOFDATE" + "textAlignment" "north-west" + "dulltext" "0" + "brighttext" "0" + "wrap" "1" + } + "OKButton" + { + "ControlName" "Button" + "fieldName" "OKButton" + "xpos" "50" + "ypos" "172" + "wide" "368" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_UPDATE_DOWNLOAD" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "OK" + "Default" "0" + } + "CancelButton" + { + "ControlName" "Button" + "fieldName" "CancelButton" + "xpos" "424" + "ypos" "172" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#GameUI_Cancel" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "wrap" "0" + "Command" "Cancel" + "Default" "0" + } +} diff --git a/resource/ui/MOTD.res b/resource/ui/MOTD.res new file mode 100644 index 0000000..d3e10ed --- /dev/null +++ b/resource/ui/MOTD.res @@ -0,0 +1,70 @@ +"Resource/UI/MOTD.res" +{ + "ClientMOTD" //master frame + { + "ControlName" "Frame" + "fieldName" "ClientMOTD" + "xpos" "0" + "ypos" "0" + "wide" "640" + "tall" "480" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "setTitleBarVisible" "0" + } + "Message" + { + "ControlName" "HTML" + "fieldName" "Message" + "xpos" "76" + "ypos" "116" + "wide" "480" + "tall" "240" + "autoResize" "3" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "ok" + { + "ControlName" "Button" + "fieldName" "ok" + "xpos" "76" + "ypos" "364" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#Cstrike_OK" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "Command" "okay" + "Default" "1" + } + "serverName" + { + "ControlName" "Label" + "fieldName" "serverName" + "xpos" "84" + "ypos" "72" + "wide" "400" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "Server Name Goes Here +++ :p" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + } +} diff --git a/resource/ui/MapGuideMenu.res b/resource/ui/MapGuideMenu.res new file mode 100644 index 0000000..84084b7 --- /dev/null +++ b/resource/ui/MapGuideMenu.res @@ -0,0 +1,202 @@ +"Resource/UI/MapGuideMenu.res" +{ + "mapguides" + { + "ControlName" "CMapGuideMenu" + "fieldName" "mapguidemenu" + "xpos" "0" + "ypos" "0" + "wide" "640" + "tall" "480" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "SysMenu" + { + "ControlName" "Menu" + "fieldName" "SysMenu" + "xpos" "0" + "ypos" "0" + "wide" "64" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "0" + "tabPosition" "0" + } + "MapGuideImage" + { + "ControlName" "ImagePanel" + "fieldName" "MapGuideImage" + "xpos" "244" + "ypos" "116" + "wide" "316" + "tall" "286" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "scaleImage" "1" + } + "choosemapguide" + { + "ControlName" "Label" + "fieldName" "choosemapguide" + "xpos" "76" + "ypos" "22" + "wide" "450" + "tall" "48" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "labelText" "#FF_MAPGUIDE_CHOOSE" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "font" "MenuTitle" + } + "overview" + { + "ControlName" "MouseOverPanelButton" + "fieldName" "overview" + "xpos" "76" + "ypos" "116" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "labelText" "#FF_MAPGUIDE_OVERVIEW" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "mapguide overview" + } + + "interest" + { + "ControlName" "MouseOverPanelButton" + "fieldName" "interest" + "xpos" "76" + "ypos" "148" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "5" + "labelText" "#FF_MAPGUIDE_INTEREST" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "mapguide interest" + } + + "extraguide1" + { + "ControlName" "MouseOverPanelButton" + "fieldName" "extraguide1" + "xpos" "76" + "ypos" "180" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "2" + "labelText" "" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "mapguide extraguide1" + } + + "extraguide2" + { + "ControlName" "MouseOverPanelButton" + "fieldName" "extraguide2" + "xpos" "76" + "ypos" "212" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "mapguide extraguide2" + } + + "extraguide3" + { + "ControlName" "MouseOverPanelButton" + "fieldName" "extraguide3" + "xpos" "76" + "ypos" "244" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "mapguide extraguide3" + } + + "extraguide4" + { + "ControlName" "Button" + "fieldName" "extraguide4" + "xpos" "76" + "ypos" "276" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "mapguide extraguide4" + } + "cancelbutton" + { + "ControlName" "Button" + "fieldName" "cancelbutton" + "xpos" "76" + "ypos" "308" + "wide" "148" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_MENU_CANCEL" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "Command" "cancel" + } +} \ No newline at end of file diff --git a/resource/ui/MapScreenshotMenu.res b/resource/ui/MapScreenshotMenu.res new file mode 100644 index 0000000..3f4c081 --- /dev/null +++ b/resource/ui/MapScreenshotMenu.res @@ -0,0 +1,56 @@ +"Resource/UI/MapScreenshotMenu.res" +{ + "map" + { + "ControlName" "CMapScreen" + "fieldName" "mapscreen" + "xpos" "c-320" + "ypos" "0" + "wide" "640" + "tall" "480" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + + + "ImagePanel" + { + "ControlName" "ImagePanel" + "fieldName" "ImagePanelLogo" + "xpos" "20" + "ypos" "26" + "wide" "600" + "tall" "426" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "image" "loading_screen_map" + "scaleImage" "1" + } + + "CloseButton" + { + "ControlName" "FFButton" + "fieldName" "CloseButton" + "xpos" "76" + "ypos" "454" + "wide" "68" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "labelText" "#FF_CLOSE" + "font" "ClassMenu" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "Command" "close" + } +} \ No newline at end of file diff --git a/resource/ui/ScoreBoard.res b/resource/ui/ScoreBoard.res new file mode 100644 index 0000000..11339c8 --- /dev/null +++ b/resource/ui/ScoreBoard.res @@ -0,0 +1,84 @@ +"Resource/UI/ScoreBoard.res" +{ + "ScoreboardFrame" + { + "ControlName" "Section" + "fieldName" "ScoreboardFrame" + "xpos" "0" + "ypos" "0" + "wide" "444" + "tall" "360" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "titleText" "#TITLE_SCOREBOARD" + } + "scores" + { + "ControlName" "CClientScoreBoardDialog" + "fieldName" "scores" + "xpos" "63" + "ypos" "42" + "wide" "444" + "tall" "360" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + } + "ServerName" + { + "ControlName" "Label" + "fieldName" "ServerName" + "xpos" "10" + "ypos" "11" + "wide" "250" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "labelText" "" + "font" "Scoreboard_Header" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "1" + } + "MapName" + { + "ControlName" "Label" + "fieldName" "MapName" + "xpos" "334" + "ypos" "11" + "wide" "100" + "tall" "24" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "labelText" "" + "font" "Scoreboard_Header" + "textAlignment" "east" + "dulltext" "0" + "brighttext" "1" + } + "PlayerList" + { + "ControlName" "SectionedListPanel" + "fieldName" "PlayerList" + "xpos" "0" + "ypos" "0" + "wide" "444" + "tall" "320" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "autoresize" "3" + "linespacing" "13" + } +} diff --git a/resource/ui/Spectator.res b/resource/ui/Spectator.res new file mode 100644 index 0000000..9a760c4 --- /dev/null +++ b/resource/ui/Spectator.res @@ -0,0 +1,91 @@ +"Resource/UI/SpectatorGUI.res" +{ + "SpectatorGUI" + { + "ControlName" "Frame" + "fieldName" "SpectatorGUI" + "tall" "480" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "topbar" + { + "ControlName" "Panel" + "fieldName" "topbar" + "xpos" "10" + "ypos" "10" + "tall" "19" + "wide" "125" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "bottombarblank" + { + "ControlName" "Panel" + "fieldName" "bottombarblank" + "xpos" "0" + "ypos" "428" + "tall" "55" // this needs to match the size of BottomBar + "wide" "640" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "playerlabel" + { + "ControlName" "Label" + "fieldName" "playerlabel" + "xpos" "c-108" + "ypos" "441" + "wide" "216" + "tall" "26" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + "textAlignment" "center" + } + "DividerBar" + { + "ControlName" "ImagePanel" + "fieldName" "DividerBar" + "xpos" "r94" + "ypos" "12" + "wide" "1" + "tall" "30" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "fillcolor" "BorderBright" + "labelText" "" + "textAlignment" "center" + } + "extrainfo" + { + "ControlName" "Label" + "fieldName" "extrainfo" + "xpos" "18" + "ypos" "12" + "wide" "150" + "tall" "15" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "labelText" "" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + } +} diff --git a/resource/ui/TeamMenu.res b/resource/ui/TeamMenu.res new file mode 100644 index 0000000..7b41d1a --- /dev/null +++ b/resource/ui/TeamMenu.res @@ -0,0 +1,360 @@ +"Resource/UI/TeamMenu.res" +{ + "ServerInfo" + { + "ControlName" "Section" + "fieldName" "ServerInfo" + "xpos" "20" //12 + "ypos" "12" + "wide" "600" //616 + "tall" "80"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles_small" + "titleText" "#TITLE_SERVERINFO" + } + "ServerInfoButton" + { + "ControlName" "FFButton" + "fieldName" "ServerInfoButton" + "xpos" "34" + "ypos" "34" + "wide" "188" + "tall" "48" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "font" "TeamMenuTitles" + "labelText" "VIEW SERVER INFORMATION" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "command" "serverinfo" + "default" "1" + } + "ServerInfoHost" + { + "ControlName" "HTML" + "fieldName" "ServerInfoHost" + "xpos" "242" //20 + "ypos" "34" + "wide" "360" //600 + "tall" "48" //51 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "wrap" "1" + //"border" "" + "tabPosition" "0" + } + "TeamSelection" + { + "ControlName" "Section" + "fieldName" "TeamSelection" + "xpos" "20" //12 + "ypos" "100" + "wide" "600" //616 + "tall" "167" + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles_large" + "titleText" "#TITLE_TEAMSELECTION" + } +// "MapScreenshot" +// { +// "ControlName" "Section" +// "fieldName" "MapScreenshot" +// "xpos" "12" //12 +// "ypos" "276" +// "wide" "190" //187 +// "tall" "187" +// "autoResize" "0" //0 +// "pinCorner" "0" +// "visible" "1" +// "enabled" "1" +// "tabPosition" "0" +// "font" "TeamMenuTitles_small" +// "titleText" "#TITLE_MAPSCREENSHOT" +// } + + "MapScreenshotButton" + { + "ControlName" "Section" //"Button" + "fieldName" "MapScreenshotButton" + "xpos" "20" + "ypos" "276" + "wide" "182" //190 + "tall" "187" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles_large" + "labelText" "#TITLE_MAPSCREENSHOT" + "textAlignment" "center" + //"dulltext" "0" + //"brighttext" "0" + "Command" "map shot" + } + "ImagePanel" + { + "ControlName" "ImagePanel" + "fieldName" "ImagePanelLogo" + "xpos" "30" + "ypos" "290" + "wide" "160" + "tall" "160" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "image" "loading_screen_map" + "scaleImage" "1" + } + + //"MapInfo" + //{ + // "ControlName" "Section" + // "fieldName" "MapInfo" + // "xpos" "212" + // "ypos" "280" + // "wide" "175" + // "tall" "50" + // "autoResize" "1" //0 + // "pinCorner" "0" + // "visible" "1" + // "enabled" "1" + // "tabPosition" "0" + // "font" "TeamMenuTitles_small" + // "titleText" "#TITLE_MAPINFO" + //} + //"ServerVars" + //{ + // "ControlName" "Section" + // "fieldName" "ServerVars" + // "xpos" "400" + // "ypos" "280" + // "wide" "227" + // "tall" "50" + // "autoResize" "0" //0 + // "pinCorner" "0" + // "visible" "1" + // "enabled" "1" + // "tabPosition" "0" + // "font" "TeamMenuTitles_small" + // "titleText" "#TITLE_SERVERVARS" + //} + "MapDescription" //objectives + { + "ControlName" "Section" + "fieldName" "MapDescription" + "xpos" "212" //212 + "ypos" "276" //342 + "wide" "408" //416 + "tall" "187" //125 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles_small" + "titleText" "#TITLE_MAPDESCRIPTION" + } + "MapDescriptionHead" + { + "ControlName" "Label" + "fieldName" "MapDescriptionHead" + "xpos" "220" //220 + "ypos" "294" //360 + "wide" "400" //399 + "tall" "16" + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "wrap" "1" + "tabPosition" "0" + } + "MapDescriptionText" + { + "ControlName" "RichText" + "fieldName" "MapDescriptionText" + "xpos" "220" //220 + "ypos" "310" //376 + "wide" "392" //400 + "tall" "143" //81 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "wrap" "0" + "border" "0" + "tabPosition" "0" + } + "team" + { + "ControlName" "CTeamMenu" + "fieldName" "teammenu" + "xpos" "c-320" //0 + "ypos" "0" + "wide" "640" //640 + "tall" "480" + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + "BlueTeamButton" + { + "ControlName" "TeamButton" + "fieldName" "BlueTeamButton" + "xpos" "76" //76 + "ypos" "114" //112 + "wide" "110" + "tall" "110" + "autoResize" "0" //0 + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "font" "TeamMenuTitles" + "labelText" "#FF_MENU_BLUE" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "team blue" + } + "RedTeamButton" + { + "ControlName" "TeamButton" + "fieldName" "RedTeamButton" + "xpos" "76" //76 + "ypos" "114" + "wide" "110" + "tall" "110" + "autoResize" "0" //0 + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "4" + "font" "TeamMenuTitles" + "labelText" "#FF_MENU_RED" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "team red" + } + "YellowTeamButton" + { + "ControlName" "TeamButton" + "fieldName" "YellowTeamButton" + "xpos" "76" + "ypos" "114" + "wide" "110" + "tall" "110" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "5" + "font" "TeamMenuTitles" + "labelText" "#FF_MENU_YELLOW" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "team yellow" + } + "GreenTeamButton" + { + "ControlName" "TeamButton" + "fieldName" "GreenTeamButton" + "xpos" "76" + "ypos" "114" + "wide" "110" + "tall" "110" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "font" "TeamMenuTitles" + "labelText" "#FF_MENU_GREEN" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "command" "team green" + } + "AutoAssignButton" + { + "ControlName" "FFButton" + "fieldName" "AutoAssignButton" + "xpos" "76" + "ypos" "234" + "wide" "96" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "3" + "font" "TeamMenuTitles" + "labelText" "#FF_MENU_AUTOTEAM" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "command" "team auto" + "default" "1" + } + "SpectateButton" + { + "ControlName" "FFButton" + "fieldName" "SpectateButton" + "xpos" "76" + "ypos" "234" + "wide" "96" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles" + "labelText" "#FF_MENU_SPECTATOR" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "Command" "team spec" + } + "FlythroughButton" + { + "ControlName" "FFButton" + "fieldName" "FlythroughButton" + "xpos" "76" + "ypos" "234" + "wide" "96" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "tabPosition" "6" + "font" "TeamMenuTitles" + "labelText" "#FF_MENU_MAPGUIDE" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "Command" "mapguidemenu" + } +} diff --git a/resource/ui/TextWindow.res b/resource/ui/TextWindow.res new file mode 100644 index 0000000..cc803f4 --- /dev/null +++ b/resource/ui/TextWindow.res @@ -0,0 +1,106 @@ +"Resource/UI/TextWindow.res" +{ + "info" + { + "ControlName" "CTextWindow" + "fieldName" "TextWindow" + "xpos" "c-320" //0 + "ypos" "0" + "wide" "640" + "tall" "480" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "tabPosition" "0" + } + + "MOTD" + { + "ControlName" "Section" + "fieldName" "MOTD" + "xpos" "20" //12 + "ypos" "12" + "wide" "600" //616 + "tall" "463"//75 + "autoResize" "0" //0 + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + "font" "TeamMenuTitles_small" + "titleText" "" + } + + "HTMLMessage" + { + "ControlName" "HTML" + "fieldName" "HTMLMessage" + "xpos" "36" + "ypos" "56" + "wide" "568" + "tall" "376" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + } + + "TextMessage" + { + "ControlName" "TextEntry" + "fieldName" "TextMessage" + "xpos" "36" + "ypos" "56" + "wide" "568" + "tall" "376" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "textAlignment" "northwest" + "textHidden" "0" + "editable" "0" + "maxchars" "-1" + "NumericInputOnly" "0" + } + + "MessageTitle" + { + "ControlName" "Label" + "fieldName" "MessageTitle" + "xpos" "46" + "ypos" "14" + "wide" "450" + "tall" "48" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "labelText" "Message Title" + "textAlignment" "west" + "dulltext" "0" + "brighttext" "0" + "font" "MenuTitle" + } + + "ok" + { + "ControlName" "FFButton" + "fieldName" "ok" + "xpos" "40" + "ypos" "444" + "wide" "128" + "tall" "20" + "autoResize" "0" + "pinCorner" "2" + "visible" "1" + "enabled" "1" + "labelText" "#PropertyDialog_OK" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "command" "okay" + "default" "1" + } +} diff --git a/scripts/HudAnimations.txt b/scripts/HudAnimations.txt new file mode 100644 index 0000000..336637f --- /dev/null +++ b/scripts/HudAnimations.txt @@ -0,0 +1,1082 @@ +// sample animation script +// +// +// commands: +// Animate +// variables: +// FgColor +// BgColor +// Position +// Size +// Blur (hud panels only) +// TextColor (hud panels only) +// Ammo2Color (hud panels only) +// Alpha (hud weapon selection only) +// SelectionAlpha (hud weapon selection only) +// TextScan (hud weapon selection only) +// +// interpolator: +// Linear +// Accel - starts moving slow, ends fast +// Deaccel - starts moving fast, ends slow +// +// RunEvent +// starts another even running at the specified time +// +// StopEvent +// stops another event that is current running at the specified time +// +// StopAnimation +// stops all animations refering to the specified variable in the specified panel +// +// StopPanelAnimations +// stops all active animations operating on the specified panel +// +// SetFont +// change to a diff font- use cl_Animation info to get Font parameter (left column) +// +// +// Useful game console commands: +// cl_Animationinfo or +// displays all the animatable variables for the hud element +// + +////////////////////// HUD MENU ///////////////////////////// + +event MenuOpen +{ + StopEvent MenuClose 0.0 + + // fade in + Animate HudMenu Alpha "255" Linear 0.0 0.1 + Animate HudMenu SelectionAlpha "255" Linear 0.0 0.1 + Animate HudMenu MenuColor "255 255 255 255" Linear 0.0 0.1 + Animate HudMenu ItemColor "200 200 200 255" Linear 0.0 0.1 + Animate HudMenu MenuBoxColor "0 0 0 25" Linear 0.0 0.1 + Animate HudMenu TextScan "1" Linear 0.0 0.1 + + // Undo any blur + Animate HudMenu Blur "1" Linear 0.0 0.01 + + // Fonts + SetFont HudMenu "TextFont" "Default" 0.0 + SetFont HudMenu "ItemFont" "Default" 0.0 + SetFont HudMenu "ItemFontPulsing" "Default" 0.0 +} + +event MenuClose +{ + // Hide it + Animate HudMenu Alpha "0" Linear 0.0 1 + Animate HudMenu SelectionAlpha "0" Linear 0.0 1 + Animate HudMenu MenuColor "0 0 0 0" Linear 0.0 1 + Animate HudMenu ItemColor "0 0 0 0" Linear 0.0 1 +} + +event MenuPulse +{ + Animate HudMenu Blur "7" Linear 0.0 0.1 + Animate HudMenu Blur "2" Deaccel 0.1 0.1 + Animate HudMenu Blur "7" Linear 0.2 0.1 + Animate HudMenu Blur "2" Deaccel 0.3 0.1 + Animate HudMenu Blur "7" Linear 0.4 0.1 + Animate HudMenu Blur "2" Deaccel 0.5 0.1 + Animate HudMenu Blur "1" Deaccel 0.6 0.4 +} + +////////////////////// FORTRESS POINTS ///////////////////////////// + +event NewTotalFortPoints +{ + + Animate HudPlayerTotalScore FgColor "HealthIncAbove100Color" Linear 0.0 0.25 + Animate HudPlayerTotalScore FgColor "FgColor" Linear 0.25 0.3 + Animate HudPlayerTotalScore Blur "3" Linear 0.0 0.1 + Animate HudPlayerTotalScore Blur "0" Deaccel 0.1 2.0 +} + +event NewLatestFortPoints +{ + + Animate HudPlayerLatestScore FgColor "HealthIncAbove100Color" Linear 0.0 0.25 +// Animate HudPlayerLatestScore FgColor "FgColor" Linear 0.75 0.3 + +// change the number after Linear here for however long you want the latest score to stay on screen before fading + Animate HudPlayerLatestScore FgColor "0 0 0 0" Linear 4.0 0.5 + Animate HudPlayerLatestScore Blur "3" Linear 0.0 0.1 + Animate HudPlayerLatestScore Blur "0" Deaccel 0.1 2.0 +} + +////////////////////// ARMOR ///////////////////////////// + +// "0 210 0 255" - semidark green +event ArmorIncrease +{ + StopEvent ArmorBelow25 0.0 + Animate HudArmor FgColor "FgColor" Linear 0.0 0.0 + Animate HudArmor FgColor "200 255 200 255" Deaccel 0.0 0.3 + Animate HudArmor FgColor "FgColor" Accel 0.3 0.3 + +} + +event ArmorDamageTaken +{ + Animate HudArmor FgColor "255 255 255 255" Linear 0.0 0.0 + Animate HudArmor FgColor "255 255 255 255" Linear 0.0 0.05 + Animate HudArmor FgColor "FgColor" Deaccel 0.05 0.05 +} + +event ArmorBelow25 +{ + Animate HudArmor FgColor "ArmorLowColor" Linear 0.0 0.0 + Animate HudArmor FgColor "ArmorLowColor" Linear 0.0 0.27 + Animate HudArmor FgColor "255 255 255 255" Linear 0.27 0.03 + Animate HudArmor FgColor "ArmorLowColor" Linear 0.3 0.01 + + RunEvent ArmorBelow25 0.31 +} + +event ArmorIncreaseBelow25 +{ + StopEvent ArmorBelow25 0.0 + RunEvent ArmorIncrease 0.0 + RunEvent ArmorBelow25 0.8 +} + +////////////////////// ADDARMOR ///////////////////////////// + +// "0 210 0 255" - semidark green +event NewAddArmor +{ + Animate HudPlayerAddArmor FgColor "FgColor" Linear 0.0 0.0 + Animate HudPlayerAddArmor FgColor "255 128 50 255" Deaccel 0.0 0.3 + + Animate HudPlayerAddArmor Position "87 406" Linear 0.0 0.0 + Animate HudPlayerAddArmor Position "87 376" Linear 0.0 4.5 + +// change the number after Linear here for however long you want the +/- armor to stay on screen before fading + Animate HudPlayerAddArmor FgColor "0 0 0 0" Linear 2.0 0.5 + Animate HudPlayerAddArmor Blur "3" Linear 0.0 0.1 + Animate HudPlayerAddArmor Blur "0" Deaccel 0.1 2.0 + +} + +event NewSubtractArmor +{ + Animate HudPlayerAddArmor FgColor "FgColor" Linear 0.0 0.0 + Animate HudPlayerAddArmor FgColor "ArmorLowColor" Deaccel 0.0 0.3 + + Animate HudPlayerAddArmor Position "87 406" Linear 0.0 0.0 + Animate HudPlayerAddArmor Position "87 376" Linear 0.0 4.5 + +// change the number after Linear here for however long you want the +/- armor to stay on screen before fading + Animate HudPlayerAddArmor FgColor "0 0 0 0" Linear 2.0 0.5 + Animate HudPlayerAddArmor Blur "3" Linear 0.0 0.1 + Animate HudPlayerAddArmor Blur "0" Deaccel 0.1 2.0 +} + +////////////////////// HEALTH ///////////////////////////// + +event HealthIncrease +{ + StopEvent HealthBelow25 0.0 + Animate HudHealth FgColor "FgColor" Linear 0.0 0.0 + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 +} + +event HealthIncreaseAbove100 +{ + StopEvent HealthBelow25 0.0 + Animate HudHealth FgColor "HealthIncAbove100Color" Linear 0.0 0.25 + Animate HudHealth FgColor "FgColor" Linear 0.25 0.3 + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 +} + +// Pertains to FortressForever HudHealth +event HealthDamageTaken +{ + Animate HudHealth FgColor "255 255 255 255" Linear 0.0 0.0 + Animate HudHealth FgColor "255 255 255 255" Linear 0.0 0.05 + Animate HudHealth FgColor "FgColor" Deaccel 0.05 0.05 +} + +// Pertains to FortressForever HudHealth +event HealthBelow25 +{ + Animate HudHealth FgColor "HealthLowColor" Linear 0.0 0.0 + Animate HudHealth FgColor "HealthLowColor" Linear 0.0 0.27 + Animate HudHealth FgColor "255 255 255 255" Accel 0.27 0.03 + Animate HudHealth FgColor "HealthLowColor" Deaccel 0.3 0.27 + Animate HudHealth FgColor "255 255 255 255" Accel 0.57 0.03 + Animate HudHealth FgColor "HealthLowColor" Deaccel 0.6 0.1 + + RunEvent HealthBelow25 0.7 +} + +// Pertains to FortressForever HudHealth +event HealthIncreaseBelow25 +{ + StopEvent HealthBelow25 0.0 + + RunEvent HealthIncrease 0.0 + RunEvent HealthBelow25 0.8 +} + +////////////////////// ADDHEALTH ///////////////////////////// + +// "0 210 0 255" - semidark green +event NewAddHealth +{ + Animate HudPlayerAddHealth FgColor "FgColor" Linear 0.0 0.0 + Animate HudPlayerAddHealth FgColor "0 210 0 255" Deaccel 0.0 0.3 + + Animate HudPlayerAddHealth Position "3 406" Linear 0.0 0.0 + Animate HudPlayerAddHealth Position "3 376" Linear 0.0 4.5 + +// change the number after Linear here for however long you want the +/- armor to stay on screen before fading + Animate HudPlayerAddHealth FgColor "0 0 0 0" Linear 2.0 0.5 + Animate HudPlayerAddHealth Blur "3" Linear 0.0 0.1 + Animate HudPlayerAddHealth Blur "0" Deaccel 0.1 2.0 + +} + +event NewSubtractHealth +{ + Animate HudPlayerAddHealth FgColor "FgColor" Linear 0.0 0.0 + Animate HudPlayerAddHealth FgColor "HealthLowColor" Deaccel 0.0 0.3 + + Animate HudPlayerAddHealth Position "3 406" Linear 0.0 0.0 + Animate HudPlayerAddHealth Position "3 376" Linear 0.0 4.5 + +// change the number after Linear here for however long you want the +/- armor to stay on screen before fading + Animate HudPlayerAddHealth FgColor "0 0 0 0" Linear 2.0 0.5 + Animate HudPlayerAddHealth Blur "3" Linear 0.0 0.1 + Animate HudPlayerAddHealth Blur "0" Deaccel 0.1 2.0 +} + +////////////////////// OTHER ///////////////////////////// + +event LevelInit +{ +} + +event OpenWeaponSelectionMenu +{ + StopEvent CloseWeaponSelectionMenu 0.0 + StopEvent WeaponPickup 0.0 + StopEvent FadeOutWeaponSelectionMenu 0.0 + + // make the display visible + Animate HudWeaponSelection Alpha "128" Linear 0.0 0.1 + Animate HudWeaponSelection SelectionAlpha "255" Linear 0.0 0.1 + Animate HudWeaponSelection FgColor "FgColor" Linear 0.0 0.1 + Animate HudWeaponSelection TextColor "BrightFg" Linear 0.0 0.1 + Animate HudWeaponSelection TextScan "1" Linear 0.0 0.1 +} + +event CloseWeaponSelectionMenu +{ + // hide the whole thing near immediately + Animate HudWeaponSelection FgColor "0 0 0 0" Linear 0.0 0.1 + Animate HudWeaponSelection TextColor "0 0 0 0" Linear 0.0 0.1 + Animate HudWeaponSelection Alpha "0" Linear 0.0 0.1 + Animate HudWeaponSelection SelectionAlpha "0" Linear 0.0 0.1 +} + +event FadeOutWeaponSelectionMenu +{ + // slowly hide the whole thing + Animate HudWeaponSelection FgColor "0 0 0 0" Linear 0.0 1.5 + Animate HudWeaponSelection TextColor "0 0 0 0" Linear 0.0 1.5 + Animate HudWeaponSelection Alpha "0" Linear 0.0 1.5 + Animate HudWeaponSelection SelectionAlpha "0" Linear 0.0 1.5 +} + +// Jiggles: Hint Box Fade in/out + +event OpenHintCenter +{ + StopEvent CloseHintCenter 0.0 + StopEvent FadeOutHintCenter 0.0 + StopEvent OpenHintCenterIcon 0.0 + + // make the display visible + //Animate HudHintCenter Alpha "180" Linear 0.0 0.1 + Animate HudHintCenter SelectionAlpha "255" Linear 0.0 0.1 + Animate HudHintCenter BGBoxColor "Dark" Linear 0.0 0.1 + Animate HudHintCenter TextColor "BrightFg" Linear 0.0 0.1 + Animate HudHintCenter TextScan "1" Linear 0.0 0.1 + Animate HudHintText Alpha "255" Linear 0.0 0.1 + Animate NextButton Alpha "255" Linear 0.0 0.1 + Animate PrevButton Alpha "255" Linear 0.0 0.1 +} + +event OpenHintCenterIcon +{ + StopEvent CloseHintCenter 0.0 + StopEvent FadeOutHintCenter 0.0 + StopEvent OpenHintCenter 0.0 + + // make the display visible + //Animate HudHintCenter Alpha "180" Linear 0.0 0.1 + Animate HudHintCenter SelectionAlpha "0" Linear 0.0 0.1 + Animate HudHintCenter BGBoxColor "Dark" Linear 0.0 0.1 + Animate HudHintCenter TextColor "BrightFg" Linear 0.0 0.1 + Animate HudHintCenter TextScan "1" Linear 0.0 0.1 + Animate HudHintText Alpha "0" Linear 0.0 0.1 + Animate NextButton Alpha "0" Linear 0.0 0.1 + Animate PrevButton Alpha "0" Linear 0.0 0.1 +} + +event CloseHintCenter +{ + // hide the whole thing near immediately + Animate HudHintCenter BGBoxColor "0 0 0 0" Linear 0.0 0.1 + Animate HudHintCenter TextColor "0 0 0 0" Linear 0.0 0.1 + //Animate HudHintCenter Alpha "0" Linear 0.0 0.1 + Animate HudHintCenter SelectionAlpha "0" Linear 0.0 0.1 + Animate HudHintText Alpha "0" Linear 0.0 0.1 + Animate NextButton Alpha "0" Linear 0.0 0.1 + Animate PrevButton Alpha "0" Linear 0.0 0.1 +} + +event FadeOutHintCenter +{ + // slowly hide the whole thing + Animate HudHintCenter BGBoxColor "0 0 0 0" Linear 0.0 1.5 + Animate HudHintCenter TextColor "0 0 0 0" Linear 0.0 1.5 + //Animate HudHintCenter Alpha "0" Linear 0.0 1.5 + Animate HudHintCenter SelectionAlpha "0" Linear 0.0 1.5 + Animate HudHintText Alpha "0" Linear 0.0 1.5 + Animate NextButton Alpha "0" Linear 0.0 1.5 + Animate PrevButton Alpha "0" Linear 0.0 1.5 +} + +// End + + +event SuitAuxPowerMax +{ + // hide the suit power + Animate HudSuitPower BgColor "0 0 0 0" Linear 0.0 0.4 + Animate HudSuitPower AuxPowerColor "0 0 0 0" Linear 0.0 0.4 +} + +event SuitAuxPowerNotMax +{ + // show suit power + Animate HudSuitPower BgColor "BgColor" Linear 0.0 0.4 + Animate HudSuitPower AuxPowerColor "255 220 0 220" Linear 0.0 0.4 +} + +event SuitAuxPowerDecreasedBelow25 +{ + // make color red + Animate HudSuitPower AuxPowerColor "255 0 0 220" Linear 0.0 0.4 +} + +event SuitAuxPowerIncreasedAbove25 +{ + // make colr bright + Animate HudSuitPower AuxPowerColor "255 220 0 220" Linear 0.0 0.4 +} + +event SuitAuxPowerNoItemsActive +{ + // resize the aux power to be the smallest size + Animate HudSuitPower Size "102 26" Linear 0.0 0.4 + Animate HudSuitPower Position "16 400" Linear 0.0 0.4 +// Animate HudSuitPower text_xpos "8" Linear 0.0 0.4 +// Animate HudSuitPower text_ypos "15" Linear 0.0 0.4 +} + +event SuitAuxPowerOneItemActive +{ + // resize the aux power to fit one item + Animate HudSuitPower Size "102 36" Linear 0.0 0.4 + Animate HudSuitPower Position "16 390" Linear 0.0 0.4 +} + +event SuitAuxPowerTwoItemsActive +{ + // resize the aux power to fit two items + Animate HudSuitPower Size "102 46" Linear 0.0 0.4 + Animate HudSuitPower Position "16 380" Linear 0.0 0.4 +} + +event SuitAuxPowerThreeItemsActive +{ + // resize the aux power to fit three items + Animate HudSuitPower Size "102 56" Linear 0.0 0.4 + Animate HudSuitPower Position "16 370" Linear 0.0 0.4 +} + +event SuitFlashlightOn +{ + Animate HudFlashlight TextColor "255 220 0 255" Linear 0.0 0.1 + Animate HudFlashlight TextColor "255 220 0 160" Deaccel 0.1 0.75 + Animate HudFlashlight BgColor "BgColor" Linear 0.0 0.75 +} + +event SuitFlashlightOff +{ + StopEvent SuitFlashlightOn 0.0 + Animate HudFlashlight TextColor "0 0 0 0" Linear 0.0 0.4 + Animate HudFlashlight BgColor "0 0 0 0" Linear 0.0 0.4 +} + +event HudTakeDamageAll +{ + RunEvent HudTakeDamageFront 0.0 + RunEvent HudTakeDamageLeft 0.0 + RunEvent HudTakeDamageRight 0.0 + RunEvent HudTakeDamageBehind 0.0 +} + +event HudTakeDamageFront +{ + Animate HudDamageIndicator DmgColorFront "255 88 0 150" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorFront "255 0 0 150" Linear 0.0 0.2 + Animate HudDamageIndicator DmgColorFront "255 0 0 0" Deaccel 0.2 0.3 +} + +event HudTakeDamageLeft +{ + Animate HudDamageIndicator DmgColorLeft "255 88 0 150" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorLeft "255 0 0 150" Linear 0.0 0.2 + Animate HudDamageIndicator DmgColorLeft "255 0 0 0" Deaccel 0.2 0.3 +} + +event HudTakeDamageRight +{ + Animate HudDamageIndicator DmgColorRight "255 88 0 150" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorRight "255 0 0 150" Linear 0.0 0.2 + Animate HudDamageIndicator DmgColorRight "255 0 0 0" Deaccel 0.2 0.3 +} + +event HudTakeDamageBehind +{ +// RunEvent HudTakeDamageLeft 0.0 +// RunEvent HudTakeDamageRight 0.0 + Animate HudDamageIndicator DmgColorBehind "255 88 0 150" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorBehind "255 0 0 150" Linear 0.0 0.2 + Animate HudDamageIndicator DmgColorBehind "255 0 0 0" Deaccel 0.2 0.3 +} + +event HudTakeDamageMidLeft +{ + Animate HudDamageIndicator DmgColorLeft "255 88 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorLeft "255 0 0 200" Linear 0.0 0.3 + Animate HudDamageIndicator DmgColorLeft "255 0 0 0" Deaccel 0.3 0.5 +} + +event HudTakeDamageMidRight +{ + Animate HudDamageIndicator DmgColorRight "255 88 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorRight "255 0 0 200" Linear 0.0 0.3 + Animate HudDamageIndicator DmgColorRight "255 0 0 0" Deaccel 0.3 0.5 +} + +event HudTakeDamageMidBehind +{ + Animate HudDamageIndicator DmgColorBehind "255 88 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorBehind "255 0 0 200" Linear 0.0 0.3 + Animate HudDamageIndicator DmgColorBehind "255 0 0 0" Deaccel 0.3 0.5 +} + +event HudTakeDamageMidFront +{ + Animate HudDamageIndicator DmgColorFront "255 88 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorFront "255 0 0 200" Linear 0.0 0.3 + Animate HudDamageIndicator DmgColorFront "255 0 0 0" Deaccel 0.3 0.5 +} + +event HudTakeDamageHighLeft +{ + Animate HudDamageIndicator DmgColorLeft "255 88 0 255" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorLeft "255 0 0 200" Linear 0.0 0.4 + Animate HudDamageIndicator DmgColorLeft "255 0 0 0" Deaccel 0.4 0.7 +} + +event HudTakeDamageHighRight +{ + Animate HudDamageIndicator DmgColorRight "255 88 0 255" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorRight "255 0 0 200" Linear 0.0 0.4 + Animate HudDamageIndicator DmgColorRight "255 0 0 0" Deaccel 0.4 0.7 +} + +event HudTakeDamageHighBehind +{ + Animate HudDamageIndicator DmgColorBehind "255 88 0 255" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorBehind "255 0 0 200" Linear 0.0 0.4 + Animate HudDamageIndicator DmgColorBehind "255 0 0 0" Deaccel 0.4 0.7 +} + +event HudTakeDamageHighFront +{ + Animate HudDamageIndicator DmgColorFront "255 88 0 255" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorFront "255 0 0 200" Linear 0.0 0.4 + Animate HudDamageIndicator DmgColorFront "255 0 0 0" Deaccel 0.4 0.7 +} + +event HudTakeDamageDrown +{ + RunEvent HudTakeDamageAll 0.0 +} + +event HudTakeDamagePoison +{ + Animate HudDamageIndicator DmgFullscreenColor "255 236 128 240" Linear 0.0 0.0 + Animate HudDamageIndicator DmgFullscreenColor "255 236 128 0" Deaccel 0.4 0.8 +} + +event HudTakeDamageBurn +{ + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 0" Deaccel 0.2 0.4 +} + +event HudTakeDamageRadiation +{ + Animate HudDamageIndicator DmgFullscreenColor "255 255 255 128" Deaccel 0.0 0.1 + Animate HudDamageIndicator DmgFullscreenColor "255 255 255 0" Deaccel 0.1 0.4 + RunEvent HudTakeDamageBehind 0.0 +} + +event HudPlayerDeath +{ + StopEvent HealthLoop 0.0 + StopEvent HealthPulse 0.0 + + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 96" Deaccel 0.1 0.2 + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 255" Deaccel 0.3 4.0 +} + +event HealthIncreasedAbove20 +{ + StopEvent HealthLoop 0.0 + StopEvent HealthPulse 0.0 + StopEvent HealthLow 0.0 + + Animate HudHealth BgColor "BgColor" Linear 0.0 0.0 + + Animate HudHealth TextColor "FgColor" Linear 0.0 0.04 + Animate HudHealth FgColor "FgColor" Linear 0.0 0.03 + + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 +} + +event HealthIncreasedBelow20 +{ + Animate HudHealth FgColor "BrightFg" Linear 0.0 0.25 + Animate HudHealth FgColor "FgColor" Linear 0.3 0.75 + + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 +} + +event SuitPowerIncreasedAbove20 +{ + StopEvent SuitLoop 0.0 + StopEvent SuitPulse 0.0 + StopEvent SuitPowerZero 0.0 + + Animate HudSuit Alpha "255" Linear 0.0 0.0 + + Animate HudSuit BgColor "BgColor" Linear 0.0 0.0 + + Animate HudSuit TextColor "FgColor" Linear 0.0 0.05 + Animate HudSuit FgColor "FgColor" Linear 0.0 0.05 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 +} + + +event SuitPowerIncreasedBelow20 +{ + StopEvent SuitPowerZero 0.0 + Animate HudSuit Alpha "255" Linear 0.0 0.0 + + Animate HudSuit FgColor "BrightFg" Linear 0.0 0.25 + Animate HudSuit FgColor "FgColor" Linear 0.3 0.75 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 +} + +event SuitPowerZero +{ + StopEvent SuitLoop 0.0 + StopEvent SuitPulse 0.0 + StopEvent SuitArmorLow 0.0 + StopEvent SuitDamageTaken 0.0 + + Animate HudSuit Alpha "0" Linear 0.0 0.4 +} + +event TestMovement +{ + Animate HudHealth Position "256 120" Linear 0.0 2.0 + Animate HudHealth Size "128 24" Linear 0.0 1.5 +} + +event HealthDamageTaken +{ + Animate HudHealth FgColor "BrightFg" Linear 0.0 0.25 + Animate HudHealth FgColor "FgColor" Linear 0.3 0.75 + + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 + + Animate HudHealth TextColor "BrightFg" Linear 0.0 0.1 + Animate HudHealth TextColor "FgColor" Deaccel 0.1 1.2 +} + +event SuitDamageTaken +{ + Animate HudSuit FgColor "BrightFg" Linear 0.0 0.25 + Animate HudSuit FgColor "FgColor" Linear 0.3 0.75 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 + + Animate HudSuit TextColor "BrightFg" Linear 0.0 0.1 + Animate HudSuit TextColor "FgColor" Deaccel 0.1 1.2 +} + +// health has been damaged to below 20% +event HealthLow +{ + StopEvent HealthDamageTaken 0.0 + StopEvent HealthPulse 0.0 + StopEvent HealthLoop 0.0 + + //Animate HudHealth BgColor "DamagedBg" Linear 0.0 0.1 + //Animate HudHealth BgColor "BgColor" Deaccel 0.1 1.75 + + Animate HudHealth FgColor "BrightFg" Linear 0.0 0.2 + Animate HudHealth FgColor "DamagedFg" Linear 0.2 1.2 + + Animate HudHealth TextColor "BrightFg" Linear 0.0 0.1 + Animate HudHealth TextColor "DamagedFg" Linear 0.1 1.2 + + Animate HudHealth Blur "5" Linear 0.0 0.1 + Animate HudHealth Blur "3" Deaccel 0.1 0.9 + + RunEvent HealthPulse 1.0 +} + +event HealthPulse +{ + Animate HudHealth Blur "5" Linear 0.0 0.1 + Animate HudHealth Blur "2" Deaccel 0.1 0.8 + Animate HudHealth TextColor "BrightDamagedFg" Linear 0.0 0.1 + Animate HudHealth TextColor "DamagedFg" Deaccel 0.1 0.8 + //Animate HudHealth BgColor "100 0 0 80" Linear 0.0 0.1 + //Animate HudHealth BgColor "BgColor" Deaccel 0.1 0.8 + + RunEvent HealthLoop 0.8 +} + +// call to loop HealthPulse +event HealthLoop +{ + RunEvent HealthPulse 0.0 +} + + +// suit armor has been damaged to below 20% +event SuitArmorLow +{ + StopEvent SuitDamageTaken 0.0 + StopEvent SuitPulse 0.0 + StopEvent SuitLoop 0.0 + +// removing this effect -- matching it to the event for normal suit damage +// so, there will be no special indication (redness, flashing) +// in the hud that the suit armor is low + +// Animate HudSuit BgColor "DamagedBg" Linear 0.0 0.1 +// Animate HudSuit BgColor "BgColor" Deaccel 0.1 1.75 + + Animate HudSuit FgColor "BrightFg" Linear 0.0 0.25 + Animate HudSuit FgColor "FgColor" Linear 0.3 0.75 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 + + Animate HudSuit TextColor "BrightFg" Linear 0.0 0.1 + Animate HudSuit TextColor "FgColor" Deaccel 0.1 1.2 + +// RunEvent SuitPulse 1.0 +} + +event SuitPulse +// this even no longer gets called +{ + Animate HudSuit Blur "5" Linear 0.0 0.1 + Animate HudSuit Blur "2" Deaccel 0.1 0.8 + Animate HudSuit TextColor "BrightDamagedFg" Linear 0.0 0.1 + Animate HudSuit TextColor "DamagedFg" Deaccel 0.1 0.8 + Animate HudSuit BgColor "100 0 0 80" Linear 0.0 0.1 + Animate HudSuit BgColor "BgColor" Deaccel 0.1 0.8 + RunEvent SuitLoop 0.8 +} + +event SuitLoop +{ +// this event no longer gets called + RunEvent SuitPulse 0.0 +} + +// ammo has been picked up +event AmmoIncreased +{ + Animate HudAmmo FgColor "0 0 255 255" Linear 0.0 0.3 + Animate HudAmmo FgColor "FgColor" Deaccel 0.3 1.5 + Animate HudAmmo Blur "5" Linear 0.0 0.0 + Animate HudAmmo Blur "0" Accel 0.01 1.5 +} + +// ammo has been decreased, but there is still some remaining +event AmmoDecreased +{ + StopEvent AmmoIncreased 0.0 + + Animate HudAmmo Blur "7" Linear 0.0 0.0 + Animate HudAmmo Blur "0" Deaccel 0.1 1.5 + + Animate HudAmmo TextColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmo TextColor "FgColor" Deaccel 0.1 0.75 +} + +// primary ammo is zero +event AmmoEmpty +{ + Animate Hudammo FgColor "HealthLowColor" Linear 0.0 0.0 +} + +// ammo2 is the total ammo for a weapon that uses clip ammo +event Ammo2Increased +{ + Animate Hudammo ammo2color "BrightFg" Linear 0.0 0.2 + Animate Hudammo ammo2color "FgColor" Accel 0.2 1.2 +} + +// total ammo has been decreased, but there is still some remaining +event Ammo2Decreased +{ + Animate Hudammo ammo2color "BrightFg" Linear 0.0 0.2 + Animate Hudammo ammo2color "FgColor" Accel 0.2 1.2 +} + +// total ammo is zero +event Ammo2Empty +{ + Animate Hudammo FgColor "HealthLowColor" Linear 0.0 0.0 +} + +event AmmoSecondaryIncreased +{ + Animate HudAmmoSecondary FgColor "BrightFg" Linear 0.0 0.15 + Animate HudAmmoSecondary FgColor "FgColor" Deaccel 0.15 1.5 + Animate HudAmmoSecondary Blur "5" Linear 0.0 0.0 + Animate HudAmmoSecondary Blur "0" Accel 0.01 1.5 +} + +event AmmoSecondaryDecreased +{ + StopEvent AmmoSecondaryIncreased 0.0 + + Animate HudAmmoSecondary Blur "7" Linear 0.0 0.0 + Animate HudAmmoSecondary Blur "0" Deaccel 0.1 1.5 + + Animate HudAmmoSecondary TextColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmoSecondary TextColor "FgColor" Deaccel 0.1 0.75 +} + +event AmmoSecondaryEmpty +{ + Animate HudAmmoSecondary FgColor "HealthLowColor" Linear 0.0 0.0 + +} + +// current weapon has been changed +event WeaponChanged +{ + //Animate HudAmmo BgColor "250 220 0 80" Linear 0.0 0.1 + //Animate HudAmmo BgColor "BgColor" Deaccel 0.1 1.0 + Animate HudAmmo FgColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmo FgColor "FgColor" Linear 0.2 1.5 +} + +// ran if we just changed to a weapon that needs clip ammo +event WeaponUsesClips +{ + Animate HudAmmo Position "r150 432" Deaccel 0.0 0.4 + Animate HudAmmo Size "132 36" Deaccel 0.0 0.4 +} + +// ran if we just changed to a weapon that does not use clip ammo +event WeaponDoesNotUseClips +{ + Animate HudAmmo Position "r118 432" Deaccel 0.0 0.4 + Animate HudAmmo Size "100 36" Deaccel 0.0 0.4 +} + +event WeaponUsesSecondaryAmmo +{ + StopAnimation HudAmmo Position 0.0 + StopAnimation HudAmmo Size 0.0 + StopPanelAnimations HudAmmoSecondary 0.0 + + //Animate HudAmmoSecondary BgColor "250 220 0 60" Linear 0.0 0.1 + //Animate HudAmmoSecondary BgColor "BgColor" Deaccel 0.1 1.0 + Animate HudAmmoSecondary FgColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmoSecondary FgColor "FgColor" Linear 0.2 1.5 + Animate HudAmmoSecondary Alpha 255 Linear 0.0 0.1 + + //Animate HudAmmo Position "r222 432" Deaccel 0.0 0.5 + //Animate HudAmmo Size "132 36" Deaccel 0.0 0.4 +} + +event WeaponDoesNotUseSecondaryAmmo +{ + StopPanelAnimations HudAmmoSecondary 0.0 + Animate HudAmmoSecondary FgColor "0 0 0 0" Linear 0.0 0.4 + //Animate HudAmmoSecondary BgColor "0 0 0 0" Linear 0.0 0.4 + Animate HudAmmoSecondary Alpha 0 Linear 0.0 0.1 +} + +event CraneMagnetFlash +{ + Animate HudCraneMagnet TextColor "255 220 0 255" Linear 0.0 0.1 + Animate HudCraneMagnet TextColor "255 220 0 160" Deaccel 0.1 0.3 + Animate HudCraneMagnet TextColor "255 170 0 220" Deaccel 0.4 0.3 + Animate HudCraneMagnet TextColor "255 220 0 255" Linear 0.8 0.2 +} + +event HintMessageShow +{ + // show the hints + Animate HudHintDisplay Alpha 255 Linear 0.0 0.5 + + // flash text + Animate HudHintDisplay FgColor "FgColor" Linear 0.0 0.01 + Animate HudHintDisplay FgColor "255 220 0 255" Linear 0.5 0.2 + Animate HudHintDisplay FgColor "FgColor" Linear 0.7 0.2 + Animate HudHintDisplay FgColor "255 220 0 255" Linear 1.5 0.2 + Animate HudHintDisplay FgColor "FgColor" Linear 1.7 0.2 + + // hide the panel after a while + Animate HudHintDisplay Alpha 0 Linear 12.0 1.0 +} + +event HintMessageHide +{ + Animate HudHintDisplay Alpha 0 Linear 0.0 0.5 +} + +event SquadMemberAdded +{ + StopEvent SquadMemberDied 0.0 + StopEvent SquadMemberLeft 0.0 + + // add in the squad member, brighter then normal color + Animate HudSquadStatus LastMemberColor "255 220 0 255" Linear 0.0 0.3 + Animate HudSquadStatus LastMemberColor "255 220 0 160" Linear 0.3 0.3 +} + +event SquadMemberLeft +{ + StopEvent SquadMemberDied 0.0 + StopEvent SquadMemberAdded 0.0 + + // fade out the icon + Animate HudSquadStatus LastMemberColor "255 220 0 0" Linear 0.0 0.5 +} + +event SquadMemberDied +{ + StopEvent SquadMemberAdded 0.0 + StopEvent SquadMemberLeft 0.0 + + // flash red, hold, then disappear + Animate HudSquadStatus LastMemberColor "255 0 0 255" Linear 0.0 0.5 + Animate HudSquadStatus LastMemberColor "255 0 0 0" Linear 2.0 2.0 +} + +event SquadMembersFollowing +{ + StopEvent SquadMembersStationed 0.0 + Animate HudSquadStatus SquadTextColor "255 220 0 255" Linear 0.0 0.2 + Animate HudSquadStatus SquadTextColor "255 220 0 160" Linear 0.2 0.4 +} + +event SquadMembersStationed +{ + StopEvent SquadMembersFollowing 0.0 + Animate HudSquadStatus SquadTextColor "255 220 0 160" Linear 0.5 0.5 +} + +event PoisonDamageTaken +{ + Animate HudPoisonDamageIndicator Alpha 255 Linear 0.0 1.0 + RunEvent PoisonLoop 0.0 +} + +event PoisonDamageCured +{ + StopEvent PoisonDamageTaken 0.0 + StopEvent PoisonLoop 0.0 + StopEvent PoisonPulse 0.0 + Animate HudPoisonDamageIndicator Alpha 0 Linear 0.0 1.0 +} + +event PoisonPulse +{ + Animate HudPoisonDamageIndicator TextColor "BrightFg" Linear 0.0 0.1 + Animate HudPoisonDamageIndicator TextColor "FgColor" Deaccel 0.1 0.8 + Animate HudPoisonDamageIndicator BgColor "100 0 0 80" Linear 0.0 0.1 + Animate HudPoisonDamageIndicator BgColor "BgColor" Deaccel 0.1 0.8 + + RunEvent PoisonLoop 0.8 +} + +// call to loop PoisonLoop +event PoisonLoop +{ + RunEvent PoisonPulse 0.0 +} + +// Grenade has been picked up +event GrenadeIncreased +{ + Animate HudGrenade FgColor "BrightFg" Linear 0.0 0.15 + Animate HudGrenade FgColor "FgColor" Deaccel 0.15 1.5 + Animate HudGrenade Blur "5" Linear 0.0 0.0 + Animate HudGrenade Blur "0" Accel 0.01 1.5 +} + +// Grenade has been decreased, but there is still some remaining +event GrenadeDecreased +{ + StopEvent GrenadeIncreased 0.0 + + Animate HudGrenade Blur "7" Linear 0.0 0.0 + Animate HudGrenade Blur "0" Deaccel 0.1 1.5 + + Animate HudGrenade TextColor "BrightFg" Linear 0.0 0.1 + Animate HudGrenade TextColor "FgColor" Deaccel 0.1 0.75 +} + +// primary Grenade is zero +event GrenadeEmpty +{ + Animate HudGrenade FgColor "HealthLowColor" Linear 0.0 0.0 +} + +// Grenade2 is the total Grenade for a weapon that uses clip Grenade +event Grenade2Increased +{ + Animate HudGrenade Grenade2color "BrightFg" Linear 0.0 0.2 + Animate HudGrenade Grenade2color "FgColor" Accel 0.2 1.2 +} + +// total Grenade has been decreased, but there is still some remaining +event Grenade2Decreased +{ + Animate HudGrenade Grenade2color "BrightFg" Linear 0.0 0.2 + Animate HudGrenade Grenade2color "FgColor" Accel 0.2 1.2 +} + +// total Grenade is zero +event Grenade2Empty +{ + Animate HudGrenade Grenade2color "HealthLowColor" Linear 0.0 0.2 +} + +event GrenadeSecondaryIncreased +{ + Animate HudGrenadeSecondary FgColor "BrightFg" Linear 0.0 0.15 + Animate HudGrenadeSecondary FgColor "FgColor" Deaccel 0.15 1.5 + Animate HudGrenadeSecondary Blur "5" Linear 0.0 0.0 + Animate HudGrenadeSecondary Blur "0" Accel 0.01 1.5 +} + +event GrenadeSecondaryDecreased +{ + StopEvent GrenadeSecondaryIncreased 0.0 + + Animate HudGrenadeSecondary Blur "7" Linear 0.0 0.0 + Animate HudGrenadeSecondary Blur "0" Deaccel 0.1 1.5 + + Animate HudGrenadeSecondary TextColor "BrightFg" Linear 0.0 0.1 + Animate HudGrenadeSecondary TextColor "FgColor" Deaccel 0.1 0.75 +} + +event GrenadeSecondaryEmpty +{ + Animate HudGrenadeSecondary FgColor "BrightDamagedFg" Linear 0.0 0.2 + Animate HudGrenadeSecondary FgColor "DamagedFg" Accel 0.2 1.2 + Animate HudGrenadeSecondary Blur "7" Linear 0.0 0.0 + Animate HudGrenadeSecondary Blur "0" Deaccel 0.1 1.5 + +} + +// current Grenades has been changed +event ClassHasGrenades +{ + Animate HudGrenade BgColor "250 220 0 80" Linear 0.0 0.1 + Animate HudGrenade BgColor "BgColor" Deaccel 0.1 1.0 + Animate HudGrenade FgColor "BrightFg" Linear 0.0 0.1 + Animate HudGrenade FgColor "FgColor" Linear 0.2 1.5 +} + +// ran if we just changed to a Grenades that needs clip Grenade +event ClassHasTwoGrenades +{ + Animate HudGrenade Position "r150 382" Deaccel 0.0 0.4 + Animate HudGrenade Size "132 36" Deaccel 0.0 0.4 +} + +// ran if we just changed to a Grenades that does not use clip Grenade +event ClassHasOneGrenade +{ + Animate HudGrenade Position "r118 382" Deaccel 0.0 0.4 + Animate HudGrenade Size "100 36" Deaccel 0.0 0.4 +} + +event FadeInBuildTimer +{ + Animate HudBuildTimer Alpha 255 Linear 0.0 0.2 +} + +event FadeOutBuildTimer +{ + Animate HudBuildTimer Alpha 0 Linear 0.0 0.2 +} + +event FadeInGrenade1Timer +{ + Animate HudGrenade1Timer Alpha 255 Linear 0.0 0.2 +} + +event FadeOutGrenade1Timer +{ + Animate HudGrenade1Timer Alpha 0 Linear 0.0 0.2 +} + +event FadeInGrenade2Timer +{ + Animate HudGrenade2Timer Alpha 255 Linear 0.0 0.2 +} + +event FadeOutGrenade2Timer +{ + Animate HudGrenade2Timer Alpha 0 Linear 0.0 0.2 +} diff --git a/scripts/HudLayout.res b/scripts/HudLayout.res new file mode 100644 index 0000000..6a30f45 --- /dev/null +++ b/scripts/HudLayout.res @@ -0,0 +1,1416 @@ +/////////////////////////////////////////////////////////// +// Fortress Forever HUD Layout resource file +// +// This file is cross-referenced and shares resources with; +// +// resource/clientscheme.res - HUD Colours & Font definitions +// scripts/ff_hud_textures.txt - Glyph definitions for the HUD font +// scripts/HudAnimations.txt - Animations for stuff like low ammo, etc. +// +/////////////////////////////////////////////////////////// + +"scripts/HudLayout.res" +{ + HudLocation // hudlocation + { + "fieldName" "HudLocation" + + "visible" "1" + "enabled" "1" + + "xpos" "3" + "ypos" "447" + "wide" "640" //256 + "tall" "480" //32 + + "text1_xpos" "4" + "text1_ypos" "20" //19 + + "TextFont" "HUD_TextSmall_Shadow" + "TextColor" "HUD_Tone_Default" // Ignored: locations are colour coded + + "ForegroundTexture" "locationBoxFG1" + "BackgroundTexture" "locationBoxBG1" + } + HudLocation2 + { + "fieldName" "HudLocation2" + + "visible" "1" + "enabled" "1" + "pinCorner" "3" + + "xpos" "85" //85 x pos controlled by HudLocation + "ypos" "447" + "wide" "640" //256 + "tall" "480" //32 + + "ForegroundTexture" "locationBoxFG2" + "BackgroundTexture" "locationBoxBG2" + } + + HudHealth + { + "fieldName" "HudHealth" + + "visible" "1" + "enabled" "1" + + "xpos" "3" + "ypos" "431" + "wide" "128" + "tall" "32" + + "digit_xpos" "44" + "digit_ypos" "8" + + "NumberFont" "HUD_NumLarge" + "NumberColor" "HUD_Tone_Default" + + "ForegroundTexture" "healthBoxFG" + "BackgroundTexture" "healthBoxBG" + } + + HudPlayerAddHealth + { + "fieldName" "HudPlayerAddHealth" + + "visible" "1" + "enabled" "1" + + "xpos" "3" + "ypos" "406" + "wide" "128" + "tall" "32" + + "HealthFont_xpos" "32" + "HealthFont_ypos" "8" + + "HealthFont" "HudAddHealth" + "TextColor" "255 255 255 255" //black + "HealthFontBG" "HudPlayerScoreBG" + + "ForegroundTexture" "playerScoreBoxFG1" + "BackgroundTexture" "playerScoreBoxBG1" + } + + HudArmor + { + "fieldName" "HudArmor" + + "visible" "1" + "enabled" "1" + + "xpos" "87" + "ypos" "431" + "wide" "128" + "tall" "32" + + "digit_xpos" "38" + "digit_ypos" "18" + + "NumberFont" "HUD_NumSmall" + "NumberColor" "HUD_Tone_Default" + + "ForegroundTexture" "armourBoxFG" + "BackgroundTexture" "armourBoxBG" + } + + HudPlayerAddArmor + { + "fieldName" "HudPlayerAddArmor" + + "visible" "1" + "enabled" "1" + + "xpos" "87" + "ypos" "406" + "wide" "128" + "tall" "32" + + "ArmorFont_xpos" "32" + "ArmorFont_ypos" "18" + + "ArmorFont" "HudAddHealth" + "TextColor" "255 255 255 255" //black + "ArmorFontBG" "HudPlayerScoreBG" + + "ForegroundTexture" "playerScoreBoxFG1" + "BackgroundTexture" "playerScoreBoxBG1" + } + + // Added by AfterShock - for displaying weapon icon in bottom right + HudWeaponInfo + { + "fieldName" "HudWeaponInfo" + + "visible" "1" + "enabled" "1" + + // xpos and ypos define where the top left corner of the panel will be + "xpos" "r124" //x pos controlled by HudAmmoInfo2 + "ypos" "447" + "zpos" "2" + + "wide" "640" // This stuff is proportional, so 640x480 is actually the size of the whole screen at any resolution. Unless, that is, you have a non-4:3 monitor. Vgui is a pain in the ass to get right then. + "tall" "480" + + "ammo_xpos" "5" // Note that these positions are relative to the position of the panel + "ammo_ypos" "18" // i.e. 0,0 is the top left corner of the panel + + "TextFont" "HudNumbers" + "TextColor" "HUD_Tone_Default" + + "IconFont" "WeaponIconsHUD" // Defines which Font to look in for the icons + "AmmoFont" "AmmoIconsSmall" // Defines which Font to look in for the icons + } + + HudAmmoInfo // should be weapon item glyphs in lower right + { + "fieldName" "HudAmmoInfo" + + "visible" "1" + "enabled" "1" + + "xpos" "r124" //x pos controlled by HudAmmoInfo2 + "ypos" "447" + "wide" "640" //128 + "tall" "480" //64 + + "text1_xpos" "0" + "text1_ypos" "0" + + "TextFont" "HudNumbers" + "TextColor" "HUD_Tone_Default" + "IconFont" "weaponglyphssmall" + + "ForegroundTexture" "weaponBoxFG1" + "BackgroundTexture" "weaponBoxBG1" + } + HudAmmoInfo2 + { + "fieldName" "HudAmmoInfo2" + + "visible" "1" + "enabled" "1" + + "xpos" "r42" + "ypos" "447" + "wide" "640" //128 + "tall" "480" //64 + + "ForegroundTexture" "weaponBoxFG2" + "BackgroundTexture" "weaponBoxBG2" + } + + HudAmmo + { + "fieldName" "HudAmmo" + + "visible" "1" + "enabled" "1" + + "xpos" "r152" //488 + "ypos" "447" + "wide" "640" //128 + "tall" "480" //32 + "digit_xpos" "4" + "digit_ypos" "19" + + "NumberFont" "HUD_NumSmall" + "NumberColor" "HUD_Tone_Default" + + "ForegroundTexture" "ammoCarriedBoxFG" + "BackgroundTexture" "ammoCarriedBoxBG" + } + + HudAmmoClip + { + "fieldName" "HudAmmoClip" + + "visible" "1" + "enabled" "1" + + "xpos" "r149" //491 + "ypos" "430" + "wide" "640" //128 + "tall" "480" //32 + + "digit_xpos" "16" + "digit_ypos" "8" + + "NumberFont" "HUD_NumLarge" + "NumberColor" "HUD_Tone_Default" + + "ForegroundTexture" "ammoLoadedBoxFG" + "BackgroundTexture" "ammoLoadedBoxBG" + } + + HudGrenade1 + { + "fieldName" "HudGrenade1" + + "visible" "1" + "enabled" "1" + + "xpos" "r91" //549 + "ypos" "414" + "wide" "640" //128 + "tall" "480" //32 + + "digit_xpos" "33" + "digit_ypos" "18" + + "icon_xpos" "10" + "icon_ypos" "25" + "icon_font" "StatusGlyphsSmall" + "icon_color" "HUD_Tone_Default" + + "NumberFont" "HUD_NumSmall" + "NumberColor" "HUD_Tone_Default" + + "ForegroundTexture" "grenPrimaryBoxFG" + "BackgroundTexture" "grenPrimaryBoxBG" + } + + HudGrenade2 // far right glyph + { + "fieldName" "HudGrenade2" + + "visible" "1" + "enabled" "1" + + "xpos" "r47" //593 + "ypos" "414" + "wide" "640" //128 + "tall" "480" //32 + + "digit_xpos" "35" + "digit_ypos" "18" + + "icon_xpos" "10" + "icon_ypos" "25" + "icon_font" "StatusGlyphsSmall" + "icon_color" "HUD_Tone_Default" + + "NumberFont" "HUD_NumSmall" + "NumberColor" "HUD_Tone_Default" + + "ForegroundTexture" "grenSecondaryBoxFG" + "BackgroundTexture" "grenSecondaryBoxBG" + } + + HudRoundInfo // top center item glyph, fucked by non 4:3 aspect ratio, new settings seem to stay in center, but text needs fixin + { + "fieldName" "HudRoundInfo" + + "visible" "1" + "enabled" "1" + + "xpos" "c-60" //256 + "ypos" "1" + "wide" "120" //128 , 120 + "tall" "128" //128 + + + "MapNameFont" "HUD_TextRoundInfo" + "MapNameColor" "HUD_Tone_Default" + "MapNameX" "32" //32 + "MapNameY" "3" + //"center_x" "1" // center text horizontally + //"RightJustify" "1" + + "TimerFont" "HUD_TextRoundInfo" + "TimerColor" "HUD_Tone_Default" + "TimerX" "43" //45 + "TimerY" "18" + + "ForegroundTexture" "RoundInfoBoxFG" + "BackgroundTexture" "RoundInfoBoxBG" + } + + HudTeamScores + { + "fieldName" "HudTeamScores" + + "visible" "1" + "enabled" "1" + + // xpos and ypos define where the top left corner of the panel will be + "xpos" "c-120" // Right in the middle of the damn screen + //"xpos" "130" // Right in the middle of the damn screen + "ypos" "7" + "wide" "640" // This stuff is proportional, so 640x480 is actually the size of the whole screen at any resolution. Unless, that is, you have a non-4:3 monitor. Vgui is a pain in the ass to get right then. + "tall" "480" + + "TeamScoreBlue_xpos" "0" // Note that these positions are relative to the position of the panel + "TeamScoreBlue_ypos" "0" // i.e. 0,0 is the top left corner of the panel + "TeamScoreRed_xpos" "200" // Note that these positions are relative to the position of the panel + "TeamScoreRed_ypos" "0" // i.e. 0,0 is the top left corner of the panel + "TeamScoreYellow_xpos" "5" // Note that these positions are relative to the position of the panel + "TeamScoreYellow_ypos" "22" // i.e. 0,0 is the top left corner of the panel + "TeamScoreGreen_xpos" "195" // Note that these positions are relative to the position of the panel + "TeamScoreGreen_ypos" "22" // i.e. 0,0 is the top left corner of the panel + + "TeamScoreBlueFont" "HudTeamScore" + "TeamScoreRedFont" "HudTeamScore" + "TeamScoreYellowFont" "HudTeamScore" + "TeamScoreGreenFont" "HudTeamScore" + + "TextColor" "Black" + + "ForegroundTexture" "TeamScoreBoxFG1" + "BackgroundTexture" "TeamScoreBoxBG1" + } + + HudPlayerTotalScore + { + "fieldName" "HudPlayerTotalScore" + + "visible" "1" + "enabled" "1" + + // xpos and ypos define where the top left corner of the panel will be + "xpos" "0" // Right in the middle of the damn screen 20 + "ypos" "0" //20 + "wide" "640" // This stuff is proportional, so 640x480 is actually the size of the whole screen at any resolution. Unless, that is, you have a non-4:3 monitor. Vgui is a pain in the ass to get right then. + "tall" "480" + + "TotalDescFont_xpos" "5" // Note that these positions are relative to the position of the panel + "TotalDescFont_ypos" "3" // i.e. 0,0 is the top left corner of the panel + "TotalScoreFont_xpos" "5" // Note that these positions are relative to the position of the panel + "TotalScoreFont_ypos" "15" // i.e. 0,0 is the top left corner of the panel + + "TotalScoreFont" "HudPlayerScore" + "TotalDescFont" "HudPlayerScoreDesc" + + "TotalScoreFontBG" "HudPlayerScoreBG" + "TotalDescFontBG" "HudPlayerScoreDescBG" + + "TextColor" "Black" + + "ForegroundTexture" "playerScoreBoxFG1" + "BackgroundTexture" "playerScoreBoxBG1" + } + HudPlayerLatestScore + { + "fieldName" "HudPlayerLatestScore" + + "visible" "1" + "enabled" "1" + + // xpos and ypos define where the top left corner of the panel will be + "xpos" "0" // Right in the middle of the damn screen + "ypos" "0" // + "wide" "640" // This stuff is proportional, so 640x480 is actually the size of the whole screen at any resolution. Unless, that is, you have a non-4:3 monitor. Vgui is a pain in the ass to get right then. + "tall" "480" + + "DescFont_xpos" "13" // Note that these positions are relative to the position of the panel + "DescFont_ypos" "33" // i.e. 0,0 is the top left corner of the panel + "ScoreFont_xpos" "8" // Note that these positions are relative to the position of the panel + "ScoreFont_ypos" "43" // i.e. 0,0 is the top left corner of the panel + + "ScoreFont" "HudBonusScore" + "DescFont" "HudBonusScoreDesc" + + "ScoreFontBG" "HudPlayerScoreBG" + "DescFontBG" "HudPlayerScoreDescBG" + + "TextColor" "255 255 255 255" //black + + "ForegroundTexture" "playerScoreBoxFG1" + "BackgroundTexture" "playerScoreBoxBG1" + } + + HudOverpressure + { + "fieldName" "HudOverpressure" + + "visible" "1" + "enabled" "1" + + "xpos" "3" + "ypos" "404" + "wide" "128" + "tall" "128" + + "text1_xpos" "34" + "text1_ypos" "12" + + "image1_xpos" "3" + "image1_ypos" "4" + + "bar_width" "75" + "bar_height" "24" + + "TextFont" "HUD_TextSmall" + "TextColor" "HUD_Tone_Default" //overridden by teamcolor of disguise + + "ForegroundTexture" "CooldownBoxFG" + "BackgroundTexture" "CooldownBoxBG" + } + + HudCellCount + { + "fieldName" "HudCellCount" + + "visible" "1" + "enabled" "1" + + "xpos" "r198" + "ypos" "447" + "xpos" "3" + "ypos" "404" + "wide" "128" + "tall" "128" + + "text_xpos" "19" + "text_ypos" "19" + + "image_xpos" "3" + "image_ypos" "18" + + "IconFont" "AmmoIconsSmall" + + "TextFont" "HUD_TextRoundInfo" + "TextColor" "HUD_Tone_Default" + + "ForegroundTexture" "CellCountBoxFG" + "BackgroundTexture" "CellCountBoxBG" + } + + HudSpyDisguise + { + "fieldName" "HudSpyDisguise" + + "visible" "1" + "enabled" "1" + + "xpos" "3" + "ypos" "404" + "wide" "128" + "tall" "128" + + "text1_xpos" "34" + "text1_ypos" "12" + + "image1_xpos" "3" + "image1_ypos" "4" + + "bar_width" "75" + "bar_height" "24" + + "DisguiseFont" "ClassGlyphs" + + "TextFont" "HUD_TextSmall" + "TextColor" "HUD_Tone_Default" //overridden by teamcolor of disguise + + "ForegroundTexture" "CooldownBoxFG" + "BackgroundTexture" "CooldownBoxBG" + } + + HudSpyDisguise2 + { + "fieldName" "HudSpyDisguise2" + + "visible" "1" + "enabled" "1" + + "xpos" "82" + "ypos" "404" + "wide" "128" + "tall" "128" + + "image1_xpos" "2" + "image1_ypos" "4" + + "WeaponFont" "WeaponIconsHUD" + "WeaponColor" "HUD_Tone_Default" + + "ForegroundTexture" "SpyDisguiseBoxFG2" + "BackgroundTexture" "SpyDisguiseBoxBG2" + } + + HudSpyDisguise3 + { + "fieldName" "HudSpyDisguise3" + + "visible" "1" + "enabled" "1" + + "xpos" "82" + "ypos" "431" + "wide" "128" + "tall" "128" + + "ForegroundTexture" "SpyDisguiseBoxFG3" + "BackgroundTexture" "SpyDisguiseBoxBG3" + } + + HudHintCenter + { + "fieldName" "HudHintCenter" + + "visible" "1" + "enabled" "1" + + "xpos" "c-130" + "ypos" "404" + + "wide" "260" + "tall" "70" + + "text1_xpos" "34" + "text1_ypos" "10" + + "text1_wide" "220" + "text1_tall" "40" + + "image1_xpos" "4" + "image1_ypos" "8" + + "IconFont" "HudHintCenterIcon" + "IconFontGlow" "HudHintCenterIconGlow" + + "TextFont" "HUD_TextSmall" + "TextColor" "HUD_Tone_Default" + "BGBoxColor" "Dark" + + + // The buttons + "B_wide" "20" + "B_tall" "10" + + "NextB_xpos" "235" + "NextB_ypos" "55" + + "PrevB_xpos" "5" + "PrevB_ypos" "55" + + // The hint index thingy + "index_xpos" "9" + "index_ypos" "45" + + + "SmallBoxSize" "36" //32 + "LargeBoxWide" "112" + "LargeBoxTall" "80" + "BoxGap" "8" + "SelectionNumberXPos" "4" + "SelectionNumberYPos" "4" + "SelectionGrowTime" "0.4" + "TextYPos" "64" + } + + + HudGrenade1Timer + { + "fieldName" "HudGrenade1Timer" + + "visible" "1" + "enabled" "1" + + "xpos" "c-123" + "ypos" "414" + "wide" "256" + "tall" "32" + + "bar_xpos" "69" + "bar_ypos" "4" + "bar_width" "118" + "bar_height" "13" + "bar_color" "HUD_Tone_Default" + + "icon_xpos" "10" + "icon_ypos" "25" + + //"icon_color" "0 0 0 255" + + "ForegroundTexture" "Gren1TimerFGBox" + "BackgroundTexture" "Gren1TimerBGBox" + } + + HudGrenade2Timer + { + "fieldName" "HudGrenade2Timer" + + "visible" "1" + "enabled" "1" + + "xpos" "c-123" + "ypos" "434" + "wide" "256" + "tall" "32" + + "bar_xpos" "69" + "bar_ypos" "16" + "bar_width" "118" + "bar_height" "13" + "bar_color" "HUD_Tone_Default" + + "icon_xpos" "8" + "icon_ypos" "24" + + //"icon_color" "0 0 0 255" + + "ForegroundTexture" "Gren2TimerFGBox" + "BackgroundTexture" "Gren2TimerBGBox" + } + + // + // you are entering untamed land! + // + + HudBuildTimer + { + "fieldName" "HudBuildTimer" + "xpos" "c-123" + "ypos" "r132" + "wide" "256" + "tall" "32" + "visible" "1" + "enabled" "1" + + "text_xpos" "256" + "text_ypos" "0" + + "icon_xpos" "40" + "icon_ypos" "8" + "icon_width" "16" + "icon_height" "16" + + "bar_xpos" "64" + "bar_ypos" "8" + "bar_width" "128" + "bar_height" "16" + "bar_color" "HUD_Tone_Default" + } + + //HudGrenade1Timer + //{ + // "fieldName" "HudGrenade1Timer" + // "xpos" "140" + // "ypos" "r56" + // "wide" "192" + // "tall" "20" + // "visible" "1" + // "enabled" "1" +// +// "text_xpos" "0" +// "text_ypos" "0" +// +// "icon_xpos" "4" +// "icon_ypos" "4" +// "icon_width" "20" +// "icon_height" "20" +// +// "bar_xpos" "16" +// "bar_ypos" "4" +// "bar_width" "128" +// "bar_height" "12" +// "bar_color" "HUD_Tone_Default" +// } +// +// HudGrenade2Timer +// { +// "fieldName" "HudGrenade2Timer" +// "xpos" "140" +// "ypos" "r32" +// "wide" "192" +// "tall" "20" +// "visible" "1" +// "enabled" "1" +// +// "text_xpos" "0" +// "text_ypos" "0" +// +// "icon_xpos" "4" +// "icon_ypos" "4" +// "icon_width" "20" +// "icon_height" "20" +// +// "bar_xpos" "16" +// "bar_ypos" "4" +// "bar_width" "128" +// "bar_height" "12" +// "bar_color" "HUD_Tone_Default" +// } + + HudBuildState + { + "fieldName" "HudBuildState" + "xpos" "r210" + "ypos" "380" + "wide" "210" + "tall" "40" + "visible" "1" + "enabled" "1" + + "text1_xpos" "24" + "text1_ypos" "3" + "text2_xpos" "24" + "text2_ypos" "22" + + "icon1_xpos" "0" + "icon1_ypos" "0" + "icon1_width" "20" + "icon1_height" "20" + + "icon2_xpos" "0" + "icon2_ypos" "20" + "icon2_width" "20" + "icon2_height" "20" + } + + + HudBuildStateSentry + { + "fieldName" "HudBuildStateSentry" + "PaintBackgroundType" "2" + } + + HudAmmoSecondary + { + "fieldName" "HudAmmoSecondary" + "xpos" "r76" + "ypos" "432" + "wide" "60" + "tall" "36" + "visible" "1" + "enabled" "1" + + "PaintBackgroundType" "2" + + "digit_xpos" "10" + "digit_ypos" "2" + + "TextColor" "HUD_Tone_Default" + } + + HudSuitPower + { + "fieldName" "HudSuitPower" + "visible" "1" + "enabled" "1" + "xpos" "16" + "ypos" "396" + "wide" "102" + "tall" "26" + + "AuxPowerLowColor" "255 0 0 220" + "AuxPowerHighColor" "255 220 0 220" + "AuxPowerDisabledAlpha" "70" + + "BarInsetX" "8" + "BarInsetY" "15" + "BarWidth" "92" + "BarHeight" "4" + "BarChunkWidth" "6" + "BarChunkGap" "3" + + "text_xpos" "8" + "text_ypos" "4" + "text2_xpos" "8" + "text2_ypos" "22" + "text2_gap" "10" + + "PaintBackgroundType" "2" + } + + HudFlashlight + { + "fieldName" "HudFlashlight" + "visible" "0" + "enabled" "1" + "xpos" "16" + "ypos" "370" + "wide" "102" + "tall" "20" + + "text_xpos" "8" + "text_ypos" "6" + "TextColor" "255 170 0 220" + + "PaintBackgroundType" "2" + } + + HudDamageIndicator + { + "fieldName" "HudDamageIndicator" + "visible" "1" + "enabled" "1" + "DmgColorLeft" "255 0 0 0" + "DmgColorRight" "255 0 0 0" + + "dmg_xmargin" "40" + "dmg_ymargin" "40" + + "dmg_depth" "40" + "dmg_outerlength" "300" + "dmg_innerlength" "240" + } + + HudHitIndicator + { + "fieldName" "HudHitIndicator" + "visible" "1" + "enabled" "1" + "zpos" "2" // draw above crosshair + } + + HudZoom + { + "fieldName" "HudZoom" + "visible" "1" + "enabled" "1" + "Circle1Radius" "66" + "Circle2Radius" "74" + "DashGap" "16" + "DashHeight" "4" + "BorderThickness" "88" + } + + HudWeaponSelection + { + "fieldName" "HudWeaponSelection" + "ypos" "16" + "visible" "1" + "enabled" "1" + "SmallBoxSize" "36" //32 + "LargeBoxWide" "112" + "LargeBoxTall" "80" + "BoxGap" "8" + "SelectionNumberXPos" "4" + "SelectionNumberYPos" "4" + "SelectionGrowTime" "0.4" + "TextYPos" "64" + } + + HudCrosshair + { + "fieldName" "HudCrosshair" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudDeathNotice + { + "fieldName" "HudDeathNotice" + "visible" "1" + "enabled" "1" + "xpos" "r640" + "ypos" "0" + "wide" "640" + "tall" "480" + + "HighlightColor" "255 255 255 100" + "ObjectiveNoticeColor" "0 0 0 180" + + "LineHeight" "22" + "RightJustify" "1" + + "TextFont" "Default" + } + + HudVehicle + { + "fieldName" "HudVehicle" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + ScorePanel + { + "fieldName" "ScorePanel" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudTrain + { + "fieldName" "HudTrain" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudMOTD + { + "fieldName" "HudMOTD" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudMessage + { + "fieldName" "HudMessage" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudMenu + { + "fieldName" "HudMenu" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + "zpos" "1" + "TextFont""Default" + "ItemFont""Default" + "ItemFontPulsing""Default" + } + + HudCloseCaption + { + "fieldName" "HudCloseCaption" + "visible" "1" + "enabled" "1" + "xpos" "c-250" + "ypos" "276" + "wide" "500" + "tall" "136" + + "BgAlpha" "128" + + "GrowTime" "0.25" + "ItemHiddenTime" "0.2" // Nearly same as grow time so that the item doesn't start to show until growth is finished + "ItemFadeInTime" "0.15" // Once ItemHiddenTime is finished, takes this much longer to fade in + "ItemFadeOutTime" "0.3" + + } + + HudChat + { + "fieldName" "HudChat" + "visible" "1" + "enabled" "1" + "xpos" "0" + "ypos" "200" + "wide" "520" + "tall" "200" + } + + HudHistoryResource + { + "fieldName" "HudHistoryResource" + "visible" "1" + "enabled" "1" + "xpos" "r252" + "ypos" "40" + "wide" "248" + "tall" "320" + + "history_gap" "24" + "icon_inset" "28" + "text_inset" "26" + "NumberFont" "HudNumbersSmall" + } + + HudGeiger + { + "fieldName" "HudGeiger" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HUDQuickInfo + { + "fieldName" "HUDQuickInfo" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudWeapon + { + "fieldName" "HudWeapon" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + "Iconfont" "WeaponIconsSmall" + } + HudAnimationInfo + { + "fieldName" "HudAnimationInfo" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudPredictionDump + { + "fieldName" "HudPredictionDump" + "visible" "1" + "enabled" "1" + "wide" "640" + "tall" "480" + } + + HudHintDisplay + { + "fieldName" "HudHintDisplay" + "visible" "0" + "enabled" "1" + "xpos" "r120" + "ypos" "r340" + "wide" "100" + "tall" "200" + "text_xpos" "8" + "text_ypos" "8" + "text_xgap" "8" + "text_ygap" "8" + "TextColor" "255 170 0 220" + + "PaintBackgroundType" "2" + } + + HudSquadStatus + { + "fieldName" "HudSquadStatus" + "visible" "1" + "enabled" "1" + "xpos" "r120" + "ypos" "380" + "wide" "104" + "tall" "46" + "text_xpos" "8" + "text_ypos" "34" + "SquadIconColor" "255 220 0 160" + "IconInsetX" "8" + "IconInsetY" "0" + "IconGap" "24" + + "PaintBackgroundType" "2" + } + + HudPoisonDamageIndicator + { + "fieldName" "HudPoisonDamageIndicator" + "visible" "0" + "enabled" "1" + "xpos" "16" + "ypos" "346" + "wide" "136" + "tall" "38" + "text_xpos" "8" + "text_ypos" "8" + "text_ygap" "14" + "TextColor" "255 170 0 220" + "PaintBackgroundType" "2" + } + HudCredits + { + "fieldName" "HudCredits" + "TextFont" "Default" + "visible" "1" + "xpos" "0" + "ypos" "0" + "wide" "640" + "tall" "480" + "TextColor" "255 255 255 192" + } + HudSpeedometer + { + "fieldName" "HudSpeedometer" + "xpos" "r65" + "ypos" "r95" + "wide" "65" + "tall" "50" + "PaintBackgroundType" "2" + "AvgSpeedFont_xpos" "0" + "AvgSpeedFont_ypos" "0" + "SpeedFont_xpos" "0" + "SpeedFont_ypos" "15" + "TextColor" "HUD_Tone_Default" + } + HudRadialMenu + { + "fieldName" "HudRadialMenu" + "visible" "1" + "enabled" "1" + } + HudCrosshairInfo + { + "fieldName" "HudCrosshairInfo" + "visible" "1" + "enabled" "1" + + // Position when hud_centerid = 0 + "text1_xpos" "20" + "text1_ypos" "280" + } + HudSentryGunStatus + { + "fieldName" "HudSentryGunStatus" + "visible" "0" + "enabled" "0" + "xpos" "16" + "ypos" "400" + "wide" "0" + "tall" "0" + "PaintBackgroundType" "2" + } + HudBuildableMessages + { + "fieldName" "HudBuildableMessages" + "visible" "0" + "enabled" "0" + "xpos" "0" + // Don't mess with the Y value + // Everything else gets overridden except the Y value... + "ypos" "300" + "wide" "0" + "tall" "0" + + "PaintBackgroundType" "2" + } + HudLua + { + "fieldName" "HudLua" + "visible" "1" + "enabled" "0" + "xpos" "0" + "ypos" "0" + "wide" "640" + "tall" "480" + + "PaintBackgroundType" "2" + + "TextColor" "255 170 0 220" + } + HudHint + { + "fieldName" "HudHint" + "visible" "1" + "enabled" "0" + "xpos" "430" + "ypos" "200" + "wide" "200" + "tall" "100" + + "PaintBackgroundType" "2" + + "TextColor" "255 170 0 220" + } + + HudStatusIcons + { + "fieldName" "HudStatusIcons" + "visible" "1" + "enabled" "1" + "xpos" "16" + "ypos" "300" + "wide" "60" + "tall" "200" + + "TextColor" "255 170 0 220" + } + HudRadar + { + "fieldName" "HudRadar" + "visible" "0" + "enabled" "1" + } + HudRadioTag + { + "fieldName" "HudRadioTag" + "visible" "0" + "enabled" "1" + } + HudObjectiveIcon + { + "fieldName" "HudObjectiveIcon" + "visible" "0" + "enabled" "1" + } + HudGameMessage + { + "fieldName" "HudGameMessage" + "visible" "0" + "enabled" "0" + "xpos" "c-200" + "ypos" "120" + "wide" "400" + "tall" "300" + "PaintBackgroundType" "1" + } + + HudSuit + { + "fieldName" "HudSuit" + "xpos" "140" + "ypos" "432" + "wide" "108" + "tall" "36" + "visible" "1" + "enabled" "1" + + "PaintBackgroundType" "2" + + + "text_xpos" "8" + "text_ypos" "20" + "digit_xpos" "50" + "digit_ypos" "2" + } + + HudVoiceSelfStatus + { + "fieldName" "HudVoiceSelfStatus" + "visible" "1" + "enabled" "1" + "xpos" "r43" + "ypos" "355" + "wide" "24" + "tall" "24" + } + + HudVoiceStatus + { + "fieldName" "HudVoiceStatus" + "visible" "1" + "enabled" "1" + "xpos" "r200" + "ypos" "0" + "wide" "100" + "tall" "400" + + "item_tall" "24" + "item_wide" "100" + + "item_spacing" "2" + + "icon_ypos" "0" + "icon_xpos" "0" + "icon_tall" "24" + "icon_wide" "24" + + "text_xpos" "26" + } + HudRadio + { + "fieldName""HudRadio" + "TextFont""Default" + "visible""1" + "xpos""10" + "ypos""c" + "wide""Default" + "tall""Default" + "text_ygap""2" + "TextColor""255 255 255 192" + "PaintBackgroundType""0" + } + + HudHintKeyDisplay + { + "fieldName" "HudHintKeyDisplay" + "visible" "0" + "enabled" "1" + "xpos" "r120" [$WIN32] + "ypos" "r340" [$WIN32] + "xpos" "r148" [$X360] + "ypos" "r338" [$X360] + "wide" "100" + "tall" "200" + "text_xpos" "8" + "text_ypos" "8" + "text_xgap" "8" + "text_ygap" "8" + "TextColor" "255 170 0 220" + + "PaintBackgroundType" "2" + } + + HUDAutoAim + { + "fieldName" "HUDAutoAim" + "visible" "1" + "enabled" "1" + "wide" "640" [$WIN32] + "tall" "480" [$WIN32] + "wide" "960" [$X360] + "tall" "720" [$X360] + } + + HudCommentary + { + "fieldName" "HudCommentary" + "xpos" "c-190" + "ypos" "350" + "wide" "380" + "tall" "40" + "visible" "1" + "enabled" "1" + + "PaintBackgroundType" "2" + + "bar_xpos" "50" + "bar_ypos" "20" + "bar_height" "8" + "bar_width" "320" + "speaker_xpos" "50" + "speaker_ypos" "8" + "count_xpos_from_right" "10" // Counts from the right side + "count_ypos" "8" + + "icon_texture" "vgui/hud/icon_commentary" + "icon_xpos" "0" + "icon_ypos" "0" + "icon_width" "40" + "icon_height" "40" + } + + HudHDRDemo + { + "fieldName" "HudHDRDemo" + "xpos" "0" + "ypos" "0" + "wide" "640" + "tall" "480" + "visible" "1" + "enabled" "1" + + "Alpha" "255" + "PaintBackgroundType" "2" + + "BorderColor" "0 0 0 255" + "BorderLeft" "16" + "BorderRight" "16" + "BorderTop" "16" + "BorderBottom" "64" + "BorderCenter" "0" + + "TextColor" "255 255 255 255" + "LeftTitleY" "422" + "RightTitleY" "422" + } + + AchievementNotificationPanel + { + "fieldName" "AchievementNotificationPanel" + "visible" "1" + "enabled" "1" + "xpos" "0" + "ypos" "180" + "wide" "f10" [$WIN32] + "wide" "f60" [$X360] + "tall" "100" + } +} diff --git a/scripts/_hl2_HudAnimations.txt b/scripts/_hl2_HudAnimations.txt new file mode 100644 index 0000000..5591f38 --- /dev/null +++ b/scripts/_hl2_HudAnimations.txt @@ -0,0 +1,628 @@ +// sample animation script +// +// +// commands: +// Animate +// variables: +// FgColor +// BgColor +// Position +// Size +// Blur (hud panels only) +// TextColor (hud panels only) +// Ammo2Color (hud panels only) +// Alpha (hud weapon selection only) +// SelectionAlpha (hud weapon selection only) +// TextScan (hud weapon selection only) +// +// interpolator: +// Linear +// Accel - starts moving slow, ends fast +// Deaccel - starts moving fast, ends slow +// +// RunEvent +// starts another even running at the specified time +// +// StopEvent +// stops another event that is current running at the specified time +// +// StopAnimation +// stops all animations refering to the specified variable in the specified panel +// +// StopPanelAnimations +// stops all active animations operating on the specified panel +// +// +// Useful game console commands: +// cl_Animationinfo or +// displays all the animatable variables for the hud element +// + + +event LevelInit +{ +} + +event OpenWeaponSelectionMenu +{ + StopEvent CloseWeaponSelectionMenu 0.0 + StopEvent WeaponPickup 0.0 + StopEvent FadeOutWeaponSelectionMenu 0.0 + + // make the display visible + Animate HudWeaponSelection Alpha "128" Linear 0.0 0.1 + Animate HudWeaponSelection SelectionAlpha "255" Linear 0.0 0.1 + Animate HudWeaponSelection FgColor "FgColor" Linear 0.0 0.1 + Animate HudWeaponSelection TextColor "BrightFg" Linear 0.0 0.1 + Animate HudWeaponSelection TextScan "1" Linear 0.0 0.1 +} + +event CloseWeaponSelectionMenu +{ + // hide the whole thing near immediately + Animate HudWeaponSelection FgColor "0 0 0 0" Linear 0.0 0.1 + Animate HudWeaponSelection TextColor "0 0 0 0" Linear 0.0 0.1 + Animate HudWeaponSelection Alpha "0" Linear 0.0 0.1 + Animate HudWeaponSelection SelectionAlpha "0" Linear 0.0 0.1 +} + +event FadeOutWeaponSelectionMenu +{ + // slowly hide the whole thing + Animate HudWeaponSelection FgColor "0 0 0 0" Linear 0.0 1.5 + Animate HudWeaponSelection TextColor "0 0 0 0" Linear 0.0 1.5 + Animate HudWeaponSelection Alpha "0" Linear 0.0 1.5 + Animate HudWeaponSelection SelectionAlpha "0" Linear 0.0 1.5 +} + +event SuitAuxPowerMax +{ + // hide the suit power + Animate HudSuitPower BgColor "0 0 0 0" Linear 0.0 0.4 + Animate HudSuitPower AuxPowerColor "0 0 0 0" Linear 0.0 0.4 +} + +event SuitAuxPowerNotMax +{ + // show suit power + Animate HudSuitPower BgColor "BgColor" Linear 0.0 0.4 + Animate HudSuitPower AuxPowerColor "255 220 0 220" Linear 0.0 0.4 +} + +event SuitAuxPowerDecreasedBelow25 +{ + // make color red + Animate HudSuitPower AuxPowerColor "255 0 0 220" Linear 0.0 0.4 +} + +event SuitAuxPowerIncreasedAbove25 +{ + // make colr bright + Animate HudSuitPower AuxPowerColor "255 220 0 220" Linear 0.0 0.4 +} + +event SuitAuxPowerNoItemsActive +{ + // resize the aux power to be the smallest size + Animate HudSuitPower Size "102 26" Linear 0.0 0.4 + Animate HudSuitPower Position "16 400" Linear 0.0 0.4 +// Animate HudSuitPower text_xpos "8" Linear 0.0 0.4 +// Animate HudSuitPower text_ypos "15" Linear 0.0 0.4 +} + +event SuitAuxPowerOneItemActive +{ + // resize the aux power to fit one item + Animate HudSuitPower Size "102 36" Linear 0.0 0.4 + Animate HudSuitPower Position "16 390" Linear 0.0 0.4 +} + +event SuitAuxPowerTwoItemsActive +{ + // resize the aux power to fit two items + Animate HudSuitPower Size "102 46" Linear 0.0 0.4 + Animate HudSuitPower Position "16 380" Linear 0.0 0.4 +} + +event SuitAuxPowerThreeItemsActive +{ + // resize the aux power to fit three items + Animate HudSuitPower Size "102 56" Linear 0.0 0.4 + Animate HudSuitPower Position "16 370" Linear 0.0 0.4 +} + +event SuitFlashlightOn +{ + Animate HudFlashlight TextColor "255 220 0 255" Linear 0.0 0.1 + Animate HudFlashlight TextColor "255 220 0 160" Deaccel 0.1 0.75 + Animate HudFlashlight BgColor "BgColor" Linear 0.0 0.75 +} + +event SuitFlashlightOff +{ + StopEvent SuitFlashlightOn 0.0 + Animate HudFlashlight TextColor "0 0 0 0" Linear 0.0 0.4 + Animate HudFlashlight BgColor "0 0 0 0" Linear 0.0 0.4 +} + +event HudTakeDamageFront +{ +} + +event HudTakeDamageLeft +{ + Animate HudDamageIndicator DmgColorLeft "255 88 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorLeft "255 0 0 200" Linear 0.0 0.3 + Animate HudDamageIndicator DmgColorLeft "255 0 0 0" Deaccel 0.3 0.5 +} + +event HudTakeDamageRight +{ + Animate HudDamageIndicator DmgColorRight "255 88 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgColorRight "255 0 0 200" Linear 0.0 0.3 + Animate HudDamageIndicator DmgColorRight "255 0 0 0" Deaccel 0.3 0.5 +} + +event HudTakeDamageBehind +{ + RunEvent HudTakeDamageLeft 0.0 + RunEvent HudTakeDamageRight 0.0 +} + +event HudTakeDamageHighLeft +{ + Animate HudDamageIndicator DmgHighColorLeft "255 88 0 255" Linear 0.0 0.0 + Animate HudDamageIndicator DmgHighColorLeft "255 0 0 200" Linear 0.0 0.4 + Animate HudDamageIndicator DmgHighColorLeft "255 0 0 0" Deaccel 0.4 2.4 +} + +event HudTakeDamageHighRight +{ + Animate HudDamageIndicator DmgHighColorRight "255 88 0 255" Linear 0.0 0.0 + Animate HudDamageIndicator DmgHighColorRight "255 0 0 200" Linear 0.0 0.4 + Animate HudDamageIndicator DmgHighColorRight "255 0 0 0" Deaccel 0.4 2.4 +} + +event HudTakeDamageHigh +{ + Animate HudDamageIndicator DmgFullscreenColor "255 88 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 200" Linear 0.0 0.4 + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 0" Deaccel 0.4 2.4 +} + +event HudTakeDamageDrown +{ + RunEvent HudTakeDamageBehind 0.0 +} + +event HudTakeDamagePoison +{ + Animate HudDamageIndicator DmgFullscreenColor "255 236 128 240" Linear 0.0 0.0 + Animate HudDamageIndicator DmgFullscreenColor "255 236 128 0" Deaccel 0.4 0.8 +} + +event HudTakeDamageBurn +{ + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 200" Linear 0.0 0.0 + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 0" Deaccel 0.2 0.4 +} + +event HudTakeDamageRadiation +{ + Animate HudDamageIndicator DmgFullscreenColor "255 255 255 128" Deaccel 0.0 0.1 + Animate HudDamageIndicator DmgFullscreenColor "255 255 255 0" Deaccel 0.1 0.4 + RunEvent HudTakeDamageBehind 0.0 +} + +event HudPlayerDeath +{ + StopEvent HealthLoop 0.0 + StopEvent HealthPulse 0.0 + + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 96" Deaccel 0.1 0.2 + Animate HudDamageIndicator DmgFullscreenColor "255 0 0 255" Deaccel 0.3 4.0 +} + +event HealthIncreasedAbove20 +{ + StopEvent HealthLoop 0.0 + StopEvent HealthPulse 0.0 + StopEvent HealthLow 0.0 + + Animate HudHealth BgColor "BgColor" Linear 0.0 0.0 + + Animate HudHealth TextColor "FgColor" Linear 0.0 0.04 + Animate HudHealth FgColor "FgColor" Linear 0.0 0.03 + + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 +} + +event HealthIncreasedBelow20 +{ + Animate HudHealth FgColor "BrightFg" Linear 0.0 0.25 + Animate HudHealth FgColor "FgColor" Linear 0.3 0.75 + + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 +} + +event SuitPowerIncreasedAbove20 +{ + StopEvent SuitLoop 0.0 + StopEvent SuitPulse 0.0 + StopEvent SuitPowerZero 0.0 + + Animate HudSuit Alpha "255" Linear 0.0 0.0 + + Animate HudSuit BgColor "BgColor" Linear 0.0 0.0 + + Animate HudSuit TextColor "FgColor" Linear 0.0 0.05 + Animate HudSuit FgColor "FgColor" Linear 0.0 0.05 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 +} + + +event SuitPowerIncreasedBelow20 +{ + StopEvent SuitPowerZero 0.0 + Animate HudSuit Alpha "255" Linear 0.0 0.0 + + Animate HudSuit FgColor "BrightFg" Linear 0.0 0.25 + Animate HudSuit FgColor "FgColor" Linear 0.3 0.75 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 +} + +event SuitPowerZero +{ + StopEvent SuitLoop 0.0 + StopEvent SuitPulse 0.0 + StopEvent SuitArmorLow 0.0 + StopEvent SuitDamageTaken 0.0 + + Animate HudSuit Alpha "0" Linear 0.0 0.4 +} + +event TestMovement +{ + Animate HudHealth Position "256 120" Linear 0.0 2.0 + Animate HudHealth Size "128 24" Linear 0.0 1.5 +} + +event HealthDamageTaken +{ + Animate HudHealth FgColor "BrightFg" Linear 0.0 0.25 + Animate HudHealth FgColor "FgColor" Linear 0.3 0.75 + + Animate HudHealth Blur "3" Linear 0.0 0.1 + Animate HudHealth Blur "0" Deaccel 0.1 2.0 + + Animate HudHealth TextColor "BrightFg" Linear 0.0 0.1 + Animate HudHealth TextColor "FgColor" Deaccel 0.1 1.2 +} + +event SuitDamageTaken +{ + Animate HudSuit FgColor "BrightFg" Linear 0.0 0.25 + Animate HudSuit FgColor "FgColor" Linear 0.3 0.75 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 + + Animate HudSuit TextColor "BrightFg" Linear 0.0 0.1 + Animate HudSuit TextColor "FgColor" Deaccel 0.1 1.2 +} + +// health has been damaged to below 20% +event HealthLow +{ + StopEvent HealthDamageTaken 0.0 + StopEvent HealthPulse 0.0 + StopEvent HealthLoop 0.0 + + Animate HudHealth BgColor "DamagedBg" Linear 0.0 0.1 + Animate HudHealth BgColor "BgColor" Deaccel 0.1 1.75 + + Animate HudHealth FgColor "BrightFg" Linear 0.0 0.2 + Animate HudHealth FgColor "DamagedFg" Linear 0.2 1.2 + + Animate HudHealth TextColor "BrightFg" Linear 0.0 0.1 + Animate HudHealth TextColor "DamagedFg" Linear 0.1 1.2 + + Animate HudHealth Blur "5" Linear 0.0 0.1 + Animate HudHealth Blur "3" Deaccel 0.1 0.9 + + RunEvent HealthPulse 1.0 +} + +event HealthPulse +{ + Animate HudHealth Blur "5" Linear 0.0 0.1 + Animate HudHealth Blur "2" Deaccel 0.1 0.8 + Animate HudHealth TextColor "BrightDamagedFg" Linear 0.0 0.1 + Animate HudHealth TextColor "DamagedFg" Deaccel 0.1 0.8 + Animate HudHealth BgColor "100 0 0 80" Linear 0.0 0.1 + Animate HudHealth BgColor "BgColor" Deaccel 0.1 0.8 + + RunEvent HealthLoop 0.8 +} + +// call to loop HealthPulse +event HealthLoop +{ + RunEvent HealthPulse 0.0 +} + + +// suit armor has been damaged to below 20% +event SuitArmorLow +{ + StopEvent SuitDamageTaken 0.0 + StopEvent SuitPulse 0.0 + StopEvent SuitLoop 0.0 + +// removing this effect -- matching it to the event for normal suit damage +// so, there will be no special indication (redness, flashing) +// in the hud that the suit armor is low + +// Animate HudSuit BgColor "DamagedBg" Linear 0.0 0.1 +// Animate HudSuit BgColor "BgColor" Deaccel 0.1 1.75 + + Animate HudSuit FgColor "BrightFg" Linear 0.0 0.25 + Animate HudSuit FgColor "FgColor" Linear 0.3 0.75 + + Animate HudSuit Blur "3" Linear 0.0 0.1 + Animate HudSuit Blur "0" Deaccel 0.1 2.0 + + Animate HudSuit TextColor "BrightFg" Linear 0.0 0.1 + Animate HudSuit TextColor "FgColor" Deaccel 0.1 1.2 + +// RunEvent SuitPulse 1.0 +} + +event SuitPulse +// this even no longer gets called +{ + Animate HudSuit Blur "5" Linear 0.0 0.1 + Animate HudSuit Blur "2" Deaccel 0.1 0.8 + Animate HudSuit TextColor "BrightDamagedFg" Linear 0.0 0.1 + Animate HudSuit TextColor "DamagedFg" Deaccel 0.1 0.8 + Animate HudSuit BgColor "100 0 0 80" Linear 0.0 0.1 + Animate HudSuit BgColor "BgColor" Deaccel 0.1 0.8 + RunEvent SuitLoop 0.8 +} + +event SuitLoop +{ +// this event no longer gets called + RunEvent SuitPulse 0.0 +} + +// ammo has been picked up +event AmmoIncreased +{ + Animate HudAmmo FgColor "BrightFg" Linear 0.0 0.15 + Animate HudAmmo FgColor "FgColor" Deaccel 0.15 1.5 + Animate HudAmmo Blur "5" Linear 0.0 0.0 + Animate HudAmmo Blur "0" Accel 0.01 1.5 +} + +// ammo has been decreased, but there is still some remaining +event AmmoDecreased +{ + StopEvent AmmoIncreased 0.0 + + Animate HudAmmo Blur "7" Linear 0.0 0.0 + Animate HudAmmo Blur "0" Deaccel 0.1 1.5 + + Animate HudAmmo TextColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmo TextColor "FgColor" Deaccel 0.1 0.75 +} + +// primary ammo is zero +event AmmoEmpty +{ + Animate Hudammo FgColor "BrightDamagedFg" Linear 0.0 0.2 + Animate Hudammo FgColor "DamagedFg" Accel 0.2 1.2 +} + +// ammo2 is the total ammo for a weapon that uses clip ammo +event Ammo2Increased +{ + Animate Hudammo ammo2color "BrightFg" Linear 0.0 0.2 + Animate Hudammo ammo2color "FgColor" Accel 0.2 1.2 +} + +// total ammo has been decreased, but there is still some remaining +event Ammo2Decreased +{ + Animate Hudammo ammo2color "BrightFg" Linear 0.0 0.2 + Animate Hudammo ammo2color "FgColor" Accel 0.2 1.2 +} + +// total ammo is zero +event Ammo2Empty +{ + Animate Hudammo ammo2color "BrightDamagedFg" Linear 0.0 0.2 + Animate Hudammo ammo2color "DamagedFg" Accel 0.2 1.2 +} + +event AmmoSecondaryIncreased +{ + Animate HudAmmoSecondary FgColor "BrightFg" Linear 0.0 0.15 + Animate HudAmmoSecondary FgColor "FgColor" Deaccel 0.15 1.5 + Animate HudAmmoSecondary Blur "5" Linear 0.0 0.0 + Animate HudAmmoSecondary Blur "0" Accel 0.01 1.5 +} + +event AmmoSecondaryDecreased +{ + StopEvent AmmoSecondaryIncreased 0.0 + + Animate HudAmmoSecondary Blur "7" Linear 0.0 0.0 + Animate HudAmmoSecondary Blur "0" Deaccel 0.1 1.5 + + Animate HudAmmoSecondary TextColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmoSecondary TextColor "FgColor" Deaccel 0.1 0.75 +} + +event AmmoSecondaryEmpty +{ + Animate HudAmmoSecondary FgColor "BrightDamagedFg" Linear 0.0 0.2 + Animate HudAmmoSecondary FgColor "DamagedFg" Accel 0.2 1.2 + Animate HudAmmoSecondary Blur "7" Linear 0.0 0.0 + Animate HudAmmoSecondary Blur "0" Deaccel 0.1 1.5 + +} + +// current weapon has been changed +event WeaponChanged +{ + Animate HudAmmo BgColor "250 220 0 80" Linear 0.0 0.1 + Animate HudAmmo BgColor "BgColor" Deaccel 0.1 1.0 + Animate HudAmmo FgColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmo FgColor "FgColor" Linear 0.2 1.5 +} + +// ran if we just changed to a weapon that needs clip ammo +event WeaponUsesClips +{ + Animate HudAmmo Position "r150 432" Deaccel 0.0 0.4 + Animate HudAmmo Size "132 36" Deaccel 0.0 0.4 +} + +// ran if we just changed to a weapon that does not use clip ammo +event WeaponDoesNotUseClips +{ + Animate HudAmmo Position "r118 432" Deaccel 0.0 0.4 + Animate HudAmmo Size "100 36" Deaccel 0.0 0.4 +} + +event WeaponUsesSecondaryAmmo +{ + StopAnimation HudAmmo Position 0.0 + StopAnimation HudAmmo Size 0.0 + StopPanelAnimations HudAmmoSecondary 0.0 + + Animate HudAmmoSecondary BgColor "250 220 0 60" Linear 0.0 0.1 + Animate HudAmmoSecondary BgColor "BgColor" Deaccel 0.1 1.0 + Animate HudAmmoSecondary FgColor "BrightFg" Linear 0.0 0.1 + Animate HudAmmoSecondary FgColor "FgColor" Linear 0.2 1.5 + Animate HudAmmoSecondary Alpha 255 Linear 0.0 0.1 + + Animate HudAmmo Position "r222 432" Deaccel 0.0 0.5 + Animate HudAmmo Size "132 36" Deaccel 0.0 0.4 +} + +event WeaponDoesNotUseSecondaryAmmo +{ + StopPanelAnimations HudAmmoSecondary 0.0 + Animate HudAmmoSecondary FgColor "0 0 0 0" Linear 0.0 0.4 + Animate HudAmmoSecondary BgColor "0 0 0 0" Linear 0.0 0.4 + Animate HudAmmoSecondary Alpha 0 Linear 0.0 0.1 +} + +event CraneMagnetFlash +{ + Animate HudCraneMagnet TextColor "255 220 0 255" Linear 0.0 0.1 + Animate HudCraneMagnet TextColor "255 220 0 160" Deaccel 0.1 0.3 + Animate HudCraneMagnet TextColor "255 170 0 220" Deaccel 0.4 0.3 + Animate HudCraneMagnet TextColor "255 220 0 255" Linear 0.8 0.2 +} + +event HintMessageShow +{ + // show the hints + Animate HudHintDisplay Alpha 255 Linear 0.0 0.5 + + // flash text + Animate HudHintDisplay FgColor "FgColor" Linear 0.0 0.01 + Animate HudHintDisplay FgColor "255 220 0 255" Linear 0.5 0.2 + Animate HudHintDisplay FgColor "FgColor" Linear 0.7 0.2 + Animate HudHintDisplay FgColor "255 220 0 255" Linear 1.5 0.2 + Animate HudHintDisplay FgColor "FgColor" Linear 1.7 0.2 + + // hide the panel after a while + Animate HudHintDisplay Alpha 0 Linear 12.0 1.0 +} + +event HintMessageHide +{ + Animate HudHintDisplay Alpha 0 Linear 0.0 0.5 +} + +event SquadMemberAdded +{ + StopEvent SquadMemberDied 0.0 + StopEvent SquadMemberLeft 0.0 + + // add in the squad member, brighter then normal color + Animate HudSquadStatus LastMemberColor "255 220 0 255" Linear 0.0 0.3 + Animate HudSquadStatus LastMemberColor "255 220 0 160" Linear 0.3 0.3 +} + +event SquadMemberLeft +{ + StopEvent SquadMemberDied 0.0 + StopEvent SquadMemberAdded 0.0 + + // fade out the icon + Animate HudSquadStatus LastMemberColor "255 220 0 0" Linear 0.0 0.5 +} + +event SquadMemberDied +{ + StopEvent SquadMemberAdded 0.0 + StopEvent SquadMemberLeft 0.0 + + // flash red, hold, then disappear + Animate HudSquadStatus LastMemberColor "255 0 0 255" Linear 0.0 0.5 + Animate HudSquadStatus LastMemberColor "255 0 0 0" Linear 2.0 2.0 +} + +event SquadMembersFollowing +{ + StopEvent SquadMembersStationed 0.0 + Animate HudSquadStatus SquadTextColor "255 220 0 255" Linear 0.0 0.2 + Animate HudSquadStatus SquadTextColor "255 220 0 160" Linear 0.2 0.4 +} + +event SquadMembersStationed +{ + StopEvent SquadMembersFollowing 0.0 + Animate HudSquadStatus SquadTextColor "255 220 0 160" Linear 0.5 0.5 +} + +event PoisonDamageTaken +{ + Animate HudPoisonDamageIndicator Alpha 255 Linear 0.0 1.0 + RunEvent PoisonLoop 0.0 +} + +event PoisonDamageCured +{ + StopEvent PoisonDamageTaken 0.0 + StopEvent PoisonLoop 0.0 + StopEvent PoisonPulse 0.0 + Animate HudPoisonDamageIndicator Alpha 0 Linear 0.0 1.0 +} + +event PoisonPulse +{ + Animate HudPoisonDamageIndicator TextColor "BrightFg" Linear 0.0 0.1 + Animate HudPoisonDamageIndicator TextColor "FgColor" Deaccel 0.1 0.8 + Animate HudPoisonDamageIndicator BgColor "100 0 0 80" Linear 0.0 0.1 + Animate HudPoisonDamageIndicator BgColor "BgColor" Deaccel 0.1 0.8 + + RunEvent PoisonLoop 0.8 +} + +// call to loop PoisonLoop +event PoisonLoop +{ + RunEvent PoisonPulse 0.0 +} diff --git a/scripts/_hl2_hud_textures.txt b/scripts/_hl2_hud_textures.txt new file mode 100644 index 0000000..c23f812 --- /dev/null +++ b/scripts/_hl2_hud_textures.txt @@ -0,0 +1,434 @@ +"sprites/640_hud" +{ + TextureData + { + "selection" + { + "file" "sprites/640hud3" + "x" "0" + "y" "180" + "width" "170" + "height" "45" + } + "dmg_bio" + { + "file" "sprites/d_icons" + "x" "42" + "y" "38" + "width" "42" + "height" "38" + } + "dmg_poison" + { + "file" "sprites/640hud8" + "x" "128" + "y" "0" + "width" "64" + "height" "64" + } + "dmg_chem" + { + "file" "sprites/640hud8" + "x" "0" + "y" "0" + "width" "64" + "height" "64" + } + "dmg_cold" + { + "file" "sprites/640hud9" + "x" "64" + "y" "0" + "width" "64" + "height" "64" + } + "dmg_drown" + { + "file" "sprites/d_icons" + "x" "42" + "y" "0" + "width" "42" + "height" "38" + } + "dmg_heat" + { + "file" "sprites/d_icons" + "x" "0" + "y" "0" + "width" "42" + "height" "38" + } + "dmg_gas" + { + "file" "sprites/640hud9" + "x" "0" + "y" "0" + "width" "64" + "height" "64" + } + "dmg_rad" + { + "file" "sprites/d_icons" + "x" "0" + "y" "38" + "width" "42" + "height" "38" + } + "dmg_shock" + { + "file" "sprites/d_icons" + "x" "84" + "y" "0" + "width" "42" + "height" "38" + } + "arrow" + { + "file" "sprites/arrow" + "x" "0" + "y" "0" + "width" "32" + "height" "32" + } + "ammo_label" + { + "file" "sprites/hud1" + "x" "120" + "y" "28" + "width" "40" + "height" "14" + } + "health_label" + { + "file" "sprites/hud1" + "x" "160" + "y" "28" + "width" "50" + "height" "14" + } + "battery_label" + { + "file" "sprites/hud1" + "x" "220" + "y" "28" + "width" "40" + "height" "14" + } + "train_back" + { + "file" "sprites/640hud5" + "x" "170" + "y" "0" + "width" "72" + "height" "72" + } + "train_stop" + { + "file" "sprites/640hud5" + "x" "170" + "y" "72" + "width" "72" + "height" "72" + } + "train_forward1" + { + "file" "sprites/640hud5" + "x" "170" + "y" "144" + "width" "72" + "height" "72" + } + "train_forward2" + { + "file" "sprites/640hud6" + "x" "170" + "y" "0" + "width" "72" + "height" "72" + } + "train_forward3" + { + "file" "sprites/640hud6" + "x" "170" + "y" "72" + "width" "72" + "height" "72" + } + "autoaim_c" + { + "file" "sprites/crosshairs" + "x" "96" + "y" "0" + "width" "24" + "height" "24" + } + "title_half" + { + "file" "sprites/640hud4" + "x" "0" + "y" "226" + "width" "256" + "height" "30" + } + "title_life" + { + "file" "sprites/640hud5" + "x" "0" + "y" "226" + "width" "220" + "height" "30" + } + "d_crowbar" + { + "file" "sprites/640hud1" + "x" "192" + "y" "0" + "width" "48" + "height" "16" + } + "d_9mmhandgun" + { + "file" "sprites/640hud1" + "x" "192" + "y" "16" + "width" "32" + "height" "16" + } + "d_357" + { + "file" "sprites/640hud1" + "x" "192" + "y" "32" + "width" "32" + "height" "16" + } + "d_9mmAR" + { + "file" "sprites/640hud1" + "x" "192" + "y" "48" + "width" "48" + "height" "16" + } + "d_shotgun" + { + "file" "sprites/640hud1" + "x" "192" + "y" "64" + "width" "48" + "height" "16" + } + "d_bolt" + { + "file" "sprites/640hud1" + "x" "192" + "y" "80" + "width" "48" + "height" "16" + } + "d_crossbow" + { + "file" "sprites/640hud1" + "x" "192" + "y" "80" + "width" "48" + "height" "16" + } + "d_rpg_rocket" + { + "file" "sprites/640hud1" + "x" "192" + "y" "96" + "width" "48" + "height" "16" + } + "d_gauss" + { + "file" "sprites/640hud1" + "x" "192" + "y" "112" + "width" "32" + "height" "16" + } + "d_egon" + { + "file" "sprites/640hud1" + "x" "192" + "y" "128" + "width" "32" + "height" "16" + } + "d_hornet" + { + "file" "sprites/640hud1" + "x" "192" + "y" "144" + "width" "48" + "height" "16" + } + "d_grenade" + { + "file" "sprites/640hud1" + "x" "192" + "y" "160" + "width" "32" + "height" "16" + } + "d_satchel" + { + "file" "sprites/640hud1" + "x" "192" + "y" "176" + "width" "32" + "height" "16" + } + "d_tripmine" + { + "file" "sprites/640hud1" + "x" "192" + "y" "192" + "width" "32" + "height" "16" + } + "d_snark" + { + "file" "sprites/640hud1" + "x" "192" + "y" "208" + "width" "32" + "height" "16" + } + "d_skull" + { + "file" "sprites/640hud1" + "x" "192" + "y" "224" + "width" "32" + "height" "16" + } + "d_tracktrain" + { + "file" "sprites/640hud1" + "x" "192" + "y" "240" + "width" "32" + "height" "16" + } + "microphone" + { + "file" "sprites/640hud1" + "x" "0" + "y" "225" + "width" "24" + "height" "24" + } + "item_battery" + { + "font" "WeaponIcons" + "character" "*" + } + "item_healthkit" + { + "font" "WeaponIcons" + "character" "+" + } + "item_longjump" + { + "file" "sprites/640hud2" + "x" "176" + "y" "96" + "width" "44" + "height" "44" + } + "grenade" + { + "file" "sprites/640hud7" + "x" "48" + "y" "96" + "width" "24" + "height" "24" + } + "crosshair" + { + "file" "sprites/qi_center" + "x" "0" + "y" "0" + "width" "40" + "height" "40" + } + "crosshair_left" + { + "font" "QuickInfo" + "character" "(" + } + "crosshair_right" + { + "font" "QuickInfo" + "character" ")" + } + "crosshair_left_full" + { + "font" "QuickInfo" + "character" "[" + } + "crosshair_right_full" + { + "font" "QuickInfo" + "character" "]" + } + "crosshair_left_empty" + { + "font" "QuickInfo" + "character" "{" + } + "crosshair_right_empty" + { + "font" "QuickInfo" + "character" "}" + } + "crosshair_default" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + "viewhair" + { + "file" "sprites/hud/v_crosshair2" + "x" "0" + "y" "0" + "width" "32" + "height" "32" + } + "gunhair" + { + "file" "sprites/hud/v_crosshair1" + "x" "0" + "y" "0" + "width" "32" + "height" "32" + } + + "progress_bar" + { + "file" "sprites/hud1" + "x" "238" + "y" "0" + "width" "10" + "height" "28" + } + + "plushair" + { + "font" "Crosshairs" + "character" "Q" +// "file" "sprites/crosshairs" +// "x" "0" +// "y" "24" +// "width" "24" +// "height" "24" + } + } +} diff --git a/scripts/decals_subrect.txt b/scripts/decals_subrect.txt new file mode 100644 index 0000000..d65a6cd --- /dev/null +++ b/scripts/decals_subrect.txt @@ -0,0 +1,413 @@ +// Decal definitions, format is +// decalname weight +// where weight is used to randomly selected a decal to apply from within the group + +// This is just an entry to map material types to "impact.xxx" +"TranslationData" +{ + "-" "" // don't decal this surface + + "C" "Impact.Concrete" + "M" "Impact.Metal" + "W" "Impact.Wood" + "Y" "Impact.Glass" + "F" "Impact.Flesh" + "B" "Impact.BloodyFlesh" + "H" "Impact.AlienFlesh" + "A" "Impact.Antlion" + "N" "Impact.Sand" + "V" "Impact.Metal" + +// These might be translated in the future + //CHAR_TEX_DIRT 'D' + //CHAR_TEX_GRATE 'G' + //CHAR_TEX_TILE 'T' + //CHAR_TEX_SLOSH 'S' + //CHAR_TEX_COMPUTER 'P' + //CHAR_TEX_CLIP 'I' + //CHAR_TEX_ANTLION 'A' + //CHAR_TEX_FOLIAGE 'O' +} + +"Impact.Concrete" +{ + "decals/concrete/shot1_subrect" "1" + "decals/concrete/shot2_subrect" "1" + "decals/concrete/shot3_subrect" "1" + "decals/concrete/shot4_subrect" "1" + "decals/concrete/shot5_subrect" "1" +} + +"Impact.Metal" +{ + "decals/metal/shot1_subrect" "1" + "decals/metal/shot2_subrect" "1" + "decals/metal/shot3_subrect" "1" + "decals/metal/shot4_subrect" "1" + "decals/metal/shot5_subrect" "1" +} + +"Impact.Wood" +{ + "decals/wood/shot1_subrect" "1" + "decals/wood/shot2_subrect" "1" + "decals/wood/shot3_subrect" "1" + "decals/wood/shot4_subrect" "1" + "decals/wood/shot5_subrect" "1" +} + +"Impact.Glass" +{ + "decals/glass/shot1_subrect" "1" + "decals/glass/shot2_subrect" "1" + "decals/glass/shot3_subrect" "1" + "decals/glass/shot4_subrect" "1" + "decals/glass/shot5_subrect" "1" +} + + +"Impact.Flesh" +{ + "decals/flesh/blood1_subrect" "1" + "decals/flesh/blood2_subrect" "1" + "decals/flesh/blood3_subrect" "1" + "decals/flesh/blood4_subrect" "1" + "decals/flesh/blood5_subrect" "1" +} + + +"Impact.BloodyFlesh" +{ + "decals/bloodyflesh/blood1_subrect" "1" + "decals/bloodyflesh/blood2_subrect" "1" + "decals/bloodyflesh/blood3_subrect" "1" + "decals/bloodyflesh/blood4_subrect" "1" + "decals/bloodyflesh/blood5_subrect" "1" +} + +"Impact.AlienFlesh" +{ + "decals/alienflesh/shot1_subrect" "1" + "decals/alienflesh/shot2_subrect" "1" + "decals/alienflesh/shot3_subrect" "1" + "decals/alienflesh/shot4_subrect" "1" + "decals/alienflesh/shot5_subrect" "1" +} + +"Impact.Antlion" +{ + "decals/antlion/shot1_subrect" "1" + "decals/antlion/shot2_subrect" "1" + "decals/antlion/shot3_subrect" "1" + "decals/antlion/shot4_subrect" "1" + "decals/antlion/shot5_subrect" "1" +} + +// Sand does not have model versions of the decals. +"Impact.Sand" +{ + "decals/sand/shot1_subrect" "1" + "decals/sand/shot2_subrect" "1" + "decals/sand/shot3_subrect" "1" + "decals/sand/shot4_subrect" "1" +} + +"Scorch" +{ + "decals/scorch1_subrect" "1" + "decals/scorch2_subrect" "1" +} + +"Blood" +{ + "decals/blood1_subrect" "1" + "decals/blood2_subrect" "1" + "decals/blood3_subrect" "1" + "decals/blood4_subrect" "1" + "decals/blood5_subrect" "1" + "decals/blood6_subrect" "1" +} + +"YellowBlood" +{ + "decals/yblood1_subrect" "1" + "decals/yblood2_subrect" "1" + "decals/yblood3_subrect" "1" + "decals/yblood4_subrect" "1" + "decals/yblood5_subrect" "1" + "decals/yblood6_subrect" "1" +} + +"GlassBreak" +{ + "decals/break1_subrect" "1" + "decals/break2_subrect" "1" + "decals/break3_subrect" "1" +} + +"BigShot" +{ + "decals/bigshot1_subrect" "1" + "decals/bigshot2_subrect" "1" + "decals/bigshot3_subrect" "1" + "decals/bigshot4_subrect" "1" + "decals/bigshot5_subrect" "1" +} + +"BulletProof" +{ + "decals/bproof1_subrect" "1" +} + +"SmallScorch" +{ + "decals/smscorch1_subrect" "1" + "decals/smscorch2_subrect" "1" + "decals/smscorch3_subrect" "1" +} + +"FadingScorch" +{ + "decals/scorchfade_subrect" "1" +} + +"BeerSplash" +{ + "decals/beersplash_subrect" "1" +} + +"ManhackCut" +{ + "decals/manhackcut_subrect" "1" + "decals/manhackcut2_subrect" "1" + "decals/manhackcut3_subrect" "1" +} + +"RedGlowFade" +{ + "decals/redglowfade" "1" +} + +"CombineBallFade" +{ + "decals/combineballfade" "1" +} + +"CombineBallFade2" +{ + "decals/combineballfade2" "1" +} + +"CombineBallFade3" +{ + "decals/combineballfade3" "1" +} + +"PlasmaGlowFade" +{ + "decals/plasmaglowfade" "1" +} + +"Splash" +{ + "decals/decalsplash" "1" +} + +"ExplosiveGunshot" +{ + "decals/concrete/shot1_subrect" "1" +} + +"Fire" +{ + "sprites/fire_floor" "1" +} + +// Currently a model version of this decal doesn't exist. +"Antion.Unburrow" +{ + "decals/unburrow_subrect" "1" +} + +"Extinguish" +{ + "decals/extinguish1_subrect" "1" + "decals/extinguish2_subrect" "1" +} + +// Currently a model version of these decals don't exist. +"Splash.Large" +{ + "decals/splash1_subrect" "1" + "decals/splash2_subrect" "1" + "decals/splash3_subrect" "1" +} + +// Currently a model version of these decals don't exist. +"Splash.Small" +{ + "decals/splash1_subrect" "1" + "decals/splash1_subrect" "1" + "decals/splash1_subrect" "1" +} + +// Currently a model version of this decal doesn't exit. +"Rollermine.Crater" +{ + "decals/rollermine_crater_subrect" "1" +} + +"BirdPoop" +{ + "decals/decal_birdpoop001_subrect" "1" + "decals/decal_birdpoop002_subrect" "1" + "decals/decal_birdpoop003_subrect" "1" + "decals/decal_birdpoop004_subrect" "1" +} + +"PaintSplatBlue" +{ + "decals/decal_paintsplatterblue001_subrect" "1" +} + +"PaintSplatGreen" +{ + "decals/decal_paintsplattergreen001_subrect" "1" +} + +"PaintSplatPink" +{ + "decals/decal_paintsplatterpink001_subrect" "1" +} + +"LaserBurn" +{ + "decals/laserburn1" "1" + "decals/laserburn2" "1" + "decals/laserburn3" "1" +} + +// Currently a model version doesn't exist and it is not in a decal page. +"Antlion.Splat" +{ + "decals/antlion/antlion_splat" "1" +} + +"Models" +{ + // World Model specific decal precache. + "decals/concrete/shot1" "1" + "decals/concrete/shot2" "1" + "decals/concrete/shot3" "1" + "decals/concrete/shot4" "1" + "decals/concrete/shot5" "1" + "decals/metal/shot1" "1" + "decals/metal/shot2" "1" + "decals/metal/shot3" "1" + "decals/metal/shot4" "1" + "decals/metal/shot5" "1" + "decals/wood/shot1" "1" + "decals/wood/shot2" "1" + "decals/wood/shot3" "1" + "decals/wood/shot4" "1" + "decals/wood/shot5" "1" + "decals/glass/shot1" "1" + "decals/glass/shot2" "1" + "decals/glass/shot3" "1" + "decals/glass/shot4" "1" + "decals/glass/shot5" "1" + "decals/flesh/blood1" "1" + "decals/flesh/blood2" "1" + "decals/flesh/blood3" "1" + "decals/flesh/blood4" "1" + "decals/flesh/blood5" "1" + "decals/bloodyflesh/blood1" "1" + "decals/bloodyflesh/blood2" "1" + "decals/bloodyflesh/blood3" "1" + "decals/bloodyflesh/blood4" "1" + "decals/bloodyflesh/blood5" "1" + "decals/alienflesh/shot1" "1" + "decals/alienflesh/shot2" "1" + "decals/alienflesh/shot3" "1" + "decals/alienflesh/shot4" "1" + "decals/alienflesh/shot5" "1" + "decals/antlion/shot1" "1" + "decals/antlion/shot2" "1" + "decals/antlion/shot3" "1" + "decals/antlion/shot4" "1" + "decals/antlion/shot5" "1" + "decals/scorch1" "1" + "decals/scorch2" "1" + "decals/blood1" "1" + "decals/blood2" "1" + "decals/blood3" "1" + "decals/blood4" "1" + "decals/blood5" "1" + "decals/blood6" "1" + "decals/blood7" "1" + "decals/blood8" "1" + "decals/yblood1" "1" + "decals/yblood2" "1" + "decals/yblood3" "1" + "decals/yblood4" "1" + "decals/yblood5" "1" + "decals/yblood6" "1" + "decals/break1" "1" + "decals/break2" "1" + "decals/break3" "1" + "decals/bigshot1" "1" + "decals/bigshot2" "1" + "decals/bigshot3" "1" + "decals/bigshot4" "1" + "decals/bigshot5" "1" + "decals/bproof1" "1" + "decals/smscorch1" "1" + "decals/smscorch2" "1" + "decals/smscorch3" "1" + "decals/scorchfade" "1" + "decals/beersplash" "1" + "decals/manhackcut" "1" + "decals/manhackcut2" "1" + "decals/manhackcut3" "1" + "decals/unburrow" "1" + "decals/extinguish1" "1" + "decals/extinguish2" "1" + "decals/splash1" "1" + "decals/splash2" "1" + "decals/splash3" "1" + "decals/rollermine_crater" "1" + "decals/decal_birdpoop001" "1" + "decals/decal_birdpoop002" "1" + "decals/decal_birdpoop003" "1" + "decals/decal_birdpoop004" "1" + "decals/decal_paintsplatterblue001" "1" + "decals/decal_paintsplattergreen001" "1" + "decals/decal_paintsplatterpink001" "1" + "decals/decal_paintsplatterblue_model" "1" + "decals/decal_paintsplattergreen_model" "1" + "decals/decal_paintsplatterpink_model" "1" + "decals/antlion/antlion_splat" "1" + + // Model specific decal precache. + "decals/beersplashmodel" "1" + "decals/bigshot1model" "1" + "decals/bigshot2model" "1" + "decals/bigshot3model" "1" + "decals/bigshot4model" "1" + "decals/bigshot5model" "1" + "decals/bproof1model" "1" + "decals/break1model" "1" + "decals/break2model" "1" + "decals/break3model" "1" + "decals/decal_paintsplatterblue_model" "1" + "decals/decal_paintsplattergreen_model" "1" + "decals/decal_paintsplatterpink_model" "1" + "decals/extinguish1model" "1" + "decals/extinguish2model" "1" + "decals/scorch1model" "1" + "decals/scorch2model" "1" + "decals/scorchfademodel" "1" + "decals/smscorch1model" "1" + "decals/smscorch2model" "1" + "decals/smscorch3model" "1" +} \ No newline at end of file diff --git a/scripts/dsp_presets.txt b/scripts/dsp_presets.txt new file mode 100644 index 0000000..0505023 --- /dev/null +++ b/scripts/dsp_presets.txt @@ -0,0 +1,1198 @@ +// DSP preset definition file. + +///////////////////////////////////// +// WARNING: do not edit this file! // +///////////////////////////////////// + +// console "dsp_reload" reloads while engine running + +// PROCESSOR TYPE: +// NULL 0 // pass through - must be 0 +// DLY 1 // simple feedback reverb +// RVA 2 // parallel reverbs +// FLT 3 // lowpass or highpass filter +// CRS 4 // chorus NOT TESTED +// PTC 5 // pitch shifter NOT TESTED (UPDATE: DOES NOT INTEGRATE WITH NEW SOUND LENGTH CODE. DO NOT USE.) +// ENV 6 // adsr envelope NOT TESTED +// LFO 7 // lfo +// EFO 8 // envelope follower/gate +// MDY 9 // mod delay +// DFR 10 // diffusor - n series allpass delays +// AMP 11 // amplifier with distortion + +// FILTER TYPE: +// LP 0 // lowpass filter +// HP 1 // highpass filter +// BP 2 // bandpass filter + +// FILTER QUALITY: +// LO 0 // quality of filter or reverb. Must be 0,1,2,3. +// MED 1 +// HI 2 +// VHI 3 + +// DELAY TYPE: +// PLAIN 0 // single feedback loop +// ALLPASS 1 // feedback and feedforward loop - flat frequency response (diffusor) +// LOWPASS 2 // lowpass filter in feedback loop +// DLINEAR 3 // linear delay, no feedback, unity gain +// FLINEAR 4 // linear delay with lowpass filter and output gain +// LOWPASS_4TAP 5 // lowpass filter in feedback loop, 4 delay taps +// PLAIN_4TAP 6 // single feedback loop, 4 delay taps + +// LFO TYPE: +// SIN 0 // sine wav +// TRI 1 // triangle wav +// SQR 2 // square wave, 50% duty cycle +// SAW 3 // forward saw wav +// RND 4 // random wav +// LOG_IN 5 // logarithmic fade in NOT TESTED +// LOG_OUT 6 // logarithmic fade out NOT TESTED +// LIN_IN 7 // linear fade in +// LIN_OUT 8 // linear fade out + +// ENVELOPE TYPE: +// LIN 0 // linear a,d,s,r +// EXP 1 // exponential a,d,s,r (IGNORED) + +// PRESET CONFIGURATION TYPE: +// SIMPLE 0 // optimized +// LINEAR 1 // optimized +// PARALLEL2 5 +// PARALLEL4 6 +// PARALLEL5 7 +// FEEDBACK 8 +// FEEDBACK3 9 +// FEEDBACK4 10 +// MOD 11 // NOT TESTED +// MOD2 12 // NOT TESTED +// MOD3 13 // NOT TESTED + +// PSET_SIMPLE 0 +// x(n)--->P(0)--->y(n) + +// PSET_LINEAR 1 +// x(n)--->P(0)-->P(1)-->...P(m)--->y(n) + +// PSET_PARALLEL2 5 +// x(n)--->P(0)-->(+)-->y(n) +// ^ +// | +// x(n)--->P(1)----- + +// PSET_PARALLEL4 6 +// x(n)--->P(0)-->P(1)-->(+)-->y(n) +// ^ +// | +// x(n)--->P(2)-->P(3)----- + +// PSET_PARALLEL5 7 +// x(n)--->P(0)-->P(1)-->(+)-->P(4)-->y(n) +// ^ +// | +// x(n)--->P(2)-->P(3)----- + +// PSET_FEEDBACK 8 +// x(n)-P(0)--(+)-->P(1)-->P(2)-->->y(n) +// ^ | +// | v +// -----P(4)<--P(3)-- + +// PSET_FEEDBACK3 9 +// x(n)---(+)-->P(0)--------->y(n) +// ^ | +// | v +// -----P(2)<--P(1)-- + +// PSET_FEEDBACK4 10 +// x(n)---(+)-->P(0)-------->P(3)--->y(n) +// ^ | +// | v +// ---P(2)<--P(1)-- + +// PSET_MOD 11 +// x(n)------>P(1)--P(2)--P(3)--->y(n) +// ^ +// x(n)------>P(0)....: + +// PSET_MOD2 12 +// x(n)-------P(1)-->y(n) +// ^ +// x(n)-->P(0)..: + + +// PSET_MOD3 13 +// x(n)-------P(1)-->P(2)-->y(n) +// ^ +// x(n)-->P(0)..: + + +// PRESET DEFINITIONS: (correct use of parentheses is critical for parsing) +// +// { <# processors> +// { ...} +// { ...} ... } + +// Presets are made up of one or more processors. A preset corresponds to a 'room'. + +// #: preset number - must be unique, no holes in # sequence (although sequential order in this file is not important) +// ptype: preset type from PSET_* above - typically LINEAR - this is how the processors are chained +// mixrng: min and max dsp mix values for sounds. mix value is based on sound source distance from listener. +// Smaller rooms have larger min values. Sounds far from listener have more dsp fx mix. +// duration: if 0.0, preset lasts until another is set +// if > 0.0 duration is preset duration in seconds. resets to previous preset when time expires +// fadetime: time to fade out preset if duration > 0.0. if fadetime < 0, exponential fade. +// db_min: for dsp_room only: if sndlvl in dB of a new sound is < db_min, reduce mix_min/max by db_mixdrop +// db_mixdrop: for dsp_room only: reduce mix_min/max by n% if sndlvl of new sound less than db_min +// so - for some rooms (ie: outside) low level sounds get less dsp fx mix + +// ******************************************************************* +// presets 0-29 map to legacy room_type 0-29. Don't change order or # +// ******************************************************************* +// # ptype mixrng dur fade dbmin mixdrop + // *** NULL PRESET *** +{ 0 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +} + + // *** AUTO PRESET *** +{ 1 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 } +} + + // *** METALIC S *** +{ 2 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 80.0 30.0 4 0.85 1.1 4000 1 0 0 0 0 0 0 0 0 0} +} + + // *** METALIC M *** +{ 3 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 80.0 30.0 4 0.9 1.4 4000 1 0 0 0 0 0 0 0 0 0} +} + + // *** METALIC L *** +{ 4 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.1483 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 100.0 30.0 4 0.95 1.8 4000 1 0 0 0 0 0 0 0 0 0} + +} + // *** TUNNEL S *** +{ 5 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 8.0 2 0.92 1.1 6000 1 0 0 0 0 0 0 0 0 0} + +} + // *** TUNNEL M *** +{ 6 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 100.0 15.0 2 0.92 1.1 5000 1 0 0 0 0 0 0 0 0 0} +} + + // *** TUNNEL L *** +{ 7 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 120.0 25.0 2 0.95 1.1 4000 1 0 0 0 0 0 0 0 0 0} +} + + // *** CHAMBER S *** +{ 8 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 6 0.9 1.4 5000 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** CHAMBER M *** +{ 9 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 6 0.9 1.4 6000 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** CHAMBER L *** +{ 10 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 9 0.9 1.4 6000 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** BRITE S *** +{ 11 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 3 0.9 1.0 5000 1 0 0 0 0 0 0 0 0} +} + + // *** BRITE M *** +{ 12 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 5 0.9 1.0 5000 1 0 0 0 0 0 0 0 0} +} + + // *** BRITE L *** +{ 13 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 6 0.9 1.0 6000 0 0 0 0 0 0 0 0 0} +} + + // *** WATER S *** +{ 14 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // AMP gain vthresh distmix vfeed modrate moddepth modglide rand + { AMP 1.0 0 0 0.0 10.0 0.6 80 0} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 82.0 59.0 2 0.4 2.0 1800 0 10 3.0 0 0 0 0 0 0 0} + +} + // *** WATER M *** +{ 15 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 5 0.9 1.4 1000 0 4 3.48 0 0 0 0 0 0 0} +} + + // *** WATER L *** +{ 16 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 7 0.9 1.0 1000 0 4 3.48 0 0 0 0 0 0 0} + + // MDY dtype delay feedback gain ftype cutoff qwidth qual modrate moddepth modglide mix + { MDY PLAIN 500.0 0.4 1.0 0 0 0 LO 2.0 0.01 15 1.0 } +} + + // *** CONCRETE S *** +{ 17 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 6 0.9 1.4 4000 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** CONCRETE M *** +{ 18 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 7 0.9 1.4 3500 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** CONCRETE L *** +{ 19 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 8 0.9 1.4 3000 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** OUTSIDE S *** +{ 20 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 300.0 0.5 0.84 LP 2000 0 LO 0 0 0} +} + + // *** OUTSIDE M *** +{ 21 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 400.0 0.5 0.84 LP 1500 0 LO 0 0 0} +} + + // *** OUTSIDE L *** +{ 22 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 750.0 0.5 0.84 LP 1000 0 LO 0 0 0} +} + + // *** CAVERN S *** +{ 23 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 150.0 0.5 0.84 LP 3000 0 LO} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 1.3 0.9 1.0 1500 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** CAVERN M *** +{ 24 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 200.0 0.7 0.6 LP 3000 0 LO} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 7 0.9 1.0 1500 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** CAVERN L *** +{ 25 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 300.0 0.7 0.6 LP 3000 0 LO} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 50.0 20.0 9 0.9 1.0 1500 1 4 3.48 0 0 0 0 0 0 0} +} + + // *** WEIRD 1 *** +{ 26 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 400.0 0.5 0.6 LP 1500 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } +} + + // *** WEIRD 2 *** +{ 27 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 400.0 0.5 0.6 LP 1500 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } +} + + // *** WEIRD 3 *** +{ 28 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS 400.0 0.5 0.6 LP 1500 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } +} + // *** WEIRD 4 *** +{ 29 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY 2 400.0 0.5 0.6 LP 1500 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } +} + +// *********************************************** +// presets 30-43 are system presets. Don't change. +// *********************************************** +// # ptype mixrng dur fade dbmin mixdrop + // *** LOWPASS - FACING AWAY *** +{ 30 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // FLT ftype cutoff qwidth quality gain + { FLT LP 3000 0 MED 1.0} + +} + // *** LOWPASS - FACING AWAY + 80ms delay *** +{ 31 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // FLT ftype cutoff qwidth quality gain + { FLT LP 1000 0 MED 1.0} + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY DLINEAR 80.0 0.0 1.0 0 0 0 LO 0 0 0} + +} + + // *** EXPLOSION RING 1 *** +{ 32 LINEAR 0.2 0.7 1.6 -1.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // FLT ftype cutoff qwidth quality gain + { FLT LP 1000 0 MED 0.25} +} + + + // *** EXPLOSION RING 2 *** +{ 33 LINEAR 0.2 0.7 1.6 -1.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // FLT ftype cutoff qwidth quality gain + { FLT LP 1000 0 MED 0.25} +} + + + // *** EXPLOSION RING 3 *** +{ 34 LINEAR 0.2 0.7 1.6 -1.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // FLT ftype cutoff qwidth quality gain + { FLT LP 1000 0 MED 0.25} +} + +{ 35 LINEAR 0.2 0.7 1.6 -1.0 80 0.5 // *** SHOCK MUFFLE 1 *** + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // LFO wavtype rate foneshot gain + { LFO SIN 3000.0 0.0 0.25} +} + +{ 36 LINEAR 0.2 0.7 1.6 -1.0 80 0.5 // *** SHOCK MUFFLE 2 *** + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // LFO wavtype rate foneshot gain + { LFO SIN 3000.0 0.0 0.25} +} + +{ 37 LINEAR 0.2 0.7 1.6 -1.0 80 0.5 // *** SHOCK MUFFLE 3 *** + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // LFO wavtype rate foneshot gain + { LFO SIN 3000.0 0.0 0.25} +} + +{ 38 LINEAR 0.2 0.7 0.0 0.0 80 0.5 // *** DISTORTED SPEAKER 0 *** + // AMP gain vthresh distmix vfeed + { AMP 100.0 0.005 1.0 0.0} + + // FLT ftype cutoff qwidth quality gain + { FLT HP 1000 0 LO 1.0} + { FLT LP 2000 0 LO 1.0} + { FLT LP 2000 0 LO 0.8} +} + +{ 39 LINEAR 0.2 0.7 1.0 -0.2 80 0.5 // *** STRIDER PRE-FIRE *** + + // LFO wavtype rate foneshot gain + { LFO SQR 50.0 0.0 0.1} +} + + // *** PLAYER SPATIAL (WALL) DELAY *** +{ 40 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // MDY dtype delay feedback gain ftype cutoff qwidth qual modrate moddepth modglide mix + { MDY LINEAR 100.0 0.0 1.0 0 0 0 0 0 0.0 50 1.0 } + +} + // *** 41-43 RESERVED for spatial delays *** + +{ 41 LINEAR 0.2 0.7 0.0 0.0 80 0.5 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 42 LINEAR 0.2 0.7 0.0 0.0 80 0.5 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 43 LINEAR 0.2 0.7 0.0 0.0 80 0.5 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } + +// ************************************************* +// presets 44-49 are slots reserved for test presets +// ************************************************* +// # ptype mixrng dur fade dbmin mixdrop + + // PTC pitch timeslice xfade +{ 44 LINEAR 0.2 0.7 0 0 0 0{ PTC 1.1 100.0 20.0 } } // pitch up 10% +{ 45 LINEAR 0.2 0.7 0 0 0 0{ PTC 0.9 100.0 20.0 } } // pitch down 10% + + // EFO thresh attackms decayms +{ 46 LINEAR 0.2 0.7 0 0 0 0 { EFO -20.0 100.0 200.0 } } + + // CRS lfowav rate depth mix +{ 47 LINEAR 0.2 0.7 0 0 0 0 { CRS SIN 10 1.0 0.5 } } + + // EFO thresh attackms decayms +{ 48 LINEAR 0.2 0.7 0 0 0 0 { EFO -30 20.0 200.0 } } +{ 49 LINEAR 0.2 0.7 0 0 0 0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } + +// ************************************************* +// presets 50-59 are slots reserved for dsp_speaker presets +// ************************************************* +// # ptype mixrng dur fade dbmin mixdrop +{ 50 LINEAR 0.2 0.7 0 0 0 0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 51 LINEAR 0.2 0.7 0 0 0 0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 52 LINEAR 0.2 0.7 0 0 0 0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 53 LINEAR 0.2 0.7 0 0 0 0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 54 LINEAR 0.2 0.7 0 0 0 0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } + +{ 55 LINEAR 0.2 0.7 0.0 0.0 80 0.5 // *** SPEAKER, LOUDER *** + // AMP gain vthresh distmix vfeed + { AMP 10.0 0.01 0.65 0.0} + { AMP 0.65 1.0 0.0 0.0} + + // FLT ftype cutoff qwidth quality gain + { FLT BP 2500 4000 HI 1.8} +} + +{ 56 LINEAR 0.2 0.7 0.0 0.0 80 0.5 // *** SPEAKER VERY SMALL *** + // AMP gain vthresh distmix vfeed + { AMP 10.0 0.01 0.65 0.0} + { AMP 0.65 1.0 0.0 0.0} + + // FLT ftype cutoff qwidth quality gain + { FLT BP 2500 3800 HI 1.0} + { FLT BP 2500 3800 HI 2.5} +} + +{ 57 LINEAR 0.2 0.7 0.0 0.0 80 0.5 // *** LOUDSPEAKER *** + // AMP gain vthresh distmix vfeed + { AMP 10.0 0.01 0.65 0.0} + { AMP 0.65 1.0 0.0 0.0} + + // FLT ftype cutoff qwidth quality gain + { FLT BP 2500 1000 HI 1.0} + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY PLAIN 180.0 0.28 1.7 LP 3000 0 LO 0 0 0} +} + +{ 58 LINEAR 0.2 0.7 0.0 0.0 80 0.5 // *** SPEAKER SMALL *** + // AMP gain vthresh distmix vfeed + { AMP 10.0 0.01 0.65 0.0} + { AMP 0.65 1.0 0.0 0.0} + + // FLT ftype cutoff qwidth quality gain + { FLT BP 2500 4000 HI 1.0} +} + +{ 59 LINEAR 0.2 0.7 0.0 0.0 80 0.5 // *** SPEAKER VERY SMALL *** + // AMP gain vthresh distmix vfeed + { AMP 10.0 0.01 0.65 0.0} + { AMP 0.65 1.0 0.0 0.0} + + // FLT ftype cutoff qwidth quality gain + { FLT BP 2500 3800 HI 1.0} + { FLT BP 2500 3800 HI 2.0} +} + +// ************************************************************ +// presets 60-100 are memory slots reserved for auto dsp create +// ************************************************************ +// # ptype mix + +{ 60 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 61 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 62 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 63 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 64 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 65 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 66 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 67 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 68 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 69 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } + +{ 70 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 71 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 72 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 73 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 74 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 75 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 76 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 77 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 78 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 79 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } + +{ 80 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 81 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 82 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 83 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 84 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 85 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 86 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 87 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 88 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 89 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } + +{ 90 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 91 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 92 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 93 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 94 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 95 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 96 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 97 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 98 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } +{ 99 LINEAR 0.2 0.7 0.0 0.0 0.0 0.0 { 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} } + +// ********************************************************* +// *** presets 100+ are templates for automatic dsp creation +// ********************************************************* + +// these convars store the index to the first preset for each shape type in dsp_presets.txt + +//ConVar adsp_room_min("adsp_room_min", 102); +//ConVar adsp_duct_min("adsp_duct_min", 106); +//ConVar adsp_hall_min("adsp_hall_min", 110); +//ConVar adsp_tunnel_min("adsp_tunnel_min", 114); +//ConVar adsp_street_min("adsp_street_min", 118); +//ConVar adsp_alley_min("adsp_alley_min", 122); +//ConVar adsp_courtyard_min("adsp_courtyard_min", 126); +//ConVar adsp_openspace_min("adsp_openspace_min", 130); +//ConVar adsp_openwall_min("adsp_openwall_min", 130); +//ConVar adsp_openstreet_min("adsp_openstreet_min", 118); +//ConVar adsp_opencourtyard_min("adsp_opencourtyard_min", 126); + +// Automatic dsp parameter notes: + +// setting dsp_room to 1 invokes the automatic dsp creator. It stays active until +// dsp_room is set to some other value. + +// The dsp interpolator blends between two presetes. For instance, a new preset is created +// between ROOM EMPTY SMALL BRIGHT and ROOM EMPTY HUGE DULL +// based on size of room and reflectivity. ROOM EMPTY vs ROOM FULL is chosen based on room diffusion - +// ie: how full of objects the room is. Room type, such as ROOM, HALL, TUNNEL is chosen based on +// shape of space. + +// For RVA: +// if w, d or h param is -1 then parameters are set using room size +// if w, d or h is non-zero, then size and size_min are ignored +// if fw, fd and fh are zero, then feedbk is used for w, d, h and normalized for constant fade time +// if fw, fd or fh is < 0, the corresponding delay param w,d,h is used as a predelay + +// For DLY: +// if delay is -1, delay is set directly from room size * 2 + +// NOTE: all presets have processor gains set such that signal in db = signal out db (0 db gain). + +////////////////////////////////// +// DO NOT MODIFY THESE PRESETS!!!! +////////////////////////////////// + + # type mix min dur fade dbmin dbdrop +{ 100 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 80.0 30.0 4 0.9 1.4 4000 1 0 0 0 0 0 0 0 0 0} +} + +{ 101 LINEAR 0.2 0.7 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 300.0 150.0 2 0.6 1.0 6000 0 0 1.141 0 0 0 0 0 0 0.23861 } + + // EFO thresh attackms decayms + { EFO -30 20.0 200.0 } +} + +// ROOM EMPTY SMALL BRIGHT - min parameters +{ 102 LINEAR 0.3 0.8 0.0 0.0 80 0.5 + // 0.9 0.9 0.5 + // -1 -1 -1 0.0 0.0 0.0 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 80.0 30.0 2 0.78 1.1 6000 1 0 0 0 0 0 0 0 0 0 } +} + +// ROOM EMPTY HUGE DULL - max parameters +{ 103 LINEAR 0.32 0.8 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 240.0 50.0 10 0.97 2.4 1800 1 0 0 0 0 0 0 0 0 0 } +} + +// ROOM DIFFUSE SMALL BRIGHT - min parameters +{ 104 LINEAR 0.63 0.8 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 80.0 30.0 3 0.78 1.4 5000 1 4 2.0 0 0 0 0 0 0 0 } +} + +// ROOM DIFFUSE HUGE DULL - max parameters +{ 105 LINEAR 0.32 0.8 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 240.0 50.0 12 0.97 2.4 1600 1 6 2.0 0 0 0 0 0 0 0 } +} + +// DUCT EMPTY SMALL BRIGHT - min parameters +{ 106 LINEAR 0.4 0.9 0.0 0.0 80 0.5 + // 6 12 4 0.95 -0.8 0.3 0 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 150.0 10.0 2 0.90 2.0 6000 1 0 0 0 0 0 0 0 0 0} +} +// DUCT EMPTY HUGE DULL - max parameters +{ 107 LINEAR 0.4 0.9 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.1483 } + // 96 192 64 0.95 -0.8 0.3 0 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 300.0 12.0 3 0.95 2.0 2000 1 0 0 0 0 0 0 0 0 0} +} +// DUCT DIFFUSE SMALL BRIGHT - min parameters +{ 108 LINEAR 0.4 0.9 0.0 0.0 80 0.5 + // 6 12 4 0.95 -0.8 0.3 0 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 150.0 10.0 2 0.90 2.0 6000 1 0 0 0 0 0 0 0 0 0} +} +// DUCT DIFFUSE HUGE DULL - max parameters +{ 109 LINEAR 0.4 0.9 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.1483 } + // 96 192 64 0.95 -0.8 0.3 0 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 300.0 12.0 3 0.95 2.0 2000 1 0 0 0 0 0 0 0 0 0} +} + + +// HALL EMPTY SMALL BRIGHT - min parameters +{ 110 LINEAR 0.3 0.8 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 3 0.0 2.0 6000 1 0 0 7 20 10 0.85 -0.9 0.3 0} +} +// HALL EMPTY HUGE DULL - max parameters +{ 111 LINEAR 0.3 0.8 0.0 0.0 80 0.5 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 6 0.0 1.8 4000 1 0 0 9 192 64 0.85 -0.3 0.3 0} +} +// HALL DIFFUSE SMALL BRIGHT - min parameters +{ 112 LINEAR 0.3 0.8 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.1483 } + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 3 0.0 2.0 6000 1 0 0 7 20 10 0.85 -0.9 0.3 0} +} +// HALL DIFFUSE HUGE DULL - max parameters +{ 113 LINEAR 0.3 0.8 0.0 0.0 80 0.5 + // DFR size #dly feedbk + { DFR 1.0 2 0.1483 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 6 0.0 1.8 4000 1 0 0 9 192 64 0.58 -0.3 0.3 0} +} + +// TUNNEL EMPTY SMALL BRIGHT - min parameters +{ 114 LINEAR 0.4 0.9 0.0 0.0 80 0.7 + // DFR size #dly feedbk + { DFR 1.0 2 0.1483 } + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 6 0.0 2.0 6000 1 0 0 8 32 10 0.94 -0.9 0.4 0} +} +// TUNNEL EMPTY HUGE DULL - max parameters +{ 115 LINEAR 0.4 0.9 0.0 0.0 80 0.7 + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 9 0.0 2.0 4000 1 0 0 48 192 64 0.97 -0.4 0.5 0} +} +// TUNNEL DIFFUSE SMALL BRIGHT - min parameters +{ 116 LINEAR 0.4 0.9 0.0 0.0 80 0.7 + // DFR size #dly feedbk gain + { DFR 1.0 3 0.15 1.0} + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 9 0.0 2.0 6000 1 0 0.0 8 32 10 0.96 -0.9 0.4 0} +} +// TUNNEL DIFFUSE HUGE DULL - max parameters +{ 117 LINEAR 0.4 0.9 0.0 0.0 80 0.7 + // DFR size #dly feedbk gain + { DFR 1.0 4 0.15 1.0} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 12 0.0 2.0 4000 1 0 0.0 48 192 64 0.97 -0.4 0.4 0} +} + +// STREET EMPTY SMALL BRIGHT - min parameters +{ 118 LINEAR 0.3 0.8 0.0 0.0 75 0.3 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 4000 1 0 0.0 50 200 120 0.48 -0.16 -0.3 0} +} +// STREET EMPTY HUGE DULL - max parameters +{ 119 LINEAR 0.3 0.8 0.0 0.0 75 0.3 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 1000 1 0 0.0 100 500 120 0.4 -0.12 -0.2 0} +} +// STREET DIFFUSE SMALL BRIGHT - min parameters +{ 120 LINEAR 0.3 0.8 0.0 0.0 75 0.3 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 4000 1 0 0.0 50 200 120 0.48 -0.16 -0.3 0} +} +// STREET DIFFUSE HUGE DULL - max parameters +{ 121 LINEAR 0.3 0.8 0.0 0.0 75 0.3 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 1000 1 0 0.0 100 500 120 0.4 -0.12 -0.2 0} +} + +// ALLEY EMPTY SMALL BRIGHT - min parameters +{ 122 LINEAR 0.32 0.8 0.0 0.0 60 0.3 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 5000 1 0 0.0 50 100 70 0.5 -0.3 -0.3 0} +} +// ALLEY EMPTY HUGE DULL - max parameters +{ 123 LINEAR 0.32 0.8 0.0 0.0 60 0.3 + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 3000 1 0 0.0 50 200 70 0.5 -0.26 -0.2 0} +} +// ALLEY DIFFUSE SMALL BRIGHT - min parameters +{ 124 LINEAR 0.32 0.8 0.0 0.0 60 0.3 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 5000 1 0 0.0 50 100 70 0.5 -0.29 -0.3 0} +} +// ALLEY DIFFUSE HUGE DULL - max parameters +{ 125 LINEAR 0.32 0.8 0.0 0.0 60 0.3 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fd fh ftap + { RVA 0.0 0.0 1 0.0 2.7 3000 1 0 0.0 50 200 70 0.5 -0.26 -0.2 0} +} + +// COURTYARD EMPTY SMALL BRIGHT - min parameters +{ 126 LINEAR 0.21 0.8 0.0 0.0 95 0.1 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS -1.0 0.5 1.2 LP 4000 0 LO -1 -1 -1} +} +// COURTYARD EMPTY HUGE DULL - max parameters +{ 127 LINEAR 0.21 0.8 0.0 0.0 95 0.1 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS -1.0 0.4 1.2 LP 900 0 LO -1 -1 -1} +} +// COURTYARD DIFFUSE SMALL BRIGHT - min parameters +{ 128 LINEAR 0.21 0.8 0.0 0.0 95 0.1 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS -1.0 0.5 1.2 LP 4000 0 LO -1 -1 -1} +} +// COURTYARD DIFFUSE HUGE DULL - max parameters +{ 129 LINEAR 0.21 0.8 0.0 0.0 95 0.1 + // DFR size #dly feedbk + { DFR 1.0 2 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LOWPASS -1.0 0.2 1.2 LP 900 0 LO -1 -1 -1} +} + +// OPENSPACE EMPTY SMALL BRIGHT - min parameters +{ 130 LINEAR 0.22 0.6 0.0 0.0 95 0.1 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LINEAR 300.0 0.2 1.0 LP 3000 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY PLAIN 180.0 0.15 1.0 LP 3000 0 LO 0 0 0} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 340.0 220.0 6 0.8 1.0 1500 0 10 2.0 0 0 0 0 0 0 0 } +} +// OPENSPACE EMPTY HUGE DULL - max parameters +{ 131 LINEAR 0.22 0.6 0.0 0.0 95 0.1 + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LINEAR 500.0 0.2 1.0 LP 3000 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 4 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY PLAIN 500.0 0.2 1.0 LP 3000 0 LO 0 0 0} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 340.0 200.0 6 0.9 1.5 900 0 10 2.0 0 0 0 0 0 0 0 } +} +// OPENSPACE DIFFUSE SMALL BRIGHT - min parameters +{ 132 LINEAR 0.2 0.7 0.0 0.0 95 0.1 + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LINEAR 300.0 0.2 1.0 LP 3000 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 3 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY PLAIN 180.0 0.15 1.0 LP 3000 0 LO 0 0 0} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 340.0 220.0 6 0.8 1.0 1500 0 10 2.0 0 0 0 0 0 0 0 } +} +// OPENSPACE DIFFUSE HUGE DULL - max parameters +{ 133 LINEAR 0.2 0.7 0.0 0.0 95 0.1 + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY LINEAR 500.0 0.2 1.0 LP 3000 0 LO 0 0 0} + + // DFR size #dly feedbk + { DFR 1.0 4 0.15 } + + // DLY dtype delay feedbk gain ftype cutoff qwidth quality tap1 tap2 tap3 + { DLY PLAIN 500.0 0.2 1.0 LP 3000 0 LO 0 0 0} + + // RVA size min #dly feedbk gain cutoff fpar fmod rate w d h fw fw fh ftap + { RVA 340.0 200.0 6 0.9 1.5 900 0 10 2.0 0 0 0 0 0 0 0 } +} + +///////////////////////////////////////////////////// +// description of parameters for all processor types: +///////////////////////////////////////////////////// + +/////////// +// Filters +/////////// + + // ftype: filter type FLT_LP, FLT_HP, FLT_BP + // cutoff: cutoff frequency in hz at -3db gain + // qwidth: width of BP (if qwidth > 0 then cutin = cutoff and cutoff = cutoff + qwidth) + // quality: QUA_LO, _MED, _HI _VHI 0,1,2,3 = # of series filters + // gain: 0-10.0 output gain + +////////// +// Delays +////////// + + // dtype: delay type DLY_PLAIN, DLY_LOWPASS, DLY_ALLPASS + // delay: delay in milliseconds (room max size in feet) + // feedback: feedback 0-1.0 + // gain: final gain of output stage, 0-10.0 + + +/////////// +// Reverbs +/////////// + + // size_max: 0-1000.0 millisec (room width in feet) - delay max + // size_min: 0-1000.0 millisec (room width in feet) - delay min + // #dly: controls # of parallel or series delays + // feedbk: 0-1.0 scales feedback parameters + // gain: final gain of output stage, 0-1.0 + // fparallel: if true, filters are built into delays, otherwise filter output only + // cutoff: if > 0, feedback loop is Lowpass filtered to cutoff in Hz + // fmoddly: if > 0 all delays are modulating delays, param controls depth in milliseconds of modulation + // rate: if fmoddly > 0, controls mod rate - ie: # of delay passes that occur between delay modulations + + // width: 0-1000.0 millisec (room width in feet) - used instead of size if non-zero + // depth: 0-1000.0 room depth in feet - used instead of size if non-zero + // height: 0-1000.0 room height in feet - used instead of size if non-zero + + // fbwidth: -1.0-1.0 material reflectivity - used as feedback param instead of decay if non-zero + // fbdepth: -1.0-1.0 material reflectivity - used as feedback param instead of decay if non-zero + // fbheight:-1.0-1.0 material reflectivity - used as feedback param instead of decay if non-zero + // if < 0, a predelay is allocated, then feedback is -1*param given + // ftaps: if > 0, scales all tap delays as D ( 1 - N * tap) n = 0,1,2,3 + + +///////////// +// Diffusors +///////////// + + // size: 0-1.0 scales all delays (13ms to 41ms * scale = delay) + // #dly : 0-4.0 controls # of series delays + // feedbk: 0-1.0 scales all feedback parameters + +////////////// +// Amplifiers +////////////// + // {amp_gain, 0.0, 10.0}, // amplification + // {amp_vthresh, 0.0, 1.0}, // threshold for distortion (1.0 = no distortion) + // {amp_distmix, 0.0, 1.0}, // mix of clean and distortion (1.0 = full distortion, 0.0 = full clean) + // {amp_vfeed, 0.0, 1.0}, // distortion feedback + // modrate, 0.01, 200.0}, // frequency at which amplitude values change to new random value. 0 is no self-modulation + // moddepth, 0.0, 1.0}, // how much amplitude changes (decreases) from current value (0-1.0) + // modglide, 0.01, 100.0}, // glide time between mapcur and ampnew in milliseconds + // rand 0, 1 // if 1, modulate randomly between gain & g*(1-depth). otherwise alternate gain/gainmin + +//////// +// LFOs +//////// + // wavtype: lfo type to use (LFO_SIN, LFO_RND...) + // rate: modulation rate in hz. for MDY, 1/rate = 'glide' time in seconds + // foneshot: 1.0 if lfo is oneshot + // gain: scale output amplitude by gain 0-1.0 + + +///////// +// Pitch +///////// + + // pitch: 0-n.0 where 1.0 = 1 octave up and 0.5 is one octave down + // timeslice: in milliseconds - size of sound chunk to analyze and cut/duplicate - 100ms nominal + // xfade: in milliseconds - size of crossfade region between spliced chunks - 20ms nominal + + +///////////// +// Envelopes +///////////// + + // etype: ENV_LINEAR, ENV_LOG - currently ignored + // amp1: attack peak amplitude 0-1.0 + // amp2: decay target amplitued 0-1.0 + // amp3: sustain target amplitude 0-1.0 + // attack time in milliseconds + // envelope decay time in milliseconds + // sustain time in milliseconds + // release time in milliseconds + // exp: if 1, use exponential curves + +////////////// +// Mod delays +////////////// + + // dtype: delay type DLY_PLAIN, DLY_LOWPASS, DLY_ALLPASS + // delay: delay in milliseconds + // feedback: feedback 0-1.0 + // gain: final gain of output stage, 0-1.0 + + // modrate: frequency at which delay values change to new random value. 0 is no self-modulation + // moddepth: how much delay changes (decreases) from current value (0-1.0) + // modglide: glide time between dcur and dnew in milliseconds + + +////////// +// Chorus +////////// + + // lfowav: lfotype is LFO_SIN, LFO_RND, LFO_TRI etc (LFO_RND for chorus, LFO_SIN for flange) + // rate: rate is modulation frequency in Hz + // depth: depth is modulation depth, 0-1.0 + // mix: mix is mix of chorus and clean signal + + +////////////////////////// +// Envelope follower/ Gate +////////////////////////// + + // threshold, 0.0, -140.0 // gate threshold in db. if 0.0 then no gate. + // attack, 0.0, 20000.0 // attack time in milliseconds + // decay, 0.0, 20000.0 // envelope decay time in milliseconds + // exp, 0.0, 1.0 // if 1.0 use exponential decay + +// UNDONE: stock reverb presets: + +// carpet hallway +// tile hallway +// wood hallway +// metal hallway + +// train tunnel +// sewer main tunnel +// concrete access tunnel +// cave tunnel +// sand floor cave tunnel + +// metal duct shaft +// elevator shaft +// large elevator shaft + +// parking garage +// aircraft hangar +// cathedral +// train station + +// small cavern +// large cavern +// huge cavern +// watery cavern +// long, low cavern + +// wood warehouse +// metal warehouse +// concrete warehouse + +// small closet room +// medium drywall room +// medium wood room +// medium metal room + +// elevator +// small metal room +// medium metal room +// large metal room +// huge metal room + +// small metal room dense +// medium metal room dense +// large metal room dense +// huge metal room dense + +// small concrete room +// medium concrete room +// large concrete room +// huge concrete room + +// small concrete room dense +// medium concrete room dense +// large concrete room dense +// huge concrete room dense + +// soundproof room +// carpet lobby +// swimming pool +// open park +// open courtyard +// wide parkinglot +// narrow street +// wide street, short buildings +// wide street, tall buildings +// narrow canyon +// wide canyon +// huge canyon +// small valley +// wide valley +// wreckage & rubble +// small building cluster +// wide open plain +// high vista + +// alien interior small +// alien interior medium +// alien interior large +// alien interior huge + +// special fx presets: + +// alien citadel + +// teleport aftershock (these presets all ADSR timeout and reset the dsp_* to 0) +// on target teleport +// off target teleport +// death fade +// beam stasis +// scatterbrain +// pulse only +// slomo +// hypersensitive +// supershocker +// physwhacked +// forcefieldfry +// juiced +// zoomed in +// crabbed +// barnacle gut +// bad transmission + + +// pst prm gn p1 p1 p3 p4 p5 p6 p7 p8.... +//dsp_parm 10 1 1.8 1.0 1.0 0.9 0 1000 500 1 1 0 0 0 0 0 0 0 // diffuse medium room, metal +//dsp_parm 10 1 1.3 1.0 1.0 0.8 0 1000 500 1 1 0 0 0 0 0 0 0 // diffuse medium room dull +//dsp_parm 10 1 1.3 1.0 1.0 0.8 0 4000 2000 1 1 0 0 0 0 0 0 0 // diffuse medium room +//dsp_parm 10 1 1.3 1.0 1.0 0.8 0 8000 2000 1 1 0 0 0 0 0 0 0 // diffuse medium room bright +//dsp_parm 10 1 1.4 1.5 1.0 0.84 0 8000 2000 1 1 0 0 0 0 0 0 0 // diffuse larger room bright + + diff --git a/scripts/ff_grenade_caltrop.txt b/scripts/ff_grenade_caltrop.txt new file mode 100644 index 0000000..dabc478 --- /dev/null +++ b/scripts/ff_grenade_caltrop.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "R" + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "R" + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "R" + } + } + "printname" "#FF_WPNHUD_CALTROP" +} diff --git a/scripts/ff_grenade_concussion.txt b/scripts/ff_grenade_concussion.txt new file mode 100644 index 0000000..484e4b2 --- /dev/null +++ b/scripts/ff_grenade_concussion.txt @@ -0,0 +1,26 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "U" + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "U" + } + + // yeah admittedly this is unlikely + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "U" + } + } + "printname" "#FF_WPNHUD_CONC" +} diff --git a/scripts/ff_grenade_emp.txt b/scripts/ff_grenade_emp.txt new file mode 100644 index 0000000..3884a3e --- /dev/null +++ b/scripts/ff_grenade_emp.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "." + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "." + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "." + } + } + "printname" "#FF_WPNHUD_EMP" +} diff --git a/scripts/ff_grenade_gas.txt b/scripts/ff_grenade_gas.txt new file mode 100644 index 0000000..39ded17 --- /dev/null +++ b/scripts/ff_grenade_gas.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "S" + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "S" + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "S" + } + } + "printname" "#FF_WPNHUD_GASGREN" +} diff --git a/scripts/ff_grenade_laser.txt b/scripts/ff_grenade_laser.txt new file mode 100644 index 0000000..5dc2726 --- /dev/null +++ b/scripts/ff_grenade_laser.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "," + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "," + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "," + } + } + "printname" "#FF_WPNHUD_LASERGREN" +} diff --git a/scripts/ff_grenade_mirv.txt b/scripts/ff_grenade_mirv.txt new file mode 100644 index 0000000..2c992c6 --- /dev/null +++ b/scripts/ff_grenade_mirv.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "/" + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "/" + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "/" + } + } + "printname" "#FF_WPNHUD_MIRV" +} diff --git a/scripts/ff_grenade_nail.txt b/scripts/ff_grenade_nail.txt new file mode 100644 index 0000000..8a5ac18 --- /dev/null +++ b/scripts/ff_grenade_nail.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "," + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "," + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "," + } + } + "printname" "#FF_WPNHUD_NAILGREN" +} diff --git a/scripts/ff_grenade_napalm.txt b/scripts/ff_grenade_napalm.txt new file mode 100644 index 0000000..cd9dca5 --- /dev/null +++ b/scripts/ff_grenade_napalm.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "T" + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "T" + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "T" + } + } + "printname" "#FF_WPNHUD_NAPALM" +} diff --git a/scripts/ff_grenade_normal.txt b/scripts/ff_grenade_normal.txt new file mode 100644 index 0000000..38f8146 --- /dev/null +++ b/scripts/ff_grenade_normal.txt @@ -0,0 +1,25 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "\" + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "\" + } + + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "\" + } + } + "printname" "#FF_WPNHUD_FRAG" +} diff --git a/scripts/ff_grenade_slowfield.txt b/scripts/ff_grenade_slowfield.txt new file mode 100644 index 0000000..76f846a --- /dev/null +++ b/scripts/ff_grenade_slowfield.txt @@ -0,0 +1,26 @@ +WeaponData +{ + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "grenade" + { + "font" "GrenadeIcons" + "character" "S" + } + + "ammo" + { + "font" "GrenadeAmmoIcons" + "character" "S" + } + + // yeah admittedly this is unlikely + "deathnotice" + { + "font" "StatusGlyphsSmall" + "character" "S" + } + } + "printname" "#FF_WPNHUD_SLOWFIELD" +} diff --git a/scripts/ff_hud_genericammo.txt b/scripts/ff_hud_genericammo.txt new file mode 100644 index 0000000..d2e98f6 --- /dev/null +++ b/scripts/ff_hud_genericammo.txt @@ -0,0 +1,48 @@ +StatusIconData +{ + TextureData + { + "AMMO_NAILS" + { + "font" "WeaponIconsSmall" + "character" "5" + } + + "AMMO_SHELLS" + { + "font" "WeaponIconsSmall" + "character" "1" + } + + "AMMO_ROCKETS" + { + "font" "WeaponIconsSmall" + "character" "8" + } + + "AMMO_CELLS" + { + "font" "WeaponIconsSmall" + "character" "6" + } + + "AMMO_DETPACK" + { + "font" "WeaponIconsSmall" + "character" "9" + } + + "AMMO_MANCANNON" + { + "font" "WeaponIconsSmall" + "character" "9" + } + + "AMMO_RADIOTAG" + { + "font" "WeaponIconsSmall" + "character" "3" + } + } + +} diff --git a/scripts/ff_hud_statusicons.txt b/scripts/ff_hud_statusicons.txt new file mode 100644 index 0000000..9bab636 --- /dev/null +++ b/scripts/ff_hud_statusicons.txt @@ -0,0 +1,106 @@ +StatusIconData +{ + TextureData + { + "concussion" + { + "font" "StatusGlyphs" + "character" "1" + } + + "infection" + { + "font" "StatusGlyphs" + "character" "2" + } + + "leginjury" + { + "font" "StatusGlyphs" + "character" "3" + } + + "caltropped" + { + "font" "StatusGlyphs" + "character" "4" + } + + "tranquilized" + { + "font" "StatusGlyphs" + "character" "5" + } + + "hallucinations" + { + "font" "StatusGlyphs" + "character" "6" + } + + "burning" + { + "font" "StatusGlyphs" + "character" "7" + } + + "drowning" + { + "font" "StatusGlyphs" + "character" "8" + } + + "radiation" + { + "font" "StatusGlyphs" + "character" "9" + } + + "cold" + { + "font" "StatusGlyphs" + "character" "0" + } + "immune" + { + "font" "StatusGlyphs" + "character" "-" + } + "radiotag" + { + "font" "StatusGlyphs" + "character" "=" + } + "burning1" + { + "font" "StatusGlyphs" + "character" "@" + } + "burning2" + { + "font" "StatusGlyphs" + "character" "#" + } + "burning3" + { + "font" "StatusGlyphs" + "character" "$" + } + "lockedon" + { + "font" "StatusGlyphs" + "character" "&" + } + "sliding" + { + "font" "StatusGlyphs" + "character" "*" + } + "slowmotion" + { + "font" "StatusGlyphs" + "character" "(" + } + } + +} diff --git a/scripts/ff_hud_textures.txt b/scripts/ff_hud_textures.txt new file mode 100644 index 0000000..adf058a --- /dev/null +++ b/scripts/ff_hud_textures.txt @@ -0,0 +1,428 @@ +HudData +{ + TextureData + { + /////////////// BACKGROUND LAYER /////////////// + + "playerScoreBoxBG1" + { + "font" "HUD_BackGround" + "character" "c" + } + "locationBoxBG1" + { + "font" "HUD_BackGround" + "character" "a" + } + "locationBoxBG2" + { + "font" "HUD_BackGround" + "character" "y" + } + "healthBoxBG" + { + "font" "HUD_BackGround" + "character" "c" + } + "armourBoxBG" + { + "font" "HUD_BackGround" + "character" "e" + } + "weaponBoxBG1" + { + "font" "HUD_BackGround" + "character" "g" + } + "weaponBoxBG2" + { + "font" "HUD_BackGround" + "character" "w" + } + "ammoCarriedBoxBG" + { + "font" "HUD_BackGround" + "character" "i" + } + "ammoLoadedBoxBG" + { + "font" "HUD_BackGround" + "character" "k" + } + "grenPrimaryBoxBG" + { + "font" "HUD_BackGround" + "character" "m" + } + "grenSecondaryBoxBG" + { + "font" "HUD_BackGround" + "character" "o" + } + "CellCountBoxBG" + { + "font" "HUD_BackGround" + "character" "m" + } + "CooldownBoxBG" + { + "font" "HUD_BackGround" + "character" "s" + } + "SpyDisguiseBoxBG" + { + "font" "HUD_BackGround" + "character" ">" + } + "SpyDisguiseBoxBG2" + { + "font" "HUD_BackGround" + "character" "]" + } + "SpyDisguiseBoxBG3" + { + "font" "HUD_BackGround" + "character" "," + } + "RoundInfoBoxBG" + { + "font" "HUD_BackGround" + "character" "q" + } + "Gren1TimerBGBox" + { + "font" "HUD_BackGround" + "character" "u" + } + "Gren2TimerBGBox" + { + "font" "HUD_BackGround" + "character" "u" + } + + /////////////// FOREGROUND LAYER /////////////// + + "playerScoreBoxFG1" + { + "font" "HUD_ForeGround" + "character" "d" + } + "locationBoxFG1" + { + "font" "HUD_ForeGround" + "character" "b" + } + "locationBoxFG2" + { + "font" "HUD_BackGround" + "character" "z" + } + "healthBoxFG" + { + "font" "HUD_ForeGround" + "character" "K" + } + "armourBoxFG" + { + "font" "HUD_ForeGround" + "character" "L" + } + "weaponBoxFG1" + { + "font" "HUD_ForeGround" + "character" "h" + } + "weaponBoxFG2" + { + "font" "HUD_BackGround" + "character" "x" + } + "ammoCarriedBoxFG" + { + "font" "HUD_ForeGround" + "character" "j" + } + "ammoLoadedBoxFG" + { + "font" "HUD_ForeGround" + "character" "l" + } + "grenPrimaryBoxFG" + { + "font" "HUD_ForeGround" + "character" "n" + } + "grenSecondaryBoxFG" + { + "font" "HUD_ForeGround" + "character" "p" + } + "CellCountBoxFG" + { + "font" "HUD_ForeGround" + "character" "n" + } + "CooldownBoxFG" + { + "font" "HUD_ForeGround" + "character" "t" + } + "SpyDisguiseBoxFG" + { + "font" "HUD_ForeGround" + "character" "<" + } + "SpyDisguiseBoxFG2" + { + "font" "HUD_ForeGround" + "character" "[" + } + "SpyDisguiseBoxFG3" + { + "font" "HUD_ForeGround" + "character" ";" + } + "RoundInfoBoxFG" + { + "font" "HUD_ForeGround" + "character" "r" + } + "Gren1TimerFGBox" + { + "font" "HUD_ForeGround" + "character" "v" + } + "Gren2TimerFGBox" + { + "font" "HUD_ForeGround" + "character" "v" + } + + /////////////// OLD STUFF /////////////// + "Health" + { + "font" "WeaponIconsSelected" + "character" "f" + } + "Armor" + { + "font" "WeaponIconsSelected" + "character" "f" + } + "Location" + { + "font" "WeaponIconsSelected" + "character" "f" + } + "Gren1" + { + "font" "WeaponIconsSelected" + "character" "f" + } + "Gren2" + { + "font" "WeaponIconsSelected" + "character" "f" + } + "Ammo" + { + "font" "WeaponIconsSelected" + "character" "f" + } + "BuildTimer" + { + "font" "WeaponIconSelected" + "character" "f" + } + "Gren1Timer" + { + "font" "WeaponIconSelected" + "character" "f" + } + "Gren2Timer" + { + "font" "WeaponIconSelected" + "character" "f" + } + + /////////// Temporarily here until a home found for it + + "death_worldspawn" + { + "font" "StatusGlyphsSmall" + "character" "M" + } + "death_door" + { + "font" "StatusGlyphsSmall" + "character" "N" + } + "death_world" + { + "font" "StatusGlyphsSmall" + "character" "O" + } + "death_miniturret" + { + "font" "StatusGlyphsSmall" + "character" "P" + } + + "death_trigger_hurt" + { + "font" "StatusGlyphsSmall" + "character" "O" + } + "d_skull" + { + "font" "StatusGlyphs" + "character" "R" + } + + /////////// Special trigger_hurt death notices. To add a new type, just match the postfix (e.g. _fall) to the DMG_ type + /////////// the trigger hurt uses and then update the string appending code in CHudDeathNotice::FireGameEvent() -> Defrag + "death_trigger_hurt_fall" + { + "font" "StatusGlyphsSmall" + "character" "M" + } + "death_trigger_hurt_drown" + { + "font" "StatusGlyphsSmall" + "character" "8" + } + "death_trigger_hurt_shock" + { + "font" "StatusGlyphsSmall" + "character" "Q" + } + "voice_player" + { + "file" "voice/icntlk_sv" + "x" "0" + "y" "0" + "width" "32" + "height" "32" + } + "voice_self" + { + "file" "voice/icntlk_local" + "x" "0" + "y" "0" + "width" "32" + "height" "32" + } + "death_burndeath_level1" + { + "font" "StatusGlyphsSmall" + "character" "@" + } + "death_burndeath_level2" + { + "font" "StatusGlyphsSmall" + "character" "#" + } + "death_burndeath_level3" + { + "font" "StatusGlyphsSmall" + "character" "$" + } + "death_sentrygun_level1" + { + "font" "StatusGlyphsSmall" + "character" "Z" + } + "death_sentrygun_level2" + { + "font" "StatusGlyphsSmall" + "character" "A" + } + "death_sentrygun_level3" + { + "font" "StatusGlyphsSmall" + "character" "B" + } + "death_sentrygun_level1_det" + { + "font" "StatusGlyphsSmall" + "character" "C" + } + "death_sentrygun_level2_det" + { + "font" "StatusGlyphsSmall" + "character" "D" + } + "death_sentrygun_level3_det" + { + "font" "StatusGlyphsSmall" + "character" "E" + } + "death_objective" + { + "font" "StatusGlyphsSmall" + "character" "+" + } + "death_objective2" + { + "font" "StatusGlyphsSmall" + "character" "_" + } + "death_headcrush" + { + "font" "StatusGlyphsSmall" + "character" "L" + } + "death_flag" + { + "font" "StatusGlyphsSmall" + "character" "F" + } + "death_railgun_bounce1" + { + "font" "StatusGlyphsSmall" + "character" "w" + } + "death_railgun_bounce2" + { + "font" "StatusGlyphsSmall" + "character" "x" + } + "death_airshot" + { + "font" "StatusGlyphsSmall" + "character" "G" + } + "build_sentrygun" + { + "file" "vgui/hud_buildable_sentry" + "x" "0" + "y" "0" + "width" "64" + "height" "64" + } + "build_dispenser" + { + "file" "vgui/hud_buildable_dispenser" + "x" "0" + "y" "0" + "width" "64" + "height" "64" + } + "build_detpack" + { + "file" "vgui/hud_buildable_detpack" + "x" "0" + "y" "0" + "width" "64" + "height" "64" + } + "build_jumppad" + { + "file" "vgui/hud_buildable_jumppad" + "x" "0" + "y" "0" + "width" "64" + "height" "64" + } + } +} diff --git a/scripts/ff_playerclass_civilian.ctx b/scripts/ff_playerclass_civilian.ctx new file mode 100644 index 0000000000000000000000000000000000000000..cb4930551dffe0525e3cf81f026c932d208bd4ef GIT binary patch literal 1181 zcmcbfufy9a72n>&8?vvscj*EIW{Q%HTyw_^8_x6zRmlGaXQ3l8ns?fSs*mhEh{ zT2aOev&=qBf61^v=Gm@KjLFWcwm5@=y? zw@|v)`uU5*uh*+@re0kUQnM#EZYCS=u?hn|x1eJ`Cr(|Eq-EUc&>?wCqlj_WgN;S8 z3_I-S%;LKFt-9gz;x%V?NElU2@O0j@aEW1t<(=G*OQx(H5&>p>n-T!namOLc~Rw2;1NZIInVQ5n-4IR3i~Xdddx*_jwd&FcGDUa>5W(X3pk>}%cmGH zr3lFypK`O?_WZDypnI;)qyx#hcUJ4p6_;qfwO}Q$)8-!@?DDrRb?nnfkBa83@RwWC ze^gpSXv23-#(xW~EqLaxc+9^3;~C-WJEcQTt?Ve5-5eHw)LZ5LGS1Z6 zQo6WkUvuGQYjp;`xmUPYUuvw3@BdlK_|Q8h`{=bz_deLaH)!^~amIMt^!fwuxO?w- zX)cvq@4s44%!t$K-LsIFqA}7dyKFSrt(e(X{g{%dZ?fm}?oTT=I6jf&72LVsLpU?2 zCsibXce_yN-4~CJ^@urmFRJFOUlPqYsqe?Z#fK#GUTyc^vyMBCtyyAvq1f+NhR!oT z{x;jW$YeUh&nCWgF~_WQLTuSPVfw_QORnnNWli+_&Cry}qiQzeg0k_u-G?^Vi)l># zW+5)R%RZ&<#Ay*3?FW^!TT=2uVe(h6Rrb{~-Bj?@jhgd6d3Lrh>%?ab+}*Z2O7{5d zjuQ7;@yGp``y#*6c_U6ceV@v>yy5C`wP*- z_w3)ACFHG{!!^s{Hq6|+lWPO+UopSSZrw7^$55?Efa~M5MXxG!L<6)Lr)n>JCevKM s@mX!E0xbSqPcM*5(0UmX6!*>A>+VvAd#6$vBadFRrMLTdxoUa2041L{;{X5v literal 0 HcmV?d00001 diff --git a/scripts/ff_playerclass_demoman.ctx b/scripts/ff_playerclass_demoman.ctx new file mode 100644 index 0000000000000000000000000000000000000000..99127e3dfe34768f10794deb19b11e3710b39278 GIT binary patch literal 1349 zcmZ{eSx^!P06@hP!3!F#&{8od*DEx^i)b~4Ji;R@5sxTk$?`}`vO#x}@>WDeiZU|S zaxu^C5+#H-T~pLbEswGmGbKsN2(Q|&{b{D(_uj`FOK~*50Q0r7o&d-3-ZlAuZ_Evm z*(4}TZVBraqNC_ow7dn>8sWi{6bxXX3|_$rLzyzV0!fQIwW3Cd2I?7Euy3|nAP6Yf z!SYC7zwA?{>TM}jJieMOEgD5&IO;V@M4?9_TCjhG1W=U&&s%kHgEzlYn*@EH;Lf|p zmPUjSmqUGmot~8qRtkX#P0Y|I*r;)lw~DV&A_w;=GoN>0_*LBbR*5bWXOjxUOmShWS`j=7Cr$E_oQ6tGV zk!6Py;a(qh0MCt^tn=SQXK9ygy8WWFx&(WH^in?V)_GRY2 z0dRmqbW`kO%L5n0!tp%w)(tzS(<)c9aY6u3XUN^}D%Y!c7INpYWWG1H)8V~mD_yl7 zSTQ?%k$I(4fpZBr7y4Qj&!rc#mxFci7Fq<4+6+UQPGHItTK^VmD&5s&1kIuw;mCrn z&_lECqE<${5o6Qexe-O%1C-wBYfUvG_@-;gPb!CwlMNm6qgNHRI4P`mQ|FOB5D9FgTWvKaQjH;lE z4%u3mH2mmY113}7b?rPS|4Q4I9yasvM}P5iD4kXg5v7mOVN6Hs_G3=Nq(w`yByz3( z$ZLYn!3P;Awoa8<6k=L*Q2TxPgIQk^+!)-^^RtfN`~nmyW4OjTX3i68Q&+@r3xOzR z0I$oz7Npj`DO)Qm>Sk+IP%$qXmtb0E8C2bv*C9=13-rz zEXU;18?gu5i5rrN1EAk~S)p5{K~biV16h9J-#6;%FRTT6%(Dn5gR=XozGB&FohJ4OgIPg7&AXJ@V$TZ2$lHz4zwQSGWaqd~)Lz(B(Z7H6Mc}p0$g+rYabrub*S4 Z47`~&!6@V@Gmwf?J5P5s1~H65{{bkyiMRj& literal 0 HcmV?d00001 diff --git a/scripts/ff_playerclass_engineer.ctx b/scripts/ff_playerclass_engineer.ctx new file mode 100644 index 0000000000000000000000000000000000000000..159474fbc1f4fee423ce6da90309ccf0576630a8 GIT binary patch literal 1369 zcmZ{hc{~#e0LN+e7(??iw-gDF9NVxMg)yF4tiu(#ugF=HD=XqHayHKp%i41ly)ZL5 z;vrk4AtSxy%wpue-e3Od^LhXNzTZE7zt3;vhPL>9c?-qkTrtn0nOgKgH37?3@%tu0 zV?5=#xx@}XX3*M$x9f^J(pg4Q2}S6V^?*VnzHX4C##qM0&DtBXM<*;uEt{rC!b6q? z6oq#7uj-WUrhsjpU0Yg|>INiz@Fv%KjSQKG{ql*k_To$<$fYA=Fax>x5aHThnYI)q z6BwSH2%OZ>1S?>y3pQ+>XF?x#M&y>JB?ey@J9}x0$=4fNhV+=|miZ8lPL2scyx_9V z9PFVd)<3){HoEEBx`te@LN!{$vT5_eP@AjPFyYR~G# z9JwYFtegjBp~s`;w>e~;%QZ>G1^n}mi!0|Po8A+&%6^9{jh5YwdfjGLyND^h(nPgD z0!GeGXj>J`9`HEWYJ>A!U*&pny1B(LZ5N57P-xZd~l5&Em# z00aCvliwv|lG7ZCj++EKl~zjcH9JXV(>n$Iv3!_2a7_m7P3f!Nz#I>Rp{3u{srOpg zX|kQ~iw3jy;Y8H2v6(PtVCcY+;z+_dhum_Z{RiE_+Ov>dN{rvizs8@Jnv1b_%nB&N ze_(cUEiY9lOvN%qWcx&zZjnSy&cK}tg$a$qJLF5dRIf>l>1BGfehwi2sLLn-d?|9kXB`d%aK9162t@ejk*7=3$JuiMRQ6L-9$Fl1k!SVza=uy2kTx zVpkstAY1`aiP!t}AJSO1io4E*l{V#z`xIqmYf<*F`Tu!qNWK?fP)i6ik=sgu;2iLt zhB#VCkgP<(q>|Mw&gyVoBX`QrJjQ=@ZCZJjv3Hm|8OXX~)E>O=x~=c94??kF8Ow>7 zTvnd0)An6r8XzOC*bp@GN8kdZi0!}n~ zDCsSiW$pH+AwAoRwbemBR&cu72!ENpwadj&+pXlgx7`GDGB?{P z9aDX(mgWqz>Ykc%ZyVqGndT8Z6f z^T!(e1nY6-O{i^zD;#?GYdM&Vjk(|>$E@w8Rs@LJEc0uoqEZHABK$>dqY(EL$bDvb zJtQt?=9}Yw_-asydnIzKFCj&Z02K)BH%Z=Cf5(jyJ2`K3Z=Sa`lDU}t@&PC=sVP;^ z$7%VIe(Skg$_vLosY(Dj?<~!(?AZrU3^YYNdE;FT^R18Q^IB@`ZRq3vFY9U-S-M{A zCEwGQ_VMdud&T()wD=D#JQ7i~O0#3m&c^}Owis9w96EsWq2P;b?Yt$g5< za?nB*0^@wx+YOc22B3%_-uhdEsWyIjrwFfS)7MG2)D14`A7fihbSjRQyV%odhxt&@ tiFq8zK`*A#lxN>8n0mO=D}+D3o;3Jf-n;7LU5x##z;sw)o;Ub~=zp&)t6cy9 literal 0 HcmV?d00001 diff --git a/scripts/ff_playerclass_hwguy.ctx b/scripts/ff_playerclass_hwguy.ctx new file mode 100644 index 0000000000000000000000000000000000000000..be695ddca22d2a7b1c733c5b286ade35ede02f2a GIT binary patch literal 1266 zcmZ{fYdjMO0Kh#nkFDrXn5mG}JTp=uwA9cvT}!c&l}C!-$)mL;rs95RQnsDAjXCog zlCY2?j~xjaYqmR7WGrKhrg5Kq?DPNs;r}0tg#jO!c$-1SbuSl8vk{wBq<{g7YjYsh zYo_E5t|IYUe9�?~MkE zLgN-Nx?m&NEwD5@?B&=km!92r9_=bgB@k=LpPkOF*t1McNzz{#2Vgc_7}{M=+~vRjt$*2)#v( zYH@S#ylL@dPUaj3XBWDOBD*)>o}C_6YoUWnCZj-8<^&{22irWeY&jL%P?+rM*rMW3l~SD8?V73>Zqy027z54op^cQgvcv6@ z8dkAz=>514`49pEAhIi)U-H`CG)y|c@N)+98L9Eh!5L^y%u9IFU*2x&V@E`d0*0x~ zQj=EYhG_r_Q{ItIE>{r04da>>_dJ#v45#q6(&8T(TO3W*KL`wpH8bRHb`3{EQP)^ouI8 zzTW#8uYdSCkc3)`;KIN0rvmjV0bJ^BjZH5(!M&9yNTo@NLLOr#1^SOJoGHwpX~DpA zb~|4DIHIf0u!99S(~Xa^M<@5}AogH6p16CxeZQD7bI%%_0KfTixQCd|k*xL27Z(}` zH-_xRjy|--b(iL1XNt=AG!VOtyHV@D5Tsl)>%2P6m|I}|@a^_3K9i6il`4el^78u`V4L!eqzX&&*U2RY1ww;>>3Yoj&1o%$K*pD ztKkL1Is#yW(fd=YnW!VN^#h8E_zT%@MfQKo`z3XFR%1~_bJT@A@h~zui8ix%8`6c} zL)Pofb9bKQ>~<%=^usN~i){AzMiiToQtGCO*DR!-3l5|Jem|m*Zhqy!>^U@6eiSJx zJ>+w@4b%)M(H0>;sga;mI%9E z&9;%7XAf8oD2yomQ*z65@9e_{7I6E0{0VY_vhW#^MHp$3P_uL@p&eh5;b+|2=Oe45 zZw{jT!fz-?+Jtwx7+#Gp^@SF$!67Yi)G&9e``4Q5+Ib=A zv5>v`37Y&z0{TB1UYw-Blf%q8NOPo~>fW2CyS+X?9fbG#e0E}tY<((>yydaG1ZdeD Ucm!I|oKd5!b){PEF9PcP4t<8 literal 0 HcmV?d00001 diff --git a/scripts/ff_playerclass_medic.ctx b/scripts/ff_playerclass_medic.ctx new file mode 100644 index 0000000000000000000000000000000000000000..86ab9b9edbc906110c3f36b27616d0486267b433 GIT binary patch literal 1263 zcmVA3&=~G1@O| z^Uz#!S7S9Dh&J5n!mGMBi8%RfAt+!$SI8P zl>qXQxx)cwP4P2M>!2!8Ot4q1_edXTGes4|u_nnvN-55zD0z0L_&?1=GHZrblBaIA zO=*edeAUf^pp9rqDp=hgsm_(HA@a?^*|swthJR86&IB}-AfP-R6DR!BC#9OToGQyb zqXe2%$%$kx>#v9lzx`$9;sl?fA>=qMZ`l{?RY$F+-X0`!>0vG?xJR zf)1{y$^NiC?^FHw9K&Mfq3iFc{71$|qE2;|X@T4+49iyqA5fC^JQDX-Q`S=ktVAuS zHzj0qm9C_ixDlbrlX~F6^f@M925~huN_RSyeNPvW+q4KgY7f^nyPzZO@|gAPrgytI zV8A(Yo;&Sp5l@Ua+`yDZSW??nx-lybiKed$iC!W{n-#H*NHd+7gP$@uQ_*z1lCKdq zcpPfDDt^W~mD;vt0kTh`xIOwcS~M1Wr5oKSnR}d~44h4MP-7YOOZaN8GL{|i@vY-? zg3uRnW(rAjHG~^#9N7T3ktc-a>rwu2^J!~bsyX?}eS##9W{&R;_FQbDxIOwcS~M1Wr5oKSnR}d~44h4MP-7XVIwhevP9f)z zVII0l9!d;xW(rAjHG~_U2rDF@?sohogTLpA_Lz5gu0=y?@T$hmLgmV5Ddd_a&)ahg zBI!4T>FxQ~j_iOw&OuYy_QOaf&)ahgBI!3aHg2-%fYXz+hzWUrxP}2^Qt*&5zCd?N ZdclKm&jA+Ep<}o<3>aAneGLkI4GPmibrJvo literal 0 HcmV?d00001 diff --git a/scripts/ff_playerclass_pyro.ctx b/scripts/ff_playerclass_pyro.ctx new file mode 100644 index 0000000000000000000000000000000000000000..1fb13d41a43f6d3d64fdce1ea0ca4cdf54da815c GIT binary patch literal 1255 zcmcbfufy9a72n>&8?vvscj*EIW{Q%HTyw_^8_x6zRm2R^)w2;ufmpM9wFthrF_ z?Ca61;+oa--v)8mUR7bdVE(pCsy6JAS@YzM^504kJ8rNDp2z1$tMiq1-eB4FY_bir{pRe<$zsu5 zZzh!A?XL+wH@nVAcSex4{=(#Df%~@@1QSgpBCh&+Mm)>yJzO}sOfrx6WODtd$*E>q zA(^+%T7@}Cu~q(DTqCpl(4)XF_(b03Hl8D83TscCt#DYz&;HTouyoRoz`Hd(UTgPWsb6QJoBKj6<=P!q3(;B= zjjx84Iq@EIU#fp8oMj+8M`!PLvlmT1_Z6ne*SK=r)muI*b*I24-nqM#uGD^6eyRS8 zkmw5LfQg@Ph(7gwme3~C_-T)z?)R?m)ujjQxu@J0H(1a9XXZV5&H|kUIZJ13xpeP{ zqQac#`L50NlUAsHw-y!Q?u=7%pDntv#_e(yQ;DnKbHR+w9UEqqO?rF(qV%V4#b2!~ zBlax6{L$d6vGD6fX3qqfc6*toE#zg{^sDyEYoXE~Mk+V$KlWJ5E=Wy%&*oyKq(8sz z)W+rORGMRd9h~HJ%})PU z(^Gxf0M~~{*4^8?>~Nh$SJ3n=uJV_p^j@y{f2;jKL41_(Z}nN%YaYcv=QlH=p}eu(CZwrGM*M zSU$Kj&G16Dq}jP8r*}MPVM<&sSij4&Z^>w-XnMQ4{EZe zNmb-|Xnl6KI3^*eW>Fl&W>S0X(2{e%XY0hO2^p?GZ1_r1M!NYhV zE}uOii1W$;v8YC&xelRAGWmu0o*KIs8`hoKUK>*XYwvxR|Lt$Z7Ydi$2}<>wlNAt? z*7u(8TTITP9k#zrqfErAmrCE&m{~n%5zido(tu>iaz2gtFAbk3eE7KbadFcH@xnAN z&tlUS=`5L>4BIEFw>*0t_^;q|W_HXf%b%xen^d;Wdv&e1YQYn=^S6t+m0p^+ynOrf zdf%G{kF8fDw!f~q1`{_k%iHv_;qqj3e|lFPY%Vy@D0XpS@(wc|iAc^`UM?U400yR8 AA^-pY literal 0 HcmV?d00001 diff --git a/scripts/ff_playerclass_scout.ctx b/scripts/ff_playerclass_scout.ctx new file mode 100644 index 0000000000000000000000000000000000000000..fa75a96571f3ba4f688da23e0e8a3908d2b26eac GIT binary patch literal 1357 zcmb8qYcvxI00(ed3Ps+!nue}7;hb!e$HZ{O##A27Baf?DP2sB4$ZIpw^@x#YF=X<% zCeKZ6<F6C{7wb`Lj0br!%xP$Nm;gO+2ae7@d#6CLN`rMh0g80f>%dI zQI!T9`_J^Sj^&i~CI{Lo2uk_GV$$rgXc!gk6KbiM4xU`?IG+Dc<;WbQfG-*3Me?AG}S>i!;5m_4Abr3Ko#q8}$*PfH}<7rADxC45NAir22Kgl{33@{9W?Dg4;_T~&eD>Nukd@AMA#S3Ea;y1>*##f`tD@+;r*Bfdo_d4hiB{gF&nQS4z%%&aLz;(%DEIWAu% zA=+T+vDzkKs0~>K@VE)y<_@<$(@~?)175qp@IUVJ*jW;vr~|4bB@CLBvd; z8pinA3b?+&PW!NgewGTbD#uI7Nweo8XBk0a501rbrCWzblb$+(VlQ20N=B zW#iY>>dlcf%;8X_Z6Xh`$+0?)g*~@e2cujMKHZp3oKEgz;oC4?@XO8^i69`viu$bi zA?+cTP$B}FpH8n;*0#7O(2aPZsGd&Xg42QX0ePx&cDt*|T6r-Sz?Wb9@0+uf5BBj=93xD=ebtk{S!X^JMzZBp& zqjlaY6uFvhL5E&1J8!d5q~A+@<7nrz;~r7jwy4VF*{^_uvGpag51^b8+wUP)Bi$I> zJe=qB2!y-;RBD;Kgu2EXvtwHA+y%J!4!H0m$-i;Igcek7@ HPEPh;Udd#Tku%TRCJbuUxK$IwSrl+cNr}RZ)i__-NfYq*DPW7sDL%nU1_^Xk{&9P ze{SP|k8vDxOKWrVpTn*5FpCLxRsY9aeMr~a<>GCW+37D^8{H~- zxklquKu5?atH(VlKu24=$RImO*I}JmY(>?5+Q!zNH{xWk?->1e*f z-q>iPar17jgr{gNcG{TC8X=A8k7c{W5(_`=oYOT!XC&Zs;Zgu0{h6{w@~XH{bk$xe zKdB%vd>(55$cL*_)YKO2g?ql#HM0?Bd*R78_QMt8Kt_bluO9wf6!IZS-uHrA_@oJD3&-zEzKTFT#t zi{4az-q=PtDYSxZyg_k{1J>>@cq=9k3wB!rzpGm-AX*?hRJ?y`8n!rCSrNJ(`Q*B6 zI!~`F^;?%YHC!bAohxXk?Wae^E2H#H*s5YUjdtKV6oZ?~04h9J} zZM6$(N3JtE?;{xTBJTFp6HKAmsYM>Y0Sh_8SiutBb^m zdCBS{CKpfmmF|SFB3(4-(|5FUY`L)=mw0{#_?k_}9>)sTxZc3MHJwb1U2Q92WCyCM zeSYa&Xn)`WVl3uBvdzpavGopI_x+U^Af~C&E>lW^m#sNBW_NI;v^z&inh%Xqt&B+zi0io^w(c zHF^*L87dFqqILEW?C0S#31VR)ZB2_EQ;1>pwE-be;eJ literal 0 HcmV?d00001 diff --git a/scripts/ff_playerclass_soldier.ctx b/scripts/ff_playerclass_soldier.ctx new file mode 100644 index 0000000000000000000000000000000000000000..10cd7163e5e5ad5f457697f83a37398dff57a622 GIT binary patch literal 1265 zcmaivZ8#GM0Dyg+49OO$(QTC7gnSfI)`SseW+a(Slq7c|oV7EK$wynVu$#8rl8Q}h za-L+Xq^rZR)@f^|Nri<>EA5!#e)Y5G{=V;@_kDiSZS5IwkOO4YBAGoUK&`e>qa@I@ zS*sRN^Bn#VY4fK8lDqaiCw6bukROP`_8}CPdtFViphe_2!;Tf&T%(Y|D~<-{Ky$RK zeagU~bv2?#xm@&+CU^E@>OQB&p51lKmygjW8fqD4r4HRJ^rkVLRpiG}){GCa zIyNeL2^)ZRA3p!2PGsi1NRWO2%h&4DbMEQ05+)(8A8;IYY3mD#+}m_RRul{-p*^Ws zP!dc-8`!ENaJjdRYmi;s_?_wGtF2p+aTrKXNV;E4yGEVp2o}7dVEuE(ob;1pVYbWs z=ckI2-@(m(QCfZBzQU7@&TYJ*5dU@#ai&J0R+6LL&7!$Ucj15`P7B|mX{4j%#C>sh z&xYLti|>cBEvkr4VQky>^`7H7b<0Iaks;ey>Jxm4wVSR6c0TT%=_86=-}<+AHqOY; zk+~CP9PupD17|A=vZqhyp1olI?*l(3@+U5T+(fSQNVK5&w>%9{t~&#axsJ1R*$z|Q zZ(zy@sL?l`bBF2=a4iUSX4ZXdbvR0Dy~OKm_BL)1iYbQ3=rN!^|GaAl!y>=iZH{jDv-< z#FTZbbi1lQWxNZoO-PW`)_M_F2-GfgT3GnN5E*z%pKQ6$mZ#T>lqK z$$*;P@ThJp+w1u)Usw!my#Qa(^v(oXPlX zxUjLYG;kH%T#ekEMz^hUkxwMkoFivWM^!Z4#w2j?Y1PZ0HvWiYgyce_yOPMbHoVb3 zcOe3ipSicRD^H9TCE7&{*66aR)@f{yodTw2vs8lj0o+;$;V1Mx*s`5h8lSQF0|!l#g|J{G7u!#t4l`TKQ$Y(lKn9wGl}QFG(aic`XqSo z!7u3aD{Plm4k(A;@sBoe;$}<{N;ruM-31Q_zx~$s;TUqx_i$Dl$NXa8=rhDpYW9hU zUR5mx`|_EeYR#UqMzj~~l(o5**)&6Pv&Fg^*1KMw`oBIZ1){-R17T1Z{rstL@bO&V zbeFOrf0xc%&vG@4=Y@bHwa(Q0>M9+p0OlR%Wg`hufj}hw$$4$! wS3aEKI2{eZc;@p0=Fr`SL%Ir-rnb2|^` zXo8^DA(H%wfY4NL_J{upe0LM@_V^g=C2bNBXuW#F$1iC!W{n-#GWFyL{N`+h&W0hiF=sB^2765I`JAnR#oV@ElFH#k|LK}?fbBdBz-G;>Cd@R|bbO~t#N^i?)%pGTN zcrp&vHjsD>KU}N5P*>+QzOj8^41E~IgHwwqM(#Uv{H~t9A{d`;%aqV+TnQ_PTl?#x zKbSFU5y$xW{aCI(&LUd{VpCibWUPtcThah&^~fK|^_j03yyhVUvig1W>k@VNG9=kQ z@r*n5ha8hGNOJ`uFQ0zOv8S%9tBFz|Ca~IY$e>8U84~p^9S?c~Gcf!0B3UFQ2et;} zuqk_?+NSwZ2ymfI3Xq#G0B6)AQu!*~B0gfoM{5z}(GO>qS5MuZ_)E1)3(G7AtOT?% zx7GyQN-3oouTQIpv@UuGdh;`oSFx{7d(l7;Fg>Q_Qmv-mm3zdsrtkmf`U~Y*qh$+{ z$`E=S&ie@dvu~ZJwRks^HUG`#b> z@~E)jNU%v^;f%<-h#8S-KfaYz$I#MyGqZXy~!Sb^WH%(u<9?j(mIBQ@FiC!W{n-#H*NHd+7gP$@uQ_*z1 zlCKdqcpPfDDt^W~mD;vt0kTh`xIOwcS~M1Wr5oKSnR}d~44h4MP-7W)4k%yrfb)>> z@vY-?g3uRnW(rAjHG~^#9N7T3ktc-a>rwu2^J!~bsyX?}eS##|DLu0313VpLQt*&5 zzCd@LRy_8ZC&skTLq1piOlPCF=oQ1>KkYVPZmgUNnn2ssJ^5mAYD&W0lYLO%)HmG+ zJA|H0F(z^l3h|br>Ub;_P%8nIE1~8bgMYE+ePtlrwu2^J#0GIE(P@=fS!9CD(C{xH87(>rwu2^J!}=t7X8p90oLlMg5J!k}Pf}&)ahg eBI!3vb^T^-3C}lY-I5gN;mzKvpl&|*fHko>4wkO~ literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_assaultcannon.ctx b/scripts/ff_weapon_assaultcannon.ctx new file mode 100644 index 0000000000000000000000000000000000000000..ad4bab26407d8908776bab86b1910503ec02d7ec GIT binary patch literal 2625 zcmZ`&S2!Dt0yT=-4W&V9kJuF|#H>BaZ;znFZj?|fMMP~{tF>z8u`q_Mn*=c9Tx-04q<>CeV80M91!_W|=?}ZF6Pxm@QgOj*l z3to0qgjWK;WI1VSh~!ML)4iUW;B6o3^4avjPEgMVB0THKKo)TRtU2~m2z;8taTkb< zP}A#dNo+9gm?T_jb$#{L77L_2Em8OU4GUZrh(E#2R$PWRe=opqMlqJVYr^!4sCwRL z;ny6EY;+^%CSoE0@U95x(T>9S^M+qZ8hiJp5+mR{H@SiLszS;>$Hq64B|JpFq@e>w zzR0_}!)aZzw~>-&oWkZPXwlcoI^k4zsb7y}(ldCh@_XZfQ;-A`cQ^ND+W+82W{g8> zs;b5E*6BU#rnm0Ii{{5Mj8DpAYvsoFPqtKxloyxQDR;@3v(|3KLFl(XO6bBp(dA+x z)(o4zf)pE$_~znG;oPg;#>I@p0~-RHSn=sg>JJHr@2PD^LSoB*zg*rCum#Q8ZHHV9 ztLbik)shp1mj!}YV?iJd6C%@vgu59k2g8hlPvcH1O5?K+laVwP0ci?5xRM)yW_l_&X~y}D?OR#T*^7Y z8rkMN**c<|#B)x*=EZ%iKm4GMs~hFZ3MKL0cx>FRuzE|FAKHB^!k6)a8Z&4?97xor zlJ30~xkWRz?$cKg2C+;ds^5jER=6px-2ndWnPo_^HWBDpnnk@hZZ+~-g?9(8tEdNX zIhV$f-an$kFEubE2RYpD5!N5<&I$=u9L3D2Ric2m7PWG_&Qz)VeGVuo3J4M!@PmrQ)(}DzYMovy$G0jw!2g1_vTUQ0@<@5hco)#FUfUI@ zwK;)W@2klJSZhr3X>U9~&q#Q%>uU-q8E_r`83kGy5WpRoef4w({S`6u$J{R^=GbO1 z$HX&zWVnlbYl-XI+Z7~iZRO$na?-cBGhhjzQMFT!?8J z*c<%36FwyXQ?QO^%3>YCLK_^lP_)`8)AJjcDg8S2(!@H>&{1dw$M#i6d5QMt&%D{$#|Hg82sOpzn4S2-Dg0HmE zPtF>4#Juf+`yW%8TL-MpPLkU9bzm*N5J2^mH+lZ4*s9E|ssLm;P^ZuSR}xL(Zgl5{ zRkU`E>>8q;@u9)&JF{Rsk60AVEUSc^qz;Yj$IEyoO`?Xr4gOER+O@7ki1DBGw780E z9aqh=Bx;rCDhi5P@YZ{zd7r~X4|ilTqx+Ql^hD0?!u6FFi;S{H28kjc7uM4tsN<6B z1AwmPcAxnj6!w7O^Y^6RFozQo#bdUJ+fBg|JQ=4@nyUs!<^{^Od^w$5bhxwYr$VdK za)g32DVK@a>W~XFxrrYr5l-|L=B8IY$TS5}+cHUA`}qxPBHWzq*l+ZD6@!P88w)R9Hg-Zbi@gMzIt?@`N8wd0Jve2T}FSh0^ z&<=m@=)D@l=p?NDp>pA|?JJ~!%-b4y((Tm{E?&Z?=6)Bbrs=Glh^06&5yQ?g0#Iz8 zlVFi}X)CjFYS5PBV2iSh7{v1Um1%&sDd}m1z5U9e;e2v1=qG#IagfKKlRR*55Ews- zeBVh_QlgZ4k|o1hNBB=OWwpPiT8A`#3=qazje}|ZY_jzpbOz9j{e9%pd?~sGA-C)b z`Ub}RPO_GLtfYJ?^A-#AF|QWl5{s2XmCDxK3HmW5shtTMnww!3sI#9^J9qU*8uhz% z*53a(5>WM*7TGMY3M|B>M{+KgS_D)|@Gmr#oQd88%s@Ho{pJTD2;O(5F5|>1U;?sz zkd11%Zm}1}nbE@G$`#OIGL;wnck<^Ru$E%OFE7)Tse$3Y D(>4T% literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_autorifle.ctx b/scripts/ff_weapon_autorifle.ctx new file mode 100644 index 0000000000000000000000000000000000000000..f333c31285545eca8d75dc761e045a59b8f7edc0 GIT binary patch literal 2255 zcmZ`&XEYm(0;P8FwGZfV5$6~R7sOM^mq0MS+XE8} zY1rv1y7xUZe6R7btgBm-g^283^DP;$vu>^`tCOe!zM#ch0ojj>@$FiF@04zcn5d|w zJ)tfmIemy@qz$=(n8&;=EPOpe*Ny>7X^BUBcNR453MJodgt9NB-3!F1{CN+EKU^mS zK8fLbBXZhO6kN>v4d(#U5=$Sw%JgP@6x1{@F{YY{F`8O;n>2cI)8(TQlp!cKYxKE# zmj+30Ds-t+H|*qoWTLG^ap^2G$hicZ6I0`C;A@OD=B8}%`Z6A_qT`&~limdV^xkQ| zKA$)rU#a3z28n4lC+n$9jq{<2r|peUW{~;cWU2eM0d>H{^-tQLmTp2nKf=|k!@~ob zCqkHf=#VKg2xc(GJ+Ak30XOWE#peW-2{rrkKvXxmA%&IeM+8?J(8RA;nZH1ZG>blhvs+j#sx-;hSg(M zr$ayZpb#QW5q!{)FSK*gc^JsJJ@-Rx(pEwbHgl2RaGNe?ZFa1Gf!}e&uP`kl8HPve zEuRIOaq7sivJA$_!(HjCb90P=%CRLu%n!y_g>Cq!ZC5bCMA~4Wg9ewVO-HgSQAzte}ssVEn}0)FkwFkW$Q!XxWOD`e_Qss^pN zaRqfyOi9XSl|@J+I-vJ6YS%|;(kFd2%;iTMCw z{I1!YE0X_Q%*;1bF^`yTlgu6-$<_l9@F=y!cdo0@>{*k+siBB-quqV5Au^%3FM@-h zf!*V`>Hs=TFhH{kW*iC<{6gRT3Sz@u{u-uSQ`74d$iT(?#Li;cAZt}qCQui9@{pv{ zxW9uk0nv}`Q@e1D?3LB5s9*O&$kU8JSD%shtN*eM_3v4rGqqZaqFF$e3p?P#K~3?4 zW{pZ!?iC!ufNjPANR=uaNa`s`7@@c8;1RLr1aYLnL&*0r?_Z!HPt!}v5Ya=}%_?CN z{H9p*?RJ?ul;$arL90PaiBf+hFlUf4=gL&qo#Z=#xsuI<@xO;g(Uh~uoJyxJ$*+`c zzcDl)B=BibSz{bU?q+eOcU8U}!xz$7EgEcM?26N9Fn zyM#4!z&waFJLlV{JU`tSzuX&YHt?7JYF`!c6oI3T$4$>%m-vMnW$w=ipg-3>$O33c zd3jJj80e0d27uHCzlhYeD8~lIj@CXCv!-uKCIxz6rDiV0U|l^geN*5b*@{BG_8-!g z{pqSdfMyHZ?C^N5up6f4rRvNiyEeA%?#i@Y)_W3Dp09o-=Zqe8!i&7`@k!5le&kvB6-x=t*5)3G%X3UB^HiZ{`XElAX48iw z7yiiJOhF>uDuH44t`ai8z7{@j5HQZq``G=7q#~v5X?~q&>Jd^+LLzTtGU>7NE~Oz% za=B97=%Ikf3dy9xMdn(eox1`gjS_#v6y}E|W~a?fXX~EY<1kig@E=>tlsC5%xrN z(V`^Qjy|X)hRfX~m)+7JMnKz8<|)>?pVohWA{l>rd#!v>lcos-+|miU=V)Kvoj855 L6P8eRz<=>Cvvyy_ literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_crowbar.ctx b/scripts/ff_weapon_crowbar.ctx new file mode 100644 index 0000000000000000000000000000000000000000..b53c8a8c5784b7dbddd7d0d84cca3835c7b846c0 GIT binary patch literal 1547 zcmV+m2K4z_7F}oT+`;`49E`ap5zd1jqy6v#9zYs2%GCvyj@hpRoy6K2g`9fT6 zyXoZ)YFD-*--GnS!3VPpRa4v$#pP#898c#p{A&a%W8iC_squl=b$GQUo`uj;#J4a? zm|zAGh=s%|F>@onKhv#7^eWw$IS7oiEl4l&QN}yn_OvF(qyf#Rjfo)fhT%~U*tuX< zkwZ{aXKN09a?OY1wlCHAoby}Fq}%Y}013pS74gaXcJ6aibeTtMwU_z?ZVhUi{#iLt zrHx^<*KRh)87@A+0C%GwChecYG`(KY{#qxS;_J>Iqy6v#9zYtq(gg}2Rj|gEFQJ(2 z^gQAeLNc)xur51ZtV;lgGE7x3NBf`J<1zMGO;o35UN9hewoMv?@eioox1Fu;@VSgJ|&f`*pM^C;LY({*b zuE4>bLTs?hDn?tMKU~0CgYMe3B>tKXco}P&>zjN(MWHwkR#i{(#pl|kU>gC|D=-em zv@3C2EG3%WCWxh95hgg>3UF+By9PUJ zGW6bPV)xkJflTFp=9PmLNx*{L)r#xys<$>je=hsLWbMT%fZ+xZcdI1^H?iL|4wO)) ztm$cshCHSkYD{}NeU{wk)eTKhU+@*rrBA^(WQcqk$(!;Wj*%eJ>%Ps=a%IIMyqTi+ zVWattCAkcsB#3Av8VNkE&iv-!b0G1)0Cprxuw6<}U+@*rrBA^dj~TqshM-As$e>8U z84~p)7_Qrc2h9^)vX1RwvA+XsgzXPw$C`aH%!37xTvI4DCZ9CAE8YJv_{1zZ4L0+; z>sw;k-o&jsP`$hMAfS{7Is*o(_>^Iwwq3OT+1n(43OY?dDTGi{Mw1zjc-Veqf4C7q zYQ_Na|MC15<7fuUNzS-Pb1Tgs8+tjD)z1lw+1eW@-eBVh1kk)A4C$2kfiG`;1yQ7?MQo>04Ro`nFDTD#YMXqK0*>?|dum zqaY=OCEatj)7KIQ=w3WHCtb>FmFRg?7PNE*OPwg8?beWTV)Oc3%{}w+%F#6gaOKvc zqEw6UKzu^DAqqn4wA0uvSpKA9?jRECaYxQ9Y?Uq#uEobS4L&+jYS>1br}G{n?^eZA zjydSsaEyH`EXMlTWJBYC>Y@@=>t*0LymCQ{OV>nc=e>Zy8V3U~;GT!8K>Tb}7PNE* zOPwfp)LDd`A8~?a2kfiG`;1!D+4`J3k3``0CyiYU#(MdEAvb@ST_T<-p|uT5j&$f; z$h0{wCo)s?l1_0$PS|pMSy|xnN!p5a9Ptyj^mJwZ^_eKZbSR|GYP!3|I5+_;Y?Uq# zuEoc*0jh97J-IEU&=GnMs-rs4JNekLoJG>)MiKckbdA9Q{9Dt6J9Khpr5T#TQ?o{> zNMA2Hu`cpbb+oEP0Mr$pLdx z4-4Ui*_f@ap`2yXF%M{5=fNw$`4FlJ>*4eMGhO48)ABeNy5qg!-F|7+8jamuUl63x xTvj>^LW*nO*Cc6j{=$>|y5fBoD zeo6_U_FjUIjnihefXZClVC6#pk})Y-V3$?|za^=WiRQ3&Zc4pdcJI%v=wJLL-m_q! zD+_UQpsYLlup_b=_`B0q5El{M4x`RHz|!0e7&~^m(~uLlQaGkaz6N#>QcL7h^)vvZ zT>yT>kXVxfErEnJMok zTkD%VF+!%;zp>3bg~VSfT)Ht7uj6nwno?gU+A8M*s5{+EPvyr9nAA6rq^~Bm5XF9~ zCPW{($t14x5C&mUZts&GOU|{$M{m4L5%^~-DruC_&%e)2G4uHdX!(_`Vk45t2!uKo z@2`7`0*&C=z_6sz;CuA*6C*6eY1E+4&YF4bk^6KuldZD2vz2W+< z#3GOC>!U9hsaZg&UMfNS?}=aiY56pc-uiHYap>f1d&j_|Mu>*8W;1gjmB=+5I>^w+ z6&UWJcfZR0T@DQj?q#h9~u#BfAsYowZZJBAG=Q{lp(yv<`i=9o7}EFV#t~Nrn;*( z@0|x)oMQF*G4n+8$GqC<%&BRJ&ewur2@l)Nw)G{5T>#UiVfjn9FVl%Is;U%&jng#| zc3i#Ra4CNy$Vx}2VsShtCU{l&B1xA+hr66pgK}A}Peb(;tNgJrBZ@F-xnBwo<~)E*+2g=5sbi`$G+_-?GJ1{~T=YL;{v%S*M*sM+@Kb)LnzYFXAjG+i>& z#dWfFMSmNwyziCy!}hveiw4k+-#9X9;PdA}u;3t=hj$#<-q{3%u=EI@bSQqbst#R3 zcYEHp;7mtnCF<$F6;6dBza;bSgHiko^X4yOPGq`F*kczuk~>u-cO9EAO@C~=h1=$$ zl|*Ttl!u&?LhX%vwmK%a-Tytbq1B9hh3vZCkr)fF{xm}tgBL14uTx8BrhyQB6aR8a zh}n(1Q*({Yu9e|_*CV!mRVYcN5eYo@ON39&94u?rscIdjJc&CWS3HDd*S1+IZ2{WNck2ukbW#HOUaO_+${ xys{t(0{twap4R`I~OAl2%1LHeG|Sd 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 LO-C>+b z0S^hQk&a^I**1SVl8@ram!>#4(*^(6FAe=&HJjr5VK)yq6>#0E#4h@f4-J1-FDE^0 z$wIVb4|;a-c*c1u@r&OiL7h;eVTibFX`zt5@L8uLP{0sLRPNIMb=p2p1%%8Z=>f_A zuB3QSPvqjF6~1@P*+K)Qt(mp60kQh)>|6PlaXX49HA6`=kARTb7`&ywV8pq*9_@F zNzQLIw`@nIsSj5zT)<|Gu~qS55mKUti&P zXxgf7C|TOflBcx$npo+i=u1U;2K5(=K&wcWWu(#;xccO;ZKjLy>jfi6X^B8PSz(DL z*$ApI+^GQF(Y$MO=9@>fl#m%CEvCb@Sa1|M`VxykUq$I)f@-Y?rf1yZ zsJ$ZwInAo%0*^;(_b95J0NwD4E6n!gI8-NDNh=@&+QQABX{o3ps`%=8~ zoz%Kiyk+Hc2wR!?Qc{+@>XJ~B7G+*Z{tiR_LQW7@L7kZ59~vyU#+)F`4miZj?35RD zD0FTFSU{nGh#PNQCASsNRU`IC%f-!oncvKDj=?&Q#~#xcCI}>^&R$)U306L~qEil| z6+zq}7X0yq=0No9bx7+gCe^Dt;|j{RUDANt8YtZ77LXc(*z z$a$K9D&N*%j$6?DC!*5eRqDRQ3r}PPMJbUmXIS&$b8qvaQGjTpe%}VyF2WyhY8YHw z8QpQ1K8Oi6WmNpY*;&8Fbg0+HD$`lQKa*Gxo?%ha@A#n3aDF}D@DWwBZ&ACLc0ZCG zEn@vNr5=dqEzWgk9jIFSTXU=tB9{C4K7H*UnG_nd?ou`2mv6=>T-ij=@lN3)XS5hK z8`@!Q6BX;$KutZDdp)pVR8P3E6Qv0EEP43#N?{g2si%-6|Ly!%UwSTm(MUR&WDz_* z-Q3duv=#yd>(}%8$rPdKz_AYFh&)qucGsH+7+OZ_LDJn;*XzHi6Ab&@LA4}B#}Y$O zL=63r%Y8MINr=x55C{ulf$1GrICj}2QdDi1`Q!M;jT@sv?4Vu@)AJ0WUXlB#QzfSe z!)0UHqoMQD;HxX*Z_KhPu-MC|8x4Pw9pVG^Q|OQ>FPckgMX<=Y3ufGhy6+#%(*8tbOdd%DY4w*3pV3#v@R&mOJH~8@ZqTtPKqrE2G)5fg7?{sfa~3+Rnrl|?U zC9=)^ioN_E`{^(zxK;I&A0?KEh&KNIoAaa0a`((tn`GMtD8N=!J2Yd+^O=rg z7l;cjX>HmE_MiMvn(@MBCt{BaJT|&GY zlE6P=`bbVE9`wB(3=tC}b{vrQ*SdQjc>m)Aai8kV!$QuM4cP_`d%8XJBnYxym8PtL zt-uNx)=U5AA#rI9no^hAyN&#sZ@<290Ja3uY6RTIYiXQ5wEa9O>-2It?{nWB>f2`% T$`{r#;>!SupQ3L!3(7!M= literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_flamethrower.ctx b/scripts/ff_weapon_flamethrower.ctx new file mode 100644 index 0000000000000000000000000000000000000000..f443a4881f045f5a3ee312a7df7446980601d251 GIT binary patch literal 2469 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 literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_grenadelauncher.ctx b/scripts/ff_weapon_grenadelauncher.ctx new file mode 100644 index 0000000000000000000000000000000000000000..852456fbc950b8badfa26bd7e5ce22213a517a2b GIT binary patch literal 2447 zcmZ`%X*d&(1J(!`38_uZRc<+R-$!ycM{brQKilLEDJl1mYmUk_$7I-&i8%^2Lhh?( z&ia*ekvZo6{lED5f1dZ_`@F~VzAl&C|5=;vJmS5Y)-2957$;PIv;h#*7r5CsaW*fV z@|L-XJSC7&o&sE1pTxQp({0veCA^F<8aeZd7Ftb-hRU$sTvX7fwIa`abC(Hx{h5QK zB^YmD_t-2=z5*2jYCb1G7QVd4p_-S$*t#{Z>xz{sq(yVh=b1%>tN$+INZVa&jd+L> zK#LwWS3Z6N8p?Io*AvShbi&e`A$iKPEzjN9uC1r*hpb zt7M=M#sc1#&~Zc6g45+9^q(ln*OHdKjdPDAy#_K=fA1l}YvyC_*a;IJ#_eU#n&FGP zh@L@j26{;;57Yv2m5$NE;au_4M0FFa@iY2rP6#1k*9q9UZ%Rx+K^ml(LC05WY{+CXCx8o(OGyb@#c5FCI9|9 zD2R1;B_P$SJrf=I^TB5Om6?p0G=e&!MhQi-*)UfBJ}wZ@ec0Zp$u4NKm?eG3DU1j{ z@6*m>XQhWT{}E}jv?Fo}UfT@Oe`2h7IQI?aV0kgZ+&>o@xDspWRF?D=3hz(-F~OUk zn0N_pxRTC(mbb;~*Bi&3yJZTB{(Iz?8U-pJ7KYK*S@DVy8EYR6KK{6&>6`wyo_&pf zzR7fA!By-2`%|7S2#23w;%M4~O*wEo)bnI=r+C1@a@4PUPtG@|O>3U!t}Cb?K99Gj zS4YVYY5L-5Y}9vG9~b5a;_~Pdwp?#@)_U+&dL_?hu8Jo&hRieKE_#;K|Dz50%11ER zEHr^6Js1kCvW6bP84M^(&*koLS+#)(IGjdJS6Gk^Z9kZ`;0!7`dwU zA(}4CoS`W z?HyU^TKcA~6E_5)${3Q4F0xuX&1JN(ar2niFz?DkQR4&NmzU7f0kXFQ(*Eq^qVe-) zL%+(Jm-pU_b60s1vE{Fv$3~cdj~Fume1F-&hT0R(mszOsr(4b!6~G0bd^3X*0NLUN znr5?S(>!#_N4O>+CZ#$DC)@svrr=zuMu)e9+pnM|sQuK47IL>J0F z$f7o|Ya_V7DFaJU+b^g z>?YAVO1VFBA0s)u3X%sC8cJ)LI8WgQk+MVy1 z#TA#xN#=kcaCYULYxw{tYKj}UO=j!Yaomet40^GC&2-DJ^1$lW&$;HVwLYlUIB!?x zjoEx3Y|+p~lndDMrB6vt zIr$hwfvvvsXCC#5nM59;?e_7tggT)2zh+N1D6BtMqBgec7C8rdw`>Dm>9tiRpA)p3 z-;}`i>x%D?bO;*!%egM5oKvRYBWY~k%lnmo; zXv*2RGZ*t@<4$st4BzE^X|-(1|lL+mYs?>A-B(bDqT?miZ&-~9!>87 ziUpm1{;>VSkEp8%!xX6)(Q~utx7E8rJmTt9jv)U>t*lx|rL9>%uifu+&ns`hT~=J_0GW$iLNHBq}#0Acx9Gdgd2 zae~VV3ftfx!rtjr^GSXp&|9zxNzW1&brC z1`x=Nqjbj_& zbE{9M-Fw&0eELJh{(K#s;d`emWh%~7O)Gt=c&MET8k`aN{i#n3iANvN&9r&)_wdqBKi02igCx^X znSpEyav=;VAd^-?NmFY2B{u*9va;sy1 z;l6BZHC+d3E^44`W7@K-bKCBGE*oI?m$9S2Hxd;au9S3fch7xS?ZD6~HYe}~=Dm2R zeX(G`W4LsYSU|~t~^{_<4_J4147zV zUjs|TD+ZRz*IW+!GcIG4quEE9ZBbHJkhr~!q3BnKJSkR&ryJ|g4A^JO5vri|7!&l<va{ee=g;f*PbLYDFH|~OU+u#1b zU5p~j%hVW?6U4SoAfH;k;fCJ2LY&q2{(!-0xBTw3kayb~pU)@rK6i&*s2Fi`&^$CU zlo%CLQpsMTLD*}gUgU0vCcD^aGrLxT(oz~yME_>`YM* u19RC&=?=YTLboTf$`5a@*7oZ%H3@>(4I|Aw+-g5(P)>hxE}DzufA|l)r_3S% literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_ic.ctx b/scripts/ff_weapon_ic.ctx new file mode 100644 index 0000000000000000000000000000000000000000..a44aca38a723a016a2b222ff256f9208ea939a5c GIT binary patch literal 2273 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 literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_medkit.ctx b/scripts/ff_weapon_medkit.ctx new file mode 100644 index 0000000000000000000000000000000000000000..f13bd7c1f3bcd993006020956e7505e1d7f2f056 GIT binary patch literal 1793 zcmV+c2mbh47F}oT+`;`49E`ap5zd1jqy6v#9zYs2%GCvyj@hpRoy6K2g`9fT6 zyXoZ)YFD-*--GnS!3VPpRa4v$#pP#898c#p{A&a%W8iC_squl=b$GQUo`uj;#J4b^ zUrit!CR76|F>@onKhv#7^eWw$IS7oiEl4l&QN}yn_OvF(qyf#Rjfo)fhT%~U*tuX< zkwZ{aXKN09a?OY1wlCHAoby}Fq}%Y}013qEF+-X0`!=~yss{x*@oRonuVx98T!g7a z+!IoMu<1`v~Q4i*`qp*d_GKXvwgg zcbD(5j_RaK38|jlRTe+!=h_@~>%>3BJ=@N~%OD5DWU`wigt>-=Sd4vDd3;!(XR2@d zi3YEMFOC0dj==;r4O!iI1mJFU|K^+}|D$od*PKGP*WarHb3HKP35-;b9HQ~&QzY-} zYLGxsvESoJp9Aln?AiwzLF}pnA)iGHI=;65&(094KGf`)X!KVbLLQ3V_LAwc0HIvz zVj1RCSzF%UJ!xAlTgm+C^zAC~nn~7xUT(U(rtKW-(DC8NNuE_jc}EJcN{W$U`J_G{ ztY3o0v@3C2EG3%WCW`1l>WSs<3f4h$5T zp(VK{eGM=((ebtnh$VXP<-ZH%?d-!msVE6bGg=hhS&_s>23x8+`r=|+jl%Wc=y|i< zqJ(JlceGC(CPp%kD6Kvb7l?=5Hi#V7Pa~h6M7(JnH};1vE_`e^QzBwBN>j0<8v!!PgBp zQzBw-e|vN)dL@PF_XZW=Ju1 zd#0yf+f?mB4(AWmgm7KDD%VDSV$K34viWGY5>?&k;>L^zukp+i*SQ<+0e*>^@z47A zA!G7SuhCzYFQJ(2^gQC-F;Z>c7@@NB8fd`Tsq#A#6CO{4$s%Mm$!aW3hM7{ReAK+{ zn2ZVt$(VEm|3UW6g_N4;EBDfSG-TM^yS>h*v>PEABe&hogof!Z(ICStY?Uq#uEocV zK8lCF4s?RM)*UWL|9dY~7PNE*OPwedY;l^APl*jJ+8bQ_5)vY2r5T#TQ?o{pbaZaC z#WJLIx$|q*=|j>Uaidr{R<{Pfk;Ds|g!JPmy+E+?u2kfiG`;1!D+4`J3k3``0CyiYU#(MdE zAvb@ST_T<-p|uT5j&$f;$h0{wCo)s?l1_0$PS|pMSy|xnN!p5a9Ptyj^mJwZ^_eKZ zbSR|GYP!3|I5+_;Y?Uq#uEoc*0jh97J-IEU&=GnMs-rqW@v>KF$X^i!(Enawv-~FL zGViqOB5iYp`iWI9X*fCjE~$SQYf-8r87G7>Z=o-%7j*8_D?^kz%GuTpA+A}}J^5mA zYD&UmyR0?D&2gyz25Pe*;TWBxkbV~5p;B?DDj?gkp!g;*5!N>ruWs7NGGQLLPGHf- zs2GQ8x5yF#%&y(QIu?<%6=E52Xbsh72kfiG`;1yQ7?MQo>04O}XQ|B7Q&*#nNgG@N zw;)&xFTNzpgqL3xbibM=W{MyWdf$9HeG`-viEnf>!QjTb1%=)qC+!Xq@f2YUkelmPzvG2O{bg7`X~~RTvQN zh*u0jcRvmEyal-gCU8g>CM6z5ejm^l?X6|Wh{7N%PUdGB7ejk3&F*sCU jwPo^jG@2p0e^_R{W~YuGDF4&(>=>*7hIR2 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 BRoVam literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_rpg.ctx b/scripts/ff_weapon_rpg.ctx new file mode 100644 index 0000000000000000000000000000000000000000..e673708112748a2fe778f7439287b727c9975908 GIT binary patch literal 2281 zcmVhIR2 zTAuS!?<^-`L!dcL6D#!hZXb1yy(f-w8*assFNS{X^Qd0(kU(ww#4A;5GHRHDn(wb%oBON`|%p^u2y zhQd6Gf@su*o3fwMzGTr3SGg}Ec5RGhM$Joju*A3E7zgp}_3q;+iM!b_*nGu!?U}cD z?`tm(FZ2=nT zR+2CCDWGIrk+Y#{`14lGq%+kv!eqynvH1m8hhl@^Et`iSWJCY`H>qLDZiIfPbFsOEg3enRu zf2=Xk?e*w9o;ls#0FZOBu=ztwPoHbNHrh3N# z>I@^n0?&Gy7~%FR$2Q~?YIyn=uwUVcvKfE!#PHHe@dKah+tbP59A43JrIv(|K%;I% z=>B_95<)Kv3CxQyS!M*Vpr1?`H;Slu2vpSSAy*vPSm}0HNEt*pq5>8Wgh!3~BHz$| zzyAU8T_O)cyts61oQ}93&+;--{EH+YwPo*;TXYMlgtt-HApi;y3QQ{-Vam+T@^|s#jy=HI`+mcV)+INV_WWW~ia2IA zt4{h_0r8Otf*iV-Oc~yA$e>8U84~p%I(VzF#FnF>bpn1jY6>QuTEBl$4@o^BmKeck6sAMeRzA{TWh)V$KAl zos0TW2uq>e;5KQ>Smy41oaA^6l@HB-H?gtBVRr>H&m8BDL;5vtWnC)n6Mm+Z8CQWp z3_=Y6wx<&zl^hm4X~NgMb$|Li7;)oB-K{0*YqLl6a`p8Fb*hvo%R6CvDn%l>5UaBm@iY zao-Xxh9 z5hgf6*vesq%lc7f?n`jF32I$hg0i*tHuDP+;q3u7-(02^SQNz_D3DTZF-l`mC>gK- zWq9~*sEUu-TTs}!+AJflnGs_*P6I$AmsLdSA+GPETLJG*+Zvyb(XsMI7M<9J186JC z1Q<(w8xse;^upl#LQR5{Z!Ms;CUaDt9&URiEmgw07(Z_ZIs*o(_>^I(lIb=&k_i$$ zyR<58**@V!FTal+(2ch64p4iaK2+5uXlE?Iyyl#ZE;KKECcQ8fbibM=W{MyWdf$9H zeG`-o>T8`{cBVRnvn-6_d|AoHp*(iQ)Um*3r5T#TQ?o{pbaZaC#WJLIx$|q*=|j@N z0AQQ|#!p9tLeYL_R$Eb;qIaH?i|E-a`qNkH5cgGmM2F)30$>|g!JPmy+E+?u2kfiG z`;1!D+4`J3k3``0CyiYU#(MdEAvb@ST_T<-p|uT5j&$f;$h0{wCo)s?l1_0$PS|pM zSy|xnN!p5a9Ptyj^mJwZ^_eKZbSR|GYP!3|I5+_;Y?Uq#uEoc*0jh97J-IEU&=GnM zs-rqW@v>KF$X^i!(Enawv-~FLGViqOB5iYp`iWI9X*fCjE~$SQYf-8r87G7>Z=o-% z7j*8_D?^kz%GuTpA+A}}J^5mAYD&UmyR0?D&2gyz25Pe*;TWBxkbV~5p;B?DDj?gk zp!g;*5!N>ruWs7NGGQLLPGHf-s2GQ8x5yF#%&y(QIu?<%6=E52Xbsh72kfiG`;1yQ z7?MQo>04O}XQ|B7Q&*#nNgG@Nw;)&xFTNzpgqL3xbibM=W{MyWdf$9HeG`-o>T8`{ zcBVSJ1%=)qC+!Xq@f2YUkelmPzvG2O{bg z7`X~~RTvQNh*u0jcRvmEyal-gCU8g>CM6z5ejm^l? zX6|Wh{7N%PUdGB7ejk3&F*sCUwPo^jG@2p0e^_R{W~YuGDF4&(>=>*7Cdm literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_shotgun.ctx b/scripts/ff_weapon_shotgun.ctx new file mode 100644 index 0000000000000000000000000000000000000000..fbdacd4665f1c256f602278be3c43bf87a4119e6 GIT binary patch literal 2300 zcmZ9MS2!CE7sl;bv-XS~EB1<6)ZWx=YE>2KpQ5!X6{SV3p!TL#jkIQq+Cl7*+BGAH z(ORLtD>vWexp>d}d!P3_$B_l%xxdtN!^oA`Cd`0(%UgPLM8u=TA&;CT%}hprA1izpA`L0<;j6HVivIKv&HcE~@0P7`{V&=z-KM&V5oXSP>4kBpQG7W=XD{tphC7$nh1ieb&Naw$9 zs|c%P8;3)*G=;LJ?vtm_O!2fJ8#3g-_G$%<*j)a+b+?99imI9Eo7V1??ot;0`A!G! zFwIaO^Gl1};r#J{dZSfGsq;!tsIRK_6}>ZBS9UM}ELnfAdqg=P>{MTQfQ>;|dH4H0 zCV84sCTRtx7trHM`$FBxVBoI9QLP|n+2#SjY=fiT%z#`fMBOql!XqERp-ST)gQV?canE>Yfn$C?CH3P;>}bU zS%EI`tEeMHw8|=YVt>>-xMibg`6XwB>dvk!h=g@S+*7vOS2-H$P|IH&W&b2;fw4S+ zH@MnjFFuERrkF_@EZ!bMzSzhWmY3xV4G{v#4e{{M$Lc3t@vlxqb=?vkL-^@9mj{E> z7OO&L@`fdlGwVjt4*!iPlE6>bGq5?Z5CW0kKC*M4!4iRYd+b?Cn9Z6(7mSXH3$csS z!_Ao!Jcge8XT!sbSg%H>8_HZ*4kO)i&OE^mEL4&Se~`T8cc6JyRM1rm=PhwR=>}{M zq(Rz0-}O<@lkmV6co>G|Q z)^&zkX%Hn}ee=sVObhsXtZsTAPx!-9U9PaSt zM5KIFL-?#!y8W%ij)tKCB}B^j1fvlr*w@j$f!+zOnvntDIJ{ znTIwI7r)hR1_w|hR&ZW@o+xcE=W=_3LW;Ob*&o|okilmYmUntzm4)$E8pFIHX3Rxa zDXr(-f0r`?U-eQe71H9;(wl;`XP4qX9?6@tOSP$9c8C;Am9G%tDF% zrz{eXH+*S9?i}qx91161DXW%-q!eoPDj+&C7^H+U48#xlE(XYKWGDE956BZ z=Rg^K8x}+$nQ=Za+G3o$;fkoP)QJ#hw#ZTVakBA5k0pO0j`+Dal7!8;<9>o}eJ+rI z``t2(MguutuTwwgxwXWes&jz|4eml{91ZEiVAG1 zB^qmC=dsZ6xRW7qL!(nblf0(>InSraBaBDJH|DjWfnq9jo!9xM38#w89cStquYFb} zZ{XeRS>}y@M8o4%Ho*`|S6vF0@W+28Q@94pcJ;W73GnmZ`A@FP<2+VvJjY-eIlJQL zQ{w?K*Ex*mVRpVHp>rJFiz;H=2g?_aya_4q*CbpsC3(C3q^nEWfZW}Acxeb}Q~R*z z(0}7todqk9Q$86FCQgj|&(M5Dgyh+amd(2Uys8o7lNu>@BjIcUZoAxe*%+)D8Of+Y ziRkB#WsixaLisAy>3Zd4_9as{@A5AriYY3yZ7K)_u?kh(wVmEH4~gYj@^|j?{eLem zzUEi`F8Fx;wIuB=go*cq?y4uLwix!?jvZj>A4ASBrJ}u;Hm>MhSsVh({~}UG)#D^kK8LSvANHt)+BJNnT3_8}8=udw<0ue0eOS<>7WXX*iI=;{ xG(6cM=ijrXB6erv`nNl9wQ>KdSce4uHz3~8T8$X0R1ja3$Mf%whbn@G>VI`^as&VX literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_sniperrifle.ctx b/scripts/ff_weapon_sniperrifle.ctx new file mode 100644 index 0000000000000000000000000000000000000000..17700fb58266f0df93c0cc29d04b00c078cb2d31 GIT binary patch literal 2557 zcmZ{iXE+p&1IO)o_Btc8v&!oD-C0>@cbVa+{173VkUg`GjL>C-b6JrsLdYiKkaehx zyUTG_$msvdo8R;N-+o_wzn|y%e(ZT4JlVX{cU&!a5DFSwiYOVnu|VXW?Hyy)S}^xXUp33ll5ueUl*&y3K@;NhVXYp^noFC z5Xd13jh=BXtaJK?Wz1PQcf|~9wM1)}Bt#t-F+HvW0=ie9qMBKn8Y5VPQH&kn`orz#)Y__IR2Y~h}Cl4z>X z77B5KCA;GS?AB1Anp_>AXABw`ezlM90&pv{jB_ihaC>|0RoK0OO@&J15#)E*1si6} z{1_Mu#%p7%e^whtLr4DucWS+elRT7mfr-TLy-)cr=^j zB@X}9QFbJXxB7O8HP< z(D;?L*7~42Okq;Zt%^jy)F2dInD1*(WDo!x=Wx&xgSI^TcHIzLh!}7raoa=|K{oh zxj9yKRqgBcxMyhF&l2Nm20peIr#CfSl^w+dj{aJ1Uejciw<1v%?AS$G%9(B%KMO4B zGGs_hjAX!E#!hE4zhqUA!=ko_Yb&+h#NhP4la()At_o6Gn#>FxzNDSs zxjD6K#*-Um?S#`7Nw!L-CJY*dz)n#xKRdxu)sB~)ks%R)S6L}DQHKa_MgD?5w@kl8 zs%*&uHRBaptKL&-Ok$(VeLLi)d^ZdQf)MqXd#yp@KMNjk|Mr;dv@Y&MM?LaFZS(_xkzL?u1c-q}Cx=GFAHs(VkO^v6ns z|CJ?JlOk=CWnWtQ(u$a8|JL9h$MT#`kp|E<{Np3eVC=H>+S6ol z8%ic8+)i>ndar%#cqZ)nO2?qjAh^tvK+Chz6HyaEdQ~yu^E8p7=mx$3@9%RK6V?RW zv^5>-&TdGD^&u7MCYlmpNx|{?QS>LFnRgVJ+enK+PSpswVnOR8lQV`5-?U)Em-C>* zG53-B!jSyk`V3;ZDPvVJ?jEleerr+4sTO=V5(M)xs=^;SUg)N4C2KvrvXZ&o_%udSpZcNKLx@C(4pLO>F{o%bX+qhx;pZ`tVl%y zoCgJ`!5&@o<+ifa)ib-S8%K~A=zbEz$Vc^CfQgYqOCOY0=i6jPVXL)$Da`n7$=@F| z>r{CNx%NhYMI-(TSQ1Gn2sT?U7#dI=7 zGx;{fOooR#W@;->qICip%xJ!pFOk1fF!pyE# zHg2zh0%F(QRH>VubYz59KF^J-UwW=_5cPK}$ z^9h~060%%;sz*w$C%a!4VASw&92^v-7TPglZgRkai1+#^dZlN?<5#`aEn=*yY@ky) z#}roH%Jq7?s=F$=i#Tc6lHK0hvwq*KK!W3A-UD0(R z94w5=7^q23yScx1KvWDI>R+hmSDFc1RFhLH#kh|c4+TzabG4VbN$%afG2;3u06$MH#3QzWz~C;@~EY{h=# zq{lzhKrnITgwN)>Gwl8;me~+&bk8J++T=8!BXCARGeW?CG4ZB$NNPyxbYmFEhNdm6 zh363tuUFK6(<@h=t!`i_{dQ_nH)~MbglMei3Q6;>HE(keooSJDDQPY_M{V$pa zd!th-)P5Ut=rZdxvUY^-2QenyU(MKgIlIep=N(Z_qQBw9Ri6sWZ8b~Jd4qzA17Y!9 zn*pl~Rs5nKGV;dF!9NR+^nS(=%Q)}-a$SRV2I!=jeuH^zb;a}u&{Hd}6(`kbpL<>H zhs+=nibVY5+~~J!2F{T7GYfwTHD18hj-=8b00zTOBgG)ms0ZT3GNmmnrWrx_`@_wu z@=~{~4zut2>)o9Xh(I9L_Kg=)p9<}9wH^k!ULK*OdxE6PCp)qdKV z?Q-Q`Il|bg(Q04SPv;v7^{3YjI8JW`rT0>vJ75#kg96+z{I5S-H5pVIxheRYL!SXm zS(LZ^U`XD<9fT6 zyXoZ)YFD-*--GnS!3VPpRa4v$#pP#898c#p{A&a%W8iC_squl=b$GQUo`uj;#J4a? zm|zAGh=s%|F>@onKhv#7^eWw$IS7oiEl4l&QN}yn_OvF(qyf#Rjfo)fhT&1E^%1TU z)}|P&5#1-*bE>Pc)u5(wd3ucStlZ1VV;e&D8iA}Z2eMgoSKSCOs{k;Jt5Js>uC>&f z2gINi&5FL7&nLnC^5L2g_PVK}JIa#gSIo*Sk^fZ~*Yr=Byb*kFUq(?cFNdb*= z**D&aeBOnX=xoef@(f>?&?7VMyTY({ zwwOAV{XM9My#Yj0@?$!f`Ft?C`_&1f74gaXcJ6aibeTtMwU_z?ZVhUi{#iLtrHx^< z*KRh)87@A+0C%GwChecYG`(I?qy_!)$b@zWukp+i*SQ=0dL>JsS{Qp|L{#q2wAweS z1*4H{(4*(g?=*;T?m~r`Jc9=zi&p5~0{aNZ@lVZ>q0Q~~1jy$tDGVD(Mwa(USmtew z!*P?^I~z;=u0m)gYnG&-Z%Q*Tj=(PHb@G?h7m9ikM*5hY6ND=v1=Pd^A^a19Kso2V!!1abM6MlYiQ>cuo5y9|VvSCI{ah780C9crml zqrvQRHN=Dn7-5GYy}y+Hfb1&z!gaQ;diGG6X!KVbLLQ3V_LAwc0HIvzVj1RCSzF%U zJ!xAlTgm+C^zAC~nn~7xUT(U(rtKW-(DC8NNuE^{cKv3ey$yi#+mZEjh>;4>{K5lg zXb=6og6><57Z@Q%)IC#|8uSqm1F8@K^XGp9XQ-l^(w>%|8(`)+QKrgR+f`ueM*L?* zkwtf)DY&~Q6NrPbdrc*uu3^iOf;U*t1-SN&8bAGmIKO-(cMzw1jzZH52rB?&BxMeL z9;CQM4U_B}K$iXk%v<2CC%%JxjzZH52rB^XV1Y}WH-a^I7pJ1n%t+>*TXVvRhW7A| zxDlVhf-cy4V2He`p`#-dVV|;RJRQsD0h%noGdBb}N#Ti)VEr{H?*N6xWnm`1q|NG< zAR-M{C3$QW1`Ob1M1@8)Yw3d6_91NT`P0`*&V0y!t#YayH};1vE_`f=4#4=K(D|4X zT}`@+kT=klzb+&`YR54q|II#2xhZ1rjX9fs+Ao&%aq$HpcXkj0+4haBy-wTiB#GID zxJkb~MfZ)WVYI#V!pO^v@RA`bSh-YuMd}zKw;mUd(38(Ph|B7xlP0#CA<&%VHPbPK zW+2=pOc$5npZioRZ4{ZZ8yGJV4D@cGB#3Av8VNjBEX7244xoDDT?J6EP1oj7U+@*r zrBA^dj~TqshM-As$e>8U84~p)7_Qrc2h9^)vX1RwvA+XsgzXPw$C`aH%!37xTvI4D zCZ9CAE8YJv_{1zZ4L0+;>sw;k-o&jsP`$hMAfS{7Is*o(_>^Iwwq3OT+1n(43OY?d zDTGi{Mw1zjc-Veqf4C7qYQ_Na|MC15<7fuUNzS-Pb1TiQj4Nf{Po-On+1eW@-eBVh1kk)A4C$2kfiG`;1yQ7?MQo>04R6 z_u!QW0{7)aS8QWziGp@AhZOhuUH3QpLQR5{Z!Ms;CUaDt9&UTf^I_ZC{(rKB{5Du3 zsJzikuGeH+D^vdHGViqOB5iYp`iWI9X*fCjE~$SQYf-8r87G7>Z=o-%7j*8_D?^kz z%GuTpA+A}}J^5mAYD&UmyR0?D&2gyz25Pe*;TWBxkbV~5p;B?DDj?gkp!g;*5!N>r zuWs7NGGQLLPGHf-s2GQ8x5yG-#hD+*1M0g4+ebEEqO`JE-AHuQ92jzGbtyIay?LUu zYn1q3J18ij?beWTV)Od7e<|p$JWF65BI({utz;}0rCVt;GM4&`_y=hQm-AJUQN`DG z{RE-23MbKupK53wSDU&rg6mG+*|Tg`P6*tHc4_K_K#8e~+1eW@GViqOB5iX-FTal+(2cf^jx{Awn_>#7#Nq2kHVFyE74TIVKEJQ;hhK$r z&Ot6UshW_2M0{VsYJM~Ge>-eLc%z~>_}104yuk|-H2KkqPuP1wwC&fHv=#*A{Y z_3*c_?Q#=D(rWlNhw2C3_T3p6F zB&LuHz{ol&b`)t%pbb+oEP0Mr$pLfq)sdt8H0!L)J^;5K8Sg@PNnTv6!;jg( RYJM~Ge>-dmeGLkI4GPtItG56E literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_supernailgun.ctx b/scripts/ff_weapon_supernailgun.ctx new file mode 100644 index 0000000000000000000000000000000000000000..3911da41137a980c671e75be8095e6728832a117 GIT binary patch literal 2400 zcmZ{iX*?5-1ICjh5`IHymY6k)9J%EPHMw)-3{A~jx3{)Wxy)3py`Z-(uUwQd|`@DEQpXd91+$B8ym|r_Mq99x&6hM7?u7tCBT;?iJvwwm& z`{hhEcYfC_5L1#OxXzv|b1&GoXDciCm=)>?!XYS-A`vP)5Pdl>ZeX4dZ(}rW{zLRhosct*68_g$Bjdw8VoRY*n}tuYHMBWVmfsLZoZP?LzrO_3kp-L?7A({p}gq z8#W2x=)8gV2dBI=9^R$)X=J)(IJSHIx)q|^B^SuJB_E8?U(F05oV+dgC!?~036?AE zoNk@>rg*I{Hhe4Ga&>z)SbVst6LX3%8EegA+st`b=wdW)srI+>LHn71Me)Hk8ZTVL zRhqbQi7;?nt!ah8>%pq{w>yc%H3)&TQA10|ZaR01DiC*Z+?1rBP24U+j}prca0}~l zE}$9L?~hm#@yqh)zW^E-gr&Vt!hq>_OzkL%%Z>v zBt2<;0ew#SMC!F^n5q3}q!YYcbW;~@mq;ral(NKRkwMDrI1 z;DwRcw!d6ko?sDaT5n{=94Tr%@3V6M_>yJ3TkwE3&#UdFtc_eu)G>u+#O291`pU?o z9@dMvKg(2XWp_te68R=vmA$cDLdU0p_Tnx%hDdb=#(!ONW8K0W9k5AQSOr4QcV_0~e9k?} zB}nGbBol1FzW1!Nh;uDqN6&O1sR%jz=)>7Om86;IS=dYPki+|C7^ymmlmBgEE>ox# z6ioT`5!qth>@I03n2`IQ&7lc)C)6NgLp8I@Psz|QJB_3K@gPRqh-`lmL@<#~^FM$7 zL^;Lwn!TIO_woW^*kg{WEVStlKbZ9o={uA zqrEK%SYmN$FWfFq$uf>qhn(^B_X{s-%?UV@Y)JgjKXh(Y=5sFGwvA~n37T$4(8>%e} z;GEJx#arJTA?%I7w5vC37FKQ$x!L*4#&?W`g_9aw?cWOrARR2UVY84%$+LX7eP#le zG2`vZ3zKiC{G7h@bE}xG@@$#yIzoekU0E~xa6hvvHiZ)#m_DLWgsZ*c9T9%mTw&BL zC<^X!-SxHn%mdT%$~Y#&b#?YJuzA(Rvi{Qr-m4kbW)Bf~Hk#XyRQ!6hAiIY1yKsY- zaNJhgIxCE-RZ9`_M6YZX1cIcl&qTyCO^3$@6Nfc#O;Q|wXO6fg^V>h@G)Q!H=nD6s zN<#Nwy)Qokh#d(k(@*YTTizCx$cw{?wSER?2iCZ9mD@CQc=Ronl2h++v=rILFx|dz zD5Z30JzEwmhs2pdt1GGptpwO-BAs%4KEnuM1QcUcOP?q*M3DuiJDAwU5G4iPJgu&#V`^e04U zuYWZCkQ8LfSC-kFD-el38$K<(AN=vixZ+QwFja#wqvh6I8n({r%s;av9vI@>Zx{AT3c95ilfwT zrhcjU36sd5e#Y&u)XyVjbvo+M?aaSFohJ?CZ4~CDcMnZ%60$-r71l$;oeE@vqc?f= zrhPie4Xwn|R^(7+{SYQAm!Y&f8m)P6`fGD5wW3a1?uZAne^gNYA zi`3&=7=TOvwn9h2OFX#PwsSxtR^00c6*<0dy5OhS(BJ>A)$7SLmbb;_y2I$IvNI&^ zuclY}ZE-TZplD#Va{#kWO1&!rK zXiyrvoFu-x@42h<|GcbD6MSNlSL5mtxxwh9L9#7V%m6KRi^*9s#c`fHl2|A75i zEf%qJZic!ix5A#r((zC`H0Y4tYc%yWwwSgz6ou_0ozu7%OBVh@d_FTPt+@JX6mHvg zLHvUtf^nH$w*d|cpOa|GM_pNW9D0`a#6D;~=zUS1@2I+n|Gj_=gs)E(fKx~@zlkhp NdRrK5v>T^Y^FKQ+!twwB literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_supershotgun.ctx b/scripts/ff_weapon_supershotgun.ctx new file mode 100644 index 0000000000000000000000000000000000000000..724eb532dc1e6a4f00f539760ee6ebd3c44a5857 GIT binary patch literal 2278 zcmZ{kc{CJ?7soB3%;1rIO@xq$>>7{(G=$CTxfeVeIg%~*yhdkSL|ld>lJmf=M* zmW*vww#+NU%!G`{y!ZRZpTBeNKlhw_zW3hm=bq~&>KnZMdGJI?8r!WTIGHY2eZt_7 zHIvjCo8x-)aIu*a_x7V?Ms*Hgi#|{As@!v?t1I6ER~bOhtL-x*p}j2FIrxE7i)N>2}mUA z$Nsfvqdy`psHDHq4;0qn8yD8RE*u{AqxL4=avG(w;mK%FlxmrEiaL9)e7rHO?f`A~ z1!cW)ATJuy&@E$@XsPvkWdZK)AdIvND}hCB-FGN@C=J6d&P@h41@K$ib{gdZo^W&F z2b=_zzm|)0ToN8BvlfGQp^%prNf?bCh;Ih(^o({&gVu+gpBu)N220CS_V4th!}fmN zQN4ARJ_@(3w1QUCfaC%H6pb1CV zl`VM>>BXCy32Or~c;2*tyScE-i?O-RK}XtEID1syvDjbgb+FimU2%`kHBGajqk;P1>P1jQY!gyUD1PBU@)Sp zouIU~=eP9aTFOno2NWR!#(`L*8al+w&=L*MK6o*ZiY(RYhjyg$njK)42hsn2I@Kw3 zo3_&K!#&s@ZF~X3r!Ill7&@%hwpDMzMZNQYz^lq26TsP?$Q{~2Nm1h}Wa^)1-J8GK zl>}ZOS_#!pJZGla0Cx|UI2y;F9W(S2fsYF?v&s9O!kQB0LqYjb861U5<%W=DF06vz zm2r^s^Y*4!fZJ3^B4bMn{N%^6Za1ushs)r{on$Lgm8`$&rrS=EN49FQOC*;Ztnk2C zi1{YBZ4D8lu-k-u&Qs@X$Sl^9cGXxcfwr)qX)!{;R7Z{d;J>8LVYx-4@SD z$9)0$gZTNga_wU1+*qp8-qGa!N&M`dc#VB?qRmCfzVr>E1Y(ZMu)OA@Z_R_~qzWnu zSRycyqSw+gj6iY`&7+X1m2t}RJ4});7fJJFL`2R_Zhs1;Gn5YgV@!d+hi=6(3K{k0 zZ1yxqq)53>uDhh$IK2@GvrepPA`VtsguNoET6^O`K18o{+Q)W9RvAA^;!fH3@k(A0sW zS2B-%F55sj14P$Mhf>CMUz^MvNIus_T5v$`QXGcLG_BZ*uZl^p4cD67K8%`#!5Jb` z1gAlB?*)hsjDh$tqr7GcOjcYWk@ZYV@B9cia!z%9>8@Y+j9Rg1tEQGl+_BEuuHQMW zvjVDBh!vF6LUGN!L|m7Nz2(5KDM18@vcFwht@GpJBHD(p)x>x2-I?D6lRHFK zM@OFWE;fOi=7azFEWrzo`7zj|3#WPcj2J6E&;NCO0o?I=C=XSr8gIN|Cy~Ny2sOKm zhPhf7N#vm@$pI-{f@Yy3Y%Z?@HT|**ewv~tRV#hEO-Yc+F56hOi8S|d9~r2RQ|{tN zDHUo7xuWZd9wbP^LiNGKC^?80!enmRvfEq4XgAr)X>o@elZ z)3e|iv6JQ+i77c9|(Lftqx}*M4zULf!dHjzHa7ef0I@h9hb-GAmo}t zrf|0}>(m#IK*}qhK0)ldX`cd!r@rY=*(b@2&A{SQpBqD%R0k;oE%mSx4S}ZNcLl3* zH%n{f;!gA6n$Y7Le6k@m9|Z3S)Kwd*#~inFU;k}*ZD7!ULgC`YQ!Z%tAun`It(|&} z_gEmIgmk)p-gL{ZwJ45qE*+tlI!>>sLxQ#_FW5ua!JmpdTJD1W9~aujN-|DCnb7|I zYoG6e*>C(5rm+i{gqh7j14%Y9@xe4+7r20Dg zbE{YC10;EEct!re>6`%KsNv-V;SgvQpQ|lK#@x6y$1uD9T|Tu-U&!uZ9>ME2F^ib( V0elSJhfSY3DnGrGBtG8%#eXXGXY>F7 literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_tommygun.ctx b/scripts/ff_weapon_tommygun.ctx new file mode 100644 index 0000000000000000000000000000000000000000..639430cf1e003f0f2e29b24bd51a72b62351dc65 GIT binary patch literal 2238 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 Ne>-dmeGLkI4GMf1VM+i1 literal 0 HcmV?d00001 diff --git a/scripts/ff_weapon_umbrella.ctx b/scripts/ff_weapon_umbrella.ctx new file mode 100644 index 0000000000000000000000000000000000000000..616d90c85358e8ddc08372d61c7459140ba68e9d GIT binary patch literal 1554 zcmV+t2JQJ;7F}oT+`;`49E`ap5zd1jqy6v#9zYs2%GCvyj@hpRoy6K2g`9fT6 zyXoZ)YFD-*--GnS!3VPpRa4v$#pP#898c#p{A&a%W8iC_squl=b$GQUo`uj;#J4a? zm|zAGh=s%|F>@onKhv#7^eWw$IS7oiEl4l&QN}yn_OvF(qyf#Rjfo)fhT%~U*tuX< zkwZ{aXKN09a?OY1wlCHAoby}Fq}%Y}013pS74gaXcJ6aibeTtMwU_z?ZVhUi{#iLt zrHx^<*KRh)87@A+0C%GwChecYG`(KY{#qxS;_J>Iqy6v#9zYtq(gg}2Rj|gEFQJ(2 z^gQAeLNc)xur51ZtV;lgGE7x3N}{t3`Tm5VEF4@gj=(PHb@G?h7m9ikM*5hY6ND=v1=Pd^A^a19 zKso;d9Rp3+RyC5-u+H@oG8Y3*03s?ES@{gN*WarHb3HKP35-;b9HQ~&QzY-}YLGxs zvESoJp9Aj{2`1l>WSs<3f4h$5Tp(VK{eGM=((ebtnh$VXP z<-ZH%?d-!msVE6bGg=hhS&_s>23x8+`r=|+jl%Wc=y|i-_XoStc%32;(VTcqp*Pb5jpN;L{#q2wAwf13_Wjf3xs(7AaV`r5=I~& zvrhi-8vuBTOBtOCV_*25_)E1)3(G7AtOT?%x7Gx97aekyK+Jz;r5T#TQ?o{pbaZaC z#WJLIx$|q*=|j@C72wFmp$gfqL$20m<=h$l;KD(Jx>DZmT3p6FB&Lx0HP=J7vcive zk}7pP=t>!X3OY?dDTGi{Mw1zjc-Veqf4C7qYQ_LkvSlz{hmrL@c+M)GT)95WNzS-P zb1ThEXzcLTZM!>*+1eW@1CA7g_N4; zEBDgRbAtSu68C#oZ=!nE8o=8*Djn_J_*H5F2@|V{{1lC9V!{utkmFr*Th13I_(sQk zqj?3gy2)qAZqMsO*itTAodzE1hAJKO$k(QQE%t4<gi-BbwE{v5Rh>-EWBlQOlz0AQQ|#!p9tLeYL_R$Eb;qIaH?i|E;SF~pwv z$+ga~832rPmADTG)QMJ+WafUozm%VK`8*Y7S7~_level_sounds.txt + // Let's leave these map ones commented so we can kinda + // force ourselves to make the autoloading map-specific level_sounds system + //"precache_file" "maps/ff_dev_test_sounds_level_sounds.txt" + //"precache_file" "maps/ff_hunted_level_sounds.txt" + + // Put your map's level_sounds txt file in "FortressForever\maps" and give it the + // EXACT SAME NAME AS YOUR MAP's FILENAME followed by _level_sounds.txt + // IE: FortressForever\maps\_level_sounds.txt + // IE: FortressForever\maps\ff_2fort_level_sounds.txt + + ////////////////////////////////////////////////////// + // HL2 game sounds (located in "source engine.gcf") // + ////////////////////////////////////////////////////// + + "precache_file" "scripts/game_sounds.txt" + "precache_file" "scripts/game_sounds_ui.txt" + "precache_file" "scripts/game_sounds_player.txt" + + // Weapon sounds + "precache_file" "scripts/game_sounds_weapons.txt" + + // HL2 World, Ambient Generic, Items, Physics, Vehicles + "precache_file" "scripts/game_sounds_world.txt" + "precache_file" "scripts/game_sounds_ambient_generic.txt" + "precache_file" "scripts/game_sounds_items.txt" + "precache_file" "scripts/game_sounds_physics.txt" + "precache_file" "scripts/game_sounds_vehicles.txt" + + // E3 level sounds + "precache_file" "scripts/level_sounds_e3_c17.txt" + "precache_file" "scripts/level_sounds_e3_town.txt" + "precache_file" "scripts/level_sounds_e3_bugbait.txt" + + // Game level sounds + "precache_file" "scripts/level_sounds_eli_lab.txt" + "precache_file" "scripts/level_sounds_trainyard.txt" + "precache_file" "scripts/level_sounds_k_lab.txt" + "precache_file" "scripts/level_sounds_k_lab2.txt" + "precache_file" "scripts/level_sounds_coast.txt" + "precache_file" "scripts/level_sounds_novaprospekt.txt" + "precache_file" "scripts/level_sounds_streetwar.txt" + "precache_file" "scripts/level_sounds_streetwar2.txt" + "precache_file" "scripts/level_sounds_breencast.txt" + "precache_file" "scripts/level_sounds_citadel.txt" + "precache_file" "scripts/level_sounds_canals.txt" + "precache_file" "scripts/level_sounds_ravenholm.txt" + "precache_file" "scripts/level_sounds_ravenholm2.txt" + "precache_file" "scripts/level_sounds_canals2.txt" + //Music Tracks + "precache_file" "scripts/level_sounds_music.txt" + + + // NPC Sounds + "precache_file" "scripts/npc_sounds_eli.txt" + "precache_file" "scripts/npc_sounds_alyx.txt" + "precache_file" "scripts/npc_sounds_dog.txt" + "precache_file" "scripts/npc_sounds_citizen.txt" + "precache_file" "scripts/npc_sounds_barney.txt" + "precache_file" "scripts/npc_sounds_soldier.txt" + "precache_file" "scripts/npc_sounds_strider.txt" + "precache_file" "scripts/npc_sounds_zombie.txt" + "precache_file" "scripts/npc_sounds_vortigaunt.txt" + "precache_file" "scripts/npc_sounds_turret.txt" + "precache_file" "scripts/npc_sounds_scanner.txt" + "precache_file" "scripts/npc_sounds_rollermine.txt" + "precache_file" "scripts/npc_sounds_poisonzombie.txt" + "precache_file" "scripts/npc_sounds_metropolice.txt" + "precache_file" "scripts/npc_sounds_combinecamera.txt" + "precache_file" "scripts/npc_sounds_manhack.txt" + "precache_file" "scripts/npc_sounds_ichthyosaur.txt" + "precache_file" "scripts/npc_sounds_blackheadcrab.txt" + "precache_file" "scripts/npc_sounds_fastheadcrab.txt" + "precache_file" "scripts/npc_sounds_headcrab.txt" + "precache_file" "scripts/npc_sounds_fastzombie.txt" + "precache_file" "scripts/npc_sounds_birds.txt" + "precache_file" "scripts/npc_sounds_gunship.txt" + "precache_file" "scripts/npc_sounds_dropship.txt" + "precache_file" "scripts/npc_sounds_barnacle.txt" + "precache_file" "scripts/npc_sounds_attackheli.txt" + "precache_file" "scripts/npc_sounds_antlionguard.txt" + "precache_file" "scripts/npc_sounds_antlion.txt" + "precache_file" "scripts/npc_sounds_env_headcrabcanister.txt" + "precache_file" "scripts/npc_sounds_combine_ball.txt" + "precache_file" "scripts/npc_sounds_combine_mine.txt" + "precache_file" "scripts/npc_sounds_sniper.txt" + "precache_file" "scripts/npc_sounds_stalker.txt" + "precache_file" "scripts/npc_sounds_gman.txt" +} diff --git a/scripts/game_sounds_weapons.txt b/scripts/game_sounds_weapons.txt new file mode 100644 index 0000000..a83689d --- /dev/null +++ b/scripts/game_sounds_weapons.txt @@ -0,0 +1,1476 @@ +// +// HL2 Weapons +// + + +// ******* +// BULLETS +// + +"Bullets.DefaultNearmiss" +{ + "channel" "CHAN_STATIC" + "volume" "0.7" + "soundlevel" "SNDLVL_140dB" + "pitch" "PITCH_NORM" + +"rndwave" + { + "wave" ">weapons/fx/nearmiss/bulletLtoR03.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR04.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR06.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR07.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR09.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR10.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR13.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR14.wav" + } +} + +"Bullets.GunshipNearmiss" +{ + "channel" "CHAN_STATIC" + "volume" "0.7" + "soundlevel" "SNDLVL_140dB" + "pitch" "50" + +"rndwave" + { + "wave" ">weapons/fx/nearmiss/bulletLtoR03.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR04.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR05.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR06.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR11.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR12.wav" + } +} + +"Bullets.StriderNearmiss" +{ + "channel" "CHAN_STATIC" + "volume" "0.7" + "soundlevel" "SNDLVL_120dB" + "pitch" "75" + +"rndwave" + { + "wave" ">weapons/fx/nearmiss/bulletLtoR11.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR13.wav" + "wave" ">weapons/fx/nearmiss/bulletLtoR14.wav" + } +} + +"FX_RicochetSound.Ricochet" +{ + "channel" "CHAN_STATIC" + "volume" "0.5, 0.6" + "soundlevel" "SNDLVL_80dB" + "pitch" "90, 110" + +"rndwave" + { + "wave" "weapons/fx/rics/ric1.wav" + "wave" "weapons/fx/rics/ric2.wav" + "wave" "weapons/fx/rics/ric3.wav" + "wave" "weapons/fx/rics/ric4.wav" + "wave" "weapons/fx/rics/ric5.wav" + } +} + +"FuncTank.Fire" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_130dB" + "pitch" "100, 120" + +"rndwave" + { + "wave" "weapons/ar1/ar1_1.wav" + "wave" "weapons/ar1/ar1_2.wav" + } +} + +// ******* +// WEAPONS +// weapon_ar2.txt + +"Weapon_AR2.Empty" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/ar2_empty.wav" +} + +"Weapon_AR2.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/ar2_reload.wav" +} + +"Weapon_AR2.Reload_Rotate" +{ + "channel" "CHAN_ITEM" + "volume" "0.9" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/ar2_reload_rotate.wav" +} + +"Weapon_AR2.Reload_Push" +{ + "channel" "CHAN_ITEM" + "volume" "0.9" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/ar2_reload_push.wav" +} +"Weapon_AR2.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.8" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "85,95" + +"rndwave" + { + "wave" "weapons/ar2/fire1.wav" + } +} + +"Weapon_AR2.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_zoomin.wav" +} + +"Weapon_AR2.Special2" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_zoomout.wav" +} + +"Weapon_AR2.Double" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/ar2/ar2_altfire.wav" +} + +"Weapon_AR2.NPC_Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/npc_ar2_reload.wav" +} + +"Weapon_AR2.NPC_Double" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/ar2/npc_ar2_altfire.wav" +} + +"Weapon_AR2.NPC_Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "95,105" + //"wave" "^weapons/ar2/npc_ar2_fire1.wav" + "wave" "^weapons/ar1/ar1_dist1.wav" +} + +"Weapon_functank.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "95,105" + "wave" "^weapons/ar1/ar1_dist1.wav" + +} + +// +// weapon_binoculars.txt +// + +"Weapon_Binoculars.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/binoculars/binoculars_zoomin.wav" +} + +"Weapon_Binoculars.Special2" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/binoculars/binoculars_zoomout.wav" +} + +"Weapon_Binoculars.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/binoculars/binoculars_zoommax.wav" +} + +// +// weapon_brickbat.txt +// + +"Weapon_Brickbat.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "1.0" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "physics/wood/wood_box_impact_hard1.wav" +} + +"Weapon_Bugbait.Splat" +{ + "channel" "CHAN_WEAPON" + "volume" "0.75" + "soundlevel" "SNDLVL_75dB" + "pitch" "90,115" + +"rndwave" + { + "wave" "weapons/bugbait/bugbait_squeeze1.wav" + "wave" "weapons/bugbait/bugbait_squeeze2.wav" + "wave" "weapons/bugbait/bugbait_squeeze3.wav" + } +} + +"Weapon_CombineGuard.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/cguard/charging.wav" +} + +// +// weapon_crowbar.txt +// + +"Weapon_Crowbar.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_105dB" + "pitch" "95,100" + + "wave" "weapons/iceaxe/iceaxe_swing1.wav" +} + +"Weapon_Crowbar.Melee_Hit" +{ + "channel" "CHAN_WEAPON" + "volume" "1.0" + "soundlevel" "SNDLVL_105dB" + "pitch" "98,102" + +"rndwave" + { + "wave" "weapons\fx\impacts\flesh\crowbar_hit1.wav" + "wave" "weapons\fx\impacts\flesh\crowbar_hit2.wav" + "wave" "weapons\fx\impacts\flesh\crowbar_hit3.wav" + } +} + +"Weapon_Crowbar.Melee_HitWorld" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_90dB" + "pitch" "90,120" + +"rndwave" + { + "wave" "weapons/crowbar/crowbar_impact1.wav" + "wave" "weapons/crowbar/crowbar_impact2.wav" + } +} + +// +// weapon_extinguisher.txt +// + +"Weapon_Extinguisher.Empty" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/ar2_empty.wav" +} + +"Weapon_Extinguisher.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/ar2_reload.wav" +} + +"Weapon_Extinguisher.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_105dB" + "wave" "weapons/extinguisher/fire1.wav" +} + +"Weapon_Extinguisher.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_105dB" + "wave" "weapons/extinguisher/release1.wav" +} + +"Weapon_Extinguisher.Double" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_105dB" + "wave" "weapons/ar2/ar2_altfire.wav" +} + +"Weapon_Extinguisher.NPC_Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_105dB" + "pitch" "95,105" + "wave" "weapons/ar2/npc_ar2_fire1.wav" +} + + +"Weapon_Extinguisher.NPC_Double" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_105dB" + "wave" "weapons/ar2/npc_ar2_altfire.wav" +} + +"Weapon_Extinguisher.NPC_Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/npc_ar2_reload.wav" +} + +// +// weapon_flaregun.txt +// + +"Weapon_FlareGun.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/flaregun/fire.wav" +} + +"Weapon_FlareGun.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/flaregun/reload.wav" +} + +"Weapon_FlareGun.Burn" +{ + "channel" "CHAN_WEAPON" + "soundlevel" "SNDLVL_NORM" + "volume" "0.65" + "wave" "weapons/flaregun/burn.wav" +} + +// +// weapon_gauss.txt +// + +"Weapon_Gauss.ChargeLoop" +{ + "channel" "CHAN_STATIC" + "volume" "VOL_NORM" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/gauss/chargeloop.wav" +} + +// +// weapon_irifle.txt +// + +"Weapon_IRifle.Empty" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/ar2/ar2_empty.wav" +} + +"Weapon_IRifle.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/irifle/irifle_fire2.wav" +} + +// +// weapon_physcannon.txt +// + +"Weapon_PhysCannon.Launch" +{ + "channel" "CHAN_WEAPON" + "volume" "0.57" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "110,120" + +"rndwave" + { + "wave" "weapons/physcannon/superphys_launch1.wav" + "wave" "weapons/physcannon/superphys_launch2.wav" + "wave" "weapons/physcannon/superphys_launch4.wav" + } +} + +"Weapon_MegaPhysCannon.Launch" +{ + "channel" "CHAN_WEAPON" + "volume" "0.6" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "130,140" + +"rndwave" + { + "wave" "weapons/physcannon/superphys_launch1.wav" + "wave" "weapons/physcannon/superphys_launch2.wav" + "wave" "weapons/physcannon/superphys_launch3.wav" + "wave" "weapons/physcannon/superphys_launch4.wav" + } +} + +"Weapon_PhysCannon.Charge" +{ + "channel" "CHAN_ITEM" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physcannon/physcannon_charge.wav" +} + +"Weapon_MegaPhysCannon.Charge" +{ + "channel" "CHAN_ITEM" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "pitch" "70,80" + "wave" "weapons/physcannon/physcannon_charge.wav" +} + +"Weapon_PhysCannon.DryFire" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physcannon/physcannon_dryfire.wav" +} + +"Weapon_MegaPhysCannon.DryFire" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "pitch" "70,80" + "wave" "weapons/physcannon/physcannon_dryfire.wav" +} + +"Weapon_PhysCannon.Pickup" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_105dB" + "wave" "weapons/physcannon/physcannon_pickup.wav" +} + +"Weapon_MegaPhysCannon.Pickup" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_105dB" + "pitch" "70,80" + "wave" "weapons/physcannon/physcannon_pickup.wav" +} + +"Weapon_PhysCannon.OpenClaws" +{ + "channel" "CHAN_VOICE" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physcannon/physcannon_claws_open.wav" +} + +"Weapon_PhysCannon.CloseClaws" +{ + "channel" "CHAN_VOICE" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physcannon/physcannon_claws_close.wav" +} + +"Weapon_PhysCannon.Drop" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_105dB" + "wave" "weapons/physcannon/physcannon_drop.wav" +} + +"Weapon_MegaPhysCannon.Drop" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_105dB" + "pitch" "50,60" + "wave" "weapons/physcannon/physcannon_drop.wav" +} + +"Weapon_PhysCannon.HoldSound" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physcannon/hold_loop.wav" +} + +"Weapon_MegaPhysCannon.HoldSound" +{ + "channel" "CHAN_STATIC" + "volume" "0.8" + "soundlevel" "SNDLVL_NORM" + "pitch" "100" + "wave" "weapons/physcannon/superphys_hold_loop.wav" +} + +"Weapon_MegaPhysCannon.ChargeZap" +{ + "channel" "CHAN_VOICE" + "volume" "0.1" + "soundlevel" "SNDLVL_NORM" + "pitch" "90,110" + +"rndwave" + { + "wave" "weapons/physcannon/superphys_small_zap1.wav" + "wave" "weapons/physcannon/superphys_small_zap2.wav" + "wave" "weapons/physcannon/superphys_small_zap3.wav" + "wave" "weapons/physcannon/superphys_small_zap4.wav" + } +} + +"Weapon_PhysCannon.TooHeavy" +{ + "channel" "CHAN_WEAPON" + "volume" "0.8" + "soundlevel" "SNDLVL_NORM" + "pitch" "100" + "wave" "weapons/physcannon/physcannon_tooheavy.wav" +} + +// +// weapon_physgun.txt +// + +"Weapon_Physgun.On" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physgun_on.wav" +} + +"Weapon_Physgun.Off" +{ + "channel" "CHAN_ITEM" + "volume" "0.42" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physgun_off.wav" +} + +"Weapon_Physgun.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.42" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/flaregun/impact.wav" +} + + +"Weapon_Physgun.LockedOn" +{ + "channel" "CHAN_STATIC" + "volume" "0.5" + "soundlevel" "SNDLVL_NORM" + "pitch" "90" + "wave" "weapons/physgun_loop1.wav" +} + +"Weapon_Physgun.Scanning" +{ + "channel" "CHAN_STATIC" + "volume" "0.5" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physgun_loop2.wav" +} + +"Weapon_Physgun.LightObject" +{ + "channel" "CHAN_STATIC" + "volume" "0.1" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physgun_loop3.wav" +} + +"Weapon_Physgun.HeavyObject" +{ + "channel" "CHAN_STATIC" + "volume" "0.1" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/physgun_loop4.wav" +} + +// +// weapon_pistol.txt +// + +"Weapon_Pistol.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/pistol/pistol_reload1.wav" +} + +"Weapon_Pistol.NPC_Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/smg1/smg1_reload.wav" +} + +"Weapon_Pistol.Empty" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/pistol/pistol_empty.wav" +} + +"Weapon_Pistol.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "98,102" + "wave" "weapons/pistol/pistol_fire2.wav" +} + +"Weapon_Pistol.NPC_Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "90,120" + "wave" "^weapons/pistol/pistol_fire3.wav" +} + +"Weapon_Pistol.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/smg1/switch_single.wav" +} + +"Weapon_Pistol.Special2" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/smg1/switch_burst.wav" +} + +"Weapon_Pistol.Burst" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "98,105" + "wave" "^weapons/smg1/smg1_fireburst1.wav" +} + +// +// weapon_rpg.txt +// + +"Weapon_RPG.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/rpg/rocketfire1.wav" +} + +"Weapon_RPG.NPC_Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/rpg/rocketfire1.wav" +} + +"Weapon_RPG.LaserOn" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_zoomin.wav" +} + +"Weapon_RPG.LaserOff" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_zoomout.wav" +} + +// +// weapon_shotgun.txt +// + +"Weapon_Shotgun.Empty" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "pitch" "95,100" + "wave" "weapons/shotgun/shotgun_empty.wav" +} + +"Weapon_Shotgun.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + +"rndwave" + { + "wave" "weapons/shotgun/shotgun_reload1.wav" + "wave" "weapons/shotgun/shotgun_reload2.wav" + "wave" "weapons/shotgun/shotgun_reload3.wav" + } +} + +"Weapon_Shotgun.Special1" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/shotgun/shotgun_cock.wav" +} + +"Weapon_Shotgun.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.86" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "98,101" + +"rndwave" + { + //"wave" "weapons/shotgun/shotgun_fire2.wav" + //"wave" "weapons/shotgun/shotgun_fire6.wav" + "wave" "weapons/shotgun/shotgun_fire7.wav" + } +} + +"Weapon_Shotgun.Double" +{ + "channel" "CHAN_WEAPON" + "volume" "1.0" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "90,95" + "wave" "weapons/shotgun/shotgun_dbl_fire7.wav" +} + +"Weapon_Shotgun.NPC_Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + +"rndwave" + { + "wave" "weapons/shotgun/shotgun_reload1.wav" + "wave" "weapons/shotgun/shotgun_reload2.wav" + "wave" "weapons/shotgun/shotgun_reload3.wav" + } +} + +"Weapon_Shotgun.NPC_Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.95" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "98,101" + "wave" "weapons/shotgun/shotgun_fire6.wav" +} + +// +// weapon_smg1.txt +// + +"Weapon_SMG1.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/smg1/smg1_reload.wav" +} + +"Weapon_SMG1.NPC_Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/smg1/smg1_reload.wav" +} + +"Weapon_SMG1.Empty" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/pistol/pistol_empty.wav" +} + +"Weapon_SMG1.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.55" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "95,105" + "wave" "weapons/smg1/smg1_fire1.wav" +} + +"Weapon_SMG1.Double" +{ + "channel" "CHAN_WEAPON" + "volume" "0.61" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "weapons/ar2/ar2_altfire.wav" +} + + +"Weapon_SMG1.NPC_Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "95,105" + "wave" "^weapons/smg1/npc_smg1_fire1.wav" +} + +"Weapon_SMG1.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/smg1/switch_single.wav" +} + +"Weapon_SMG1.Special2" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/smg1/switch_burst.wav" +} + +"Weapon_SMG1.Burst" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "98,105" + "wave" "^weapons/smg1/smg1_fire1.wav" +} + +// +// weapon_sniperrifle.txt +// + +"Weapon_SniperRifle.Special1" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_zoomin.wav" +} + +"Weapon_SniperRifle.Special2" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_zoomout.wav" +} + +"Weapon_SniperRifle.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_reload.wav" +} + +"Weapon_SniperRifle.NPC_Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/sniper/sniper_reload.wav" +} + +"Weapon_SniperRifle.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "98,102" + "wave" "weapons/sniper/sniper_fire.wav" +} + +"Weapon_SniperRifle.NPC_Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "98,102" + "wave" "weapons/sniper/sniper_fire.wav" +} + +"Weapon_StunStick.Swing" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "pitch" "95,102" + +"rndwave" + { + "wave" "weapons/stunstick/stunstick_swing1.wav" + "wave" "weapons/stunstick/stunstick_swing2.wav" + } +} + +"Weapon_StunStick.Melee_Miss" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + +"rndwave" + { + "wave" "weapons/stunstick/stunstick_swing1.wav" + "wave" "weapons/stunstick/stunstick_swing2.wav" + } +} + +"Weapon_StunStick.Melee_Hit" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_105dB" + "pitch" "98,102" + +"rndwave" + { + "wave" "weapons/stunstick/stunstick_fleshhit1.wav" + "wave" "weapons/stunstick/stunstick_fleshhit2.wav" + } +} + +"Weapon_StunStick.Melee_HitWorld" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_105dB" + "pitch" "98,102" + +"rndwave" + { + "wave" "weapons/stunstick/stunstick_impact1.wav" + "wave" "weapons/stunstick/stunstick_impact2.wav" + } +} + +"Weapon_StunStick.Activate" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "pitch" "98,102" + +"rndwave" + { + "wave" "weapons/stunstick/spark1.wav" + "wave" "weapons/stunstick/spark2.wav" + "wave" "weapons/stunstick/spark3.wav" + } +} + +"Weapon_StunStick.Deactivate" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "pitch" "98,102" + +"rndwave" + { + "wave" "weapons/stunstick/spark1.wav" + "wave" "weapons/stunstick/spark2.wav" + "wave" "weapons/stunstick/spark3.wav" + } +} + +"WeaponFrag.Throw" +{ + "channel" "CHAN_VOICE" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + + "wave" "weapons/slam/throw.wav" +} + +"WeaponFrag.Roll" +{ + "channel" "CHAN_VOICE" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + + "wave" "weapons/slam/throw.wav" +} + +"Weapon_Mortar.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "1.0" + "pitch" "90,110" + "soundlevel" "SNDLVL_GUNFIRE" + "wave" "^weapons/mortar/mortar_fire1.wav" +} + +"Weapon_Mortar.Incomming" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "pitch" "90,110" + "soundlevel" "SNDLVL_120dB" + "wave" "weapons/mortar/mortar_shell_incomming1.wav" +} + +"Weapon_Mortar.Impact" +{ + "channel" "CHAN_WEAPON" + "volume" "1.0" + "soundlevel" "SNDLVL_GUNFIRE" + +"rndwave" + { + "wave" "weapons/mortar/mortar_explode1.wav" + "wave" "weapons/mortar/mortar_explode2.wav" + "wave" "weapons/mortar/mortar_explode3.wav" + } +} + + +"Func_Tank.BeginUse" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/shotgun/shotgun_cock.wav" +} + +// +// weapon_357 +// + +"Weapon_357.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.93" + "soundlevel" "SNDLVL_GUNFIRE" + "pitch" "88,93" + +"rndwave" + { + "wave" "weapons/357/357_fire2.wav" + "wave" "weapons/357/357_fire3.wav" + } +} + +"Weapon_357.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/357/reload1.wav" +} + +"Weapon_357.OpenLoader" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/357/357_reload1.wav" +} + +"Weapon_357.RemoveLoader" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/357/357_reload4.wav" +} + +"Weapon_357.ReplaceLoader" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/357/357_reload3.wav" +} + +"Weapon_357.Spin" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/357/357_spin1.wav" +} + +// +// weapon_crossbow +// + +"Weapon_Crossbow.Single" +{ + "channel" "CHAN_WEAPON" + "volume" "0.61" + "soundlevel" "SNDLVL_NORM" + "pitch" "93,108" + "wave" "weapons/crossbow/fire1.wav" +} + +"Weapon_Crossbow.Reload" +{ + "channel" "CHAN_ITEM" + "volume" "0.7" + "pitch" "93,108" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/crossbow/reload1.wav" +} + +"Weapon_Crossbow.BoltFly" +{ + "channel" "CHAN_VOICE" + "volume" "0.6" + "pitch" "90,110" + "soundlevel" "SNDLVL_NORM" + "wave" "weapons/crossbow/bolt_fly4.wav" +} + +"Weapon_Crossbow.BoltElectrify" +{ + "channel" "CHAN_WEAPON" + "volume" "0.6" + "pitch" "93,108" + "soundlevel" "SNDLVL_NORM" + +"rndwave" + { + "wave" "weapons/crossbow/bolt_load1.wav" + "wave" "weapons/crossbow/bolt_load2.wav" + } +} + +"Weapon_Crossbow.BoltHitBody" +{ + "channel" "CHAN_BODY" + "volume" "0.7" + "pitch" "93,108" + "soundlevel" "SNDLVL_80db" + +"rndwave" + { + "wave" "weapons/crossbow/hitbod1.wav" + "wave" "weapons/crossbow/hitbod2.wav" + } +} + +"Weapon_Crossbow.BoltHitWorld" +{ + "channel" "CHAN_BODY" + "volume" ".95,1.0" + "pitch" "110,130" + "soundlevel" "SNDLVL_80db" + "wave" "weapons/crossbow/hit1.wav" +} + +"Weapon_Crossbow.BoltSkewer" +{ + "channel" "CHAN_STATIC" + "volume" "0.9" + "soundlevel" "SNDLVL_90db" + "pitch" "90,110" + "wave" "weapons/crossbow/bolt_skewer1.wav" + +} + +// ************* +// BASE GRENADES +// + +"BaseExplosionEffect.Sound" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_135dB" + "pitch" "PITCH_NORM" + +"rndwave" + { + "wave" "^grenades/Frag/explosion1.wav" + "wave" "^grenades/Frag/explosion2.wav" + "wave" "^grenades/Frag/explosion3.wav" + "wave" "^grenades/Frag/explosion4.wav" + } +} + +"WaterExplosionEffect.Sound" +{ + "channel" "CHAN_STATIC" + "volume" "1.0" + "soundlevel" "SNDLVL_140dB" + "pitch" "80,130" + +"rndwave" + { + "wave" "^weapons/underwater_explode3.wav" + "wave" "^weapons/underwater_explode4.wav" + } +} + +"BaseGrenade.Explode" +{ + "channel" "CHAN_VOICE" + "volume" "1.0" + "soundlevel" "SNDLVL_85dB" + +"rndwave" + { + "wave" "^grenades/Frag/Debris1.wav" + "wave" "^grenades/Frag/Debris2.wav" + "wave" "^grenades/Frag/Debris3.wav" + } +} + +"BaseGrenade.StopSounds" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + "wave" "common/null.wav" +} + +"BaseGrenade.BounceSound" +{ + "channel" "CHAN_VOICE" + "volume" "1.0" + "soundlevel" "SNDLVL_80dB" + "pitch" "90,110" + "wave" ")grenades/bounce.wav" +} + +"GrenadeBeam.HitSound" +{ + "channel" "CHAN_VOICE" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + +"rndwave" + { + "wave" "weapons/fx/rics/laser_ric1.wav" + "wave" "weapons/fx/rics/laser_ric2.wav" + "wave" "weapons/fx/rics/laser_ric3.wav" + } +} + +"GrenadeBottle.Detonate" +{ + "channel" "CHAN_VOICE" + "volume" "1.0" + "soundlevel" "SNDLVL_75dB" + +"rndwave" + { + "wave" "physics/glass/glass_bottle_break2.wav" + } +} + +"GrenadeBugBait.Splat" +{ + "channel" "CHAN_WEAPON" + "volume" "0.9" + "soundlevel" "SNDLVL_80dB" + "pitch" "95,105" + +"rndwave" + { + "wave" "weapons/bugbait/bugbait_impact1.wav" + "wave" "weapons/bugbait/bugbait_impact3.wav" + } +} + +"GrenadeHomer.StopSounds" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + "wave" "common/null.wav" +} + +"Grenade_Molotov.Detonate" +{ + "channel" "CHAN_VOICE" + "volume" "1.0" + "soundlevel" "SNDLVL_75dB" + +"rndwave" + { + "wave" "physics/glass/glass_bottle_break2.wav" + } +} + +"GrenadePathfollower.StopSounds" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + "wave" "common/null.wav" +} + +"GrenadeScanner.StopSound" +{ + "channel" "CHAN_WEAPON" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + "wave" "common/null.wav" +} + +"TripwireGrenade.ShootRope" +{ + "channel" "CHAN_BODY" + "volume" "0.7" + "soundlevel" "SNDLVL_75dB" + "pitch" "100" + "wave" "weapons/tripwire/ropeshoot.wav" +} + +// +// Alyx's EMP effect +// + +"AlyxEMP.Charge" +{ + "channel" "CHAN_WEAPON" + "volume" "0.65" + "soundlevel" "SNDLVL_90dB" + "pitch" "100,120" + //"wave" "weapons/stunstick/alyx_stunner_charge2.wav" + "wave" "weapons/stunstick/alyx_stunner2.wav" +} + +"AlyxEMP.Discharge" +{ + "channel" "CHAN_WEAPON" + "volume" "0.65" + "soundlevel" "SNDLVL_90dB" + "pitch" "100,120" + +"rndwave" + { + "wave" "weapons/stunstick/alyx_stunner1.wav" + "wave" "weapons/stunstick/alyx_stunner2.wav" + } +} + +"AlyxEMP.Stop" +{ + "channel" "CHAN_WEAPON" + "volume" "0.8" + "soundlevel" "SNDLVL_75dB" + "wave" "common/null.wav" +} + +// ************** +// BASE CHARACTER +// + +"GenericNPC.GunSound" +{ + "channel" "CHAN_WEAPON" + "soundlevel" "SNDLVL_75dB" + "pitch" "95,105" + +"rndwave" + { + "wave" "^weapons/ar1/ar1_dist1.wav" + "wave" "^weapons/ar1/ar1_dist1.wav" + "wave" "^weapons/ar1/ar1_dist2.wav" + } +} + +"Grenade.Blip" +{ + "channel" "CHAN_WEAPON" + "volume" "0.95" + "soundlevel" "SNDLVL_70dB" + "wave" "weapons/grenade/tick1.wav" +} + + diff --git a/scripts/gameinfo.txt b/scripts/gameinfo.txt new file mode 100644 index 0000000..d82f5f7 --- /dev/null +++ b/scripts/gameinfo.txt @@ -0,0 +1,13 @@ +// Valve Game Info file +// These are key/value pairs. Certain mods will use different settings. +// +GameInfo +{ + game "Fortress Forever" + //title "COUNTER-STRIKE'" + //title2 "source" + type multiplayer_only + nomodels 1 + nohimodel 1 + nocrosshair 0 +} diff --git a/scripts/hl2_scripts.dsp b/scripts/hl2_scripts.dsp new file mode 100644 index 0000000..eb3a169 --- /dev/null +++ b/scripts/hl2_scripts.dsp @@ -0,0 +1,304 @@ +# Microsoft Developer Studio Project File - Name="hl2_scripts" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 60000 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=hl2_scripts - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "hl2_scripts.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "hl2_scripts.mak" CFG="hl2_scripts - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "hl2_scripts - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "hl2_scripts - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName ""$/HL2/release/dev/hl2/scripts", ACAAAAAA" +# PROP Scc_LocalPath "." +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "hl2_scripts - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "hl2_scripts - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "hl2_scripts - Win32 Release" +# Name "hl2_scripts - Win32 Debug" +# Begin Group "AI Schedules" + +# PROP Default_Filter "*.sch" +# Begin Source File + +SOURCE=.\barney.sch +# End Source File +# Begin Source File + +SOURCE=.\citizen.sch +# End Source File +# Begin Source File + +SOURCE=.\default.sch +# End Source File +# Begin Source File + +SOURCE=.\kungfu_owen.sch +# End Source File +# Begin Source File + +SOURCE=.\lead_monster.sch +# End Source File +# Begin Source File + +SOURCE=.\metro_police.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_assassin.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_barnacle.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_barney.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_bullsquid.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_combine.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_conscript.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_headcrab.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_manhack.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_mortarsynth.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_odell.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_stalker.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_vortigaunt.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_wscanner.sch +# End Source File +# Begin Source File + +SOURCE=.\npc_zombie.sch +# End Source File +# Begin Source File + +SOURCE=.\odell.sch +# End Source File +# Begin Source File + +SOURCE=.\proto_sniper.sch +# End Source File +# Begin Source File + +SOURCE=.\sacktick.sch +# End Source File +# Begin Source File + +SOURCE=.\scanner.sch +# End Source File +# Begin Source File + +SOURCE=.\talk_monster.sch +# End Source File +# End Group +# Begin Group "Weapon Scripts" + +# PROP Default_Filter "*.txt" +# Begin Source File + +SOURCE=.\weapon_ar1.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_ar2.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_binoculars.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_brickbat.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_flaregun.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_hmg1.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_iceaxe.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_ml.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_molotov.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_physgun.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_shotgun.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_slam.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_smg1.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_smg2.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_sniperrifle.txt +# End Source File +# Begin Source File + +SOURCE=.\weapon_stunstick.txt +# End Source File +# End Group +# Begin Group "Misc Scripts" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\640_hud.txt +# End Source File +# Begin Source File + +SOURCE=.\kb_act.lst +# End Source File +# Begin Source File + +SOURCE=.\kb_def.lst +# End Source File +# Begin Source File + +SOURCE=.\kb_keys.lst +# End Source File +# Begin Source File + +SOURCE=.\liblist.gam +# End Source File +# Begin Source File + +SOURCE=.\materials.txt +# End Source File +# Begin Source File + +SOURCE=.\rooms.lst +# End Source File +# Begin Source File + +SOURCE=.\sentences.txt +# End Source File +# Begin Source File + +SOURCE=.\settings.scr +# End Source File +# Begin Source File + +SOURCE=.\titles.txt +# End Source File +# Begin Source File + +SOURCE=.\woncomm.lst +# End Source File +# End Group +# End Target +# End Project diff --git a/scripts/kb_act.lst b/scripts/kb_act.lst new file mode 100644 index 0000000..a2c15aa --- /dev/null +++ b/scripts/kb_act.lst @@ -0,0 +1,62 @@ +"blank" "==========================" +"blank" "#Valve_Movement_Title" +"blank" "==========================" +"+forward" "#Valve_Move_Forward" +"+back" "#Valve_Move_Back" +"+moveleft" "#Valve_Move_Left" +"+moveright" "#Valve_Move_Right" +"+speed" "#Valve_Walk" +"+jump" "#Valve_Jump" +"+duck" "#Valve_Duck" +"blank" "==========================" +"blank" "#FF_Combat_Title" +"blank" "==========================" +"+attack" "#FF_Attack1" +"+attack2" "#FF_Attack2" +"+reload" "#Valve_Reload_Weapon" +"+gren1" "#FF_Gren1" +"+gren2" "#FF_Gren2" +"toggleone" "#FF_ToggleGren1" +"toggletwo" "#FF_ToggleGren2" +"invprev" "#Valve_Previous_Weapon" +"invnext" "#Valve_Next_Weapon" +"lastinv" "#Valve_Last_Weapon_Used" +"blank" "==========================" +"blank" "#Valve_Communication_Title" +"blank" "==========================" +"+voicerecord" "#Valve_Use_Voice_Communication" +"say" "#Valve_Chat_Message" +"say_team" "#Valve_Team_Message" +"+medengymenu" "#FF_MedEngyMenu" +"blank" "==========================" +"blank" "#Valve_Miscellaneous_Title" +"blank" "==========================" +"+showscores" "#Valve_Display_Scores" +"+hintcenter" "#FF_HintCenter" +"+mapshot" "#FF_MapShot" +"+use" "#Valve_Use_Items" +"discard" "#FF_DiscardAmmo" +"dropitems" "#FF_DropItems" +"flaginfo" "#FF_FlagInfo" +"impulse 100" "#Valve_Flashlight" +"impulse 201" "#Valve_Spray_Logo" +"jpeg" "#Valve_Take_Screen_Shot" +"quit" "#Valve_Quit_Game" +"blank" "==========================" +"blank" "#Valve_Miscellaneous_Keyboard_Keys_Title" +"blank" "==========================" +"+left" "#Valve_Turn_Left" +"+right" "#Valve_Turn_Right" +"+moveup" "#Valve_Swim_Up" +"+movedown" "#Valve_Swim_Down" +"+lookup" "#Valve_Look_Up" +"+lookdown" "#Valve_Look_Down" +"centerview" "#FF_Reset_View" +"+strafe" "#Valve_Strafe_Modifier" +"+mlook" "#FF_Mouse_Look" +"+klook" "#FF_Keyboard_Look" +"blank" "==========================" +"blank" "#FF_TeamOptions" +"blank" "==========================" +"changeteam" "#FF_ChangeTeam" +"changeclass" "#FF_ChangeClass" diff --git a/scripts/kb_def.lst b/scripts/kb_def.lst new file mode 100644 index 0000000..de42478 --- /dev/null +++ b/scripts/kb_def.lst @@ -0,0 +1,63 @@ +"h" "+hintcenter" +"k" "+voicerecord" +"c" "dropitems" +"x" "discard" +"z" "+medengymenu" +"w" "+forward" +"UPARROW" "+forward" +"s" "+back" +"DOWNARROW" "+back" +"LEFTARROW" "+left" +"RIGHTARROW" "+right" +"a" "+moveleft" +"d" "+moveright" +"SPACE" "+jump" +"CTRL" "+duck" +"TAB" "+showscores" +"e" "+use" +"'" "+moveup" +"/" "+movedown" +"PGUP" "+lookup" +"PGDN" "+lookdown" +"END" "centerview" +"ALT" "+strafe" +"INS" "+klook" +";" "+mlook" +"r" "+reload" +"SHIFT" "+speed" +"MOUSE1" "+attack" +"ENTER" "+attack" +"MOUSE2" "+attack2" +"\\" "+attack2" +"l" "impulse 100" +"t" "impulse 201" +"f" "+gren1" +"g" "+gren2" +"1" "slot1" +"2" "slot2" +"3" "slot3" +"4" "slot4" +"5" "slot5" +"6" "slot6" +"7" "slot7" +"8" "slot8" +"9" "slot9" +"0" "slot10" +"MWHEELUP" "invprev" +"[" "invprev" +"MWHEELDOWN" "invnext" +"]" "invnext" +"q" "lastinv" +"F5" "jpeg" +"F10" "quit prompt" +"PAUSE" "pause" +"ESCAPE" "escape" +"~" "toggleconsole" +"`" "toggleconsole" +"+" "sizeup" +"=" "sizeup" +"-" "sizedown" +"y" "say" +"u" "say_team" +"b" "changeclass" +"n" "changeteam" \ No newline at end of file diff --git a/scripts/kb_keys.lst b/scripts/kb_keys.lst new file mode 100644 index 0000000..079fa39 --- /dev/null +++ b/scripts/kb_keys.lst @@ -0,0 +1,256 @@ +0 "" "" DEFAULTCOLOR +1 "" "" DEFAULTCOLOR +2 "" "" DEFAULTCOLOR +3 "" "" DEFAULTCOLOR +4 "" "" DEFAULTCOLOR +5 "" "" DEFAULTCOLOR +6 "" "" DEFAULTCOLOR +7 "" "" DEFAULTCOLOR +8 "" "" DEFAULTCOLOR +9 "TAB" "TAB" DEFAULTCOLOR +10 "" "" DEFAULTCOLOR +11 "" "" DEFAULTCOLOR +12 "" "" DEFAULTCOLOR +13 "ENTER" "ENTER" DEFAULTCOLOR +14 "" "" DEFAULTCOLOR +15 "" "" DEFAULTCOLOR +16 "" "" DEFAULTCOLOR +17 "" "" DEFAULTCOLOR +18 "" "" DEFAULTCOLOR +19 "" "" DEFAULTCOLOR +20 "" "" DEFAULTCOLOR +21 "" "" DEFAULTCOLOR +22 "" "" DEFAULTCOLOR +23 "" "" DEFAULTCOLOR +24 "" "" DEFAULTCOLOR +25 "" "" DEFAULTCOLOR +26 "" "" DEFAULTCOLOR +27 "ESCAPE" "ESCAPE" DEFAULTCOLOR +28 "" "" DEFAULTCOLOR +29 "" "" DEFAULTCOLOR +30 "" "" DEFAULTCOLOR +31 "" "" DEFAULTCOLOR +32 "SPACE" "SPACE" DEFAULTCOLOR +33 "!" "!" DEFAULTCOLOR +34 """ """ DEFAULTCOLOR +35 "#" "#" DEFAULTCOLOR +36 "$" "$" DEFAULTCOLOR +37 "BACKSPACE" "BACKSPACE" DEFAULTCOLOR +38 "&" "&" DEFAULTCOLOR +39 "'" "'" DEFAULTCOLOR +40 "(" "(" DEFAULTCOLOR +41 ")" ")" DEFAULTCOLOR +42 "*" "*" DEFAULTCOLOR +43 "+" "+" DEFAULTCOLOR +44 "," "," DEFAULTCOLOR +45 "-" "-" DEFAULTCOLOR +46 "." "." DEFAULTCOLOR +47 "/" "/" DEFAULTCOLOR +48 "0" "0" DEFAULTCOLOR +49 "1" "1" DEFAULTCOLOR +50 "2" "2" DEFAULTCOLOR +51 "3" "3" DEFAULTCOLOR +52 "4" "4" DEFAULTCOLOR +53 "5" "5" DEFAULTCOLOR +54 "6" "6" DEFAULTCOLOR +55 "7" "7" DEFAULTCOLOR +56 "8" "8" DEFAULTCOLOR +57 "9" "9" DEFAULTCOLOR +58 ":" ":" DEFAULTCOLOR +59 ";" ";" DEFAULTCOLOR +60 "<" "<" DEFAULTCOLOR +61 "=" "=" DEFAULTCOLOR +62 ">" ">" DEFAULTCOLOR +63 "?" "?" DEFAULTCOLOR +64 "@" "@" DEFAULTCOLOR +65 "A" "A" DEFAULTCOLOR +66 "B" "B" DEFAULTCOLOR +67 "C" "C" DEFAULTCOLOR +68 "D" "D" DEFAULTCOLOR +69 "E" "E" DEFAULTCOLOR +70 "F" "F" DEFAULTCOLOR +71 "G" "G" DEFAULTCOLOR +72 "H" "H" DEFAULTCOLOR +73 "I" "I" DEFAULTCOLOR +74 "J" "J" DEFAULTCOLOR +75 "K" "K" DEFAULTCOLOR +76 "L" "L" DEFAULTCOLOR +77 "M" "M" DEFAULTCOLOR +78 "N" "N" DEFAULTCOLOR +79 "O" "O" DEFAULTCOLOR +80 "P" "P" DEFAULTCOLOR +81 "Q" "Q" DEFAULTCOLOR +82 "R" "R" DEFAULTCOLOR +83 "S" "S" DEFAULTCOLOR +84 "T" "T" DEFAULTCOLOR +85 "U" "U" DEFAULTCOLOR +86 "V" "V" DEFAULTCOLOR +87 "W" "W" DEFAULTCOLOR +88 "X" "X" DEFAULTCOLOR +89 "Y" "Y" DEFAULTCOLOR +90 "Z" "Z" DEFAULTCOLOR +91 "[" "[" DEFAULTCOLOR +92 "\" "\" DEFAULTCOLOR +93 "]" "]" DEFAULTCOLOR +94 "^" "^" DEFAULTCOLOR +95 "_" "_" DEFAULTCOLOR +96 "`" "`" DEFAULTCOLOR +97 "a" "a" DEFAULTCOLOR +98 "b" "b" DEFAULTCOLOR +99 "c" "c" DEFAULTCOLOR +100 "d" "d" DEFAULTCOLOR +101 "e" "e" DEFAULTCOLOR +102 "f" "f" DEFAULTCOLOR +103 "g" "g" DEFAULTCOLOR +104 "h" "h" DEFAULTCOLOR +105 "i" "i" DEFAULTCOLOR +106 "j" "j" DEFAULTCOLOR +107 "k" "k" DEFAULTCOLOR +108 "l" "l" DEFAULTCOLOR +109 "m" "m" DEFAULTCOLOR +110 "n" "n" DEFAULTCOLOR +111 "o" "o" DEFAULTCOLOR +112 "p" "p" DEFAULTCOLOR +113 "q" "q" DEFAULTCOLOR +114 "r" "r" DEFAULTCOLOR +115 "s" "s" DEFAULTCOLOR +116 "t" "t" DEFAULTCOLOR +117 "u" "u" DEFAULTCOLOR +118 "v" "v" DEFAULTCOLOR +119 "w" "w" DEFAULTCOLOR +120 "x" "x" DEFAULTCOLOR +121 "y" "y" DEFAULTCOLOR +122 "z" "z" DEFAULTCOLOR +123 "{" "{" DEFAULTCOLOR +124 "|" "|" DEFAULTCOLOR +125 "}" "}" DEFAULTCOLOR +126 "~" "~" DEFAULTCOLOR +127 "BACKSPACE" "BACKSPACE" DEFAULTCOLOR +128 "UPARROW" "UPARROW" DEFAULTCOLOR +129 "DOWNARROW" "DOWNARROW" DEFAULTCOLOR +130 "LEFTARROW" "LEFTARROW" DEFAULTCOLOR +131 "RIGHTARROW" "RIGHTARROW" DEFAULTCOLOR +132 "ALT" "ALT" DEFAULTCOLOR +133 "CTRL" "CTRL" DEFAULTCOLOR +134 "SHIFT" "SHIFT" DEFAULTCOLOR +135 "F1" "F1" DEFAULTCOLOR +136 "F2" "F2" DEFAULTCOLOR +137 "F3" "F3" DEFAULTCOLOR +138 "F4" "F4" DEFAULTCOLOR +139 "F5" "F5" DEFAULTCOLOR +140 "F6" "F6" DEFAULTCOLOR +141 "F7" "F7" DEFAULTCOLOR +142 "F8" "F8" DEFAULTCOLOR +143 "F9" "F9" DEFAULTCOLOR +144 "F10" "F10" DEFAULTCOLOR +145 "F11" "F11" DEFAULTCOLOR +146 "F12" "F12" DEFAULTCOLOR +147 "INS" "INS" DEFAULTCOLOR +148 "DEL" "DEL" DEFAULTCOLOR +149 "PGDN" "PGDN" DEFAULTCOLOR +150 "PGUP" "PGUP" DEFAULTCOLOR +151 "HOME" "HOME" DEFAULTCOLOR +152 "END" "END" DEFAULTCOLOR +153 "" "" DEFAULTCOLOR +154 "" "" DEFAULTCOLOR +155 "" "" DEFAULTCOLOR +156 "" "" DEFAULTCOLOR +157 "" "" DEFAULTCOLOR +158 "" "" DEFAULTCOLOR +159 "" "" DEFAULTCOLOR +160 "" "" DEFAULTCOLOR +161 "" "" DEFAULTCOLOR +162 "" "" DEFAULTCOLOR +163 "" "" DEFAULTCOLOR +164 "" "" DEFAULTCOLOR +165 "" "" DEFAULTCOLOR +166 "" "" DEFAULTCOLOR +167 "" "" DEFAULTCOLOR +168 "" "" DEFAULTCOLOR +169 "" "" DEFAULTCOLOR +170 "" "" DEFAULTCOLOR +171 "" "" DEFAULTCOLOR +172 "" "" DEFAULTCOLOR +173 "" "" DEFAULTCOLOR +174 "" "" DEFAULTCOLOR +175 "" "" DEFAULTCOLOR +176 "" "" DEFAULTCOLOR +177 "" "" DEFAULTCOLOR +178 "" "" DEFAULTCOLOR +179 "" "" DEFAULTCOLOR +180 "" "" DEFAULTCOLOR +181 "" "" DEFAULTCOLOR +182 "" "" DEFAULTCOLOR +183 "" "" DEFAULTCOLOR +184 "" "" DEFAULTCOLOR +185 "" "" DEFAULTCOLOR +186 "" "" DEFAULTCOLOR +187 "" "" DEFAULTCOLOR +188 "" "" DEFAULTCOLOR +189 "" "" DEFAULTCOLOR +190 "" "" DEFAULTCOLOR +191 "" "" DEFAULTCOLOR +192 "" "" DEFAULTCOLOR +193 "" "" DEFAULTCOLOR +194 "" "" DEFAULTCOLOR +195 "" "" DEFAULTCOLOR +196 "" "" DEFAULTCOLOR +197 "" "" DEFAULTCOLOR +198 "" "" DEFAULTCOLOR +199 "" "" DEFAULTCOLOR +200 "MOUSE1" "MOUSE1" COLOR 0 255 255 +201 "MOUSE2" "MOUSE2" COLOR 0 255 255 +202 "MOUSE3" "MOUSE3" COLOR 0 255 255 +203 "JOY1" "JOY1" COLOR 255 0 0 +204 "JOY2" "JOY2" COLOR 255 0 0 +205 "JOY3" "JOY3" COLOR 255 0 0 +206 "JOY4" "JOY4" COLOR 255 0 0 +207 "AUX1" "AUX1" DEFAULTCOLOR +208 "AUX2" "AUX2" DEFAULTCOLOR +209 "AUX3" "AUX3" DEFAULTCOLOR +210 "AUX4" "AUX4" DEFAULTCOLOR +211 "AUX5" "AUX5" DEFAULTCOLOR +212 "AUX6" "AUX6" DEFAULTCOLOR +213 "AUX7" "AUX7" DEFAULTCOLOR +214 "AUX8" "AUX8" DEFAULTCOLOR +215 "AUX9" "AUX9" DEFAULTCOLOR +216 "AUX10" "AUX10" DEFAULTCOLOR +217 "AUX11" "AUX11" DEFAULTCOLOR +218 "AUX12" "AUX12" DEFAULTCOLOR +219 "AUX13" "AUX13" DEFAULTCOLOR +220 "AUX14" "AUX14" DEFAULTCOLOR +221 "AUX15" "AUX15" DEFAULTCOLOR +222 "AUX16" "AUX16" DEFAULTCOLOR +223 "AUX17" "AUX17" DEFAULTCOLOR +224 "AUX18" "AUX18" DEFAULTCOLOR +225 "AUX19" "AUX19" DEFAULTCOLOR +226 "AUX20" "AUX20" DEFAULTCOLOR +227 "AUX21" "AUX21" DEFAULTCOLOR +228 "AUX22" "AUX22" DEFAULTCOLOR +229 "AUX23" "AUX23" DEFAULTCOLOR +230 "AUX24" "AUX24" DEFAULTCOLOR +231 "AUX25" "AUX25" DEFAULTCOLOR +232 "AUX26" "AUX26" DEFAULTCOLOR +233 "AUX27" "AUX27" DEFAULTCOLOR +234 "AUX28" "AUX28" DEFAULTCOLOR +235 "AUX29" "AUX29" DEFAULTCOLOR +236 "AUX30" "AUX30" DEFAULTCOLOR +237 "AUX31" "AUX31" DEFAULTCOLOR +238 "AUX32" "AUX32" DEFAULTCOLOR +239 "MWHEELDOWN" "MWHEELDOWN" DEFAULTCOLOR +240 "MWHEELUP" "MWHEELUP" DEFAULTCOLOR +241 "" "" DEFAULTCOLOR +242 "" "" DEFAULTCOLOR +243 "" "" DEFAULTCOLOR +244 "" "" DEFAULTCOLOR +245 "" "" DEFAULTCOLOR +246 "" "" DEFAULTCOLOR +247 "" "" DEFAULTCOLOR +248 "" "" DEFAULTCOLOR +249 "" "" DEFAULTCOLOR +250 "" "" DEFAULTCOLOR +251 "" "" DEFAULTCOLOR +252 "" "" DEFAULTCOLOR +253 "" "" DEFAULTCOLOR +254 "" "" DEFAULTCOLOR +255 "PAUSE" "PAUSE" DEFAULTCOLOR diff --git a/scripts/liblist.gam b/scripts/liblist.gam new file mode 100644 index 0000000..4991c7c --- /dev/null +++ b/scripts/liblist.gam @@ -0,0 +1,9 @@ +// Valve Game Info file +// These are key/value pairs. Certain mods will use different settings. +// +game "Fortress Forever Biotches" +startmap "mulch_test" +trainingmap "t0a0" +hlversion "1000" +mpentity "info_player_start" +gamedll "dlls\server.dll" diff --git a/scripts/sentences.txt b/scripts/sentences.txt new file mode 100644 index 0000000..86882c3 --- /dev/null +++ b/scripts/sentences.txt @@ -0,0 +1,102 @@ +// Fortress Forever SPEECH SYSTEM SENTENCES. +// Do not use TABS. Separate sentence-names from wave definitions with single spaces only. + +// --------- Canal Zone --------- // +CZ_GOTCP1 bully/CZ_GOTCP1 +CZ_LOSTCP1 bully/CZ_LOSTCP1 +CZ_GOTCP2 bully/CZ_GOTCP2 +CZ_LOSTCP2 bully/CZ_LOSTCP2 +CZ_GOTCP3 bully/CZ_GOTCP3 +CZ_LOSTCP3 bully/CZ_LOSTCP3 +CZ_GOTCP4 bully/CZ_GOTCP4 +CZ_LOSTCP4 bully/CZ_LOSTCP4 +CZ_GOTCP5 bully/CZ_GOTCP5 +CZ_LOSTCP5 bully/CZ_LOSTCP5 +CZ_GOTALL bully/CZ_GOTALL _comma _comma _comma _comma CZ_POINTSRESET +CZ_THEYGOTALL bully/CZ_THEYGOTALL _comma _comma _comma _comma CZ_POINTSRESET +CZ_BCC_DET bully/CZ_BCC_DET +CZ_RCC_DET bully/CZ_RCC_DET + +// --------- Capture the Flag --------- // +CTF_YOUCAP bully/CTF_YOUCAP +CTF_TEAMCAP bully/CTF_TEAMCAP +CTF_THEYCAP bully/CTF_THEYCAP +CTF_YOUGOTFLAG bully/CTF_YOUGOTFLAG +CTF_YOUGOTFLAG2 bully/CTF_YOUGOTFLAG2 +CTF_YOUGOTFLAG3 bully/CTF_YOUGOTFLAG3 +CTF_YOUGOTFLAG4 bully/CTF_YOUGOTFLAG4 +CTF_GOTFLAG bully/CTF_GOTFLAG +CTF_GOTFLAG2 bully/CTF_GOTFLAG2 +CTF_GOTFLAG3 bully/CTF_GOTFLAG3 +CTF_GOTFLAG4 bully/CTF_GOTFLAG4 +CTF_LOSTFLAG bully/CTF_LOSTFLAG +CTF_LOSTFLAG2 bully/CTF_LOSTFLAG2 +CTF_LOSTFLAG3 bully/CTF_LOSTFLAG3 +CTF_LOSTFLAG4 bully/CTF_LOSTFLAG4 +CTF_FLAGBACK bully/CTF_FLAGBACK +CTF_EFLAGBACK bully/CTF_EFLAGBACK + +// --------- Hunted --------- // +HTD_DOORS bully/HTD_DOORS + +// --------- The Rock --------- // +RK_BYARDOPEN bully/RK_BYARDOPEN +RK_RYARDOPEN bully/RK_RYARDOPEN +RK_KEYBACK vox/female/your key has returned +RK_EKEYBACK vox/female/enemy key has returned +RK_GOTKEY vox/female/your team has the enemy key +RK_LOSTKEY vox/female/the enemy has your key +RK_BSCORE vox/female/blue team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_RSCORE vox/female/red team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_TAKEKEY vox/female/take key to enemy gas chamber +FBALL_BSCORE vox/female/blue team scores +FBALL_RSCORE vox/female/red team scores + +// --------- Attack/Defend --------- // +AD_600SEC bully/AD_600SEC +AD_300SEC bully/AD_300SEC +AD_120SEC bully/AD_120SEC +AD_60SEC bully/AD_60SEC +AD_30SEC bully/AD_30SEC +AD_10SEC bully/AD_10SEC +AD_9SEC bully/AD_9SEC +AD_8SEC bully/AD_8SEC +AD_7SEC bully/AD_7SEC +AD_6SEC bully/AD_6SEC +AD_5SEC bully/AD_5SEC +AD_4SEC bully/AD_4SEC +AD_3SEC bully/AD_3SEC +AD_2SEC bully/AD_2SEC +AD_1SEC bully/AD_1SEC +AD_CP1 bully/AD_CP1 +AD_CP2 bully/AD_CP2 +AD_HOLD bully/AD_HOLD +AD_CAP bully/AD_CAP +AD_GATESOPEN bully/AD_GATESOPEN +AD_ATTACK bully/AD_ATTACK +AD_DEFEND bully/AD_DEFEND + +// --------- Shutdown2 --------- // +SD_REDDOWN bully/SD_REDDOWN +SD_REDUP bully/SD_REDUP +SD_BLUEDOWN bully/SD_BLUEDOWN +SD_BLUEUP bully/SD_BLUEUP + +// --------- Push --------- // +CTF_YOUSCORE bully/CTF_YOUSCORE +CTF_TEAMSCORE bully/CTF_TEAMSCORE +CTF_THEYSCORE bully/CTF_THEYSCORE +CTF_YOUHAVEBALL bully/CTF_YOUHAVEBALL +CTF_TEAMHASBALL bully/CTF_TEAMHASBALL +CTF_ENEMYHASBALL bully/CTF_ENEMYHASBALL +CTF_BALLRETURN bully/CTF_BALLRETURN + +// --------- Win --------- // +WIN_BLUE bully/WIN_BLUE +WIN_RED bully/WIN_RED +WIN_YELLOW bully/WIN_YELLOW +WIN_GREEN bully/WIN_GREEN +WINNING_YOURTEAM bully/WINNING_YOURTEAM +WINNING_ENEMYTEAM bully/WINNING_ENEMYTEAM + +CZ_POINTSRESET bully/CZ_POINTSRESET diff --git a/scripts/sentences_bully.txt b/scripts/sentences_bully.txt new file mode 100644 index 0000000..a142580 --- /dev/null +++ b/scripts/sentences_bully.txt @@ -0,0 +1,100 @@ +// Fortress Forever SPEECH SYSTEM SENTENCES. +// Do not use TABS. Separate sentence-names from wave definitions with single spaces only. + +// --------- Canal Zone --------- // +CZ_GOTCP1 bully/CZ_GOTCP1 +CZ_LOSTCP1 bully/CZ_LOSTCP1 +CZ_GOTCP2 bully/CZ_GOTCP2 +CZ_LOSTCP2 bully/CZ_LOSTCP2 +CZ_GOTCP3 bully/CZ_GOTCP3 +CZ_LOSTCP3 bully/CZ_LOSTCP3 +CZ_GOTCP4 bully/CZ_GOTCP4 +CZ_LOSTCP4 bully/CZ_LOSTCP4 +CZ_GOTCP5 bully/CZ_GOTCP5 +CZ_LOSTCP5 bully/CZ_LOSTCP5 +CZ_GOTALL bully/CZ_GOTALL _comma _comma _comma _comma CZ_POINTSRESET +CZ_THEYGOTALL bully/CZ_THEYGOTALL _comma _comma _comma _comma CZ_POINTSRESET +CZ_BCC_DET bully/CZ_BCC_DET +CZ_RCC_DET bully/CZ_RCC_DET + +// --------- Capture the Flag --------- // +CTF_YOUCAP bully/CTF_YOUCAP +CTF_TEAMCAP bully/CTF_TEAMCAP +CTF_THEYCAP bully/CTF_THEYCAP +CTF_YOUGOTFLAG bully/CTF_YOUGOTFLAG +CTF_YOUGOTFLAG2 bully/CTF_YOUGOTFLAG2 +CTF_YOUGOTFLAG3 bully/CTF_YOUGOTFLAG3 +CTF_YOUGOTFLAG4 bully/CTF_YOUGOTFLAG4 +CTF_GOTFLAG bully/CTF_GOTFLAG +CTF_GOTFLAG2 bully/CTF_GOTFLAG2 +CTF_GOTFLAG3 bully/CTF_GOTFLAG3 +CTF_GOTFLAG4 bully/CTF_GOTFLAG4 +CTF_LOSTFLAG bully/CTF_LOSTFLAG +CTF_LOSTFLAG2 bully/CTF_LOSTFLAG2 +CTF_LOSTFLAG3 bully/CTF_LOSTFLAG3 +CTF_LOSTFLAG4 bully/CTF_LOSTFLAG4 +CTF_FLAGBACK bully/CTF_FLAGBACK +CTF_EFLAGBACK bully/CTF_EFLAGBACK + +// --------- Hunted --------- // +HTD_DOORS bully/HTD_DOORS + +// --------- The Rock --------- // +RK_BYARDOPEN bully/RK_BYARDOPEN +RK_RYARDOPEN bully/RK_RYARDOPEN +RK_KEYBACK vox/female/your key has returned +RK_EKEYBACK vox/female/enemy key has returned +RK_GOTKEY vox/female/your team has the enemy key +RK_LOSTKEY vox/female/the enemy has your key +RK_BSCORE vox/female/blue team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_RSCORE vox/female/red team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_TAKEKEY vox/female/take key to enemy gas chamber +FBALL_BSCORE vox/female/blue team scores +FBALL_RSCORE vox/female/red team scores + +// --------- Attack/Defend --------- // +AD_600SEC bully/AD_600SEC +AD_300SEC bully/AD_300SEC +AD_120SEC bully/AD_120SEC +AD_60SEC bully/AD_60SEC +AD_30SEC bully/AD_30SEC +AD_10SEC bully/AD_10SEC +AD_9SEC bully/AD_9SEC +AD_8SEC bully/AD_8SEC +AD_7SEC bully/AD_7SEC +AD_6SEC bully/AD_6SEC +AD_5SEC bully/AD_5SEC +AD_4SEC bully/AD_4SEC +AD_3SEC bully/AD_3SEC +AD_2SEC bully/AD_2SEC +AD_1SEC bully/AD_1SEC +AD_CP1 bully/AD_CP1 +AD_CP2 bully/AD_CP2 +AD_HOLD bully/AD_HOLD +AD_CAP bully/AD_CAP +AD_GATESOPEN bully/AD_GATESOPEN +AD_ATTACK bully/AD_ATTACK +AD_DEFEND bully/AD_DEFEND + +// --------- Shutdown2 --------- // +SD_REDDOWN bully/SD_REDDOWN +SD_REDUP bully/SD_REDUP +SD_BLUEDOWN bully/SD_BLUEDOWN +SD_BLUEUP bully/SD_BLUEUP + +// --------- Push --------- // +CTF_YOUSCORE bully/CTF_YOUSCORE +CTF_TEAMSCORE bully/CTF_TEAMSCORE +CTF_THEYSCORE bully/CTF_THEYSCORE +CTF_YOUHAVEBALL bully/CTF_YOUHAVEBALL +CTF_TEAMHASBALL bully/CTF_TEAMHASBALL +CTF_ENEMYHASBALL bully/CTF_ENEMYHASBALL +CTF_BALLRETURN bully/CTF_BALLRETURN + +// --------- Win --------- // +WIN_BLUE bully/WIN_BLUE +WIN_RED bully/WIN_RED +WIN_YELLOW bully/WIN_YELLOW +WIN_GREEN bully/WIN_GREEN +WINNING_YOURTEAM bully/WINNING_YOURTEAM +WINNING_ENEMYTEAM bully/WINNING_ENEMYTEAM diff --git a/scripts/sentences_common.txt b/scripts/sentences_common.txt new file mode 100644 index 0000000..ba71ba7 --- /dev/null +++ b/scripts/sentences_common.txt @@ -0,0 +1,22 @@ +// Fortress Forever SPEECH SYSTEM SENTENCES. +// Do not use TABS. Separate sentence-names from wave definitions with single spaces only. + + +//////////// +// Test // +//////////// +VOX_TEST_COMMON vox/female/t e s t c o m m o n + + +/////////////////////////////////////// +// ff_anticitizen common sentences // +/////////////////////////////////////// +AD_AC_CP1 vox/female/yellow team secured command point one +AD_AC_CP2 vox/female/yellow team secured command point two +AD_AC_HOLD vox/female/blue team holds blue base +AD_AC_CAP vox/female/yellow team captured blue base + +AD_RADIO_1 npc/overwatch/radiovoice/on1 riot404 yellow citizen infection isnow inprogress on3 allunitsapplyforwardpressure off2 +AD_RADIO_2 npc/overwatch/radiovoice/on1 assault243 isnow inprogress on3 isolate cauterize level5anticivilactivity off2 +AD_RADIO_3 npc/overwatch/radiovoice/on1 highpriorityregion isnow infestedzone on3 preparetoinnoculate off2 + diff --git a/scripts/sentences_female.txt b/scripts/sentences_female.txt new file mode 100644 index 0000000..9933b2a --- /dev/null +++ b/scripts/sentences_female.txt @@ -0,0 +1,100 @@ +// Fortress Forever SPEECH SYSTEM SENTENCES. +// Do not use TABS. Separate sentence-names from wave definitions with single spaces only. + +// --------- Canal Zone --------- // +CZ_GOTCP1 vox/female/command point one secured +CZ_LOSTCP1 vox/female/command point one is now hostile +CZ_GOTCP2 vox/female/command point two secured +CZ_LOSTCP2 vox/female/command point two is now hostile +CZ_GOTCP3 vox/female/command point three secured +CZ_LOSTCP3 vox/female/command point three is now hostile +CZ_GOTCP4 vox/female/command point four secured +CZ_LOSTCP4 vox/female/command point four is now hostile +CZ_GOTCP5 vox/female/command point five secured +CZ_LOSTCP5 vox/female/command point five is now hostile +CZ_GOTALL vox/female/all command points secured _comma _comma _comma command points reset +CZ_THEYGOTALL vox/female/enemy captured all command points _comma _comma _comma command points reset +CZ_BCC_DET vox/female/blue command center detonation +CZ_RCC_DET vox/female/red command center detonation + +// --------- Capture the Flag --------- // +CTF_YOUCAP vox/female/you captured the enemy flag +CTF_TEAMCAP vox/female/your team captured the flag +CTF_THEYCAP vox/female/the enemy team captured the flag +CTF_YOUGOTFLAG vox/female/you have the enemy flag +CTF_YOUGOTFLAG2 vox/female/you have the enemy flag +CTF_YOUGOTFLAG3 vox/female/you have the enemy flag +CTF_YOUGOTFLAG4 vox/female/you have the enemy flag +CTF_GOTFLAG vox/female/your team has the enemy flag +CTF_GOTFLAG2 vox/female/your team has the enemy flag +CTF_GOTFLAG3 vox/female/your team has the enemy flag +CTF_GOTFLAG4 vox/female/your team has the enemy flag +CTF_LOSTFLAG vox/female/the enemy has your flag +CTF_LOSTFLAG2 vox/female/the enemy has your flag +CTF_LOSTFLAG3 vox/female/the enemy has your flag +CTF_LOSTFLAG4 vox/female/the enemy has your flag +CTF_FLAGBACK vox/female/your flag has returned +CTF_EFLAGBACK vox/female/the enemy flag has returned + +// --------- Hunted --------- // +HTD_DOORS vox/female/escape door open + +// --------- The Rock --------- // +RK_BYARDOPEN vox/female/blue yard has been breached +RK_RYARDOPEN vox/female/red yard has been breached +RK_KEYBACK vox/female/your key has returned +RK_EKEYBACK vox/female/enemy key has returned +RK_GOTKEY vox/female/your team has the enemy key +RK_LOSTKEY vox/female/the enemy has your key +RK_BSCORE vox/female/blue team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_RSCORE vox/female/red team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_TAKEKEY vox/female/take key to enemy gas chamber +FBALL_BSCORE vox/female/blue team scores +FBALL_RSCORE vox/female/red team scores + +// --------- Attack/Defend --------- // +AD_600SEC vox/female/ten minutes remaining +AD_300SEC vox/female/five minutes remaining +AD_120SEC vox/female/two minutes remaining +AD_60SEC vox/female/sixty seconds remaining +AD_30SEC vox/female/thirty seconds remaining +AD_10SEC vox/female/ten +AD_9SEC vox/female/nine +AD_8SEC vox/female/eight +AD_7SEC vox/female/seven +AD_6SEC vox/female/six +AD_5SEC vox/female/five +AD_4SEC vox/female/four +AD_3SEC vox/female/three +AD_2SEC vox/female/two +AD_1SEC vox/female/one +AD_CP1 vox/female/blue team secured command point one +AD_CP2 vox/female/blue team secured command point two +AD_HOLD vox/female/red team holds red base +AD_CAP vox/female/blue team captured red base +AD_GATESOPEN vox/female/_comma +AD_ATTACK vox/female/_comma +AD_DEFEND vox/female/_comma + +// --------- Shutdown2 --------- // +SD_REDDOWN vox/female/red security has been deactivated +SD_REDUP vox/female/red security has been reactivated +SD_BLUEDOWN vox/female/blue security has been deactivated +SD_BLUEUP vox/female/blue security has been reactivated + +// --------- Push --------- // +CTF_YOUSCORE vox/female/you captured the ball +CTF_TEAMSCORE vox/female/your team captured the ball +CTF_THEYSCORE vox/female/the enemy team captured the ball +CTF_YOUHAVEBALL vox/female/you have the ball +CTF_TEAMHASBALL vox/female/your team has the ball +CTF_ENEMYHASBALL vox/female/the enemy has the ball +CTF_BALLRETURN vox/female/the ball has returned + +// --------- Win --------- // +WIN_BLUE vox/female/blue team wins +WIN_RED vox/female/red team wins +WIN_YELLOW vox/female/yellow team wins +WIN_GREEN vox/female/green team wins +WINNING_YOURTEAM vox/female/_comma +WINNING_ENEMYTEAM vox/female/_comma diff --git a/scripts/sentences_robot.txt b/scripts/sentences_robot.txt new file mode 100644 index 0000000..2d48ae6 --- /dev/null +++ b/scripts/sentences_robot.txt @@ -0,0 +1,100 @@ +// Fortress Forever SPEECH SYSTEM SENTENCES. +// Do not use TABS. Separate sentence-names from wave definitions with single spaces only. + +// --------- Canal Zone --------- // +CZ_GOTCP1 vox/robot/command point one secured +CZ_LOSTCP1 vox/robot/command point one is now hostile +CZ_GOTCP2 vox/robot/command point two secured +CZ_LOSTCP2 vox/robot/command point two is now hostile +CZ_GOTCP3 vox/robot/command point three secured +CZ_LOSTCP3 vox/robot/command point three is now hostile +CZ_GOTCP4 vox/robot/command point four secured +CZ_LOSTCP4 vox/robot/command point four is now hostile +CZ_GOTCP5 vox/robot/command point five secured +CZ_LOSTCP5 vox/robot/command point five is now hostile +CZ_GOTALL vox/robot/all command points secured _comma _comma _comma command points reset +CZ_THEYGOTALL vox/robot/enemy captured all command points _comma _comma _comma command points reset +CZ_BCC_DET vox/robot/blue command center detonation +CZ_RCC_DET vox/robot/red command center detonation + +// --------- Capture the Flag --------- // +CTF_YOUCAP vox/robot/you captured the enemy flag +CTF_TEAMCAP vox/robot/your team captured the flag +CTF_THEYCAP vox/robot/the enemy team captured the flag +CTF_YOUGOTFLAG vox/robot/you have the enemy flag +CTF_YOUGOTFLAG2 vox/robot/you have the enemy flag +CTF_YOUGOTFLAG3 vox/robot/you have the enemy flag +CTF_YOUGOTFLAG4 vox/robot/you have the enemy flag +CTF_GOTFLAG vox/robot/your team has the enemy flag +CTF_GOTFLAG2 vox/robot/your team has the enemy flag +CTF_GOTFLAG3 vox/robot/your team has the enemy flag +CTF_GOTFLAG4 vox/robot/your team has the enemy flag +CTF_LOSTFLAG vox/robot/the enemy has your flag +CTF_LOSTFLAG2 vox/robot/the enemy has your flag +CTF_LOSTFLAG3 vox/robot/the enemy has your flag +CTF_LOSTFLAG4 vox/robot/the enemy has your flag +CTF_FLAGBACK vox/robot/your flag has returned +CTF_EFLAGBACK vox/robot/the enemy flag has returned + +// --------- Hunted --------- // +HTD_DOORS vox/robot/escape door open + +// --------- The Rock --------- // +RK_BYARDOPEN vox/robot/blue yard has been breached +RK_RYARDOPEN vox/robot/red yard has been breached +RK_KEYBACK vox/robot/your key has returned +RK_EKEYBACK vox/robot/enemy key has returned +RK_GOTKEY vox/robot/your team has the enemy key +RK_LOSTKEY vox/robot/the enemy has your key +RK_BSCORE vox/robot/blue team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_RSCORE vox/robot/red team scores _comma _comma _comma nerve gas released _comma _comma _comma secure protective suit immediately +RK_TAKEKEY vox/robot/take key to enemy gas chamber +FBALL_BSCORE vox/robot/blue team scores +FBALL_RSCORE vox/robot/red team scores + +// --------- Attack/Defend --------- // +AD_600SEC vox/robot/ten minutes remaining +AD_300SEC vox/robot/five minutes remaining +AD_120SEC vox/robot/two minutes remaining +AD_60SEC vox/robot/sixty seconds remaining +AD_30SEC vox/robot/thirty seconds remaining +AD_10SEC vox/robot/ten +AD_9SEC vox/robot/nine +AD_8SEC vox/robot/eight +AD_7SEC vox/robot/seven +AD_6SEC vox/robot/six +AD_5SEC vox/robot/five +AD_4SEC vox/robot/four +AD_3SEC vox/robot/three +AD_2SEC vox/robot/two +AD_1SEC vox/robot/one +AD_CP1 vox/robot/blue team secured command point one +AD_CP2 vox/robot/blue team secured command point two +AD_HOLD vox/robot/red team holds red base +AD_CAP vox/robot/blue team captured red base +AD_GATESOPEN vox/robot/_comma +AD_ATTACK vox/robot/_comma +AD_DEFEND vox/robot/_comma + +// --------- Shutdown2 --------- // +SD_REDDOWN vox/robot/red security has been deactivated +SD_REDUP vox/robot/red security has been reactivated +SD_BLUEDOWN vox/robot/blue security has been deactivated +SD_BLUEUP vox/robot/blue security has been reactivated + +// --------- Push --------- // +CTF_YOUSCORE vox/robot/you captured the ball +CTF_TEAMSCORE vox/robot/your team captured the ball +CTF_THEYSCORE vox/robot/the enemy team captured the ball +CTF_YOUHAVEBALL vox/robot/you have the ball +CTF_TEAMHASBALL vox/robot/your team has the ball +CTF_ENEMYHASBALL vox/robot/the enemy has the ball +CTF_BALLRETURN vox/robot/the ball has returned + +// --------- Win --------- // +WIN_BLUE vox/robot/blue team wins +WIN_RED vox/robot/red team wins +WIN_YELLOW vox/robot/yellow team wins +WIN_GREEN vox/robot/green team wins +WINNING_YOURTEAM vox/robot/_comma +WINNING_ENEMYTEAM vox/robot/_comma diff --git a/scripts/sentences_tfc.txt b/scripts/sentences_tfc.txt new file mode 100644 index 0000000..34a5616 --- /dev/null +++ b/scripts/sentences_tfc.txt @@ -0,0 +1,100 @@ +// Fortress Forever SPEECH SYSTEM SENTENCES. +// Do not use TABS. Separate sentence-names from wave definitions with single spaces only. + +// --------- Canal Zone --------- // +CZ_GOTCP1 vox/tfc/command point one secured +CZ_LOSTCP1 vox/tfc/command point one is now hostile +CZ_GOTCP2 vox/tfc/command point two secured +CZ_LOSTCP2 vox/tfc/command point two is now hostile +CZ_GOTCP3 vox/tfc/command point three secured +CZ_LOSTCP3 vox/tfc/command point three is now hostile +CZ_GOTCP4 vox/tfc/command point four secured +CZ_LOSTCP4 vox/tfc/command point four is now hostile +CZ_GOTCP5 vox/tfc/command point five secured +CZ_LOSTCP5 vox/tfc/command point five is now hostile +CZ_GOTALL vox/tfc/all command point secured _comma _comma _comma command point reset +CZ_THEYGOTALL vox/tfc/enemy captured all command points _comma _comma _comma command points reset +CZ_BCC_DET vox/tfc/blue command center detonation +CZ_RCC_DET vox/tfc/red command center detonation + +// --------- Capture the Flag --------- // +CTF_YOUCAP vox/tfc/you captured the enemy flag +CTF_TEAMCAP vox/tfc/your team captured the flag +CTF_THEYCAP vox/tfc/the enemy team captured the flag +CTF_YOUGOTFLAG vox/tfc/you have the enemy flag +CTF_YOUGOTFLAG2 vox/tfc/you have the enemy flag +CTF_YOUGOTFLAG3 vox/tfc/you have the enemy flag +CTF_YOUGOTFLAG4 vox/tfc/you have the enemy flag +CTF_GOTFLAG vox/tfc/your team has the enemy flag +CTF_GOTFLAG2 vox/tfc/your team has the enemy flag +CTF_GOTFLAG3 vox/tfc/your team has the enemy flag +CTF_GOTFLAG4 vox/tfc/your team has the enemy flag +CTF_LOSTFLAG vox/tfc/the enemy has your flag +CTF_LOSTFLAG2 vox/tfc/the enemy has your flag +CTF_LOSTFLAG3 vox/tfc/the enemy has your flag +CTF_LOSTFLAG4 vox/tfc/the enemy has your flag +CTF_FLAGBACK vox/tfc/your flag has returned +CTF_EFLAGBACK vox/tfc/the enemy flag has returned + +// --------- Hunted --------- // +HTD_DOORS vox/tfc/escape door open + +// --------- The Rock --------- // +RK_BYARDOPEN vox/tfc/blue yards has been breached +RK_RYARDOPEN vox/tfc/red yards has been breached +RK_KEYBACK vox/tfc/your key has returned +RK_EKEYBACK vox/tfc/enemy key has returned +RK_GOTKEY vox/tfc/your team has the enemy key +RK_LOSTKEY vox/tfc/the enemy has your key +RK_BSCORE vox/tfc/blue team scores _comma _comma _comma nerve_gas_released _comma _comma _comma secure protective suit immediately +RK_RSCORE vox/tfc/red team scores _comma _comma _comma nerve_gas_released _comma _comma _comma secure protective suit immediately +RK_TAKEKEY vox/tfc/take key to enemy gas chamber +FBALL_BSCORE vox/tfc/blue team scores +FBALL_RSCORE vox/tfc/red team scores + +// --------- Attack/Defend --------- // +AD_600SEC vox/tfc/ten minutes remaining +AD_300SEC vox/tfc/five minutes remaining +AD_120SEC vox/tfc/two minutes remaining +AD_60SEC vox/tfc/sixty seconds remaining +AD_30SEC vox/tfc/thirty seconds remaining +AD_10SEC vox/tfc/ten +AD_9SEC vox/tfc/nine +AD_8SEC vox/tfc/eight +AD_7SEC vox/tfc/seven +AD_6SEC vox/tfc/six +AD_5SEC vox/tfc/five +AD_4SEC vox/tfc/four +AD_3SEC vox/tfc/three +AD_2SEC vox/tfc/two +AD_1SEC vox/tfc/one +AD_CP1 vox/tfc/blue team secured command point one +AD_CP2 vox/tfc/blue team secured command point two +AD_HOLD vox/tfc/red team holds red base +AD_CAP vox/tfc/blue team captured red base +AD_GATESOPEN vox/tfc/_comma +AD_ATTACK vox/tfc/_comma +AD_DEFEND vox/tfc/_comma + +// --------- Shutdown2 --------- // +SD_REDDOWN vox/tfc/red security has been deactivated +SD_REDUP vox/tfc/red security is now operating +SD_BLUEDOWN vox/tfc/blue security has been deactivated +SD_BLUEUP vox/tfc/blue security is now operating + +// --------- Push --------- // +CTF_YOUSCORE vox/tfc/you captured the flag +CTF_TEAMSCORE vox/tfc/your team captured the flag +CTF_THEYSCORE vox/tfc/the enemy team captured the flag +CTF_YOUHAVEBALL vox/tfc/you have the flag +CTF_TEAMHASBALL vox/tfc/your team has the flag +CTF_ENEMYHASBALL vox/tfc/the enemy has the flag +CTF_BALLRETURN vox/tfc/the flag has returned + +// --------- Win --------- // +WIN_BLUE vox/tfc/blue team wins +WIN_RED vox/tfc/red team wins +WIN_YELLOW vox/tfc/yellow team wins +WIN_GREEN vox/tfc/green team wins +WINNING_YOURTEAM vox/tfc/_comma +WINNING_ENEMYTEAM vox/tfc/_comma diff --git a/scripts/soundmixers.txt b/scripts/soundmixers.txt new file mode 100644 index 0000000..29ba060 --- /dev/null +++ b/scripts/soundmixers.txt @@ -0,0 +1,236 @@ +// Halflife 2 custom sound mixers. +// These Sound Mixers are referenced by name from Soundscapes, and are used to provide +// custom volume control over various sound categories, called 'mix groups' + +// "GROUPRULES" specifies the rules for inclusion of a sound in a mix group. +// Rules are checked sequentially (from top to bottom). All fields must match +// in a row in order for a sound to match the group. A sound my be included +// in up to 8 mix groups. + +// LIMITS: +// up to 64 unique mix groups +// up to 76 group rules entries +// up to 32 sound mixers +// all strings are limited to 31 characters! + +// NOTE2: at runtime, you can display the classname of the sound source by +// setting snd_showclassname 1 in the console. + +// NOTE3: main character dialog during critical scenes is ducked using a separate code path which, when +// active, temporarilly disables mixer ducking (prevent double ducking). +// Lower priority sounds are ducked by higher priority sounds, if "is ducked" is enabled. +// Only sounds with "causes ducking" enabled can cause a lower priority sound to be ducked. + +"GROUPRULES" +{ +// NOTE: order these from least general to most general + +// directory or .wav classname Causes Duck to Ducker +// group name name substring substring chan sndlvl_min sndlvl_max priority Is Ducked Ducking Percent Threshold +// ---------- -------------- --------- ---- ---------- ---------- -------- --------- ------- ------- --------- + + "Vort_Dialog" "/vort" "" "" "" "" "60" "0" "1" "100" "20" + "Alyx_Dialog" "/alyx" "" "" "" "" "60" "0" "1" "100" "20" + "Alyx_Dialog" "/al_" "" "" "" "" "60" "0" "1" "100" "20" + "Citizen_Dialog" "/citizen" "" "" "" "" "60" "0" "1" "100" "20" + "Citizen_Dialog" "/female" "" "" "" "" "60" "0" "1" "100" "20" + "Citizen_Dialog" "/male" "" "" "" "" "60" "0" "1" "100" "20" + "Monk_Dialog" "/monk" "" "" "" "" "60" "0" "1" "100" "20" + "Eli_Dialog" "/eli_" "" "" "" "" "60" "0" "1" "100" "20" + "Kleiner_Dialog" "/kl_" "" "" "" "" "60" "0" "1" "100" "20" + "Breen_Dialog" "/br_" "" "" "" "" "60" "0" "1" "100" "20" + "Mossman_Dialog" "/mo_" "" "" "" "" "60" "0" "1" "100" "20" + "Barney_Dialog" "/ba_" "" "" "" "" "60" "0" "1" "100" "20" + "Gman_Dialog" "/gman_" "" "" "" "" "60" "0" "1" "100" "20" + "Metrocop_Dialog" "/mcop" "" "" "" "" "60" "0" "1" "100" "20" + "Soldier_Dialog" "/cs_" "" "" "" "" "60" "0" "1" "100" "20" + + "bullethit" "impact_bullet" "" "" "" "" "50" "0" "0" "100" "40" + "bulletmiss" "nearmiss" "" "" "" "" "50" "0" "0" "100" "40" + "Explosions" "explo" "" "" "120" "" "50" "0" "1" "100" "40" + + "Player_Suit" "fvox/" "Player" "" "" "" "50" "0" "0" "100" "40" + "Player_Weapons_Loud" "weapon" "Player" "" "140" "" "50" "0" "1" "100" "40" + "Player_Weapons" "weapon" "Player" "" "" "" "50" "0" "1" "100" "40" + "Player" "player/" "Player" "" "" "" "50" "0" "0" "100" "40" + "Player" "physics/" "Player" "" "" "" "50" "0" "0" "100" "40" + + "NPC_Voice" "" "NPC" "CHAN_VOICE" "" "" "50" "0" "1" "100" "40" + "NPC_Weapons_Loud" "" "NPC" "CHAN_WEAPON" "140" "" "50" "0" "1" "100" "40" + "NPC_Weapons" "" "NPC" "CHAN_WEAPON" "" "" "50" "0" "1" "100" "40" + "NPC_Body" "" "NPC" "CHAN_BODY" "" "" "50" "0" "0" "100" "40" + "NPC_Looping" "" "NPC" "CHAN_STATIC" "" "" "50" "0" "0" "100" "40" + "NPC" "" "NPC" "" "" "" "50" "0" "0" "100" "40" + + "AHELI_WEAPON" "aheli_weapon" "" "" "140" "" "50" "0" "1" "100" "40" + "GUNSHIP_WEAPON" "gunship_weapon" "" "" "140" "" "50" "0" "1" "100" "40" + "STRIDER_WEAPON" "strider_weapon" "" "" "140" "" "50" "0" "1" "100" "40" + + "Ambient_Alarms" "ambient/alarms" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Atmosphere" "ambient/atmos" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Wind" "ambient/wind" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Water" "ambient/water" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Fire" "ambient/fire" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Gas" "ambient/gas" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Levels" "ambient/levels" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Creatures" "ambient/creatures" "" "" "" "" "20" "1" "0" "60" "40" + "Ambient_Machines" "ambient/machines" "" "" "" "" "50" "1" "0" "60" "40" + + "Trains" "plats/" "" "" "" "" "50" "0" "0" "100" "40" + "Doors" "doors/" "" "" "" "" "50" "0" "0" "100" "40" + "Buttons" "buttons/" "" "" "" "" "50" "0" "0" "100" "40" + "Items" "items/" "" "" "" "" "50" "0" "0" "100" "40" + "Beams" "beams/" "" "" "" "" "50" "0" "0" "100" "40" + "Vehicles" "vehicles/" "" "" "" "" "20" "1" "0" "68" "40" + "Vehicles_Looping" "vehicles/" "" "CHAN_STATIC" "" "" "20" "1" "0" "68" "40" + + "UI" "common/" "" "" "" "" "50" "0" "0" "100" "40" + "UI" "ui/" "" "" "" "" "50" "0" "0" "100" "40" + + "Physics" "physics/" "" "" "" "" "50" "0" "0" "100" "40" + "Ambient" "ambien" "" "" "" "" "50" "0" "0" "100" "40" + "Music" "music/" "" "" "" "" "25" "1" "1" "75" "40" + "Dialog" "vo/" "" "" "" "" "60" "0" "1" "100" "20" + "Dialog" "combined/" "" "" "" "" "60" "0" "1" "100" "20" + "Combat" "weapon" "" "" "110" "" "50" "0" "0" "100" "40" + "Combat" "explo" "" "" "110" "" "50" "0" "0" "100" "40" + "Weapons" "weapon" "" "" "120" "" "50" "0" "0" "100" "40" + + "Quiet" "" "" "" "0" "70" "50" "0" "0" "100" "40" + "Medium" "" "" "" "71" "90" "50" "0" "0" "100" "40" + "Loud" "" "" "" "91" "100" "50" "0" "0" "100" "40" + "VeryLoud" "" "" "" "101" "149" "50" "0" "0" "100" "40" + "SuperLoud" "" "" "" "150" "" "50" "0" "0" "100" "40" + + "All" "" "" "" "" "" "50" "0" "0" "100" "40" +} + + +//---------------------------------------------------------------- +// Sound Mixers, referenced in Soundscapes via "SOUNDMIXER" "name" +// New Sound Mixers may be created by level designers or sound engineer. +//---------------------------------------------------------------- + +// This is the default mix for the game. +// The mix value of a sound will be set to the value referenced by the +// least general group found that includes the sound. (top to bottom search of grouprules) + +"Default_Mix" +{ + +// group name mix value +// ---------- --------- + "Explosions" "0.90" + "Player_Weapons_Loud" "1.0" + "Player_Suit" "0.56" + "Weapons" "0.79" + + "AHELI_WEAPON" "0.85" + "GUNSHIP_WEAPON" "0.85" + "STRIDER_WEAPON" "0.85" + "bullethit" "0.67" + + "Music" "0.81" + + "All" "0.72" +} + + +"Display_Mix" +{ +// group name mix value +// ---------- --------- + "Explosions" "1.0" + "Physics" "0.7" + "Ambient" "0.7" + "Music" "0.7" + "Vehicles" "0.7" + "Vehicles_Looping" "0.7" + "Ambient_Alarms" "0.7" + "Trains" "0.7" + "Doors" "0.7" + "Buttons" "0.7" + "Items" "0.7" + "Beams" "0.7" + "UI" "0.7" + "bullethit" "0.7" + "bulletmiss" "0.7" + "Player_Suit" "0.7" + "Player_Weapons_Loud" "0.7" + "Player_Weapons" "0.7" + "Player" "0.7" + "NPC_Voice" "0.7" + "NPC_Weapons" "0.7" + "NPC_Weapons_Loud" "0.7" + "NPC_Body" "0.7" + "NPC_Looping" "0.7" + "AHELI_WEAPON" "1.0" + "GUNSHIP_WEAPON" "1.0" + "STRIDER_WEAPON" "1.0" + "NPC" "0.7" + "Dialog" "0.7" + "Weapons" "0.8" + "Alyx_Dialog" "0.7" + "Citizen_Dialog" "0.7" + "Barney_Dialog" "0.7" + "Metrocop_Dialog" "0.7" + "Soldier_Dialog" "0.7" + "All" "0.7" +} + +"Voicetest_Mix" +{ +// group name mix value +// ---------- --------- + + "NPC_Voice" "1.0" + "Dialog" "1.0" + "Alyx_Dialog" "1.0" + "Citizen_Dialog" "1.0" + "Barney_Dialog" "1.0" + "Metrocop_Dialog" "1.0" + "Soldier_Dialog" "1.0" + "All" "0.1" +} + +"Citadel_Dialog_Only" +{ +// group name mix value +// ---------- --------- + + "NPC_Voice" "0.72" + "Dialog" "0.72" + "Alyx_Dialog" "0.72" + "Gman_Dialog" "0.72" + "Music" "0.81" + "All" "0.01" +} + +// add new sound mixers here...ALWAYS use Default_Mix as a template. + +// +//Soundmixer for hunted sewers ghroth experiment +// + +"huntedsewers_mix" +{ +// group name mix value +// ---------- --------- + "Explosions" "0.90" + "bullethit" "0.67" + "bulletmiss" "0.7" + "Player" "0.7" + "Player_Weapons_Loud" "1.0" + "Player_Weapons" "0.7" + "Weapons" "0.79" + "Ambient" "0.7" + "Ambient_Water" "0.7" + "Ambient_Atmosphere" "0.7" + "Physics" "0.7" + "Doors" "0.7" + "Buttons" "0.7" + "Items" "0.7" + "Music" "0.81" + "UI" "0.7" + "All" "0.72" +} \ No newline at end of file diff --git a/scripts/soundscapes_ff.txt b/scripts/soundscapes_ff.txt new file mode 100644 index 0000000..4856dd6 --- /dev/null +++ b/scripts/soundscapes_ff.txt @@ -0,0 +1,197 @@ +// DSP Effects +// 0 : "Normal (off)" +// 1 : "Generic" +// 2 : "Metal Small" +// 3 : "Metal Medium" +// 4 : "Metal Large" +// 5 : "Tunnel Small" +// 6 : "Tunnel Medium" +// 7 : "Tunnel Large" +// 8 : "Chamber Small" +// 9 : "Chamber Medium" +// 10: "Chamber Large" +// 11: "Bright Small" +// 12: "Bright Medium" +// 13: "Bright Large" +// 14: "Water 1" +// 15: "Water 2" +// 16: "Water 3" +// 17: "Concrete Small" +// 18: "Concrete Medium" +// 19: "Concrete Large" +// 20: "Big 1" +// 21: "Big 2" +// 22: "Big 3" +// 23: "Cavern Small" +// 24: "Cavern Medium" +// 25: "Cavern Large" +// 26: "Weirdo 1" +// 27: "Weirdo 2" +// 28: "Weirdo 3" + +// General soundscapes + +// This soundscape enables automatic dsp + +"ff_automatic" +{ + "dsp" "1" + "dsp_volume" "1.0" + "SOUNDMIXER" "Display_Mix" +} + +// This soundscape enables automatic dsp at 50% mix - good if you have +// a lot of dialog that must be understood at any distance + +"ff_automatic_dialog" +{ + "dsp" "1" + "dsp_volume" "0.5" + "SOUNDMIXER" "Voicetest_Mix" +} + +// +//Ghroths soundscape and soundmixer experiment, if the soundscapes below are worthy, then they can be moved to the _soundscape.txt +// + +//---------------------------------------------------------------- +// soundmixers.txt, referenced in soundscapes_ff via "SOUNDMIXER" "name" +//---------------------------------------------------------------- + +"ff_huntedsewers" +{ + "dsp" "1" + "dsp_volume" "1.0" + "SOUNDMIXER" "huntedsewers_mix" + + "playsoundscape" + { + "name" "ff_huntedsewers.water" + "volume" "1.0" + } + + "playsoundscape" + { + "name" "ff_huntedsewers.air" + "volume" "1.0" + } +} + +"ff_huntedsewers.water" +{ + "dsp" "15" + "dsp_volume" "1.0" + "SOUNDMIXER" "huntedsewers_mix" + + "playlooping" + { + "volume" "0.5" + "pitch" "95" + "soundlevel" "SNDLVL_NORM" + "position" "0" + "wave" "ambient/water/water_run1.wav" + } + + "playlooping" + { + "volume" "0.5" + "pitch" "100" + "soundlevel" "SNDLVL_NORM" + "position" "1" + "wave" "ambient/water/water_run1.wav" + } + + "playlooping" + { + "volume" "0.5" + "pitch" "105" + "soundlevel" "SNDLVL_NORM" + "position" "2" + "wave" "ambient/water/water_run1.wav" + } +} + +"ff_huntedsewers.air" +{ + "dsp" "18" + "dsp_volume" "1.0" + "SOUNDMIXER" "huntedsewers_mix" + + "playlooping" + { + "volume" "0.5" + "pitch" "95" + "soundlevel" "SNDLVL_NORM" + "position" "3" + "wave" "ambient/atmosphere/ambience_base.wav" + } + + "playlooping" + { + "volume" "0.5" + "pitch" "100" + "soundlevel" "SNDLVL_NORM" + "position" "4" + "wave" "ambient/atmosphere/ambience_base.wav" + } + + "playlooping" + { + "volume" "0.5" + "pitch" "105" + "soundlevel" "SNDLVL_NORM" + "position" "5" + "wave" "ambient/atmosphere/ambience_base.wav" + } + + "playlooping" + { + "volume" "0.5" + "pitch" "100" + "soundlevel" "SNDLVL_NORM" + "position" "6" + "wave" "ambient/atmosphere/ambience_base.wav" + } + + "playlooping" + { + "volume" "0.5" + "pitch" "95" + "soundlevel" "SNDLVL_NORM" + "position" "7" + "wave" "ambient/atmosphere/ambience_base.wav" + } +} + +"ff_huntedsewers.distant" +{ + "dsp" "15" + "dsp_volume" "1.0" + "SOUNDMIXER" "huntedsewers_mix" + + "playrandom" + { + "volume" "0.5,1.0" + "time" "0.1,3.0" + "pitch" "95,105" + "position" "1" + + "rndwave" + { + "wave" "ambient/water/distant_drip1.wav" + "wave" "ambient/water/distant_drip2.wav" + "wave" "ambient/water/distant_drip3.wav" + "wave" "ambient/water/distant_drip4.wav" + } + } + + "playlooping" + { + "volume" "0.5" + "pitch" "95" + "soundlevel" "SNDLVL_NORM" + "position" "0" + "wave" "ambient/atmosphere/quiet_cellblock_amb.wav" + } + +} diff --git a/scripts/soundscapes_ff_anticitizen.txt b/scripts/soundscapes_ff_anticitizen.txt new file mode 100644 index 0000000..bfffc10 --- /dev/null +++ b/scripts/soundscapes_ff_anticitizen.txt @@ -0,0 +1,241 @@ +//Soundscapes for ff_anticitizen. +//Created by Nezumi + +//p1_off_spawn +//p1_outside +//p1_inside +//p1_def_spawn +//p2_generic +//p2_tech +//p2_tunnel +//p3_outside + +"p1_off_spawn" +{ + "dsp" "1" + + "playlooping" + { + "volume" ".3" + "pitch" "60" + "wave" "ambient/atmosphere/plaza_amb.wav" + } +} + +"p1_outside" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.5" + "pitch" "100" + "wave" "ambient/atmosphere/town_ambience.wav" + } + + "playrandom" + { + "time" "8, 16" + "volume" "0.2, 0.5" + "pitch" "70, 90" + "rndwave" + { + "wave" "ambient/wind/wind_hit1.wav" + "wave" "ambient/wind/wind_hit2.wav" + "wave" "ambient/wind/wind_hit3.wav" + } + } + + "playrandom" + { + "time" "35, 50" + "volume" "0.8, 0.9" + "pitch" "100" + "rndwave" + { + "wave" "npc/overwatch/cityvoice/f_confirmcivilstatus_1_spkr.wav" + "wave" "npc/overwatch/cityvoice/fprison_restrictorsdisengaged.wav" + "wave" "npc/overwatch/cityvoice/f_anticivil1_5_spkr.wav" + } + } +} + +"p1_inside" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/atmosphere/town_ambience.wav" + } + + "playrandom" + { + "time" "35, 50" + "volume" "0.6, 0.7" + "pitch" "100" + "rndwave" + { + "wave" "npc/overwatch/cityvoice/f_confirmcivilstatus_1_spkr.wav" + "wave" "npc/overwatch/cityvoice/fprison_restrictorsdisengaged.wav" + "wave" "npc/overwatch/cityvoice/f_anticivil1_5_spkr.wav" + } + } +} + +"p1_def_spawn" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.1" + "pitch" "100" + "wave" "ambient/atmosphere/quiet_cellblock_amb.wav" + } +} + + +"p2_generic" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/atmosphere/engine_room.wav" + } + + "playrandom" + { + "time" "35, 50" + "pitch" "100" + "volume" "0.6, 0.9" + "rndwave" + { + "wave" "npc/overwatch/cityvoice/f_evasionbehavior_1_spkr.wav" + "wave" "npc/overwatch/cityvoice/f_protectionresponse_4_spkr.wav" + "wave" "npc/overwatch/cityvoice/fprison_detectionsystemsout.wav" + } + } +} + +"p2_tech" +{ + "dsp" "1" + + "playsoundscape" + { + "name" "p2_generic" + "volume" "1" + } + + "playrandom" + { + "time" "4, 10" + "volume" "0.2, 0.6" + "pitch" "100" + "rndwave" + { + "wave" "ambient/machines/combine_terminal_idle1.wav" + "wave" "ambient/machines/combine_terminal_idle2.wav" + "wave" "ambient/machines/combine_terminal_idle3.wav" + "wave" "ambient/machines/combine_terminal_idle4.wav" + } + } + + "playrandom" + { + "time" "35, 50" + "volume" "0.6, 0.9" + "pitch" "100" + "rndwave" + { + "wave" "npc/overwatch/cityvoice/f_evasionbehavior_1_spkr.wav" + "wave" "npc/overwatch/cityvoice/f_protectionresponse_4_spkr.wav" + "wave" "npc/overwatch/cityvoice/fprison_detectionsystemsout.wav" + } + } +} + +"p2_tunnel" +{ + "dsp" "1" + + "playsoundscape" + { + "name" "p2_generic" + "volume" "1" + "pitch" ".8" + } + + "playrandom" + { + "time" "6, 16" + "volume" "0.2, 0.4" + "pitch" "90, 110" + "rndwave" + { + "wave" "ambient/materials/rock1.wav" + "wave" "ambient/materials/rock2.wav" + "wave" "ambient/materials/rock3.wav" + "wave" "ambient/materials/rock4.wav" + } + } +} + +"p3_outside" +{ + "dsp" "1" + + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/wind/wasteland_wind.wav" + } + + "playrandom" + { + "time" "4, 10" + "volume" "0.3, 0.6" + "pitch" "90, 110" + "rndwave" + { + "wave" "ambient/materials/rock1.wav" + "wave" "ambient/materials/rock2.wav" + "wave" "ambient/materials/rock3.wav" + "wave" "ambient/materials/rock4.wav" + "wave" "ambient/materials/rock5.wav" + } + } + + "playrandom" + { + "time" "8, 16" + "volume" "0.2, 0.3" + "pitch" "70, 90" + "rndwave" + { + "wave" "ambient/wind/wind_hit1.wav" + "wave" "ambient/wind/wind_hit2.wav" + "wave" "ambient/wind/wind_hit3.wav" + } + } + + "playrandom" + { + "time" "50, 80" + "volume" "0.6, 0.9" + "pitch" "100" + "rndwave" + { + "wave" "npc/overwatch/cityvoice/fprison_airwatchdispatched.wav" + "wave" "npc/overwatch/cityvoice/fprison_dropforcesixandeight.wav" + "wave" "npc/overwatch/cityvoice/f_protectionresponse_5_spkr.wav" + } + } +} \ No newline at end of file diff --git a/scripts/soundscapes_ff_tiger.txt b/scripts/soundscapes_ff_tiger.txt new file mode 100644 index 0000000..9381d33 --- /dev/null +++ b/scripts/soundscapes_ff_tiger.txt @@ -0,0 +1,272 @@ +//soundscapes for ff_tiger +//written by Nezumi. + +//outside +"outside" +{ + "dsp" "1" + "playlooping" + { + "volume" ".4" + "pitch" "100" + "wave" "ambient/atmosphere/town_ambience.wav" + } + + "playrandom" + { + "time" "4.0, 4.2" + "volume" "0.3, 0.5" + "pitch" "80, 120" + "rndwave" + { + "wave" "ambient/water/distant_wave1.wav" + "wave" "ambient/water/distant_wave2.wav" + "wave" "ambient/water/distant_wave3.wav" + } + } + + "playrandom" + { + "time" "8.0, 15.0" + "volume" "0.2, 0.4" + "pitch" "80, 100" + "rndwave" + { + "wave" "ambient/wind/wind_hit1.wav" + "wave" "ambient/wind/wind_hit2.wav" + "wave" "ambient/wind/wind_hit3.wav" + } + } +} + +//light house +"lhouse" +{ + "dsp" "1" + "playlooping" + { + "volume" ".3" + "pitch" "100" + "wave" "ambient/wind/wasteland_wind.wav" + } + + "playrandom" + { + "time" "4.0, 4.2" + "volume" "0.1, 0.3" + "pitch" "60, 100" + "rndwave" + { + "wave" "ambient/water/distant_wave1.wav" + "wave" "ambient/water/distant_wave2.wav" + "wave" "ambient/water/distant_wave3.wav" + } + } + + "playrandom" + { + "time" "12.0, 20.0" + "volume" "0.1, 0.2" + "pitch" "80, 100" + "rndwave" + { + "wave" "ambient/wind/wind_hit1.wav" + "wave" "ambient/wind/wind_hit2.wav" + "wave" "ambient/wind/wind_hit3.wav" + } + } +} + +//red base tunnels. +"rtun" +{ + "dsp" "1" + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/atmosphere/undercity_loop1.wav" + } + + "playlooping" + { + "volume" "1" + "pitch" "80" + "position" "1" + "wave" "ambient/water/lake_water.wav" + } + + "playrandom" + { + "time" "1.0, 5.0" + "volume" "0.3, 0.6" + "pitch" "80, 110" + "rndwave" + { + "wave" "ambient/water/distant_drip1.wav" + "wave" "ambient/water/distant_drip2.wav" + "wave" "ambient/water/distant_drip3.wav" + "wave" "ambient/water/distant_drip4.wav" + } + } +} + +//red spawn room +"rspawn" +{ + "dsp" "1" + "playlooping" + { + "volume" "0.6" + "pitch" "100" + "wave" "ambient/atmosphere/undercity_loop1.wav" + } + + "playlooping" + { + "volume" ".3" + "pitch" "100" + "position" "0" + "wave" "ambient/levels/canals/dam_water_loop2.wav" + } + + "playlooping" + { + "volume" "0.6" + "pitch" "100" + "position" "1" + "wave" "ambient/atmosphere/pipe1.wav" + } + + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "position" "2" + "wave" "ambient/atmosphere/pipe1.wav" + } + + "playlooping" + { + "volume" "0.6" + "pitch" "100" + "position" "3" + "wave" "ambient/levels/canals/generator_ambience_loop1.wav" + } +} + +//warehouses +"whouse" +{ + "dsp" "1" + "playlooping" + { + "volume" ".2" + "pitch" "100" + "wave" "ambient/atmosphere/indoor2.wav" + } + + "playrandom" + { + "time" "4.0, 4.2" + "volume" "0.1, 0.2" + "pitch" "60, 100" + "rndwave" + { + "wave" "ambient/water/distant_wave1.wav" + "wave" "ambient/water/distant_wave2.wav" + "wave" "ambient/water/distant_wave3.wav" + } + } + + "playrandom" + { + "time" "12.0, 20.0" + "volume" "0.1, 0.2" + "pitch" "80, 100" + "rndwave" + { + "wave" "ambient/wind/wind_hit1.wav" + "wave" "ambient/wind/wind_hit2.wav" + "wave" "ambient/wind/wind_hit3.wav" + } + } +} + +//laundry tunnels +"ltun" +{ + "dsp" "1" + "playlooping" + { + "volume" "0.5" + "pitch" "100" + "wave" "ambient/atmosphere/laundry_amb.wav" + } + + "playrandom" + { + "time" "4.0, 4.2" + "volume" "0.1, 0.2" + "pitch" "60, 100" + "rndwave" + { + "wave" "ambient/water/distant_wave1.wav" + "wave" "ambient/water/distant_wave2.wav" + "wave" "ambient/water/distant_wave3.wav" + } + } + + "playrandom" + { + "time" "12.0, 20.0" + "volume" "0.1, 0.2" + "pitch" "80, 100" + "rndwave" + { + "wave" "ambient/wind/wind_hit1.wav" + "wave" "ambient/wind/wind_hit2.wav" + "wave" "ambient/wind/wind_hit3.wav" + } + } +} + +//blue tunnels +"btun" +{ + "dsp" "1" + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/atmosphere/tunnel1.wav" + } + + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/atmosphere/underground.wav" + } + +} + +//blue spawn +"bspawn" +{ + "dsp" "1" + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "wave" "ambient/atmosphere/ambience_base.wav" + } + + "playlooping" + { + "volume" "0.3" + "pitch" "100" + "position" "1" + "wave" "ambient/atmosphere/pipe1.wav" + } +} \ No newline at end of file diff --git a/scripts/soundscapes_manifest.txt b/scripts/soundscapes_manifest.txt new file mode 100644 index 0000000..a83b519 --- /dev/null +++ b/scripts/soundscapes_manifest.txt @@ -0,0 +1,31 @@ +soundscapes_manifest +{ + // Generic FF soundscapes + "file" "scripts/soundscapes_ff.txt" + + // Map-specific FF soundscapes (no need to list map soundscapes here anymore) + // Place in "maps" folder with the filename as _soundscapes.txt + //"file" "maps/ff_dev_test_sounds_soundscapes.txt" + //"file" "maps/ff_hunted_soundscapes.txt" + + // Put your map's soundscape txt file in "FortressForever\maps" and give it the + // EXACT SAME NAME AS YOUR MAP's FILENAME followed by _soundscapes.txt + // IE: FortressForever\maps\_soundscapes.txt + // IE: FortressForever\maps\ff_2fort_soundscapes.txt + + + ////////////////////////////////////////////////////// + // HL2 soundscapes (located in "source engine.gcf") // + ////////////////////////////////////////////////////// + + "file" "scripts/soundscapes.txt" + "file" "scripts/soundscapes_canals.txt" + "file" "scripts/soundscapes_klab.txt" + "file" "scripts/soundscapes_elab.txt" + "file" "scripts/soundscapes_streetwar.txt" + "file" "scripts/soundscapes_citadel.txt" + "file" "scripts/soundscapes_town.txt" + "file" "scripts/soundscapes_coast.txt" + "file" "scripts/soundscapes_prison.txt" + "file" "scripts/soundscapes_trainyard.txt" +} diff --git a/scripts/vehicles/jeep_test.txt b/scripts/vehicles/jeep_test.txt new file mode 100644 index 0000000..d471534 --- /dev/null +++ b/scripts/vehicles/jeep_test.txt @@ -0,0 +1,269 @@ +// This is a test jeep type vehicle for the wasteland + +"vehicle" +{ + "wheelsperaxle" "2" + "body" + { + "countertorquefactor" "1" + "massCenterOverride" "0 0 0" + "massoverride" "800" // kg + "addgravity" "0.33" + } + "engine" + { + "horsepower" "350" + "maxrpm" "3000" + "maxspeed" "35" // mph + "maxReverseSpeed" "20" // mph + "autotransmission" "1" + "axleratio" "4.56" + "gear" "1.86" // 1st gear + "gear" "1.59" // 2nd gear + "gear" "1.17" // 3rd gear + "gear" "1.0" // 4th gear + "gear" "0.84" // 5th gear + "shiftuprpm" "1500" + "shiftdownrpm" "300" + + "boost" + { +// "force" "1.5" // 1.5 car body mass * gravity * inches / second ^ 2 + "duration" "1.0" // 1 second of boost + "delay" "15" // 15 seconds before you can use it again + "torqueboost" "1" // enable "sprint" mode of vehicle, not force type booster + "maxspeed" "50" // maximum turbo speed + "force" "2.5" // use for value as a boost factor + } + } + "steering" + { + "degrees" "26" + "fastdampen" "0.35" + "slowcarspeed" "0" + "fastcarspeed" "40" + "slowsteeringrate" "4" + "faststeeringrate" "2" + "steeringRestFactor" "1.5" + "turnbrake" "0.25" + + "skidallowed" "1" + "dustcloud" "1" + } + + // front axle + "axle" + { + "wheel" + { + "radius" "18" + "mass" "100" + "inertia" "0.5" // steady the car (fixes the oscillation of the axles about z) + "damping" "0" + "rotdamping" "0.0" + "material" "jeeptire" + "skidmaterial" "slidingrubbertire" + "brakematerial" "brakingrubbertire" + } + "suspension" + { + "springConstant" "80" + "springDamping" "4" + "stabilizerConstant" "110" + "springDampingCompression" "4" + "maxBodyForce" "250" + } + + "torquefactor" "0.8" + "brakefactor" "0.5" + } + + // rear axle + "axle" + { + "wheel" + { + "radius" "20" + "mass" "100" + "inertia" "0.5" // steady the car (fixes the oscillation of the axles about z) + "damping" "0" + "rotdamping" "0.0" + "material" "jeeptire" + "skidmaterial" "slidingrubbertire" + "brakematerial" "brakingrubbertire" + } + "suspension" + { + "springConstant" "80" + "springDamping" "4" + "stabilizerConstant" "110" + "springDampingCompression" "4" + "maxBodyForce" "250" + } + "torquefactor" "0.2" + "brakefactor" "0.5" + } +} + +"vehicle_sounds" +{ + // List gears in order from lowest speed to highest speed + + "gear" + { + "max_speed" "0.3" + "speed_approach_factor" "1.0" + } + + "gear" + { + "max_speed" "0.5" + "speed_approach_factor" "0.07" + } + "gear" + { + "max_speed" "0.75" + "speed_approach_factor" "0.07" + } + "gear" + { + "max_speed" "0.90" + "speed_approach_factor" "0.035" + } + "gear" + { + "max_speed" "0.95" + "speed_approach_factor" "0.015" + } + "gear" + { + "max_speed" "2.0" + "speed_approach_factor" "0.03" + } + "state" + { + "name" "SS_START_WATER" + "sound" "ATV_start_in_water" + } + + "state" + { + "name" "SS_START_IDLE" + "sound" "ATV_engine_start" + } + "state" + { + "name" "SS_SHUTDOWN_WATER" + "sound" "ATV_stall_in_water" + } + "state" + { + "name" "SS_IDLE" + "sound" "ATV_engine_idle" + } + "state" + { + "name" "SS_REVERSE" + "sound" "ATV_reverse" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_0" + "sound" "ATV_rev" + "min_time" "0.75" + } + "state" + { + "name" "SS_GEAR_0_RESUME" + "sound" "ATV_engine_idle" + "min_time" "0.75" + } + "state" + { + "name" "SS_GEAR_1" + "sound" "ATV_firstgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_1_RESUME" + "sound" "ATV_firstgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_2" + "sound" "ATV_secondgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_2_RESUME" + "sound" "ATV_secondgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_3" + "sound" "ATV_thirdgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_3_RESUME" + "sound" "ATV_thirdgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_4" + "sound" "ATV_fourthgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_4_RESUME" + "sound" "ATV_fourthgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_SLOWDOWN_HIGHSPEED" + "sound" "ATV_throttleoff_fastspeed" + } + "state" + { + "name" "SS_SLOWDOWN" + "sound" "ATV_throttleoff_slowspeed" + } + "state" + { + "name" "SS_TURBO" + "sound" "ATV_turbo_on" + "min_time" "2.5" + } + "state" + { + "name" "SS_SHUTDOWN" + "sound" "ATV_engine_stop" + } + "crashsound" + { + "min_speed" "350" + "min_speed_change" "250" + "sound" "ATV_impact_medium" + "gear_limit" "1" + } + "crashsound" + { + "min_speed" "450" + "min_speed_change" "350" + "sound" "ATV_impact_heavy" + } + + + "skid_lowfriction" "ATV_skid_lowfriction" + "skid_normalfriction" "ATV_skid_normalfriction" + "skid_highfriction" "ATV_skid_highfriction" +} diff --git a/scripts/vehicles/jeep_test_hl2.txt b/scripts/vehicles/jeep_test_hl2.txt new file mode 100644 index 0000000..d471534 --- /dev/null +++ b/scripts/vehicles/jeep_test_hl2.txt @@ -0,0 +1,269 @@ +// This is a test jeep type vehicle for the wasteland + +"vehicle" +{ + "wheelsperaxle" "2" + "body" + { + "countertorquefactor" "1" + "massCenterOverride" "0 0 0" + "massoverride" "800" // kg + "addgravity" "0.33" + } + "engine" + { + "horsepower" "350" + "maxrpm" "3000" + "maxspeed" "35" // mph + "maxReverseSpeed" "20" // mph + "autotransmission" "1" + "axleratio" "4.56" + "gear" "1.86" // 1st gear + "gear" "1.59" // 2nd gear + "gear" "1.17" // 3rd gear + "gear" "1.0" // 4th gear + "gear" "0.84" // 5th gear + "shiftuprpm" "1500" + "shiftdownrpm" "300" + + "boost" + { +// "force" "1.5" // 1.5 car body mass * gravity * inches / second ^ 2 + "duration" "1.0" // 1 second of boost + "delay" "15" // 15 seconds before you can use it again + "torqueboost" "1" // enable "sprint" mode of vehicle, not force type booster + "maxspeed" "50" // maximum turbo speed + "force" "2.5" // use for value as a boost factor + } + } + "steering" + { + "degrees" "26" + "fastdampen" "0.35" + "slowcarspeed" "0" + "fastcarspeed" "40" + "slowsteeringrate" "4" + "faststeeringrate" "2" + "steeringRestFactor" "1.5" + "turnbrake" "0.25" + + "skidallowed" "1" + "dustcloud" "1" + } + + // front axle + "axle" + { + "wheel" + { + "radius" "18" + "mass" "100" + "inertia" "0.5" // steady the car (fixes the oscillation of the axles about z) + "damping" "0" + "rotdamping" "0.0" + "material" "jeeptire" + "skidmaterial" "slidingrubbertire" + "brakematerial" "brakingrubbertire" + } + "suspension" + { + "springConstant" "80" + "springDamping" "4" + "stabilizerConstant" "110" + "springDampingCompression" "4" + "maxBodyForce" "250" + } + + "torquefactor" "0.8" + "brakefactor" "0.5" + } + + // rear axle + "axle" + { + "wheel" + { + "radius" "20" + "mass" "100" + "inertia" "0.5" // steady the car (fixes the oscillation of the axles about z) + "damping" "0" + "rotdamping" "0.0" + "material" "jeeptire" + "skidmaterial" "slidingrubbertire" + "brakematerial" "brakingrubbertire" + } + "suspension" + { + "springConstant" "80" + "springDamping" "4" + "stabilizerConstant" "110" + "springDampingCompression" "4" + "maxBodyForce" "250" + } + "torquefactor" "0.2" + "brakefactor" "0.5" + } +} + +"vehicle_sounds" +{ + // List gears in order from lowest speed to highest speed + + "gear" + { + "max_speed" "0.3" + "speed_approach_factor" "1.0" + } + + "gear" + { + "max_speed" "0.5" + "speed_approach_factor" "0.07" + } + "gear" + { + "max_speed" "0.75" + "speed_approach_factor" "0.07" + } + "gear" + { + "max_speed" "0.90" + "speed_approach_factor" "0.035" + } + "gear" + { + "max_speed" "0.95" + "speed_approach_factor" "0.015" + } + "gear" + { + "max_speed" "2.0" + "speed_approach_factor" "0.03" + } + "state" + { + "name" "SS_START_WATER" + "sound" "ATV_start_in_water" + } + + "state" + { + "name" "SS_START_IDLE" + "sound" "ATV_engine_start" + } + "state" + { + "name" "SS_SHUTDOWN_WATER" + "sound" "ATV_stall_in_water" + } + "state" + { + "name" "SS_IDLE" + "sound" "ATV_engine_idle" + } + "state" + { + "name" "SS_REVERSE" + "sound" "ATV_reverse" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_0" + "sound" "ATV_rev" + "min_time" "0.75" + } + "state" + { + "name" "SS_GEAR_0_RESUME" + "sound" "ATV_engine_idle" + "min_time" "0.75" + } + "state" + { + "name" "SS_GEAR_1" + "sound" "ATV_firstgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_1_RESUME" + "sound" "ATV_firstgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_2" + "sound" "ATV_secondgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_2_RESUME" + "sound" "ATV_secondgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_3" + "sound" "ATV_thirdgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_3_RESUME" + "sound" "ATV_thirdgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_4" + "sound" "ATV_fourthgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_4_RESUME" + "sound" "ATV_fourthgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_SLOWDOWN_HIGHSPEED" + "sound" "ATV_throttleoff_fastspeed" + } + "state" + { + "name" "SS_SLOWDOWN" + "sound" "ATV_throttleoff_slowspeed" + } + "state" + { + "name" "SS_TURBO" + "sound" "ATV_turbo_on" + "min_time" "2.5" + } + "state" + { + "name" "SS_SHUTDOWN" + "sound" "ATV_engine_stop" + } + "crashsound" + { + "min_speed" "350" + "min_speed_change" "250" + "sound" "ATV_impact_medium" + "gear_limit" "1" + } + "crashsound" + { + "min_speed" "450" + "min_speed_change" "350" + "sound" "ATV_impact_heavy" + } + + + "skid_lowfriction" "ATV_skid_lowfriction" + "skid_normalfriction" "ATV_skid_normalfriction" + "skid_highfriction" "ATV_skid_highfriction" +} diff --git a/scripts/vehicles/jeep_test_old.txt b/scripts/vehicles/jeep_test_old.txt new file mode 100644 index 0000000..8a4546a --- /dev/null +++ b/scripts/vehicles/jeep_test_old.txt @@ -0,0 +1,269 @@ +// This is a test jeep type vehicle for the wasteland + +"vehicle" +{ + "wheelsperaxle" "2" // wheels per axle + "body" + { + + "massCenterOverride" "0 0 0" // leave at vec3_origin for no override + "massoverride" "800" // in kg, leave at 0 for no override (kg) + "addgravity" "0.33" // keeps car down + } + "engine" + { + "horsepower" "350" // engine power + "maxrpm" "3000" // max rounds per minute + "maxspeed" "35" // forward mph + "maxReverseSpeed" "20" // backward mph + "autotransmission" "1" // true for auto, false for manual + "axleratio" "4.56" // ratio of engine rev to axle rev + "gear" "1.86" // 1st gear (max 6 gears) + "gear" "1.59" // 2nd gear + "gear" "1.17" // 3rd gear + "gear" "1.0" // 4th gear + "gear" "0.84" // 5th gear + "shiftuprpm" "1500" // max RPMs to switch to a higher gear + "shiftdownrpm" "300" // min RPMs to switch to a lower gear + + "boost" + { +// "force" "1.5" // 1.5 car body mass * gravity * inches / second ^ 2 + "duration" "1.0" // 1 second of boost + "delay" "15" // 15 seconds before you can use it again + "torqueboost" "1" // enable "sprint" mode of vehicle, not force type booster + "maxspeed" "50" // maximum turbo speed + "force" "2.5" // use for value as a boost factor + } + } + "steering" + { + "degrees" "60" // angle in degrees of steering + + "slowcarspeed" "0" // this is the max speed of "slow" + "fastcarspeed" "40" // this is the min speed of "fast" + "slowsteeringrate" "4" // this is the speed the wheels are steered when the vehicle is "slow" + "faststeeringrate" "2" // this is the speed the wheels are steered when the vehicle is "fast" + "steeringRestFactor" "1.5" // this is the speed at which the wheels move toward their resting state (straight ahead) + + + "skidallowed" "1" // true/false skid flag + "dustcloud" "1" // flag for creating a dustcloud behind vehicle + } + + // front axle + "axle" + { + "wheel" + { + "radius" "18" + "mass" "100" // in kg + "inertia" "0.5" // steady the car (fixes the oscillation of the axles about z) + "damping" "0" // usually 0 + "rotdamping" "0.0" // usually 0 + "material" "jeeptire" // tire surface properties + "skidmaterial" "slidingrubbertire" // surface properties when sliding + "brakematerial" "brakingrubbertire" // surface properties wen breaking + } + "suspension" + { + "springConstant" "80" + "springDamping" "4" + "stabilizerConstant" "110" + "springDampingCompression" "4" + "maxBodyForce" "250" + } + + "torquefactor" "0.8" // normalized to 1 across all axles + "brakefactor" "0.5" // normalized to 1 across all axles + } + + // rear axle + "axle" + { + "wheel" + { + "radius" "20" + "mass" "100" + "inertia" "0.5" // steady the car (fixes the oscillation of the axles about z) + "damping" "0" + "rotdamping" "0.0" + "material" "jeeptire" + "skidmaterial" "slidingrubbertire" + "brakematerial" "brakingrubbertire" + } + "suspension" + { + "springConstant" "80" + "springDamping" "4" + "stabilizerConstant" "110" + "springDampingCompression" "4" + "maxBodyForce" "250" + } + "torquefactor" "0.2" + "brakefactor" "0.5" + } +} + +"vehicle_sounds" +{ + // List gears in order from lowest speed to highest speed + + "gear" + { + "max_speed" "0.3" + "speed_approach_factor" "1.0" + } + + "gear" + { + "max_speed" "0.5" + "speed_approach_factor" "0.07" + } + "gear" + { + "max_speed" "0.75" + "speed_approach_factor" "0.07" + } + "gear" + { + "max_speed" "0.90" + "speed_approach_factor" "0.035" + } + "gear" + { + "max_speed" "0.95" + "speed_approach_factor" "0.015" + } + "gear" + { + "max_speed" "2.0" + "speed_approach_factor" "0.03" + } + "state" + { + "name" "SS_START_WATER" + "sound" "ATV_start_in_water" + } + + "state" + { + "name" "SS_START_IDLE" + "sound" "ATV_engine_start" + } + "state" + { + "name" "SS_SHUTDOWN_WATER" + "sound" "ATV_stall_in_water" + } + "state" + { + "name" "SS_IDLE" + "sound" "ATV_engine_idle" + } + "state" + { + "name" "SS_REVERSE" + "sound" "ATV_reverse" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_0" + "sound" "ATV_rev" + "min_time" "0.75" + } + "state" + { + "name" "SS_GEAR_0_RESUME" + "sound" "ATV_engine_idle" + "min_time" "0.75" + } + "state" + { + "name" "SS_GEAR_1" + "sound" "ATV_firstgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_1_RESUME" + "sound" "ATV_firstgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_2" + "sound" "ATV_secondgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_2_RESUME" + "sound" "ATV_secondgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_3" + "sound" "ATV_thirdgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_3_RESUME" + "sound" "ATV_thirdgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_4" + "sound" "ATV_fourthgear" + "min_time" "0.5" + } + "state" + { + "name" "SS_GEAR_4_RESUME" + "sound" "ATV_fourthgear_noshift" + "min_time" "0.5" + } + "state" + { + "name" "SS_SLOWDOWN_HIGHSPEED" + "sound" "ATV_throttleoff_fastspeed" + } + "state" + { + "name" "SS_SLOWDOWN" + "sound" "ATV_throttleoff_slowspeed" + } + "state" + { + "name" "SS_TURBO" + "sound" "ATV_turbo_on" + "min_time" "2.5" + } + "state" + { + "name" "SS_SHUTDOWN" + "sound" "ATV_engine_stop" + } + "crashsound" + { + "min_speed" "350" + "min_speed_change" "250" + "sound" "ATV_impact_medium" + "gear_limit" "1" + } + "crashsound" + { + "min_speed" "450" + "min_speed_change" "350" + "sound" "ATV_impact_heavy" + } + + + "skid_lowfriction" "ATV_skid_lowfriction" + "skid_normalfriction" "ATV_skid_normalfriction" + "skid_highfriction" "ATV_skid_highfriction" +} diff --git a/scripts/weapon_cubemap.txt b/scripts/weapon_cubemap.txt new file mode 100644 index 0000000..1882edd --- /dev/null +++ b/scripts/weapon_cubemap.txt @@ -0,0 +1,72 @@ +// Cubemap visualization tool + +// This weapon script was taken from "source engine.gcf" so we can +// use different "bucket" and "bucket_position" settings in FF. + +WeaponData +{ + // Weapon data is loaded by both the Game and Client DLLs. + "printname" "#HL2_Cubemap" + "viewmodel" "models/shadertest/envballs.mdl" + "playermodel" "models/shadertest/envballs.mdl" + "anim_prefix" "envballs" + "bucket" "0" + "bucket_position" "2" + + "clip_size" "-1" + "clip2_size" "-1" + + "default_clip" "-1" + "default_clip2" "-1" + + "primary_ammo" "None" + "secondary_ammo" "None" + + "weight" "0" + "item_flags" "0" + + // Weapon Sprite data is loaded by the Client DLL. + TextureData + { + "weapon" + { + "file" "sprites/w_icons1" + "x" "128" + "y" "128" + "width" "128" + "height" "64" + } + "weapon_s" + { + "file" "sprites/w_icons1b" + "x" "128" + "y" "128" + "width" "128" + "height" "64" + } + "ammo" + { + "file" "sprites/a_icons1" + "x" "55" + "y" "60" + "width" "73" + "height" "15" + } + "crosshair" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + "autoaim" + { + "file" "sprites/crosshairs" + "x" "0" + "y" "48" + "width" "24" + "height" "24" + } + } +} \ No newline at end of file diff --git a/sprays/FF_logo.tga b/sprays/FF_logo.tga new file mode 100644 index 0000000000000000000000000000000000000000..1e103efdd3334b0655bfc6de0dfa164bb65531cf GIT binary patch literal 262162 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

    1LSI)HEWIn2RZubZ~G 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

    8YW@9oDkg0r^zcg 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

    q!8FTN|Z^Q@4 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 literal 0 HcmV?d00001 diff --git a/sprays/blue_logo_sign.tga b/sprays/blue_logo_sign.tga new file mode 100644 index 0000000000000000000000000000000000000000..0a1641b24e5610d321196d1a3409d685b3943838 GIT binary patch literal 262162 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 literal 0 HcmV?d00001 diff --git a/sprays/green_logo_sign.tga b/sprays/green_logo_sign.tga new file mode 100644 index 0000000000000000000000000000000000000000..5cbf524f107ecd90655b85a3804091d9130a5797 GIT binary patch literal 262162 zcmeIb2asf0cAnRj-g|GVs=XO+cc!Pud+%-cOiz#L9^2DBuE(3*oi$u88KOub08l|7 zLJCooKuQ5Hf&w6LMUfyta1nq2a)Y4&2r|F`2})Q{kVs;8x}U!PzI<6PvtCtZc9|}7 zU&O7fL+KJ?B6F*|H_HrN2#WnVL=X_v{xd0V@G30V@G30V@G30V@G30V@G3 z0V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G3 z0V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G3 z0V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G3 z0V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G30V@G3 z0V@G30V@G30V@G30V@G3fz2y{n`rv2o45J4KDbBV&X)=FSgN#Gt@`$rV7&kuk88OIK7Dv8*}S_y0p3H&9RIo#hD z+W%?JO>7Ra*j8EzY-kBwM(e&$S*Wis^!pFE=D>!QjBT8iz{Zxq>ojkn{ypyRr#7~T zZ0oE9Hk<@%wCEQoG40|o(DIcxNM88 z1U8HWzDrBS?$@z)+(})S8~gm;z5hC&=?x<>+Yl>(^)CV0`2I0v?7o~jKkc+mY<0Sy z>~e~?m7J;g)Y#YZoPSQSwn2noH!Fd2EP$!-H^q3-;l7C*jndn|8V%?sA&1Y;_th zbxr?o9Gi98Z|^WAdsT74>v>+#v0vu*na%o7uwa~ zT5tRMJ#)Y2e^VF>n#X6H&PUsw>XRKOQj7-PXMtz_kl&xA*v(47N?>Ir@E5rK*nKmU zjX0Gj+fGMw{u?vQ`JK5w@AZA}v!@Sq-rwmoU!8SQd(&e-r&p(+!g5`<)plb9G_t zdi3h7nBoq_ZdL+T0+UJL4o?49l(G9Y=c4PdcSc^gYlyCq1F>Kj%*8))RA))Qyik$%}T&ZAXowy^7BMCzJ#&y z&0^!*Ii8J=ek?zrY=W8n1t+mH?bM&|vX6gYob|%7jqLY zy8YEkU{g!rMOyzO%2@O2R5aw|Z>c!#4|Xz#qw8ya_U7uKPtEzSZgo1GUq8}tk~`+G zexX#zDLvQ(6S&i9qYo_VBh`RNzH^Z3UA&H0``@2;8?N(B4!lEehmU&dc39siXvY=aqi4mc%BfpJx>>C zy@6hFbhKX4I>9*b!8WJ#aMKB8!eh6EcFQ*S0L5-r0-H?&-=@K1_mz1#KGxw2_WRzr z(0)hy{x+weIX^p5zjQK}GtL~J1_LzCI3wF27v`}pZ~e)$1(@zi8<{z7%hex+z^ z{$|Z_Z1j3SHVK0pJPdBIJuz-jc}eVMC9shsP@pmYJ!PzZuk&P6mu+4BXe__nE3)x* zoYreCCv$0b?B|SIr&tr4w-l(G9jc7JgW$A^u5)H=WUhHyDs(bX$Xv@#JkZ|pj${?TR}9Pkc<9a^+bp6`M6 zg24^qS1d^%Ar^50Is6glip$V$Rs!o)0^g$IW54r}Vwl)_*4rO#8;#>LYjJQq^sUzG zZ6|x>#CW{1>*a4l>4ApRet!&~qi+n5FHt^4#Uh>sZty2~zO@am*B-Dr>%Es|{{za{ zeJr&ng`VF8hu5>~FJ^1wSQFoz{Qu?0n#}nVadnJcr=a@BT5%H(WY#2JA0Ouv+eG{A z?Z!577P!IRrY>Kh*v(2{txMn#75q<>vHICmbP60_+4SYsTjTL_C@$Y%Zmyh|t81(} zjjDU;L39A>FxDEtKQ?IG0%N=c+~CQz{?E7d+q4ppjqmSJ#_nUXjn|&8n>leLj!%6D zelErMR1bEXXnkVL?Yw%WFUmOiYw}L!vaFN+N)~@XFfMSoO{t5sX1toX|9fMBhZ`hT z@hotIKTmzS6uVgotQ85|OhqQM@v&ZSzXiSqf4S*Li|P9wKPP_m>@}r%{g`J@{9Ezv zqBH&JHpUbA>b9Bh^`mtsoE<#|Xq;#sZ5n*g*^dFT4W2b_@Q-P;av9srO5j{e;2Tt6 z?EWWwY~=}Td>?8JFMWT6FOB2vw|2Pv+}*jDok^ZKd~WudtTX+waQ?*qGXAJ^-eWBI zbjH{pr=~`?r+6orfOkjuCh$ovIzFiFe%v57km0(H*#B!Bx3)oqV7FD5fNXrC`T7k0#TL3m(Mjw`If?Bl^Sya|t26V> zy-wze(f<1Q_O$B@d}V<#0GyC8gT`M-A76Bw(->#Qpq)U!o8~CDq!CNEuJ~cO&?yryaoKf|e3T<&(ue9m=ZD%SqzmJ8| z5q$fs2R_>6giDM26sBS!r}pBE>El6jeCy2_Fu)BbdqdU45SVq&V!95;Onfrf#TvN5 zv%oQ&ShfGYeb8o=fNXq!i!ye9oCwFKm|Jmh_{M-1*q-|Hb!RF$zrRjW51pI4wnV=)iS8FJ~! zPbVE%@4vra4}3RspKO8X<>>njt($v&q4_!-eXlf~NOfsge(BWh4|h1}OA1b;5O%t! zy3X|H(@q3EK6ydTnf)p;#m75Nh?s-ifwD96#a@H=^V$;hnYuXVw80>l`uh5^;TD5$ zAhCVUUJ*(~obvtP8#sR?Uy0TZ*hXX{k*#FHnBsp+T`g`9A=qu%B=B|aG>q_*g zt#E&Yu_rJ;3q!#AJPNKqb7|hpHamozkPtMcW+fCTJg=gK!D@+h)cr ze3cRK!rt?}&-4Z80x$P;0Z#@&pS|&~1J=;s2CrP5l1%>nyG?arb7f zEI9FPDHG4DKB#dgiOoHSPqF>3%Oxb6o%*%7Ji4Fla$@8RT(JG&DW|HKpp%2#p_;qv z@DnVACop`a*zi(lb^no~X0AwOWtd>5~n=JL`*4JWn@od0Y1@2G3E zzHkh`aD&p({e8Cm4(o`!#;dPl7s}`w8Uqy5u;3V=HG*)1*iz)b$V?vZBy6U&4I%`) zEhvHOIP&|HvHP0g$)ex1-yM--kG`)t-(cS#u3~FnJQlXZyxTtI_N&&LJDkcxqvzA0 zdZ*4yJJVm??c{DKI)yvo3sycb`jYTI@!d%$2fs+}KptB?>w@>`f7l+IuWoa)`|~EJ zfb^Nt-3wz5Bam9R>9F>cNb(7&6#MTnj z?gf5RO!3_myIBbgOW-qp82eocW#GwVP8DaivDq)g$LG!Ynj^u=WG)*|k56GI^YV5o zPe<)=$C(O`Uq7!cwI?dr&+s9>z&cx49p+HQ5j2jqoh`}}cz4w)+*EWT`7q-Xz6NZ0 zMu)+--#7~P=y|Stq2Yvw)+pZnV_*`6QSxkn#$JKXBe7?4-ZA+~D^HQDSb0oT$3?~f zlZyl!i)<~jxp?&%^Yg#tyeW#^tORx;g8!8=_B+(a@r~li_W7|C*B>b?KIi-E5QeW) zYvShX*vQlun3p4^@vqmt;@e{M-I~$wTPIm_^fYTs1;>ZT$m*I%-|CHmGQS7#PC2)|Y{~2Yh_eQp7*`Q^MRxJC1c`|zQmh|_t#IczA zl=SQoP z&Ds7srS`EVf4kRbS?^9_^AZN3LaxrjZDsQP)Sc2DMe0T0M3-oSEtu+Y^J-mCf7Znp zM=RL;dj9;@o6}C|_L5V7y5SV)|Kk43T$&4%SNXA453?W}2QfrXk7xVyw>9XyaMKya z+ZHwp&u%f#9^j2te98vXqJ878v3$?`+kCH6?6&bGa05;J0VVKV4*ETFMaI~i7sc`Q z=X`AD#Oq0i4Z7DPzlFg3HePI?TZ0WeHR}{^4%Weg?kRn^{0Me^Vh8HagTucd<+5yA%EKB8@7 zzZ2rmHa0$NcgDuIm=4N&=g#?UC)V=WqsEA(U93)}JA};vFM$4Eex&SRwHjIfspuA? ztE8?fW4{B7L;PT7ch0Gk%SW;P@vU*k!~zLhbewx*Uu+zmHup{KO&Wim{DVn+2L8#q2};Of&RCTEep@A6#F;xk*`c~A9CVMmvL zUE`0514@jxaiz!!tT{P;e$Ldtet6nRbyD~M-24Dr7$4FXyZ3D{XUfLb`G7vYGik6$ z$`z<}LTozW6z;1!Ghf?l`hWKN5^I6^x_tp%!|VU5>q_vCd;dGtvHpT^O2R8HW*6x3 z4W1otP`1HKD0W-_5;#l~{vXPCeP1{}<};IXLpk;q>G!fbDOR@j+_V#43@1D8vjffx z5ocS+2iIavq1fDU>{~_bhM8*$PVOdbmE`rVzc6F?!ek$-J%isbfqw8balpzO+*?0O zzoCO%-wJWp+lHDcfnkOlL93H(8Vcs}_Ar-tn8nFH{dya)CPJDsspZkx_2;`r5*MUvmps zH2Q_fbCnFRi%;;}QFScdN&f;1eTPtm%%`9=#Fgbj92ak`2VtUgjT>jPm3<2w_K8!acfYmlcWvtQ#S z^YQEA10bd_V2v=Ujc0S*F)V2xt8^&^36sp>zY zjNSLg!tt4Wy5g_xvNotYv8}#!{shmOq+U8Vb)M@75Ed_U4Sw!Lo|OZ4C!1daT%PRV z>W__=8crk^c8a&x;R|np1Ef!bDIB(?YkVo(j@=MWabbe>oYG?r#tQry?`?Hb=Yto# zE|2|i&<>cng0;ju@&STVdImpXWb_(ku{KO{OtBNf8XFuI^&iUaC=h@K9nD6pRpm!x^VgDtOcmpjgw{!cuU zWK+7g#N5yN`}wZ3#TSQ{xq|TtyPW)V@*hmnw&glEbzzRSs_u+y!Z`%3+w_}kgV+wV zCX$V3!sma7^X;}aB`{01CbRMFf{#!7qi}o+>5p1NntZyfqgneVcP*}eQ-?|4sj<#4 z-Bp64cNc4P*6#~EBaH4|f41i8`j4@`r_ahCCi{V|Ny5XUb%bBSM!saJkCU6Ys z**nZwuKHr@fkAYVI$PTy|Hw7AJxYCkNEz?{$lN7diDKJE;rL_=H|uRckFul z+9Usb2W*~ffD7S(bJyj-2;@zky(XL?u03uRzo8pD6vdt=oUYLcdh34I{wMnx>jeEK zA08ZhsS90vU~u`5b67<2tgG-=lgE9yIvSCaBwK&V89;w{t6j7?1z!l(GMJiZ>OGPq@+r z=X|{0%$W1qhfZlL#EKY?&H`RgiR2dBUl zbRF3mbzj*ey6DuhHHu$k+%~P`d7)gyaEJAI)``Uk8UyrOoA^cXES^Q4V#O4fD0W+Y z30%V?e}^*m`zG73a%GOf@kwXa++l3{^t(x(v6APO?r%A>U*F^8u9%O*RgAvkbo6{- z|1=lt-8TLIfnNXTnAY$fZ-47JSipzsP7xjeaedMDtJn|q zjPg_D8Sn9g%l{`osO}MK1dmNCDVN3Wt-Pp;!B8JJ{XfVqz}R4NkubiU1#a+P^L%R? zLEEZiWr zp$Y46ZG#AGg|`{*|BIBd|2HvsGiA5yV)ypqU(Gzg```bRUr%#B>)tXrmngpSNuIG< z=Z5gdx8T32Jmt>w{^wTU6iN1C?kf-b`af&;;=SM!W#eM)63T>JUqARhVRkZCHpx1So3I}jJD@^JJXl-aDvh$H2)uR=l?MLB^6?WRfjzMfzzMwampk3LjCnU7vHn+ zF)KEseaapGg2w?DHz?bXY(&CJPEgl>!nyk>c3XZ4JkBluFUolT4=`%k>&r&hm#sJW zf9;L|?YHn;gY{t0|!iUrcxAf2Lw zZs9$*3U^?v8#nQGGhf>SPtcs+;GMH3K7BSD#b!u`Mi*erU+}$<{f9ZD3SM%;{OUiV z%@#L^5SD2Z_Ufl7{r7Iv_h^~5Fj!ZuNo6xz=zlEk+0KVs9r?H>wEvD>mr-?{^mrB? z(CN>1(=X@jY*~22Ymd+20^++<^i>z%XYlwvU!A!6(Ay z~MoWNBga95FspaQ*Pb zyv`fDE~DytHpgSNs53*JPW5^3ddWUj~fdNeHcH5W-yVutRicy0T z@U97ymo!E$0PUytWu5$Ot{xyB56%6;5h`bhFo51QNzN0dxNvLP>A)`>-|h30Oz=PR z?zh^X1Nqk%nJ0v!=-Y#Rde<2Bm2L12irvm$0#PpgSCsyH7xY~iIpIJJPF{MQ;@bRc z{N5Pv=9K|QgZ(;6UkbX{n*I%4wt1}Kl;QPJJr&2RIK>3<{a(H0$5K4L>HjCm!_$iy zNbX1)9HDpKLZ4MIyy?r`7~V)Z!u{bQ#$M27ye!-@$3YOSCycF39O6yJn`l73kAsuCY})z=#cpRWfp2kX|NS2RE?cc^e2N1J z#D4a4J2U5_7q3K|?r@z}a=&mZI?f3f(-SVi@du_STypjHlx%rguPbjDMX_;l?0I40 z=QT#k))5rL>(w`XSq?kEwDJE>;ronK!PF5CAnsygPXIrkxwJP1fb$pkm&RP-X~Xa( zc=uUvpX$?!ukL=tScbk6ydJ=3^43;35_jS^nbWt%XshB;>~{7N5KrU0cT4Yc<~nS; ztV><4$l$SCacRnHVff+J;T$#G_BipiZSeL}@b^aH$*c9aJEDvM?KiMxntVL2Pow@E z_ABD?Qp5x5KBWgL@PY4Q3;-t#->!FW;fs_Hyz{B>!A+xA#IPd>Q(Pv`r|~B;j!F-Z z9U$3TQ;7RR_6XV3ynC(JPw_1k;7Jn?x~mKLd_6hS ziC9mV^%U>Fcmsry(tIzRgz^iN?wRuotSea#y;G{Y)=BjvyjzB2B*1>$*C%^?gXC3P zq|NVf%x+7Uz+2p6K+e)*^*@@Yt7(izhcmf0;E)x6-0-#QeZNY4ZtlvQ@z3Sp9a4T! ztzpIO>DfKR`CWdb0bX~DQv~NX1(%58c04?<<}uj`6)U5-KZE@j&!A#rkhS6lgex?D zbMEckSMnB*nD|MPa1t9#(#>=60P9`0s=whI12d*Iqhdhjy<^e`dVGUg{}ee_Hq?N& zi(lSuOP9b5w-}Ib3?2)uXZ^Wn^ncP^B`i;o+&1En9lmZO>?_8%NM0W0?a5x1AznwA z{~n)DPghmHRxU5$_3MYg2jKgQ$~V9~KOi$tw^i&PxaX|=h3HDMsZ7N~CKgEVc)$O1 zzA(Y!BNjKo44CB9Ma$3mw-)|Siv3UwNQaong=|Z*jfndoJl{9)8??c0%O`<<#H|MU zbM270EP6N&y}$VLWurX{{N})Yho7_7_LWPdbPw2FaJZSv(@skHyZrs1aZtKZ_Bz*2 z)qDv~pslRuGf`~yu0P-3pY>fjlhy|DP8_}vYzc4#3D2v1z(yBV{*c~S(Z&uaY+&-d zq=`$8Z(m=&ze)a|A#5WCKaS4R3eW{KHi~O4;GQ-{5TPvN_9pilkaO-U!n610v!ig; zgX z;Pq+aF9Z`MjIeTzXkHgbxMWv@L)g6g%4uX`fx#8P17`dM;H+ZJwH5cX694b?rFp}f zVqz=FaUxyQjG6e9#FaYqOvMN{DRx^v2^6{2Ku+#hEoSW9ve#Ch+E{B)+B*DB4eTc` zfYbZA7MwdxusrzbpU3u(eO~=pw!HMku1;Qr?|s z9!_7_b@6wI!>`)&(FwOJzlhiGy-$q^@{#IYE`a|tx%G$@^z!LsnE%8ZD&3-Xq~%QU zOyxaqyl{58iI-Crt9>uYu=NgpK*dWQ2*d&$r%rZTehECuEeHC);$jucrg)8<51&4K z-bUM3K4956>*60rUoYIjT#W5g{ojxIHR~hcf#CEG5i68EpqTzad!EJs<1cs+KS6|e z0AdUcf0)s$T;IMpGj$KeQ&q?X6sbqJ27lq5fotD^|ItR1eT7)ZHo1CPar-ZasG)Hr~ZN)TNGif)xi(gA*P@V&t7sb zc0n+~nTs~A?JwwEiV+j3e1!5n)t+I^IUiT@KQI4lZ|~@nz<)FRe^E|5!`;Drq?ong z;~RB9f`49IX2P%+?{)DI(#hjsSk&gy1LV&X9$377=moKE(%AF$-Pj6!HUN#EvggHE zS7^jSOrU&zHDOqp*J@9}k0rjF zq5s`R-B&!&%opU{CWc>a45i%uC{Ba+abov+{k-!&{rf!nx0mO8UjJt<-x*_FPyhGw z1IgEi&Y#@r#uv&rsAmXAJoCjK!$mX|-k2Dxp!X#X-n#t`Hqf`ob#iDv4;$AgUy$8a zUIKrWM-23F<()QpDBffZfSx;ie539cZYw)8U)=*Ycic&CPdLrzo5bW7;OHyR_rV0v z&sEy*?bI8 zTOA4ffXDRz2l7wVS(^z9pgfiSV;lK>@b0a+fFzh-#llB7V0@L=PXA{N-Cuf> zd>|Tg{l|LWe}+%Ht)2uv6|=86oM;mcE;umv3MGeECzOjfl~6O-vv- z;^OV|*Sf;|N;ils1^Ww6Yq)?+;N>(jk!)&FgHv9LOjhDr@v3TW5!S@4frj2ao_Qa| zZmTDO9Xx8F@2JnK?{`1iZG73o$Ir!nv=KL)`Zch1CjS+^)Sf1H47L#YMgzFc{*>n=DRx_33H&CH8+b3PaQi7< za{*lTz`4WMF86+JKbTqU#oZ6lNyN#?yREgjVr@Fu2#v0{`Jdmvnb^aZt7Z8aDg#cC6Ctk^~2 zijA#OyaeDd~~OZO{(@!;6wf5vKjk9W}hu`A2ARJt#a>qPcwyRE(i-sX`5{X;fd ztpT*g)tYVi_-gDc&Q5uF#FeEv&CefU?B?j&MRE3@4%dj*26sKdF@N1-rypCk&@sdSjE~>oiV^cN6_ZV~M|wtNA^5ExD74 zE!UXs+qsj#-{sK*??vr#^8KL~*PesJ23>gg_)6}V@RfHy z33!it@3XLXHF6M7p+9@|5Px_36Z*@`0UV}YKhUSf19I4DPHe#SW#aVk)n~7n>G4;UqV6cPaKk|N8Uz5MztD8PG_qI;LtBrb7rg% z|6ql=UgMF;r>?byp5d?e(05^yD~}Dv%@xQktQ^CE*Kt1`t5e_A{(nl2?)q#OYmq>^ z|9^!%>~`)X@GOrWcwfZ}(#7^IJYc-Xe?NTAO6)6sMt$GpnLNgNm$_D4If|w8^!o<+ zCAIdgGDd}Zw*M&WOLHC^9)W#__g}fWrAKRCEkDpQu{>%+`*@4~@8Zyl@Yl|Kd$*JB z<>vLbQM{i0yr8V}%MUln*^va>mtY-Iq<_2I0kZeWk2>7XV)*%#=Swld@-+%er18Xy zx5!*wL{En+%j3xz>hq>wYg}M_nEv_>#;!Tu%*`c9orQ{|ZNOpu_ zTcp38%l+N_PqCqxwG`{Gfcq;KwcXC01oAvuF_-=SjWB7lqse|PT%iBhN_{tRA0le-W`*NLb3TekA9+i$rh$HwsMy% zA9oCXF0T#ZK-bzp_J8H_>X6$~xb$#wNasNZs*tBceN4|6&#!Wcg=2(ptnD`;?ol#kf|yy=Y>Qo3B%E$&?~{rp5r_J-p|x)4OAhG$MYAxxg^-aFvtn!$eNuD6xDOZjxnd9sWt>GYKb#56|#|n*LAS-ss|w zpZ~n_!(ffS*xipW*4R_%^<}>-Wv^EbA@Pr@Un}QsoBS-A&y}N1=SJ&rle`U=@W-yc zBut%hmlz!fn_>29cdj+@3iu8Bb_?kNv{^il!VdVKyWHP}sdnxDaH`xJXiHLV8oQl) z3EWE+2Hu6#g-PZL=DN4HIdSsh3?E;Pea%7DLvB7<<5SZd)zf=r1It}K_s+;)F0PW| ztwj?%QYVjB^Yx}#f2Vyh^vdgz+pLrb{IQ9eN>o#*GH+CzxlQ{trKSd;#R{qtY6eZs%SC5vuTSDgAd}cG||v=m5;Q-aPC- zzSQqg-b>lH&3ow6>%IQ3e$-%&%EHYdJ$?9jQ*rcyDmv_hv5N8OxSO9s*k1HvJ>SdM zCw*rDJ}TmO;0Ka@jX8e$b8`6Lmk-y%;Ej?_q!T<=+W%y2rMbEL!89CY zf$Q?X=M6t&!F}Ny;FN6B_nSwt`_IQ9{0pwN+uD)9Pg9kF|9R;yVF7ls{>GlQjB)Ck zGwaVbn7``odx>4X|6Y1_FWLWC$4bYS|2hjlPjXM%47Wl1%Ci&SPP_?Y zMf14&TaUkwc~Cq(O`aJAOPoN@8Mck7-3hSz!WarqBO5@5oFQA#A!5`gfu5mfD2IUb z5%pu`1rmpPkiShBgisOwadBXAKW|+w8)x@(*&^ZwznFuUI2503jV`WjjWNp0EF72W z(t=~FA^V>vSKp`X39@U}p6xKkFN{M9lIf`5On!+s!ICj%7RiAYaQ;{M&2DQ)0=H3> zf&Wu#ZwlKPegM{s@g0Lc^5JvG-B&)L`Z40aS}}6##(6(nTiv|(Q#LPQU4*OWJvRP( z`ipd3`P^i~QqdZIp=Zn1SAL{o)-mC7$Z(s;rYYZF|9N0(I@lDdj}P)6YrYaLM`K@G zx`J$f=qVlSj*1P`xDeY(|Cddh@uzr4fpxVzpDS)qT!Nb0%lB7UXAkz{%oT8mVTWtH z$zDegB9yjcl?z+v@Z;T9k_QQUgdt*Qg zdqRQO1o01R4YH8#vyglj`#pCci~UGgEY^?YP6#-6AHUgc?MPsXs{A3P|G!cnXgrU- z2pvEeGyk!(`L6YN6%3u$w7R}{lk$(w^?%vVHNP4=KK)GZj+w*g2h!8kXS7}xHmD1K zMiGB<5O=oXgo^jp%(b)M+Dkt!nz>l>t$d43eDVIghb{DWrJJNK$`Th8H@*Vl0xIMyQ;st4dhb)XdSRryA4+%FgMAPgfti$V zM7Bj&c3R^IC+y;Z`*uK{DcwN1+`aqBKcBmHK2Fg)KFO!JBxUz+zKGqw=cn~u|9!sO zZS6_m>r|=#KInV#X7DiB0Gdae#IMg^hYz2>(0-&Cbt=Tfczs{z<*`+DKgMo`?%R@G zADg{==fzuV#^x2@nk42XW&Cr(;^l9ynAjHK|2#~-|9Kj(#I4hO6}?mMJ3hHfIy4Jf^jT@80Ca76+r`qiZ$pP31%Q286=`>yIwcIwd<{ z1AF6qJ7E-CW0_ng^&?%=&eVm+*MJZoxMXo@V&@!~3$`5C5k91Z#2S;q89Jc*1<%z~&^|v-0dE;N?-=o{5h^C(onT z=dmZW;Nq2yLAJXRxjw!73a_iRala2sUuHh9ztG0_(7<-V8stcmXSC6e+D`p2`~0S3 zwP(Qs4%ss_=eFNQ@2R;ufOLp1JUE6|h`CvK!3;Wu#tQwW*o6Y?i75Pd#&$=Ybq{gp zXg^Pm(LkGMZ~XGw5%d`@N1Y`0zUniKE%{)4{CxSL zic@{GLVj-IdM`)^@?;8Qrx@NibE26i4MvE*YUcDAba*)Vw#MkI@Ox^Ge~IO;BxaC~V#q+cn{SkKR62h;jvpzo{ybFIdJ7O}P}CgxT;zQGu|zqL-d{dbnr*_PPT1W_?Q{_4EpF7ESgCA$UsIhh&#zAtQU!~Y> z?MmQtsy6VymtAQ3Gu}aRHc#=+4Idx1uRMCvsWmSIoog_(x77?*tpRqf#r)TTcVGA& z*#{I?Z`K93RPj}1n6olw4p%H-@_h1W?@h7>mVHh(FbZ}A=`7hRi)PFc=VbpF=a{*a zb+xcT%DpQcNA*fwp!Eo`kJuQ@9PZsu_v{tfC;Dq^o}uRmQ*3@?T+tX|#tPpxW;{AU ztly{jF?umoG4M#q-6{Bl;KODf9>6%OjvBAfH?qo8Mn5ufkX{{-O9?E2I8cP?SIk0R zF8C>>=gV#(EO8q-s&wEZl1yvlJ1O2%16#rP(c?Px|4)+e^Ox_bz^yWmpDXZx=f76p zg<~+7OL0hmu^2wi{wox_tz8LBQ?-Hrn{u=$f1TEgarErrZk4c(%n;DqsBcXJF~*|EWvi(!zdVuA%S9 zwpJp?RE8XW?pnNOYeO$LeW5p=XnpPZ`@{htTU+MxqLaSJ#jVI5*{?_Mdlei|`5<#S zYxpwuvI5U3;u|bu@2Wl{oIS;_|5G2WLxg`z>;Uus=`MJL=i-gB*W|I?6CZ~yUNH}fTi^@4f8@&F{*r1rlSUbkEz(L~EkW4(e$WPh7k0(d!B>hDG3+WHD ze_@-+_v-!cqU3!rSnJ2JF@S0IexLL+L+pf!Uj&C85I?TGo--7?t!)YXeX2M24&dLa zK1odOhnj27UN6)=Wdjg~uW$$N^)=W8@K+1NpWKr~*Uh{9@YwB)4V(GYkAL^x|3)v) zuk$Xs%Hi(HTwkDHyYsH*;l@#LvgGy=x4)S;8Be4`>z?Xs=?hs;4D<1TcWRx`8r{{A z6<;^ae697kSvSZYfF2)V{X7qUAXy26K<=;dBdj$%`yXRQM}EGSXAGx^+AmChPz-z= zd!1|$>bt6|>AzgxJ}Et>U~B~5IzaXf;SrPM4w1dV;~Jflk2`MZ9-52QZs{q)QIyfc z(&u9r+(luoPok4$Snp?VuNZ!Wz_$6{g%RJCC$WQn#_%Q1$7b2Qo@=|`d$l{Jchz5V z`*Y4TdaCi~1n7Rjrp}sUUYtF1nz5b9 ze+~ad`5-tm>AAw1fpyQEmv<`ngV#HS4@&Wa=q`%aOYWJQcZcgJ+;HoS4&2{!IGEy{ zj4RwzoV8{gp)QK!8NSxP@AZF!UBa#)9kqVT(ZT)f`wmTw@(i zd3GBAT-S-9$BGMM=9_!XT&g)$e#C(~2H*u1^V4`5JU(-!)(%m4P;^Zc9b0`^Ho+G5 zxoCEAySQ+IT9?!h*ZY1n!!3SOsb_nH^K*=~wQQQo4ca{3bY{Lqz6?0cgdq@?PV;yj z+eMAoI?c24pSb=u;%tdw5XPbM0Cq(%3CeM(HCvp|#QBV~#1bUIOc}eY@Bcd>pR@d3 zxCmjWrT=*LRNs9SV`_8zAcS?Y{Q~tI=r^@PbucNr=^t~xvf*=69M?Gc(M&H`E?~UDf|< z;E`M62f=pL(prJ_ym-Q5#P}7k)7RLK?^%o=|k7ryq*YT9c_Z=A!zhNI0p=OG-FdhJD%n@yR9DyC|CFoDgFPY-ZR;lgxOQhQ2(*@{$1RB z;^2$mmzyHqu<;seZ}7B+Ym@%3bw>@m|EPA#uG#%`Paj(-e1Wh>@mXQuu`yuNJe&SM z>bd9oc#eF=-S@FO5K|ay4Xw9aei^I#^G{l5+s{(pfp=bOkr0?#xd-M*xWnsz)>{o`V{1^m;EGt z@$%YFM%8IGj+Y-5haqF+lYtm9tNZg$Scls^)Op~Ym+wj#8QI@Lsreii!{@J;{rD^x z0)yv)lm9;Ouh_DMv6a0|emBFrwLo0Izm1s#%>Rm0;u>M=Bj^>v*~quqdd0O3=D_Iq zuUYTk!>q#;^Vt0at_b`&0qwE5eGtkz+~U-EkQan^SsYpVUoW>GfM*50JFD`WV(#Rd zm;Fz1Yx2{{mM8na@>R7M8%lSK)_KwwVI#qIAnt@%8y_baB(42r7n5&HV~lK+=d!KK z{p=L_jC}sWMnL_@5TqFf!|WGuLW%O^=IlvC-(RNiVxP^cztY%qwcew zj+bcHG&$7EU=0H5tu>_G)~^Jvr0N6zSJ|C4-piI9kk4V@+~I52>b_!%%lPhPWLIB9Ukqv{{)2$Ku94_utW<<*Hp6n3afZuM{>M7#mI1em^Ya}stcEI1sV%rLxi@b6}^%<_;B>Re$SAX^5WW>dz zxFqobrNAK9i6;^lUx00EKqlTZE00wTb|?#fxqJu-WL3JG9G${2e*l-l$K)g+Zpk}; zy?%xn*Tms0ek0jW1KM!|zu9eLNZ_B)jDi1g^{JY{18Yq?d~7}K=ZPPzlZ#s%W5(Af z{~f%f_2;qq!JDNxn=6&I3=a@^XT=bUt9ab@DdtX`V#+HZ+@S6wzAjxa`+{NwWgCbQzd!Ch*V=g@;$3t>I(qVPAc{MNWY>F{{G*Di1(>hMZg7 zw23opos@42PJv4n<_;Kcr(%ZQmVIcEP;|_E$QDa_%UupbbBc@)8bTyI%H{ zi%mX1<%kOK0o&X@{3AEuc7!$!ytDH8E@J;3ICuEkwXmPR4W5xF;lu%_r#ad6*TIX= z9GxYvcJV=R>1{Lo1mo5>Os+!Z@~*Mf z4q@j<-D|BK7jLlQKMV#OE}?+>UCwWI+n5sgn>1_Sf37^$GvC~2xH5*1t>yhFyjNXp z^5WN(O-^+!!<{Rx4wu7I*gtrz4|N9GJ5HMlchpQAfS1=;eg$#w>RMs{geR8XB<%b+ z_ghQn$S2wr#}VUO01t$)Vs_iO5_p8B4ZO4R{my)Ym|${A4j)^~`^uHwfICaPKHZOJ zO#Uv#{wu#{>!i5;>Hn_5%5CmC)a*U zJObn$!7k|WY)k)GfGc<6XO61VavV=xl!V_@woTSV^Ye}U2G6kD#+Sf#G;!elOu=_K zjSj6m0p7bke9l_hFWm#zFMfG{u8XR$diVfkqci&d32cAx_y*<48K*76{3?f$$>l?? zB4LTdE2cGuu2&qD`jPUHk8{7ZaE>@ejots2K)e5Y)X{DmUjiYTIG8J(cUrn`2V9%< zX^yYiBKund+m*rPo*-8LmO`IHQ+Wc+7$AE+`31@gh?t zn!@Gn79N1u0&=5|bI)^mj>bW?LH5y9uuim#`q^!BNZ>Eg%z<~dgfD&OYpj=p z4!i@&T`6Yq1}^8d#= zgE@02slW7l&6nlJo7fb|^$BK1x69`$r-6e$ZrrPFCX0gwYANsD6EfcmkZz) zZC+1aj!m}x4(**A1DF$pqZikme_cIrj{p2~@I6l4efQIy@N&9ql=NlF`70bNIrGTx zr(9ve{8r%lE#J+bMuwG>#hZqM_D<4m1EGmUiQJl{ej%M{d2r? z&&8+Wn49oED(2hEm+Y&Daz%A0cH3MM_>krfyq~!n%FgV!nIn4fF2l#q^}gm}@$XdO zsZRF%SK>17euQn#i~)=T%*~3|%adDYsr60mBRBc`aDagWFnPgy`GD(3U95!i9917- ze4zi=UYvI1H(2U3SK|5<+(*+N&zhV_UhZb!b8KEugs};?9khAieO2xU<$zPJu;F9p zdSAMH>v+ehJfVEsT7z#h7=P7E*d^KMGzOU5qRL;*`hBT&HuL6DVhG>@RR3>-GY}`B z;tmsA6UHAPj-l!kofc9^T0?2+WlYW{&w4(68LqRJ@9@S zJl%WKCgyGU*ty)V9%;c?XDU!!iu|KUhi3fb9?WDR$8vrMtu=9IvTG<%?57+#R?%#w#UkP~X)+~I3iYG1sYt&_wk5wE0J zeA(W_&#C!d`MqV6&ybg+0uONaW9|3=X ztO4e~FT?N8D(vI$2Y(}eZ|Vx(mR#oaKeHz9t@+(~nE9D`U-67yJdn;`YEjP6+H+uu zjm?Xvqbo*xJt&krFVyKQa>{9T$q&`*>r zZ~C)cYr+qZhND_`Yw^|OiM>}{v-?Y~-M^;;7+pXc@S%>n-(r9TFU3q-v6wIk=2<3{l{Q_IkMdd-i={?_~2!>`prsV*A_T z=v03sXHWI%!1ui0E`J**{ayeI(D~3EZ<^#86gDVL?6hL13MTS zLreERPFly|^NZLbX1|3$H#n}#=JiBib~6(A8U7CR6ZzB>-|Ek)F?`NS?kh(@^JRC< zub5uh`n`3xaJl0B$lqBvJYDkn39G-7`HU1N-FgeWA-uwMVvO>{94g*Gxq=Pf$T3&{ z@bZk8?knRbICnhZ;yZ7=sN84R{pZJZ{|W!Q1jTMv0+PTTl!5*)yYcL|$)8Cs%;94z zy&uj*+`Jw1t<0saPrZJm0nca8?$3O0IKJU6D3hmKJU?}C?NgzZ#oy#_QA`lF(PxD> zBqq?T0bDzv?2+x0;DD=PCt8o2z9(#Aw0&;Y0dZn{rp50~j-P=4*U#{q-K+#W2`I<& zzoYcu71@qjC*i?+-t}$ykFE4~<=C#l-KRb#JW~3+G&Xeto#A87m7DX`G~@))sGFx z5aX-LjLB86W^Y2lv60^UMuyRI11{DfqswN4&`}vf9d`j@9kzK;FrLB zUJ&Bmwtjc}Lb%aof2Skp&FbrlrHjwP?+JIm=6b_V2Bx=sH@UnRlbR=l$L-+XKx_f>O%!ftTml!=c!~Jr333oDwJq^& z=>Ft(D&xluxR=fA>3{3(cfSM%a)pQD_`TqYHry90j0IA>ZRKHNc|P7v-aT-(4#QRRp?-kG|g8IpVzeS1r?Yu1;#Eiikmma7) z(FVDJo&Vsn$=n!4<=kBAv&Xr2g^Jr}xtmtbpPjv?Y_JBU zduyieOWzQ_Cw)15J8<}Eu2)=tO>zBj|4qYRUp>?|T>QiJUCsUM_1H&C43AQ_>`>v^ue=jr3q^f%4>iV-$`K)6XmJ)3_S9um_o<=nwfVe;-=x^nhFjXC0Q zP+o@snOw_ncC!*#Oak+Ah3AQ_Q;v}3h^gnn{r56liqT*2=@Vn0xeT1&mDtee|0Zt_ z{cPnr52GpJgF9;q#MZCab_dKg(*l5H<(s~Qo!S^|I51ZE$f!J-N1ZFwo45k16 z#K?&&-st=?t^vaND0cj9hI3RLzIt9L5jLEgvN=j8s612w{|n#e>%`gN3s_6@zF$82 zp1Zl^bl@Qp@33O+ls7FFmi zh;LoKF(7wyk+`jyh4{U%puKjp5*SAUM>%Pr|L6CEd-*2u0N4YEk4>^am6&o0Hx&#f zUH-hzJJ|NX&=_t?czmLD@#)h4<@bl*xAPHtz$5g1^yx{SbFR)6e|qOVZ~*uQHHLLQ z*y?1iOgmesf1UP-Lrl5WisTrLu>Q%y$rWN;SaN-(`@aAO(wl8Z*v+B)S=}Fj*llbH zh!^BXl>U1ZEk&If?CyEiy8hoM`VJPR@>ms2y2~#Zt;bBhF4@dnU-~wGM= zx^NJzq~Bqpy8C1?>bmp=DaJ7L7W#SxzM$yV82meo1>y~o9RpiI=1O495AKD3~Ft%u)|I}!#LTqlm9dXP9}#VCPcYM;W7sr-A$ zMDh7uY=c@8D3`e6p3b&y;`N{X_CDeu+}sF5_py0B5s2L;lED3(J@7v29o-79EWHPP zcIeos{mi8qCt8WZEe@X#arDyb<)aQ2!uZY=+eb|Ai^Qwa@25Xt4ZAlmKkdZN9aXQD zJRU)3YT(aM&aK8#Z~&}x)Yrp}q?0!J#b_@)#^Np&WEb?2zL;g z?;DXn*KSqQDG-w|kE?w{wsM&Hxw`#t`tG_gJ6%P=`~(D9`o z=MIo(;|LtJ#LP9|(@kt!nvG%j`R8&!Os*2e3o9R)Vg;n{6z;+|aH>sP-58xBxF^+d z3jaq2yyc|z6*f~CgyP+Sy8rv!&u&%%XCr~1<)VT2vGQ;gpEg*a`T3&<&hxHIUXa1& z)#2SN_3?U5xcp=TH#$Et{qpx2P7mT~)L*=7H_E5hK9vW_5uhBxYWtgtVOH*7;+x^+ z76wXfHMT=ALWP?qTlbi}E%5xrcLeHX%JX11D}l3-z@1z)&>uB_&wOhSajm2E^Eez` zDL4e{FV@LF}Dl!wi1})!r!Cx-$h~aG*_3% zhw1-)_Kh=8CwEm@Djh-%}QV?68H`m54>CI z`x*npF*kfn`*FB>+OM~r;*G8zo7|1f5A3eyJaKmz&J3{r;?7HB^9s7hM*c0@i4h~H z*kSSqnYEDoAL8oU{%#2bDDeE%}QV?5)f`|ppVA4 zGUtE=5-->Au^9YUn){p2lS6=9JmScdU#t8uzQZ1WpXPjVdkw@BfDIVF*GAr#Ewu_y z`1EJ!?%;x&uMy*f4L{b5!*KxLF)~tKlQcO+Vx5K8TFOOQKL*Di>wqD7{Sy0jvl3Vi z2@I?O^sY5o!`7c3+AuRG5-!ST278MMLi7jG>(7!?NYHGJ>Q zwx78QdnmYFVT78;dust?m%G+o)4Tcrm_axY{jxE+{orSeBWwTfeE*M>62)#-0?Q$R zS#C1-jxqoH<4cuWD%Ogc+?e7Dsy$1-shvr~i=la}{WkL(J}<@idiR+MPZ><0d}F3y z0}qpDM_hgjmJG+>;TMmV`P6q)qI^=&DNMn37N$fCQ75Y3iZLe)4`u}4gGvmpt^~Qx z$uYGr<%H*Betw?g zcC!*#P6_-fH*?=R-&#GnI|;T8{=0g_i8SF0WG&ix4?8y47RBp|&rf;rqE(lNR^x^^ zJgWz*PU+ExQ+lLV_+ERWMj>6%72pCdfX^>rKh^gVwh?g% zZHc&c)DW>z!dG3<)}QA)>saAfGWhwu^A~*o1ICp8HJkXDxIARnSH2Y%D<=lF-7@|#CNOmhrRNz`BeD>ihLR>ij7zK0p*`l{u$+WD8Ebj?OypU zK7W()eadh2%CGbJYrXQ1`Bc#wN#!3=guPSw2fgw=KL38N{0g5czuYV0TT%IYl)ppy zeTuPjR1en9z>RRGiVsB?fif|eLX~ux+m*VN}ov;3*abudYyH^y8x}#UN@~JXQ zndudstJ3Y24xf6bo0LYc)c8~pPeFxJrpVr{QlR81IZCEil6gniQp5MQ`N#$jmy}S~*Uhm%&nE&KOxi1yF zF7Exz)dg(*#I=I!7yo_ZmFAhm_Jrmjy{q~>O0nDWNZ?v-qxFgLb=IG0oHl&pU@g)Y zr;NX`^#(apD23|^UqExam{yh3UK56CV)7(Sco^1Huy#MwFm&ICY-fdJy{tYMEjGqA~gnwYC@xO{!IJdv- zL^_GnA+VI3^CODvqjs|rm_!1yx1W}uxpJ_2I(1>r@Kz~Cy>Wc&Y2$Np`@Y`8nR6Ker?h_HoQw!FIr z>usyFwk7Z+)pH65!1$3j#%_W~GH?9BNa4aP)$U%0rnh?!YuB3{<& z{uFm}5<3&8+i#OA?YTPZHTplk8-D+9m-R{ZW}86*rvK*-Bv+lM_X~$& zx3wt&;Vt14EuL<{y;yy`@?#TsXy^a6`QKXGwQ}cwxaS&2h?&2)!dE~^L9OO7WcB3td0bVJmycq{y4Sg zyH4S@J~zMztMhpKlno?-i)o9KK0iflS?jbfmj9Lw)W(h06!EkCehBP;{pjqM#a#h+{+uoMaWAX<$&oi{o^%3RX_pWVKc z8`^6(tpvU|71;u|v~fBijv4d;%Kl9&jrGy+e<7bAHrp@bGlp0AM^sxpDR#3Gm{bD) z1s6EQyGmzL7xeS|+%f4*?D?xE0bv0CAX*}3jp!OL1U+&VJQ@Xq4#c2H14b(o{l+~5M438u4Mbats@_4d;cy+5_pEiL6 z&gWc{V>rn#g?@nx6>U4-4zI^{1>#-4=q|Q(4e+3VtBixe;3eVxLgYE(J}Q<6e2D_Jmm3NEDu2Cq>L;vB)~p1y*7yET z`kY>~HMJF6PZF4+vVW8EHz>-tVYjs@fi%_nd5SpMUR;}1w6(Gluo75d30My16&A3) zy_JBKfR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%ui zfR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%ui zfR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%ui zfR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%ui rfR%uifR%uifR%uifR%uifR%uifR%uifR%uifR%uifR(^Tl)(QF1fpfX literal 0 HcmV?d00001 diff --git a/sprays/mulch_face.tga b/sprays/mulch_face.tga new file mode 100644 index 0000000000000000000000000000000000000000..549a871fdc44c62643a82fd663dad4a92cbafc43 GIT binary patch literal 262162 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�UgO6?8EIfGV_6!e|ms?fc&RWGvr<$ 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

    ~}pt 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 z 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 literal 0 HcmV?d00001 diff --git a/sprays/yellow_logo_sign.tga b/sprays/yellow_logo_sign.tga new file mode 100644 index 0000000000000000000000000000000000000000..5d12125a9a9bf1fad0a478a6ee8c84dfc6c7a1ef GIT binary patch literal 262188 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

    0R~F7k$n+g!FyO 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 g2!H?x^k@RVe_-l_X$eyjQd4f3ac@G>gj