// Training Script //echo("Running Training Script"); datablock AudioProfile(TrainingHudUpdateSound) { filename = "gui/objective_notification.wav"; description = AudioDefault3d; preload = true; }; datablock AudioProfile(MessageRecieveSound) { filename = "gui/objective_notification.wav"; description = AudioDefault3d; preload = true; }; // for training5 datablock ForceFieldBareData(defaultNoTeamLavaLightField) { fadeMS = 1000; baseTranslucency = 1; powerOffTranslucency = 0; teamPermiable = false; otherPermiable = false; color = "1.0 0.4 0.0"; targetTypeTag = 'ForceField'; texture[0] = "skins/forcef1"; texture[1] = "skins/forcef2"; texture[2] = "skins/forcef3"; texture[3] = "skins/forcef4"; texture[4] = "skins/forcef5"; framesPerSec = 10; numFrames = 5; scrollSpeed = 15; umapping = 1.0; vmapping = 0.15; }; // load the voice text and wav file exec("scripts/spDialog.cs"); function setSinglePlayerGlobals() { // server settings //$MPRestoreBotCount = $Host::BotCount; this one is done automatically in server.cs $MPRestoreBotMatchBotCount = $Host::BotMatchBotCount; $MPRestoreBotsEnabled = $Host::BotsEnabled; $MPRestoreMaxBotDifficulty = $Host::MaxBotDifficulty; $MPRestoreMaxPlayers = $Host::MaxPlayers; $MPRestoreMinBotDifficulty = $Host::MinBotDifficulty; $MPRestoreTimeLimit = $Host::TimeLimit; $MPRestoreTournamentMode = $Host::TournamentMode; $MPRestorewarmupTime = $Host::warmupTime; $MPRestoreTeamDamage = $teamDamage; //$Host::BotCount = "0"; $Host::BotMatchBotCount = "0"; $Host::BotsEnabled = "0"; $Host::MaxBotDifficulty = "1"; $Host::MaxPlayers = "64"; $Host::MinBotDifficulty = "0"; $Host::TimeLimit = "9999999"; $Host::TournamentMode = "false"; $Host::warmupTime = "0"; if($pref::trainingDifficulty < 1 || $pref::trainingDifficulty > 3) $pref::trainingDifficulty = 1; if($pref::trainingDifficulty == 1) $teamDamage = false; else $teamDamage = true; // game settings $MPRestoreteamSkin[1] = $teamSkin[1]; $MPRestoreteamName[1] = $teamName[1]; $MPRestoreholoName[1] = $holoName[1]; $MPRestoreswitchSkin[1] = $switchSkin[1]; $MPRestoreteamSkin[2] = $teamSkin[2]; $MPRestoreteamName[2] = $teamName[2]; $MPRestoreholoName[2] = $holoName[2]; $MPRestoreswitchSkin[2] = $switchSkin[2]; $playerTeam = 1; $teamSkin[$playerTeam] = 'swolf'; $teamName[$playerTeam] = 'StarWolf'; $holoName[$playerTeam] = "StarWolf"; $switchSkin[$playerTeam] = 'swolf'; $playerLivesAtEasy = 3; $EnemyTeam = 2; $teamSkin[$EnemyTeam] = 'Horde'; $teamName[$EnemyTeam] = 'Bioderm Horde'; // $holoName[$enemyTeam] = "Bioderm"; // $switchSkin[$enemyTeam] = 'Bioderm'; if($enemyName $= "") $EnemyName = "Enemy"; $trainingDefenseTauntList = "bas.enemy slf.att.attack slf.def.defend wrn.enemy tgt.acquired gbl.brag slf.def.base vqk.help"; $trainingOffenseTauntList = "slf.att.attack gbl.brag vqk.help att.distract att.attack ene.disarray glb.awesome need.cover"; } function resetSinglePlayerGlobals() { //error("================ single player global vars reset!"); // server settings //$Host::BotCount = $MPRestoreBotCount; $Host::BotMatchBotCount = $MPRestoreBotMatchBotCount; $Host::BotsEnabled = $MPRestoreBotsEnabled; $Host::MaxBotDifficulty = $MPRestoreMaxBotDifficulty; $Host::MaxPlayers = $MPRestoreMaxPlayers; $Host::MinBotDifficulty = $MPRestoreMinBotDifficulty; $Host::TimeLimit = $MPRestoreTimeLimit; $Host::TournamentMode = $MPRestoreTournamentMode; $Host::warmupTime = $MPRestorewarmupTime; $teamDamage = $MPRestoreTeamDamage; // game settings $teamSkin[1] = $MPRestoreteamSkin[1]; $teamName[1] = $MPRestoreteamName[1]; $holoName[1] = $MPRestoreholoName[1]; $switchSkin[1] = $MPRestoreswitchSkin[1]; $teamSkin[2] = $MPRestoreteamSkin[2]; $teamName[2] = $MPRestoreteamName[2]; $holoName[2] = $MPRestoreholoName[2]; $switchSkin[2] = $MPRestoreswitchSkin[2]; } // Actors //======================================================================================= function addEnemies() { %num = $numberOfEnemies[$pref::TrainingDifficulty]; error("Adding " @ %num @" enemies!"); %group = nameToId("MissionGroup/Teams/Team2/DropPoints"); for(%i = 0; %i < %num; %i++){ %name = getUniqueEnemyName(); %voice = "Derm"@getRandom(1,3); %voicePitch = 1 - ((getRandom(20) - 10)/100); //%client = AIConnect($EnemyName@%i, $EnemyTeam, $missionBotSkill[$pref::TrainingDifficulty], true); %client = AIConnect(%name, $EnemyTeam, $missionBotSkill[$pref::TrainingDifficulty], true, %voice, %voicePitch); $Enemy[%i] = %client; %client.race = "Bioderm"; setTargetSkin(%client.target, $teamSkin[$enemyTeam]); //setTargetVoice(%client.target, addTaggedString(%client.voice)); //error("Setting race of "@$Enemy[%i]@" to "@$Enemy[%i].race); if(%group.getObject(%i).Equipment || %group.getObject(%i).specialObjectives) { %client.equipment = %group.getObject(%i).Equipment; //error("Client: "@%client@ " has equipment "@%client.equipment); %client.SpecialObjectives = %group.getObject(%i).SpecialObjectives; //error("Client: "@%client@ " has specialEd "@%client.SpecialObjectives); game.equip(%client.player); } // this seems redundant after equip %client.player.setArmor(%client.armor); } } // there are times (missions 2 and 4) where bots are not added with // addEnemies(). there are x waves of bots with y number in each wave // i do it a couple of times so im going to localize it here rather than // do it twice or cut and paste it function spawnWave(%wave) { for(%i=1; %i<=$numberInWave[$pref::TrainingDifficulty]; %i++) { %name = getUniqueEnemyName(); %voice = "Derm"@getRandom(1,3); %voicePitch = 1 - ((getRandom(20) - 10)/100); %thisAi = aiConnect(%name, $enemyTeam, $missionBotSkill[$pref::TrainingDifficulty], false, %voice, %voicePitch); //%thisAi = aiConnect("Wave"@%wave@"num"@%i, $enemyTeam, $missionBotSkill[$pref::TrainingDifficulty], false); // here we differentiate the different drop points for wave spawned bots (these spawned bots are "!offense") //error("added enemy "@%thisAi); %thisAi.race = "Bioderm"; %thisAi.voice = "Derm"@getRandom(3); setTargetSkin(%thisAI.target, $teamSkin[$enemyTeam]); setTargetVoice(%thisAI.target, addTaggedString(%thisAI.voice)); %equipment = pickEquipment(); game.equip(%thisAi.player, %equipment); //%client.player.setArmor(%thisAi.armor); //create a little group game.NumberInWave[%wave]++; %thisAI.MemberOfWave = %wave; //anything mission specific that has to be done with this client missionSpawnedAI(%thisAi); } game.spawnWaveTimer = spawnWaveTimer(%wave, false); } function addPlayersTeam(%num) { //echo($player.team@"<---------players team on addPlayerTeam"); getTeammateGlobals(); for(%i=0; %i< %num; %i++){ $Teammate[%i] = %client = AIConnect($TeammateWarnom[%i], $playerTeam, $teammateSkill[%i], true, $teammateVoice[%i]); %client.sex = $teammateGender[%i]; %client.equipment = $teammateEquipment[%i]; setTargetSkin(%client.target, $teamSkin[$playerTeam]); game.equip(%client.player); %client.player.setArmor(%client.armor); if (! %client.defaultTasksAdded) { %client.defaultTasksAdded = true; %client.addTask(AIEngageTask); %client.addTask(AIPickupItemTask); %client.addTask(AIUseInventoryTask); %client.addTask(AIEngageTurretTask); %client.addtask(AIDetectMineTask); } } //add Player=============================================================== $player.lives = $playerLivesAtEasy - $pref::TrainingDifficulty; game.spawnPlayer($player, false); setTargetSkin($player.target, $teamSkin[$playerTeam]); } function getUniqueEnemyName() { if(!$enemyNameCount) return; %used = false; %name = pickUniqueEnemyName(); %used = enemyNameIsUsed(%name); while(%used) { if(%emergency++ > 1000) { //error("Too many times in the name while loop...using DEFAULT"); return $enemyName; } %name = pickUniqueEnemyName(); %used = enemyNameIsUsed(%name); } return %name; } function pickUniqueEnemyName() { %random = getRandom(1, $enemyNameCount); %name = $EnemyNameList[%random]; //error("returning" SPC %name SPC "from pick"); return %name; } function enemyNameIsUsed(%name) { %number = game.usedNameCount; for(%i = 0; %i <= %number; %i++) { if(game.usedName[%i] $= %name) return true; } // the name is unused game.usedName[game.usedNameCount++] = %name; return false; } function spawnWaveTimer(%wave, %reset) { //error("SpawnTimer ACTIVATED"); if(%reset) { cancel(game.spawnWaveTimer); %timeForAction = 60000 * 5; //5 min } else %timeForAction = 60000 * 5; //5 min game.spawnWaveTimer = schedule(%timeForAction, game, destroyWave, %wave); } function DestroyWave(%wave) { // this group has enemies in it that are dawdling and // need to be killed to keep the game progressing %num = clientGroup.getCount(); for(%i = 0; %i < %num; %i++) { %client = clientGroup.getObject(%i); if(%client.player && %client.MemberOfWave == %wave) { %client.player.applyDamage(%client.player.getDataBlock().maxDamage); enemyWaveMemberKilled(%client); } } } function SinglePlayerGame::onClientKilled(%game, %clVictim, %clKiller, %damageType, %implement) { if(game.missionOver) return; %clVictim.dead = true; if(%clvictim.team == $enemyTeam && getRandom(1,1000) == 69) doText(Any_jingo02); missionClientKilled(%clVictim, %clKiller); if(%clVictim.MemberOfWave) enemyWaveMemberKilled(%clVictim ); Parent::onClientKilled(%game, %clVictim, %clKiller, %damageType, %implement); cancel(%clVictim.respawnTimer); if(%clVictim == $player) { // dead players are not out of bounds cancel($player.OOB); $player.deaths++; %num = $player.lives; if( %num >= 1) { if(%num == 1) %textNum = "one life"; else %textNum = %num SPC "lives"; messageBoxOk("Restart", "You have" SPC %textNum SPC "remaining.", "spawnSinglePlayer();"); } else schedule(3000, $player.player, singlePlayerDead); } } function enemyWaveMemberKilled(%client) { %wave = %client.MemberOfWave; %remaining = game.numberInWave[%wave]--; //error("Debug: Script reports that client " @ %client @ " was a member of wave " @ %wave @ " that now has " @ %remaining @ " members remaining."); if(%remaining == 0) { missionWaveDestroyed(%wave); if (%wave+1 <= $numberOfWaves[$pref::TrainingDifficulty]) spawnWave(%wave+1); //else error("Debug: " @ %wave @ " was the last wave."); } } function SinglePlayerGame::assignClientTeam(%game, %client) { // The players team is set in singlePlayer::clientMissionDropReady // and the bots are added to a team with aiConnect // so this is unnecessary } function singlePlayerGame::AIHasJoined() { // Big deal...my missions are crawling with AI // lets get rid of this mundane console spam } function SinglePlayerGame::updateKillScores() { // Do nothing other than get rid of the console warning... } function singlePlayerGame::biodermAssume(%game, %client) { //error(%client SPC "might talk."); // dont do anything if we have just done this if(%client.spgSpeaking) return; %probability = 2; %time = 30; // secs // we are going to POSSIBLY talk. flag it for %time secs %client.spgSpeaking = true; schedule(%time * 1000, %client, resetSpeakingFlag, %client); if(getRandom(%probability) == 1) trainingBiodermSpeaks(%client); } function resetSpeakingFlag(%client) { //error(%client SPC "can now speak again."); %client.spgSpeaking = false; } function trainingBiodermSpeaks(%client) { if(%client.offense) // offense = defense? %tauntlist = $trainingDefenseTauntList; //yes this seem wrong but its not else %tauntlist = $trainingOffenseTauntList; %num = getWordCount(%tauntList); %random = getRandom(%num - 1); %use = getWord(%tauntList, %random); //echo("Derm taunting:" SPC %use); playTargetAudio( %client.target, addTaggedString(%use), AudioClose3d, false ); } function singlePlayerDead() { missionFailed($player.miscMsg[trainingDeathLoss]); AIMissionEnd(); $objectiveQ[$enemyTeam].clear(); cancel($player.distanceCheckSchedule); } function SinglePlayerGame::missionLoadDone(%game) { DefaultGame::missionLoadDone(%game); setSinglePlayerGlobals(); $matchStarted = true; //this has to happen sometime because game.startMatch never gets called %game.clearDeployableMaxes(); } function SinglePlayerGame::notifyMatchStart(%game, %time) { //do nothing } function SinglePlayerGame::clientMissionDropReady(%game, %client) { DefaultGame::clientMissionDropReady(%game, %client); //echo(%client @ " is single player Ready!!!"); messageClient(%client, 'MsgClientReady', "", %game.class); $Player = %client; $player.race = "Human"; $player.team = $playerTeam; $player.setTeam($playerTeam); setTargetSkin($teammate[%i].target, $teamSkin[$playerTeam]); createText($player); HUDMessageVector.clear(); messageClient(%client, 'MsgMissionDropInfo', "", $MissionDisplayName, $MissionTypeDisplayName, $ServerName ); // We don't start in observer mode, so disable: commandToClient(%client, 'setHudMode', 'Standard'); //custom training keymap %game.createCustomKeyMap(); addEnemies(); //echo($player.team@"<---------players team on mission drop ready"); addPlayersTeam($numberOfTeammates); //everybody's in, enable the AI system AISystemEnabled(true); $player.setControlObject( $player.player ); $player.camera = new Camera() { dataBlock = Observer; }; startCurrentMission(%game); } function SinglePlayerGame::AIInit(%game) { //error("initializing Bot Q's for SinglePlayerGame..."); for (%i = 0; %i <= %game.numTeams; %i++) { if (!isObject($ObjectiveQ[%i])) { $ObjectiveQ[%i] = new AIObjectiveQ(); MissionCleanup.add($ObjectiveQ[%i]); } //error("team " @ %i @ " objectives load..."); $ObjectiveQ[%i].clear(); AIInitObjectives(%i, %game); } AIInit(); // Bots never throw grenades on Easy skills if($pref::TrainingDifficulty == 1) $AIDisableGrenades = true; } // unlike the MP game, sometimes we start with switches (flipFlops) // already on one team or the other and they are unskinned function setFlipFlopSkins(%group) { if(!%group) %group = nameToID("Teams"); for(%i = 0; %i < %group.getCount(); %i++) { %this = %group.getObject(%i); if(%this.getClassName() $= "SimGroup") setFlipFlopSkins(%this); else if(%this.getDataBlock().getName() $= "FlipFlop") setTargetSkin(%this.getTarget(), $teamSkin[%this.team]); } } function singlePlayerGame::gameOver(%game) { moveMap.push(); ServerConnection.setBlackOut(false, 0); $timeScale = 1; game.missionOver = true; // clear the inventory and weapons hud error("clearing Inv HUD"); $player.SetInventoryHudClearAll(); // im gonna try dropping all the clients %count = clientGroup.getCount(); echo("count=" SPC %count); for(%i = 0; %i < %count; %i++) { %client = clientGroup.getObject(%i); game.client[%i] = %client; freeClientTarget(%client); } for(%i = 0; %i < %count; %i++) { %client = game.client[%i]; echo("client=" SPC %client); if(%client.isAIControlled()) %client.drop(); } //disable the AI system AISystemEnabled(false); $AIDisableChatResponse = ""; game.deactivatePackages(); if(isObject( $player.currentWaypoint )) $player.currentWaypoint.delete(); if($player.OOB) cancel($player.OOB); // clear the objective HUD messageClient($player, 'MsgClearObjHud', ""); resetSinglePlayerGlobals(); $currentMissionType = ""; DefaultGame::GameOver(%game); } function singlePlayerGame::deactivatePackages(%game) { error("singlePlayerGame packages deactivated"); //Deactivate packages...gotta catch'm all //deactivatepackage(SinglePlayer); deactivatepackage(Training1); deactivatepackage(Training2); deactivatepackage(Training3); deactivatepackage(Training4); deactivatepackage(Training5); deactivatepackage(Training6); deactivatePackage(singlePlayerMissionAreaEnforce); } //------------------------------------------------------------------------------------ // Voice line, text, function and audio parsing //================================================================================= // this is how we handle ALL the voice distribition and playing // its NOT pretty function doText(%name, %extraTime, %priority) { if($player.text[%name, priority] || %priority) addToQueueNext(%name); else addToQueueEnd(%name); $player.text[%name, extraTime] = %extraTime; processText(); } function processText(%cont) { //we may need to fudge everysound to get it timed right %universalSoundFudgingConstant = 400; if($currentlyPlaying && !%cont) return; %name = $player.Textque0; if(%name $= "") return; //echo("processing: "@%name); if($player.Text[%name, eval] !$= "") eval($player.text[%name, eval]); if($player.Text[%name, text] !$= "") { // the old way: messageClient($player, 0, '\c2%1: %2',$trainerName, $player.Text[%name, line]); messageClient($player, 0, "\c5"@$player.Text[%name, text]); serverPlay2d(MessageRecieveSound); } if($player.Text[%name, wav] !$= "") { //messageClient($player, 0, "~w"@$player.Text[%name, wav]); %audio = alxCreateSource( AudioChat, $player.Text[%name, wav] ); alxPlay( %audio ); } removeFromQueue(); %wavLen = alxGetWaveLen($player.text[%name, wav]); //echo("got wave length of: "@%wavLen); //if(%wavLen < 400) // %wavLen = 400; // you cant go back in time, vge %time = %wavLen + $player.text[%name, extraTime] + %universalSoundFudgingConstant; //echo("total delay time of"@%time); $currentlyPlaying = schedule(%time , $player.player, processText, true); schedule(%time, 0, eval, "$currentlyPlaying = false;"); } function removeFromQueue() { %i = 1; while($player.textque[%i] !$= "") { $player.textque[%i-1] = $player.textque[%i]; %i++; } $player.textque[%i-1] = ""; } function addToQueueEnd(%name) { %q = 0; while($player.Textque[%q] !$= ""){ %q++; } $player.Textque[%q] = %name; } function addToQueueNext(%name) { %q = 0; while($player.Textque[%q] !$= ""){ %q++; } for(%i=%q; %i>0; %i--) $player.textque[%i] = $player.textque[%i-1]; $player.textque0 = %name; } function echoQueue() { echo("Textque -------------------------------"); %i = 0; while($player.Textque[%i] !$= "") { echo(%i@": "@$player.Textque[%i]); %i++; } } function clearQueue() { for(%i=0;%i<100; %i++) $player.textQue[%i] = ""; } //handy waypoint setting tool //========================================================================= function setWaypointAt(%location, %name, %team) { %team = (!%team ? $playerTeam : %team); // if(!%name) // %name = ""; if ( isObject( $player.currentWaypoint ) ) $player.currentWaypoint.delete(); $player.currentWaypoint = new WayPoint(TurretTower) { position = %location; rotation = "1 0 0 0"; scale = "1 1 1"; dataBlock = "WayPointMarker"; team = %team; name = %name; }; MissionCleanup.add($player.currentWaypoint); } //this is just a little consolidation of functions //its a little gregarious but allows text to live in spdialg.cs //intent is to make hud updating easier and localization easier too ;) function updateTrainingObjectiveHud( %objectiveNum ) { //sound objectiveHud.setVisible(false); schedule(400, game, eval, "objectiveHud.setVisible(true);"); serverPlay2d(TrainingHudUpdateSound); //clear old text messageClient($player, 'MsgSPCurrentObjective1', "", ' '); messageClient($player, 'MsgSPCurrentObjective2', "", ' '); // find the lines from the spdialog file that are now attached to the sp client %who = $player; %mission = $currentMission; for(%x = 1; %x <= 2; %x++) %newObjectiveLine[%x] = $player.objHud[%mission, %objectiveNum, %x]; //add new text messageClient($player, 'MsgSPCurrentObjective1', "", %newObjectiveLine1); if(%newObjectiveLine2 !$= "") messageClient($player, 'MsgSPCurrentObjective2', "", %newObjectiveLine2); } // Misc/Overwrites //======================================================================================= function isSafe(%object, %radius) { %team = %object.team; %position = %object.player.getTransform(); //check for enemy players %num = clientGroup.getCount(); for(%client = 0; %client <= %num; %client++) { if(%team != %client.team && %client.player) { %enemyPos = %client.player.getTransform(); //okay, just in case we dont have a player for that client //AND are close to "0 0 0" vge if(!%enemyPos) %dist = 100000; else %dist = vectorDist(%position, %enemyPos); //error("Debug: Client "@%client@" is "@%dist@" away"); if ( %dist < %radius){ //error("Unsafe because of client "@%client@" at a distance of "@%dist@"!!!!"); return false; } } } //error("Safe for a radius of "@%radius@"!"); return true; } function singlePlayerGame::onAIRespawn(%game, %client) { // add the default tasks if (! %client.defaultTasksAdded) { %client.defaultTasksAdded = true; %client.addTask(AIEngageTask); %client.addTask(AIPickupItemTask); %client.addTask(AIUseInventoryTask); %client.addTask(AIEngageTurretTask); %client.addtask(AIDetectMineTask); if(%client.team == $playerTeam || $pref::trainingDifficulty == 3) %client.addTask(AITauntCorpseTask); } } function singlePlayerGame::onAIKilled(%game, %clVictim, %clAttacker, %damageType, %implement) { // dont respawn AI (this is overwritten in some of the mission packages) } function singleplayerGame::onClientDamaged(%game, %clVictim, %clAttacker, %damageType, %implement) { //the DefaultGame will set some vars DefaultGame::onClientDamaged(%game, %clVictim, %clAttacker, %damageType, %implement); //now see if both were on the same team if(%clAttacker && %clAttacker != %clVictim && %clVictim.team == %clAttacker.team) { %game.friendlyFireMessage(%clVictim, %clAttacker); } } function singleplayerGame::onAIDamaged(%game, %clVictim, %clAttacker, %damageType, %implement) { if(%clVictim.team != %clAttacker.team && %clVictim.MemberOfWave) { spawnWaveTimer(%clVictim.MemberOfWave, true); } if (%clAttacker && %clAttacker != %clVictim && %clAttacker.team == %clVictim.team) { schedule(250, %clVictim, "AIPlayAnimSound", %clVictim, %clAttacker.player.getWorldBoxCenter(), "wrn.watchit", -1, -1, 0); //clear the "lastDamageClient" tag so we don't turn on teammates... unless it's uberbob! %clVictim.lastDamageClient = -1; } } // find number of players on a team // why isnt this in a std lib function getPlayersOnTeam(%team) { %num = clientGroup.getCount(); for(%i=0; %i<%num; %i++){ %client = clientGroup.getObject(%i); if(%client.team == %team && %client.player) %count++; } return %count; } //mission completion/falure stuff============================================ function missionComplete(%text) { $player.endMission = schedule(15000, game, forceFinish); messageBoxOk("Victory", %text, "forceFinish();"); //AI stop clearQueue(); AIMissionEnd(); $objectiveQ[$enemyTeam].clear(); } function forceFinish() { $timeScale = 1; //kill the thread if we pressed a button to get here... cancel($player.endMission); //make sure we end the game neatly Game.gameOver(); //immediately disconnect - bringing us back to the main menu... Disconnect(); } function missionFailed(%text) { $player.endMission = schedule(30000, game, forceFinish); MessageBoxYesNo("Failure", %text, "reloadMission();", "forceFinish();"); //AI stop clearQueue(); AIMissionEnd(); $objectiveQ[$enemyTeam].clear(); } function reloadMission() { cancel($player.endMission); Game.gameOver(); loadMission($currentMission, singlePlayer); debriefContinue(); } // silly...we fed it a movemap binding it retuns the capitalized key in (almost) english function findTrainingControlButtons( %name ) { %controlName = moveMap.getBinding(%name); if (%controlName $= "") return "[no key binding]"; %prettyName = strupr(getMapDisplayName(getWord(%controlName, 0), getWord(%controlName, 1))); %next = 2; while( getWord( %controlName, %next ) !$= "" ) { %extra = "-"@strupr(getWord( %controlName, 2 )); %prettyName = %prettyName @ %extra; %next++; } return %prettyName; } // just a kinda cool little effect function firstPersonQuickPan() { if($firstperson) { toggleFirstPerson($player); schedule(4000, $player.player, toggleFirstPerson, $player); } } // Player spawning/respawning==================================================== //since we are going through pickTeamSpawn rather than pickPlayerSpawn // and for a couple other reasons, we are going to need to manually determine // if this is a respawn or not. function spawnSinglePlayer() { $player.lives--; game.spawnPlayer($player, true); $player.setControlObject($player.player); //messageClient($player, 0, "Respawns Remaining: "@$player.lives); } function singleplayerGame::observerOnTrigger() { //we dont want the player respawning (yet) return false; } function SinglePlayerGame::spawnPlayer( %game, %client, %respawn ) { //error("Spawn Player: %client = " @%client@" %respawn = "@%respawn); %spawnPoint = %game.pickPlayerSpawn( %client, %respawn ); %game.createPlayer( %client, %spawnPoint, %respawn ); } function singlePlayerGame::playerSpawned(%game, %player) { defaultGame::playerSpawned(%game, %player); } function singleplayerGame::pickPlayerSpawn(%game, %client, %respawn) { // the bots, for some reason, always pass in %respawn as true // well that's horse pucky, since the bots never respawn in SPG // so I do this stupid thing if(%client.isAIcontrolled()) %respawn = false; if(!%client.offense) // this is a wave spawned attack bot %respawn = true; %game.pickTeamSpawn( %client, %respawn); } function singleplayerGame::pickTeamSpawn(%game, %client, %respawn) { %team = %client.team; if(%respawn) { %group = nameToID("MissionGroup/Teams/team"@%team@"/DropPoints/Respawns"); if(! isObject(%group)) { //error("Client" SPC %client SPC "is attempting a respawn with no drop point"); return "0 0 300"; } else %spawnLoc = %group.getObject(game.respawnPoint); //error("REspawn loc is: " @ %spawnLoc); } else { %group = nameToID("MissionGroup/Teams/team" @ %team @ "/DropPoints"); %spawnLoc = %group.getObject(game.spawnLoc[%team]); //error("spawn loc is: "@game.spawnLoc[%team]); game.spawnLoc[%team]++; } return %spawnLoc.getTransform(); } function SinglePlayerGame::createCustomKeymap(%game) { // new ActionMap(TrainingMap); // TrainingMap.bindCmd( keyboard, "escape", "escapeFromGame();", "" ); } //======================================================================================= // Escape dialog functions: //======================================================================================= function SinglePlayerEscapeDlg::onWake( %this ) { $timeScale = 0; if( OptionsDlg.isAwake()) { Canvas.popDialog( OptionsDlg ); } } function SinglePlayerEscapeDlg::onSleep( %this ) { // spMap.pop(); // spMap.delete(); } function SinglePlayerEscapeDlg::leaveGame( %this ) { Canvas.popDialog( SinglePlayerEscapeDlg ); MessageBoxYesNo( "LEAVE GAME", $player.miscMsg[LeaveGame], "forceFinish();", "$timeScale = 1;" ); } function SinglePlayerEscapeDlg::gotoSettings( %this ) { Canvas.popDialog( SinglePlayerEscapeDlg ); Canvas.pushDialog( OptionsDlg ); } function SinglePlayerEscapeDlg::returnToGame( %this ) { //error( "** CALLING SinglePlayerEscapeDlg::returnToGame **" ); $timeScale = 1; Canvas.popDialog( SinglePlayerEscapeDlg ); movemap.push(); //trainingmap.push(); } function singlePlayerGame::OptionsDlgSleep(%game) { $enableDirectInput = 1; activateDirectInput(); Canvas.pushDialog( SinglePlayerEscapeDlg ); // the player may have changed his keys // we need to reload the big spdialog string table that // holds all the text related to the players keymappings createText($player); } // mission Area package package singlePlayerMissionAreaEnforce { // -begin mission area package------------------------------------------------- // OOB function SinglePlayerGame::leaveMissionArea(%game, %playerData, %player) { parent::leaveMissionArea(%game, %playerData, %player); if(%player == $player.player) { $player.leftMissionArea++; %timeAllowed = 30; $player.OOB = schedule(%timeAllowed *1000, 0, wussOut, %player); clearQueue(); doText(Any_offcourse); MessageClient($player, 0, $player.miscMsg[OOB]); %player.playerLeftMissionArea = true; } } function SinglePlayerGame::enterMissionArea(%game, %playerData, %player) { parent::enterMissionArea(%game, %playerData, %player); if(%player == $player.player && %player.playerLeftMissionArea) { //echo("player back in bounds"); cancel($player.OOB); clearQueue(); doText(Any_alright); MessageClient($player, 0, $player.miscMsg[InBounds]); } } function wussOut(%player) { clearQueue(); doText(Any_abort); missionFailed($player.miscMsg[OOBLoss]); } // -end mission area package------------------------------------------------- }; // Custom Particle effects for training5 datablock ParticleData(BeforeT5particle) { dragCoefficient = 0; gravityCoefficient = -0.017094; inheritedVelFactor = 0.0176125; constantAcceleration = -0.8; lifetimeMS = 1248; lifetimeVarianceMS = 0; useInvAlpha = 1; spinRandomMin = -200; spinRandomMax = 200; textureName = "particleTest"; colors[0] = "1.000000 0.677165 0.000000 1.000000"; colors[1] = "0.708661 0.507812 0.000000 1.000000"; colors[2] = "0.000000 0.000000 0.000000 0.000000"; colors[3] = "1.000000 1.000000 1.000000 1.000000"; sizes[0] = 0.991882; sizes[1] = 2.99091; sizes[2] = 4.98993; sizes[3] = 1; times[0] = 0; times[1] = 0.2; times[2] = 1; times[3] = 2; }; datablock ParticleData(AfterT5particle) { dragCoefficient = 0; gravityCoefficient = -0.017094; inheritedVelFactor = 0.0176125; constantAcceleration = -1.1129; lifetimeMS = 2258; lifetimeVarianceMS = 604; useInvAlpha = 1; spinRandomMin = -200; spinRandomMax = 200; textureName = "special/Smoke/smoke_001"; colors[0] = "1.000000 0.677165 0.000000 1.000000"; colors[1] = "0.181102 0.181102 0.181102 1.000000"; colors[2] = "0.000000 0.000000 0.000000 0.000000"; colors[3] = "1.000000 1.000000 1.000000 1.000000"; sizes[0] = 0.991882; sizes[1] = 2.99091; sizes[2] = 4.98993; sizes[3] = 1; times[0] = 0; times[1] = 0.2; times[2] = 1; times[3] = 2; }; datablock ParticleEmitterData(BeforeT5) { ejectionPeriodMS = 16; periodVarianceMS = 10; ejectionVelocity = 7.45968; velocityVariance = 0.25; ejectionOffset = 0; thetaMin = 0; thetaMax = 180; phiReferenceVel = 0; phiVariance = 360; overrideAdvances = 0; orientParticles= 0; orientToNormal = 0; orientOnVelocity = 1; particles = "BeforeT5particle"; }; datablock ParticleEmitterData(AfterT5) { ejectionPeriodMS = 10; periodVarianceMS = 0; ejectionVelocity = 10.25; velocityVariance = 0.25; ejectionOffset = 0; thetaMin = 0; thetaMax = 180; phiReferenceVel = 0; phiVariance = 360; overrideAdvances = 0; orientParticles= 0; orientToNormal = 0; orientOnVelocity = 1; particles = "AfterT5particle"; };