commit a2cad424bd89904c5795afebf754e4c6248a347c Author: 6arelyFuture Date: Thu Jul 11 12:21:35 2024 +0200 init: public release diff --git a/.gitea/scripts/ci.sh b/.gitea/scripts/ci.sh new file mode 100755 index 0000000..89b35fb --- /dev/null +++ b/.gitea/scripts/ci.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Validate OAT version +if [[ -z "$OAT_VERSION" ]]; then + echo "No OAT version was specified, please set the OAT_VERSION environment variable." + exit 1 +fi + +# Make sure we have cURL (and file for debugging) +dpkg --add-architecture i386 +apt-get update +apt-get install -y curl file libstdc++-13-dev:i386 + +# Construct the download URL +DOWNLOAD_URL="https://github.com/Laupetin/OpenAssetTools/releases/download/v${OAT_VERSION}/oat-linux.tar.gz" + +echo "Downloading OAT from: $DOWNLOAD_URL" + +# Define temporary directory +TEMP_DIR="/tmp/oat_download" + +# Create temporary directory if it doesn't exist +mkdir -p "$TEMP_DIR" + +# Download the tar.gz file to the temporary directory +curl -L -o "${TEMP_DIR}/oat-linux.tar.gz" "$DOWNLOAD_URL" + +# Extract the contents of the tar.gz file +tar -xzf "${TEMP_DIR}/oat-linux.tar.gz" -C "${TEMP_DIR}" + +# Copy the executables to /usr/local/bin and make them executable +cp "${TEMP_DIR}/Linker" "${TEMP_DIR}/Unlinker" /usr/local/bin/ +chmod +x /usr/local/bin/Linker /usr/local/bin/Unlinker + +# Clean up temporary directory +rm -rf "$TEMP_DIR" + +echo "OpenAssetTools version $OAT_VERSION has been installed." + +Linker -v arena diff --git a/.gitea/workflows/link.yml b/.gitea/workflows/link.yml new file mode 100644 index 0000000..76cdcf7 --- /dev/null +++ b/.gitea/workflows/link.yml @@ -0,0 +1,36 @@ +name: link + +on: [push] + +env: + OAT_VERSION: "0.14.1" + +jobs: + link-linux: + name: Link assets on Linux + runs-on: ubuntu-latest + steps: + - name: Check out files + uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + # NOTE - If LFS ever starts getting used for storing zones, switch this to true! + lfs: false + + - name: Link assets + uses: addnab/docker-run-action@v3 + with: + image: ubuntu:mantic + options: --volumes-from=${{ env.JOB_CONTAINER_NAME }} + run: | + cd ${{ github.workspace }} + export OAT_VERSION=${{ env.OAT_VERSION }} + ./.gitea/scripts/ci.sh + + - name: Upload assets + uses: actions/upload-artifact@v3 + with: + name: arena + path: | + zone_out/arena/mod.ff diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..232bfc2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2024, AlterWare +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..dd38668 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# IW5 Arena: A mod for Plutonium.pw and IW5-Mod + +## Build + +- Build a mod.ff archive using [OpenAssetTools][oat-link]. +- Place the mod.ff archive in `Call of Duty Modern Warfare 3/mods/arena`. +- Set `fs_game` Dvar to `mods/arena` then execute `vid_restart`. + +## Known Issues + +You must place `arena.txt` , `_gametypes.txt` and `gtnw.txt` in the `Call of Duty Modern Warfare 3/mods/arena/maps/mp/gametypes` folder manually. + +## Bonus + +GTNW has been added. Thanks to: + +* [callanb][callanb-link] + +* [ZoneTool][zonetool-link] + +* [Laupetin][laupetin-link] + +[oat-link]: https://openassettools.dev +[callanb-link]: https://github.com/callanb +[zonetool-link]: https://github.com/ZoneTool/zonetool +[laupetin-link]: https://github.com/Laupetin diff --git a/zone_raw/arena/english/localizedstrings/mod.str b/zone_raw/arena/english/localizedstrings/mod.str new file mode 100644 index 0000000..de60ab3 --- /dev/null +++ b/zone_raw/arena/english/localizedstrings/mod.str @@ -0,0 +1,23 @@ +VERSION "1" +CONFIG "C:/trees/cod3/cod3/bin/StringEd.cfg" +FILENOTES "Arena mod" + +REFERENCE MPUI_GTNW +LANG_ENGLISH "Global Thermonuclear War" + +REFERENCE MPUI_GTNW_RECIPE_DESC +LANG_ENGLISH "Global thermonuclear war." + +REFERENCE MPUI_GTNW_RECIPE_NAME +LANG_ENGLISH "Global Thermonuclear War" + +REFERENCE OBJECTIVES_GTNW +LANG_ENGLISH "Be the first to capture the Nuclear Strike crate to win." + +REFERENCE PRESENCE_ARENA +LANG_ENGLISH "Arena" + +REFERENCE PRESENCE_GTNW +LANG_ENGLISH "GTNW" + +ENDMARKER diff --git a/zone_raw/arena/maps/mp/gametypes/_gametypes.txt b/zone_raw/arena/maps/mp/gametypes/_gametypes.txt new file mode 100644 index 0000000..a5b5350 --- /dev/null +++ b/zone_raw/arena/maps/mp/gametypes/_gametypes.txt @@ -0,0 +1,18 @@ +dm +dom +sd +sab +war +koth +dd +ctf +oic +grnd +tdef +arena +gtnw +conf +infect +jugg +gun +tjugg \ No newline at end of file diff --git a/zone_raw/arena/maps/mp/gametypes/arena.gsc b/zone_raw/arena/maps/mp/gametypes/arena.gsc new file mode 100644 index 0000000..bcef1a3 --- /dev/null +++ b/zone_raw/arena/maps/mp/gametypes/arena.gsc @@ -0,0 +1,442 @@ +// IW5 GSC SOURCE +// Decompiled by https://github.com/xensik/gsc-tool +// Rewritten by ReaaLx + +main() +{ + if ( getdvar( "mapname" ) == "mp_background" ) + return; + + maps\mp\gametypes\_globallogic::init(); + maps\mp\gametypes\_callbacksetup::SetupCallbacks(); + maps\mp\gametypes\_globallogic::SetupCallbacks(); + + maps\mp\_utility::registerRoundSwitchDvar( level.gameType, 0, 0, 9 ); + maps\mp\_utility::registerTimeLimitDvar( level.gameType, 10 ); + maps\mp\_utility::registerScoreLimitDvar( level.gameType, 500 ); + maps\mp\_utility::registerRoundLimitDvar( level.gameType, 1 ); + maps\mp\_utility::registerWinLimitDvar( level.gameType, 1 ); + maps\mp\_utility::registerNumLivesDvar( level.gameType, 0 ); + maps\mp\_utility::registerHalfTimeDvar( level.gameType, 0 ); + + level.teamBased = 1; + level.objectiveBased = 1; + level.onPrecacheGameType = ::onPrecacheGameType; + level.onStartGameType = ::onStartGameType; + level.getSpawnPoint = ::getSpawnPoint; + level.onSpawnPlayer = ::onSpawnPlayer; + level.onNormalDeath = ::onNormalDeath; + level.onPlayerKilled = ::onPlayerKilled; + level.onDeadEvent = ::onDeadEvent; + game["dialog"]["gametype"] = "arena"; + + if ( getdvarint( "g_hardcore" ) ) + game["dialog"]["gametype"] = "hc_" + game["dialog"]["gametype"]; + else if ( getdvarint( "camera_thirdPerson" ) ) + game["dialog"]["gametype"] = "thirdp_" + game["dialog"]["gametype"]; + else if ( getdvarint( "scr_diehard" ) ) + game["dialog"]["gametype"] = "dh_" + game["dialog"]["gametype"]; + + game["strings"]["overtime_hint"] = &"MP_FIRST_BLOOD"; +} + +onPrecacheGameType() +{ + precacheshader( "compass_waypoint_captureneutral" ); + precacheshader( "compass_waypoint_capture" ); + precacheshader( "compass_waypoint_defend" ); + precacheshader( "waypoint_captureneutral" ); + precacheshader( "waypoint_capture" ); + precacheshader( "waypoint_defend" ); +} + +onStartGameType() +{ + setclientnamemode( "auto_change" ); + + if ( !isdefined( game["switchedsides"] ) ) + game["switchedsides"] = 0; + + if ( game["switchedsides"] ) + { + oldAttackers = game["attackers"]; + oldDefenders = game["defenders"]; + game["attackers"] = oldDefenders; + game["defenders"] = oldAttackers; + } + + maps\mp\_utility::setObjectiveText( "allies", &"OBJECTIVES_ARENA" ); + maps\mp\_utility::setObjectiveText( "axis", &"OBJECTIVES_ARENA" ); + + if ( level.splitscreen ) + { + maps\mp\_utility::setObjectiveScoreText( "allies", &"OBJECTIVES_ARENA" ); + maps\mp\_utility::setObjectiveScoreText( "axis", &"OBJECTIVES_ARENA" ); + } + else + { + maps\mp\_utility::setObjectiveScoreText( "allies", &"OBJECTIVES_ARENA_SCORE" ); + maps\mp\_utility::setObjectiveScoreText( "axis", &"OBJECTIVES_ARENA_SCORE" ); + } + + maps\mp\_utility::setObjectiveHintText( "allies", &"OBJECTIVES_ARENA_HINT" ); + maps\mp\_utility::setObjectiveHintText( "axis", &"OBJECTIVES_ARENA_HINT" ); + level.spawnMins = ( 0, 0, 0 ); + level.spawnMaxs = ( 0, 0, 0 ); + maps\mp\gametypes\_spawnlogic::placeSpawnPoints( "mp_tdm_spawn_allies_start" ); + maps\mp\gametypes\_spawnlogic::placeSpawnPoints( "mp_tdm_spawn_axis_start" ); + maps\mp\gametypes\_spawnlogic::addSpawnPoints( "allies", "mp_tdm_spawn" ); + maps\mp\gametypes\_spawnlogic::addSpawnPoints( "axis", "mp_tdm_spawn" ); + level.mapCenter = maps\mp\gametypes\_spawnlogic::findBoxCenter( level.spawnMins, level.spawnMaxs ); + setmapcenter( level.mapCenter ); + allowed[0] = "dom"; + allowed[1] = "airdrop_pallet"; + allowed[2] = "arena"; + maps\mp\gametypes\_rank::registerScoreInfo( "capture", 200 ); + maps\mp\gametypes\_gameobjects::main( allowed ); + precacheFlag(); + thread arenaFlagWaiter(); + thread arenaTimeFlagWaiter(); +} + +precacheFlag() +{ + game["flagmodels"] = []; + game["flagmodels"]["neutral"] = "prop_flag_neutral"; + game["flagmodels"]["allies"] = maps\mp\gametypes\_teams::getTeamFlagModel( "allies" ); + game["flagmodels"]["axis"] = maps\mp\gametypes\_teams::getTeamFlagModel( "axis" ); + precachemodel( game["flagmodels"]["neutral"] ); + precachemodel( game["flagmodels"]["allies"] ); + precachemodel( game["flagmodels"]["axis"] ); + precachestring( &"MP_CAPTURING_FLAG" ); + precachestring( &"MP_LOSING_FLAG" ); + precachestring( &"MP_DOM_YOUR_FLAG_WAS_CAPTURED" ); + precachestring( &"MP_DOM_ENEMY_FLAG_CAPTURED" ); + precachestring( &"MP_DOM_NEUTRAL_FLAG_CAPTURED" ); + precachestring( &"MP_ENEMY_FLAG_CAPTURED_BY" ); + precachestring( &"MP_NEUTRAL_FLAG_CAPTURED_BY" ); + precachestring( &"MP_FRIENDLY_FLAG_CAPTURED_BY" ); +} + +arenaTimeFlagWaiter() +{ + level endon( "down_to_one" ); + level endon( "game_end" ); + + for ( ;; ) + { + timeLeft = maps\mp\gametypes\_gamelogic::getTimeRemaining(); + + if ( timeLeft < 61000 ) + break; + + wait 1; + } + + level notify( "arena_flag_time" ); + thread arenaFlag(); +} + +arenaFlagWaiter() +{ + level endon( "game_end" ); + level endon( "arena_flag_time" ); + + for ( ;; ) + { + if ( level.inGracePeriod == 0 ) + break; + + wait 0.05; + } + + for ( ;; ) + { + if ( getteamplayersalive( "axis" ) == 1 ) + { + thread arenaFlag(); + level notify( "down_to_one" ); + break; + } + + if ( getteamplayersalive( "allies" ) == 1 ) + { + thread arenaFlag(); + level notify( "down_to_one" ); + break; + } + + wait 1; + } +} + +getSpawnPoint() +{ + spawnteam = self.pers["team"]; + + if ( game["switchedsides"] ) + spawnteam = maps\mp\_utility::getOtherTeam( spawnteam ); + + if ( level.inGracePeriod ) + { + spawnPoints = maps\mp\gametypes\_spawnlogic::getSpawnpointArray( "mp_tdm_spawn_" + spawnteam + "_start" ); + spawnPoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random( spawnPoints ); + } + else + { + spawnPoints = maps\mp\gametypes\_spawnlogic::getTeamSpawnPoints( spawnteam ); + spawnPoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_NearTeam( spawnPoints ); + } + + return spawnPoint; +} + +onSpawnPlayer() +{ + self.usingObj = undefined; + level notify( "spawned_player" ); +} + +onNormalDeath( victim, attacker, lifeId ) +{ + score = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ); + attacker maps\mp\gametypes\_gamescore::giveTeamScoreForObjective( attacker.pers["team"], score ); + team = victim.team; + + if ( game["state"] == "postgame" ) + attacker.finalKill = 1; +} + +onPlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, killId ) +{ + thread checkAllowSpectating(); +} + +onTimeLimit() +{ + if ( game["status"] == "overtime" ) + winner = "forfeit"; + else if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] ) + winner = "overtime"; + else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] ) + winner = "axis"; + else + winner = "allies"; + + thread maps\mp\gametypes\_gamelogic::endGame( winner, game["strings"]["time_limit_reached"] ); +} + +checkAllowSpectating() +{ + wait 0.05; + update = 0; + + if ( !level.aliveCount[game["attackers"]] ) + { + level.spectateOverride[game["attackers"]].allowEnemySpectate = 1; + update = 1; + } + + if ( !level.aliveCount[game["defenders"]] ) + { + level.spectateOverride[game["defenders"]].allowEnemySpectate = 1; + update = 1; + } + + if ( update ) + maps\mp\gametypes\_spectating::updateSpectateSettings(); +} + +arenaFlag() +{ + level.lastStatus["allies"] = 0; + level.lastStatus["axis"] = 0; + arenaFlag = getentarray( "flag_arena", "targetname" ); + primaryFlags = getentarray( "flag_primary", "targetname" ); + secondaryFlags = getentarray( "flag_secondary", "targetname" ); + + if ( !isdefined( arenaFlag[0] ) ) + { + if ( primaryFlags.size + secondaryFlags.size < 1 ) + { + maps\mp\gametypes\_callbacksetup::AbortLevel(); + return; + } + + setupDomFlag( primaryFlags, secondaryFlags ); + } + else + level.arenaFlag = arenaFlag[0]; + + trigger = level.arenaFlag; + + if ( isdefined( trigger.target ) ) + visuals[0] = getent( trigger.target, "targetname" ); + else + { + visuals[0] = spawn( "script_model", trigger.origin ); + visuals[0].angles = trigger.angles; + } + + visuals[0] setmodel( game["flagmodels"]["neutral"] ); + + arenaFlag = maps\mp\gametypes\_gameobjects::createUseObject( "neutral", trigger, visuals, ( 0, 0, 100 ) ); + arenaFlag maps\mp\gametypes\_gameobjects::allowUse( "enemy" ); + arenaFlag maps\mp\gametypes\_gameobjects::setUseTime( 20.0 ); + arenaFlag maps\mp\gametypes\_gameobjects::setUseText( &"MP_CAPTURING_FLAG" ); + label = arenaFlag maps\mp\gametypes\_gameobjects::getLabel(); + arenaFlag.label = label; + arenaFlag maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "compass_waypoint_defend" ); + arenaFlag maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_defend" ); + arenaFlag maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "compass_waypoint_captureneutral" ); + arenaFlag maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_captureneutral" ); + arenaFlag maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" ); + arenaFlag.onUse = ::onUse; + arenaFlag.onBeginUse = ::onBeginUse; + arenaFlag.onUseUpdate = ::onUseUpdate; + arenaFlag.onEndUse = ::onEndUse; + arenaFlag.isArena = 1; + iprintlnbold( "Arena flag spawned" ); + level.arenaFlag playsound( "flag_spawned" ); + traceStart = visuals[0].origin + ( 0, 0, 32 ); + traceEnd = visuals[0].origin + ( 0, 0, -32 ); + trace = bullettrace( traceStart, traceEnd, 0, undefined ); + upangles = vectortoangles( trace["normal"] ); + arenaFlag.baseeffectforward = anglestoforward( upangles ); + arenaFlag.baseeffectright = anglestoright( upangles ); + arenaFlag.baseeffectpos = trace["position"]; + arenaFlag.levelFlag = level.arenaFlag; + level.arenaFlag = arenaFlag; +} + +setupDomFlag( primaryFlags, secondaryFlags ) +{ + for ( index = 0; index < index.size; index++ ) + { + label = primaryFlags[index].script_label; + + if ( label != "_b" ) + { + primaryFlags[index] delete(); + continue; + } + + level.arenaFlag = primaryFlags[index]; + return; + } +} + +onDeadEvent( team ) +{ + if ( team == game["attackers"] ) + level thread arena_endGame( game["defenders"], game["strings"][game["attackers"] + "_eliminated"] ); + else if ( team == game["defenders"] ) + level thread arena_endGame( game["attackers"], game["strings"][game["defenders"] + "_eliminated"] ); +} + +arena_endGame( winningTeam, endReasonText ) +{ + thread maps\mp\gametypes\_gamelogic::endGame( winningTeam, endReasonText ); +} + +giveFlagCaptureXP( touchList ) +{ + level endon( "game_ended" ); + wait 0.05; + maps\mp\_utility::WaitTillSlowProcessAllowed(); + players = getarraykeys( touchList ); + + for ( index = 0; index < players.size; index++ ) + { + player = touchList[players[index]].player; + player thread [[ level.onXPEvent ]]( "capture" ); + maps\mp\gametypes\_gamescore::givePlayerScore( "capture", player ); + player thread maps\mp\_matchdata::logGameEvent( "capture", player.origin ); + } +} + +onUse( player ) +{ + team = player.pers["team"]; + oldTeam = maps\mp\gametypes\_gameobjects::getOwnerTeam(); + label = maps\mp\gametypes\_gameobjects::getLabel(); + + player logString( "flag captured: " + self.label ); + + self.captureTime = gettime(); + maps\mp\gametypes\_gameobjects::setOwnerTeam( team ); + maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "compass_waypoint_capture" ); + maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_capture" ); + self.visuals[0] setmodel( game["flagmodels"][team] ); + + if ( oldTeam == "neutral" ) + { + otherTeam = maps\mp\_utility::getOtherTeam( team ); + thread maps\mp\_utility::printAndSoundOnEveryone( team, otherTeam, &"MP_NEUTRAL_FLAG_CAPTURED_BY", &"MP_NEUTRAL_FLAG_CAPTURED_BY", "mp_war_objective_taken", undefined, player ); + statusDialog( "secured_a", team ); + statusDialog( "enemy_has_a", otherTeam ); + } + else + thread maps\mp\_utility::printAndSoundOnEveryone( team, oldTeam, &"MP_ENEMY_FLAG_CAPTURED_BY", &"MP_FRIENDLY_FLAG_CAPTURED_BY", "mp_war_objective_taken", "mp_war_objective_lost", player ); + + thread giveFlagCaptureXP( self.touchList[team] ); + player notify( "objective", "captured" ); + thread flagCaptured( team, &"MP_DOM_NEUTRAL_FLAG_CAPTURED" ); +} + +onBeginUse( player ) +{ + ownerTeam = maps\mp\gametypes\_gameobjects::getOwnerTeam(); + self.didStatusNotify = 0; + + if ( ownerTeam == "neutral" ) + { + otherTeam = maps\mp\_utility::getOtherTeam( player.pers["team"] ); + statusDialog( "securing_a", player.pers["team"] ); + self.objPoints[player.pers["team"]] thread maps\mp\gametypes\_objpoints::startFlashing(); + statusDialog( "losing_a", otherTeam ); + return; + } + + self.objPoints["allies"] thread maps\mp\gametypes\_objpoints::startFlashing(); + self.objPoints["axis"] thread maps\mp\gametypes\_objpoints::startFlashing(); +} + +onUseUpdate( team, progress, change ) +{ + if ( progress > 0.05 && change && !self.didStatusNotify ) + { + otherTeam = maps\mp\_utility::getOtherTeam( team ); + statusDialog( "losing_a", otherTeam ); + statusDialog( "securing_a", team ); + self.didStatusNotify = 1; + } +} + +onEndUse( team, player, success ) +{ + self.objPoints["allies"] thread maps\mp\gametypes\_objpoints::stopFlashing(); + self.objPoints["axis"] thread maps\mp\gametypes\_objpoints::stopFlashing(); +} + +statusDialog( dialog, team ) +{ + if ( gettime() < level.lastStatus[team ] + 6000 ) + return; + + thread delayedLeaderDialog( dialog, team ); + level.lastStatus[team ] = gettime(); +} + +delayedLeaderDialog( sound, team ) +{ + level endon( "game_ended" ); + wait 0.1; + maps\mp\_utility::WaitTillSlowProcessAllowed(); + maps\mp\_utility::leaderDialog( sound, team ); +} + +flagCaptured( winningTeam, endReasonText ) +{ + maps\mp\gametypes\_gamelogic::endGame( winningTeam, endReasonText ); +} diff --git a/zone_raw/arena/maps/mp/gametypes/arena.gscbin b/zone_raw/arena/maps/mp/gametypes/arena.gscbin new file mode 100644 index 0000000..4d050e8 Binary files /dev/null and b/zone_raw/arena/maps/mp/gametypes/arena.gscbin differ diff --git a/zone_raw/arena/maps/mp/gametypes/arena.txt b/zone_raw/arena/maps/mp/gametypes/arena.txt new file mode 100644 index 0000000..077a2aa --- /dev/null +++ b/zone_raw/arena/maps/mp/gametypes/arena.txt @@ -0,0 +1,3 @@ +"MPUI_ARENA" +"MPUI_ARENA_RECIPE_NAME" +"MPUI_ARENA_RECIPE_DESC" diff --git a/zone_raw/arena/maps/mp/gametypes/gtnw.gsc b/zone_raw/arena/maps/mp/gametypes/gtnw.gsc new file mode 100644 index 0000000..39a6a83 --- /dev/null +++ b/zone_raw/arena/maps/mp/gametypes/gtnw.gsc @@ -0,0 +1,371 @@ +#include common_scripts\utility; +#include maps\mp\_utility; +#include maps\mp\gametypes\_hud_util; + +main() +{ + maps\mp\gametypes\_globallogic::init(); + maps\mp\gametypes\_callbacksetup::SetupCallbacks(); + maps\mp\gametypes\_globallogic::SetupCallbacks(); + + registerRoundSwitchDvar( level.gameType, 0, 0, 9 ); + registerTimeLimitDvar( level.gameType, 10 ); + setOverrideWatchDvar( "scorelimit", 0 ); + registerRoundLimitDvar( level.gameType, 1 ); + registerWinLimitDvar( level.gameType, 1 ); + registerNumLivesDvar( level.gameType, 0 ); + registerHalfTimeDvar( level.gameType, 0 ); + + level.gtnw = true; + level.teamBased = true; + level.onPrecacheGameType = ::onPrecacheGameType; + level.onStartGameType = ::onStartGameType; + level.getSpawnPoint = ::getSpawnPoint; + level.onTimeLimit = ::onTimeLimit; + level.onNormalDeath = ::onNormalDeath; + + game["dialog"]["offense_obj"] = "capture_obj"; + game["dialog"]["defense_obj"] = "capture_obj"; + game["dialog"]["gametype"] = "gtw"; + + level thread onPlayerConnect(); +} + +onPlayerConnect() +{ + for ( ;; ) + { + level waittill( "connected", player ); + player.touchingNuke = false; // Custom + player.useBar = player createPrimaryProgressBar(); + player.useBar.useTime = 100; + player.useBar hideElem(); + player.useBarText = player createPrimaryProgressBarText(); + player.useBarText setText( &"MP_CAPTURING_NUKE" ); + player.useBarText hideElem(); + } +} + +onPrecacheGameType() +{ + precacheShader( "waypoint_defend" ); + precacheShader( "waypoint_capture" ); + precacheString( &"MP_CAPTURING_NUKE" ); +} + +onStartGameType() +{ + if ( !isdefined( game["switchedsides"] ) ) + game["switchedsides"] = false; + + if ( !isdefined( game["original_defenders"] ) ) + game["original_defenders"] = game["defenders"]; + + if ( game["switchedsides"] ) + { + oldAttackers = game["attackers"]; + oldDefenders = game["defenders"]; + game["attackers"] = oldDefenders; + game["defenders"] = oldAttackers; + } + + setClientNameMode( "auto_change" ); + + setObjectiveText( game["attackers"], &"OBJECTIVES_GTNW" ); + setObjectiveText( game["defenders"], &"OBJECTIVES_GTNW" ); + setObjectiveHintText( game["attackers"], &"OBJECTIVES_GTNW_HINT" ); + setObjectiveHintText( game["defenders"], &"OBJECTIVES_GTNW_HINT" ); + setObjectiveScoreText( game["attackers"], &"OBJECTIVES_GTNW_SCORE" ); + setObjectiveScoreText( game["defenders"], &"OBJECTIVES_GTNW_SCORE" ); + + level.spawnMins = ( 0, 0, 0 ); + level.spawnMaxs = ( 0, 0, 0 ); + maps\mp\gametypes\_spawnlogic::placeSpawnPoints( "mp_ctf_spawn_allies_start" ); + maps\mp\gametypes\_spawnlogic::placeSpawnPoints( "mp_ctf_spawn_axis_start" ); + maps\mp\gametypes\_spawnlogic::addSpawnPoints( "allies", "mp_ctf_spawn_allies" ); + maps\mp\gametypes\_spawnlogic::addSpawnPoints( "axis", "mp_ctf_spawn_axis" ); + + level.mapCenter = maps\mp\gametypes\_spawnlogic::findBoxCenter( level.spawnMins, level.spawnMaxs ); + setMapCenter( level.mapCenter ); + + maps\mp\gametypes\_rank::registerScoreInfo( "kill", 50 ); + maps\mp\gametypes\_rank::registerScoreInfo( "headshot", 100 ); + maps\mp\gametypes\_rank::registerScoreInfo( "assist", 20 ); + maps\mp\gametypes\_rank::registerScoreInfo( "capture", 500 ); + + allowed[0] = "gtnw"; + allowed[1] = "dd_bombzone"; + + maps\mp\gametypes\_gameobjects::main( allowed ); + + thread setupNukeSite(); +} + +setupNukeSite() +{ + // Check for GTNW ents first, as some maps may include them. Otherwise use DD overtime bombsite. + nukeZone = getEnt( "gtnw_zone", "targetname" ); + bombZones = getEntArray( "dd_bombzone", "targetname" ); + + // Do not check here nukeZone as some maps do not include them, check bombZones + assertEx( isDefined( bombZones ), "DD Zone doesn't exist in this map" ); + + foreach ( bombZone in bombZones ) + { + visuals = getEntArray( bombZone.target, "targetname" ); + label = bombZone.script_label; + collision = getEnt( "dd_bombzone_clip" + label, "targetname" ); + + if ( isDefined( nukeZone ) || label == "_a" || label == "_b" ) + { + bombZone delete (); + visuals[0] delete (); + collision delete (); + } + + if ( !isDefined( nukeZone ) && label == "_c" ) + { + nukeZone = bombZone; + } + } + + level.lastStatus["allies"] = 0; + level.lastStatus["axis"] = 0; + + nukeSite = maps\mp\gametypes\_gameobjects::createUseObject( "neutral", nukeZone, [], ( 0, 0, 100 ) ); + nukeSite maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "waypoint_defend" ); + nukeSite maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_defend" ); + nukeSite maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "waypoint_captureneutral" ); + nukeSite maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_captureneutral" ); + nukeSite maps\mp\gametypes\_gameobjects::allowUse( "none" ); + nukeSite maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" ); + nukeSite.onBeginUse = ::onBeginUse; + nukeSite.onEndUse = ::onEndUse; + nukeSite.noUseBar = true; + nukeSite.touchRadius = 100; + nukeSite thread scoring( nukeZone.origin ); + + thread waitForNuke(); +} + +waitForNuke() +{ + level endon( "game_ended" ); + level waittill( "nuke_death" ); + team = level.nukeOwner.pers["team"]; + + thread maps\mp\gametypes\_gamelogic::endgame( team, game["strings"][getOtherTeam( team ) + "_eliminated"] ); +} + +onBeginUse( player ) +{ + player.useBar showElem(); + player.useBarText showElem(); + return; +} + +onEndUse( team, player, success ) +{ + player.useBar hideElem(); + player.useBarText hideElem(); + return; +} + +scoring( origin ) +{ + level endon( "game_ended" ); + + for ( ;; ) + { + touching["allies"] = 0; + touching["axis"] = 0; + + foreach ( player in level.players ) + { + if ( isAlive( player ) && distance2D( origin, player.origin ) < self.touchRadius ) + { + if ( !player.touchingNuke ) + { + player.startTouchTime = getTime(); + } + + player.touchingNuke = true; + touching[player.pers["team"]]++; + player.useBar showElem(); + player.useBarText showElem(); + } + else + { + if ( player.touchingNuke ) + { + player.startTouchTime = undefined; + } + + player.touchingNuke = false; + player.useBar hideElem(); + player.useBarText hideElem(); + } + } + + if ( touching["allies"] == 0 && touching["axis"] == 0 ) + { + setDvar( "ui_danger_team", "none" ); + self maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "waypoint_captureneutral" ); + self maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_captureneutral" ); + self maps\mp\gametypes\_gameobjects::setOwnerTeam( "none" ); + wait 1; + continue; + } + + self maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", "waypoint_defend" ); + self maps\mp\gametypes\_gameobjects::set3DIcon( "friendly", "waypoint_defend" ); + self maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "waypoint_capture" ); + self maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_capture" ); + + if ( touching["allies"] < touching["axis"] ) + { + if ( maps\mp\gametypes\_gamescore::_getTeamScore( "axis" ) < 100 ) + { + maps\mp\gametypes\_gamescore::giveTeamScoreForObjective( "axis", 1 ); + } + + self thread setUseBarScore( "axis" ); + setDvar( "ui_danger_team", "allies" ); + self maps\mp\gametypes\_gameobjects::setOwnerTeam( "axis" ); + + if ( maps\mp\gametypes\_gamescore::_getTeamScore( "axis" ) >= 100 ) + { + self maps\mp\gametypes\_gameobjects::allowUse( "none" ); + activateNuke( "axis" ); + return; + } + } + else if ( touching["allies"] > touching["axis"] ) + { + if ( maps\mp\gametypes\_gamescore::_getTeamScore( "allies" ) < 100 ) + { + maps\mp\gametypes\_gamescore::giveTeamScoreForObjective( "allies", 1 ); + } + + self thread setUseBarScore( "allies" ); + setDvar( "ui_danger_team", "axis" ); + self maps\mp\gametypes\_gameobjects::setOwnerTeam( "allies" ); + + if ( maps\mp\gametypes\_gamescore::_getTeamScore( "allies" ) >= 100 ) + { + self maps\mp\gametypes\_gameobjects::allowUse( "none" ); + activateNuke( "allies" ); + return; + } + } + else + { + self maps\mp\gametypes\_gameobjects::set2DIcon( "enemy", "waypoint_captureneutral" ); + self maps\mp\gametypes\_gameobjects::set3DIcon( "enemy", "waypoint_captureneutral" ); + + self maps\mp\gametypes\_gameobjects::setOwnerTeam( "none" ); + setDvar( "ui_danger_team", "contested" ); + } + + wait 1; + + } +} + +activateNuke( team ) +{ + self nukeCaptured( team ); + self maps\mp\gametypes\_gameobjects::setVisibleTeam( "none" ); + self maps\mp\gametypes\_gameobjects::allowUse( "none" ); + // Reward the player who has been on the capture for the longest recently. + bestTime = 99999999; + level.nukeOwner = undefined; + + foreach ( player in level.players ) + { + player.useBar hideElem(); + player.useBarText hideElem(); + + if ( player.team == team && player.touchingNuke ) + { + if ( player.startTouchTime < bestTime ) + { + level.nukeOwner = player; + bestTime = player.startTouchTime; + } + } + } + + assert( isDefined( level.nukeOwner ) ); + level.nukeOwner maps\mp\killstreaks\_nuke::tryUseNuke( 1 ); +} + +nukeCaptured( team ) +{ + level endon( "game_ended" ); + wait 0.05; + WaitTillSlowProcessAllowed(); + + foreach ( player in level.players ) + { + if ( player.team == team ) + { + player thread maps\mp\gametypes\_hud_message::SplashNotify( "captured_nuke", maps\mp\gametypes\_rank::getScoreInfoValue( "capture" ) ); + player thread [[level.onXPEvent]]( "capture" ); + maps\mp\gametypes\_gamescore::givePlayerScore( "capture", player ); + } + } +} + +setUseBarScore( team ) +{ + teamScore = getTeamScore( team ); + + foreach ( player in level.players ) + { + if ( player.team == team && player.touchingNuke ) + player.useBar updateBar( teamScore / 100, 0 ); + } +} + +getSpawnPoint() +{ + spawnteam = self.pers["team"]; + + if ( game["switchedsides"] ) + spawnteam = getOtherTeam( spawnteam ); + + if ( level.inGracePeriod ) + { + spawnPoints = getentarray( "mp_ctf_spawn_" + spawnteam + "_start", "classname" ); + spawnPoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random( spawnPoints ); + } + else + { + spawnPoints = maps\mp\gametypes\_spawnlogic::getTeamSpawnPoints( spawnteam ); + spawnPoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_NearTeam( spawnPoints ); + } + + return spawnPoint; +} + +onTimeLimit() +{ + if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] ) + { + thread maps\mp\gametypes\_gamelogic::endGame( "tie", game["strings"]["time_limit_reached"] ); + } + else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] ) + { + thread maps\mp\gametypes\_gamelogic::endGame( "axis", game["strings"]["time_limit_reached"] ); + } + else + { + thread maps\mp\gametypes\_gamelogic::endGame( "allies", game["strings"]["time_limit_reached"] ); + } +} + +onNormalDeath( victim, attacker, lifeId ) +{ + return; +} diff --git a/zone_raw/arena/maps/mp/gametypes/gtnw.gscbin b/zone_raw/arena/maps/mp/gametypes/gtnw.gscbin new file mode 100644 index 0000000..7080b8e Binary files /dev/null and b/zone_raw/arena/maps/mp/gametypes/gtnw.gscbin differ diff --git a/zone_raw/arena/maps/mp/gametypes/gtnw.txt b/zone_raw/arena/maps/mp/gametypes/gtnw.txt new file mode 100644 index 0000000..254302a --- /dev/null +++ b/zone_raw/arena/maps/mp/gametypes/gtnw.txt @@ -0,0 +1,3 @@ +"MPUI_GTNW" +"MPUI_GTNW_RECIPE_NAME" +"MPUI_GTNW_RECIPE_DESC" diff --git a/zone_raw/arena/mod b/zone_raw/arena/mod new file mode 100644 index 0000000..2d5958d --- /dev/null +++ b/zone_raw/arena/mod @@ -0,0 +1 @@ +Legalize Nuclear Bombs \ No newline at end of file diff --git a/zone_raw/arena/mp/basemaps.arena b/zone_raw/arena/mp/basemaps.arena new file mode 100644 index 0000000..3cfa536 --- /dev/null +++ b/zone_raw/arena/mp/basemaps.arena @@ -0,0 +1,215 @@ +{ + map "bonus_map" + longname "DLC_MAPS" + description "DLC_MAPS_DESC" + mapimage "loadscreen_mp_bonusmaps" + mappack "0" +} + +{ + map "mp_seatown" + longname "MPUI_SEATOWN" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_SEATOWN" + mapimage "preview_mp_seatown" + mapoverlay "compass_overlay_map_blank" + allieschar "sas_urban" + axischar "opforce_henchmen" + environment "desert" + mappack "0" +} + +{ + map "mp_dome" + longname "MPUI_DOME" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_DOME" + mapimage "preview_mp_dome" + mapoverlay "compass_overlay_map_blank" + allieschar "delta_multicam" + axischar "opforce_urban" + environment "desert" + mappack "0" +} + +{ + map "mp_plaza2" + longname "MPUI_ARKADEN" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_ARKADEN" + mapimage "preview_mp_plaza2" + mapoverlay "compass_overlay_map_blank" + allieschar "sas_urban" + axischar "opforce_urban" + environment "urban" + mappack "0" +} + +{ + map "mp_mogadishu" + longname "MPUI_BAKAARA" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_BAKAARA" + mapimage "preview_mp_mogadishu" + mapoverlay "compass_overlay_map_blank" + allieschar "pmc_africa" + axischar "opforce_africa" + environment "urban_militia" + mappack "0" +} + +{ + map "mp_paris" + longname "MPUI_RESISTANCE" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_RESISTANCE" + mapimage "preview_mp_paris" + mapoverlay "compass_overlay_map_blank" + allieschar "gign_paris" + axischar "opforce_urban" + environment "urban" + mappack "0" +} + +{ + map "mp_exchange" + longname "MPUI_DOWNTURN" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_DOWNTURN" + mapimage "preview_mp_exchange" + mapoverlay "compass_overlay_map_blank" + allieschar "delta_multicam" + axischar "opforce_air" + environment "urban" + mappack "0" +} + +{ + map "mp_bootleg" + longname "MPUI_BOOTLEG" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_BOOTLEG" + mapimage "preview_mp_bootleg" + mapoverlay "compass_overlay_map_blank" + allieschar "pmc_africa" + axischar "opforce_urban" + environment "urban" + mappack "0" +} + +{ + map "mp_carbon" + longname "MPUI_CARBON" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_CARBON" + mapimage "preview_mp_carbon" + mapoverlay "compass_overlay_map_blank" + allieschar "pmc_africa" + axischar "opforce_africa" + environment "forest_militia" + mappack "0" +} + +{ + map "mp_hardhat" + longname "MPUI_HARDHAT" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_HARDHAT" + mapimage "preview_mp_hardhat" + mapoverlay "compass_overlay_map_blank" + allieschar "delta_multicam" + axischar "opforce_air" + environment "urban" + mappack "0" +} + +{ + map "mp_alpha" + longname "MPUI_LOCKDOWN" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_LOCKDOWN" + mapimage "preview_mp_alpha" + mapoverlay "compass_overlay_map_blank" + allieschar "delta_multicam" + axischar "opforce_urban" + environment "urban" + mappack "0" +} + +{ + map "mp_village" + longname "MPUI_VILLAGE" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_VILLAGE" + mapimage "preview_mp_village" + mapoverlay "compass_overlay_map_blank" + allieschar "pmc_africa" + axischar "opforce_africa" + environment "forest_militia" + mappack "0" +} + +{ + map "mp_lambeth" + longname "MPUI_FALLEN" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_FALLEN" + mapimage "preview_mp_lambeth" + mapoverlay "compass_overlay_map_blank" + allieschar "delta_multicam" + axischar "opforce_woodland" + environment "forest" + mappack "0" +} + +{ + map "mp_radar" + longname "MPUI_OUTPOST" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_OUTPOST" + mapimage "preview_mp_radar" + mapoverlay "compass_overlay_map_blank" + allieschar "delta_multicam" + axischar "opforce_snow" + environment "arctic" + mappack "0" +} + +{ + map "mp_interchange" + longname "MPUI_INTERCHANGE" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_INTERCHANGE" + mapimage "preview_mp_interchange" + mapoverlay "compass_overlay_map_blank" + allieschar "delta_multicam" + axischar "opforce_woodland" + environment "urban" + mappack "0" +} + +{ + map "mp_underground" + longname "MPUI_UNDERGROUND" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_UNDERGROUND" + mapimage "preview_mp_underground" + mapoverlay "compass_overlay_map_blank" + allieschar "sas_urban" + axischar "opforce_air" + environment "urban" + mappack "0" +} + +{ + map "mp_bravo" + longname "MPUI_MISSION" + gametype "dm war sab sab2 dom sd sd2 hc thc ctf koth arena gtnw" + description "MPUI_DESC_MAP_MISSION" + mapimage "preview_mp_bravo" + mapoverlay "compass_overlay_map_blank" + allieschar "pmc_africa" + axischar "opforce_africa" + environment "forest_militia" + mappack "0" +} diff --git a/zone_raw/arena/mp/perktable.csv b/zone_raw/arena/mp/perktable.csv new file mode 100644 index 0000000..230f4cd --- /dev/null +++ b/zone_raw/arena/mp/perktable.csv @@ -0,0 +1,89 @@ +a0,b1,c2,d3,e4,f5,g6,h7,i8,j9 +0,specialty_null,PERKS_NONE,specialty_ks_null,PERKS_NONE,,,,specialty_null,PERKS_NONE +1,specialty_longersprint,PERKS_LONGERSPRINT,specialty_longersprint,PERKS_DESC_LONGERSPRINT,perk1,,,specialty_fastmantle,PERKS_LONGERSPRINT_PRO +2,specialty_fastreload,PERKS_SLEIGHT_OF_HAND,specialty_fastreload,PERKS_DESC_SLEIGHT_OF_HAND,perk1,,,specialty_quickswap,PERKS_SLEIGHT_OF_HAND_PRO +3,specialty_scavenger,PERKS_SCAVENGER,specialty_scavenger,PERKS_DESC_SCAVENGER,perk1,,,specialty_extraammo,PERKS_SCAVENGER_PRO +4,specialty_blindeye,PERKS_BLINDEYE,specialty_blindeye,PERKS_DESC_BLINDEYE,perk1,,,specialty_fasterlockon,PERKS_BLINDEYE_PRO +5,specialty_paint,PERKS_PAINT,specialty_paint,PERKS_DESC_PAINT,perk1,,,specialty_paint_pro,PERKS_PAINT_PRO +6,specialty_hardline,PERKS_HARDLINE,specialty_hardline,PERKS_DESC_HARDLINE,perk2,,,specialty_rollover,PERKS_HARDLINE_PRO +7,specialty_coldblooded,PERKS_ASSASSIN,specialty_coldblooded,PERKS_DESC_ASSASSIN,perk2,,,specialty_spygame,PERKS_ASSASSIN_PRO +8,specialty_heartbreaker,PERKS_ASSASSIN,specialty_coldblooded,PERKS_DESC_HEARTBREAKER,slot_null,,,specialty_null,PERKS_NONE +9,specialty_quickdraw,PERKS_QUICKDRAW,specialty_quickdraw,PERKS_DESC_QUICKDRAW,perk2,,,specialty_fastoffhand,PERKS_QUICKDRAW_PRO +10,specialty_twoprimaries,PERKS_OVERKILL,specialty_twoprimaries,PERKS_DESC_OVERKILL,perk2,,,specialty_overkillpro,PERKS_OVERKILL_PRO +11,_specialty_blastshield,PERKS_BLASTSHIELD,specialty_blastshield,PERKS_DESC_BLASTSHIELD,perk2,,,specialty_stun_resistance,PERKS_BLASTSHIELD_PRO +12,specialty_detectexplosive,PERKS_BOMB_SQUAD,specialty_bombsquad,PERKS_DESC_BOMB_SQUAD,perk3,,,specialty_selectivehearing,PERKS_BOMB_SQUAD_PRO +13,specialty_autospot,PERKS_IRON_LUNGS,specialty_ironlungs,PERKS_DESC_IRON_LUNGS,perk3,,,specialty_holdbreath,PERKS_IRON_LUNGS_PRO +14,specialty_bulletaccuracy,PERKS_STEADY_AIM,specialty_steadyaim,PERKS_DESC_STEADY_AIM,perk3,,,specialty_fastsprintrecovery,PERKS_STEADY_AIM_PRO +15,specialty_steadyaimpro,PERKS_STEADY_AIM,specialty_steadyaim_upgrade,PERKS_DESC_STEADY_AIM,slot_null,,,specialty_null,PERKS_NONE +16,specialty_quieter,PERKS_DEADSILENCE,specialty_quieter,PERKS_DESC_DEADSILENCE,perk3,,,specialty_falldamage,PERKS_DEADSILENCE_PRO +17,specialty_stalker,PERKS_STALKER,specialty_stalker,PERKS_DESC_STALKER,perk3,,,specialty_delaymine,PERKS_STALKER_PRO +18,specialty_fastmantle,PERKS_LONGERSPRINT_PRO,specialty_longersprint_upgrade,PERKS_UPGRADE_LONGERSPRINT,upgrade1,,,specialty_null,PERKS_NONE +19,specialty_quickswap,PERKS_SLEIGHT_OF_HAND_PRO,specialty_fastreload_upgrade,PERKS_UPGRADE_SLEIGHT_OF_HAND,upgrade1,,,specialty_null,PERKS_NONE +20,specialty_extraammo,PERKS_SCAVENGER_PRO,specialty_scavenger_upgrade,PERKS_UPGRADE_SCAVENGER,upgrade1,,,specialty_null,PERKS_NONE +21,specialty_fasterlockon,PERKS_BLINDEYE_PRO,specialty_blindeye_upgrade,PERKS_UPGRADE_BLINDEYE,upgrade1,,,specialty_null,PERKS_NONE +22,specialty_armorpiercing,PERKS_BLINDEYE_PRO,specialty_blindeye_upgrade,PERKS_UPGRADE_BLINDEYE,upgrade1,,,specialty_null,PERKS_NONE +23,specialty_paint_pro,PERKS_PAINT_PRO,specialty_paint_upgrade,PERKS_UPGRADE_PAINT,upgrade1,,,specialty_null,PERKS_NONE +24,specialty_rollover,PERKS_HARDLINE_PRO,specialty_hardline_upgrade,PERKS_UPGRADE_HARDLINE,upgrade2,,,specialty_null,PERKS_NONE +25,specialty_assists,PERKS_HARDLINE_PRO,specialty_hardline_upgrade,PERKS_UPGRADE_HARDLINE,upgrade2,,,specialty_null,PERKS_NONE +26,specialty_spygame,PERKS_ASSASSIN_PRO,specialty_coldblooded_upgrade,PERKS_UPGRADE_ASSASSIN,upgrade2,,,specialty_null,PERKS_NONE +27,specialty_empimmune,PERKS_ASSASSIN_PRO,specialty_coldblooded_upgrade,PERKS_UPGRADE_ASSASSIN,upgrade2,,,specialty_null,PERKS_NONE +28,specialty_fastoffhand,PERKS_QUICKDRAW_PRO,specialty_quickdraw_upgrade,PERKS_UPGRADE_QUICKDRAW,upgrade2,,,specialty_null,PERKS_NONE +29,specialty_overkillpro,PERKS_OVERKILL_PRO,specialty_twoprimaries_upgrade,PERKS_UPGRADE_OVERKILL,upgrade2,,,specialty_null,PERKS_NONE +30,specialty_stun_resistance,PERKS_BLASTSHIELD_PRO,specialty_blastshield_upgrade,PERKS_UPGRADE_BLASTSHIELD,upgrade2,,,specialty_null,PERKS_NONE +31,specialty_holdbreath,PERKS_IRON_LUNGS_PRO,specialty_ironlungs_upgrade,PERKS_UPGRADE_IRON_LUNGS,upgrade3,,,specialty_null,PERKS_NONE +32,specialty_selectivehearing,PERKS_BOMB_SQUAD_PRO,specialty_bombsquad_upgrade,PERKS_UPGRADE_BOMB_SQUAD,upgrade3,,,specialty_null,PERKS_NONE +33,specialty_fastsprintrecovery,PERKS_STEADY_AIM_PRO,specialty_steadyaim_upgrade,PERKS_UPGRADE_STEADY_AIM,upgrade3,,,specialty_null,PERKS_NONE +34,specialty_falldamage,PERKS_DEADSILENCE_PRO,specialty_quieter_upgrade,PERKS_UPGRADE_DEADSILENCE,upgrade3,,,specialty_null,PERKS_NONE +35,specialty_delaymine,PERKS_STALKER_PRO,specialty_stalker_upgrade,PERKS_UPGRADE_STALKER,upgrade3,,,specialty_null,PERKS_NONE +36,throwingknife_mp,PERKS_KNIFETHROW,equipment_throwing_knife,PERKS_DESC_KNIFETHROW,equipment,,,specialty_null, +37,c4_mp,PERKS_C4,equipment_c4,PERKS_REMOTE_DETONATION_EXPLOSIVE,equipment,2,,specialty_null, +38,claymore_mp,PERKS_CLAYMORE,equipment_claymore,PERKS_TRIP_ACTIVATED_EXPLOSIVE,equipment,2,,specialty_null, +39,frag_grenade_mp,PERKS_FRAG_X_1,equipment_frag,PERKS_DESC_FRAG_X1,equipment,2,,specialty_null, +40,semtex_mp,PERKS_SEMTEX,equipment_semtex,PERKS_DESC_SEMTEX,equipment,,,specialty_null, +41,bouncingbetty_mp,PERKS_BOUNCINGBETTY,equipment_bouncing_betty,PERKS_DESC_BOUNCINGBETTY,equipment,,,specialty_null, +42,specialty_tacticalinsertion,PERKS_TACTICALINSERTION,equipment_flare,PERKS_DESC_TACTICALINSERTION,equipment,1,,specialty_null, +43,trophy_mp,PERKS_TROPHY,equipment_trophy,PERKS_DESC_TROPHY,equipment,1,,specialty_null, +44,smoke_grenade_mp,PERKS_SMOKE_GRENADE,equipment_smoke_grenade,PERKS_DESC_SMOKE_GRENADE,equipment,2,,specialty_null, +45,emp_grenade_mp,PERKS_EMP_GRENADE,equipment_emp_grenade,PERKS_DESC_EMP_GRENADE,equipment,2,,specialty_null, +46,flash_grenade_mp,PERKS_FLASH_GRENADE,equipment_flash_grenade,PERKS_DESC_FLASH_GRENADE,equipment,2,,specialty_null, +47,concussion_grenade_mp,PERKS_CONCUSSION_GRENADE,equipment_concussion_grenade,PERKS_DESC_CONCUSSION_GRENADE,equipment,2,,specialty_null, +48,specialty_scrambler,PERKS_SCRAMBLER_ITEM,equipment_scrambler,PERKS_DESC_SCRAMBLER_ITEM,equipment,1,,specialty_null, +49,specialty_portable_radar,PERKS_PORTABLE_RADAR_ITEM,equipment_portable_radar,PERKS_DESC_PORTABLE_RADAR_ITEM,equipment,1,,specialty_null, +50,specialty_revenge,PERKS_REVENGE,specialty_revenge,PERKS_DESC_REVENGE,perk4,5,,specialty_null, +51,specialty_grenadepulldeath,PERKS_MARTYRDOM,specialty_grenadepulldeath,PERKS_DROP_A_LIVE_GRENADE_WHEN,perk4,4,,specialty_null, +52,specialty_c4death,PERKS_C4DEATH,specialty_c4death,PERKS_DESC_C4DEATH,perk4,6,,specialty_null, +53,specialty_finalstand,PERKS_FINALSTAND,specialty_finalstand,PERKS_DESC_FINALSTAND,perk4,4,,specialty_null, +54,specialty_juiced,PERKS_JUICED,specialty_juiced,PERKS_DESC_JUICED,perk4,4,,specialty_null, +55,specialty_uav,PERKS_UAV,specialty_uav,PERKS_DESC_UAV,perk4,6,,specialty_null, +56,specialty_stopping_power,PERKS_STOPPING_POWER,specialty_stopping_power,PERKS_DESC_STOPPING_POWER,perk4,5,,specialty_null, +57,streaktype_assault,PERKS_ASSAULT,streaktype_assault,PERKS_DESC_ASSAULT,perk5,,,specialty_null, +58,streaktype_support,PERKS_SUPPORT,streaktype_support,PERKS_DESC_SUPPORT,perk5,,,specialty_null, +59,streaktype_specialist,PERKS_SPECIALIST,streaktype_specialist,PERKS_DESC_SPECIALIST,perk5,,,specialty_null, +60,specialty_bulletpenetration,PERKS_DEEP_IMPACT,specialty_bulletpenetration,PERKS_DESC_DEEP_IMPACT,proficiency,,,specialty_null, +61,specialty_marksman,PERKS_MARKSMAN,specialty_marksman,PERKS_DESC_MARKSMAN,proficiency,,,specialty_null, +62,specialty_sharp_focus,PERKS_SHARPFOCUS,specialty_sharp_focus,PERKS_DESC_SHARPFOCUS,proficiency,,,specialty_null, +63,specialty_bling,PERKS_BLING,specialty_bling,PERKS_DESC_BLING,proficiency,,,specialty_null, +64,specialty_secondarybling,PERKS_SECONDARY_BLING,specialty_bling_upgrade,PERKS_DESC_SECONDARY_BLING,slot_null,,,specialty_null, +65,specialty_pistoldeath,PERKS_LAST_STAND,specialty_pistoldeath,PERKS_PULL_OUT_YOUR_PISTOL,slot_null,,,specialty_null, +66,specialty_armorvest,PERKS_JUGGERNAUT,specialty_armorvest,PERKS_INCREASED_HEALTH,slot_null,,,specialty_null, +67,specialty_bulletdamage,PERKS_STOPPING_POWER,specialty_bulletdamage,PERKS_INCREASED_BULLET_DAMAGE,slot_null,,,specialty_null, +68,specialty_light_armor,PERKS_LIGHT_ARMOR,specialty_light_armor,PERKS_DESC_LIGHT_ARMOR,slot_null,,,specialty_null, +69,specialty_holdbreathwhileads,PERKS_HOLDBREATHWHILEADS,specialty_holdbreathwhileads,PERKS_DESC_HOLDBREATHWHILEADS,proficiency,,,specialty_null, +70,specialty_longerrange,PERKS_LONGERRANGE,specialty_longerrange,PERKS_DESC_LONGERRANGE,proficiency,,,specialty_null, +71,specialty_fastermelee,PERKS_FASTERMELEE,specialty_fastmeleerecovery,PERKS_DESC_FASTERMELEE,proficiency,,,specialty_null, +72,specialty_reducedsway,PERKS_REDUCEDSWAY,specialty_reducedsway,PERKS_DESC_REDUCEDSWAY,proficiency,,,specialty_null, +73,specialty_lightweight,PERKS_LIGHTWEIGHT,specialty_lightweight,PERKS_DESC_LIGHTWEIGHT,proficiency,,,specialty_null, +74,specialty_moredamage,PERKS_MOREDAMAGE,specialty_moredamage,PERKS_DESC_MOREDAMAGE,proficiency,,,specialty_null, +75,specialty_radarblip,,,,slot_null,,,, +76,specialty_radararrow,,,,slot_null,,,, +77,specialty_radarjuggernaut,,,,slot_null,,,, +78,specialty_marathon,PERKS_MARATHON,specialty_marathon,PERKS_DESC_MARATHON,perk1,,,specialty_fastmantle,PERKS_MARATHON_PRO +79,specialty_jumpdive,PERKS_JUMPDIVE,specialty_jumpdive,PERKS_DESC_JUMPDIVE,slot_null,,,specialty_null, +perk1,0.3333,0.4941,0.6196,,,,,, +perk2,0.5255,0.5686,0.3804,,,,,, +perk3,0.6196,0.3373,0.3373,,,,,, +perk4,1,0.5,0,,,,,, +equipment,1,0.8,0.4,,,,,, +upgrade1,1,0.8,0.4,,,,,, +upgrade2,1,0.8,0.4,,,,,, +upgrade3,1,0.8,0.4,,,,,, diff --git a/zone_raw/arena/mp/recipes/arena.recipe b/zone_raw/arena/mp/recipes/arena.recipe new file mode 100644 index 0000000..01aa951 Binary files /dev/null and b/zone_raw/arena/mp/recipes/arena.recipe differ diff --git a/zone_raw/arena/mp/recipes/gtnw.recipe b/zone_raw/arena/mp/recipes/gtnw.recipe new file mode 100644 index 0000000..01aa951 Binary files /dev/null and b/zone_raw/arena/mp/recipes/gtnw.recipe differ diff --git a/zone_raw/arena/zone_source/arena.zone b/zone_raw/arena/zone_source/arena.zone new file mode 100644 index 0000000..d3053ba --- /dev/null +++ b/zone_raw/arena/zone_source/arena.zone @@ -0,0 +1,28 @@ +// Call Of Duty: Modern Warfare 3 +>game,IW5 +>name,mod + +localize,mod + +// Add custom gamemodes +rawfile,maps/mp/gametypes/_gametypes.txt + +// Gamemode scripts +scriptfile,maps/mp/gametypes/arena +scriptfile,maps/mp/gametypes/gtnw + +// Copied from war.recipe +rawfile,mp/recipes/arena.recipe +rawfile,mp/recipes/gtnw.recipe + +// Maybe we don't need this +rawfile,mp/basemaps.arena + +// UI Loc strings +rawfile,maps/mp/gametypes/arena.txt +rawfile,maps/mp/gametypes/gtnw.txt + +// For testing +stringtable,mp/perktable.csv + +rawfile,mod