//$MissionName is the file name of the mission //$MapName is the displayed name(no underscore,spaces) //$GameType (CTF,Hunters) function DefaultGame::activatePackages(%game) { // activate the default package for the game type activatePackage(DefaultGame); if(isPackage(%game.class) && %game.class !$= DefaultGame) activatePackage(%game.class); } function DefaultGame::deactivatePackages(%game) { deactivatePackage(DefaultGame); if(isPackage(%game.class) && %game.class !$= DefaultGame) deactivatePackage(%game.class); } package DefaultGame { function FlipFlop::objectiveInit(%data, %flipflop) { // add this flipflop to missioncleanup %flipflopSet = nameToID("MissionCleanup/FlipFlops"); if(%flipflopSet <= 0) { %flipflopSet = new SimSet("FlipFlops"); MissionCleanup.add(%flipflopSet); } %flipflopSet.add(%flipflop); // see if there's a holo projector associated with this flipflop // search the flipflop's folder for a holo projector // if one exists, associate it with the flipflop %flipflop.projector = 0; %folder = %flipflop.getGroup(); for(%i = 0; %i < %folder.getCount(); %i++) { %proj = %folder.getObject(%i); // weird, but line below prevents console error if(%proj.getClassName() !$= "SimGroup" && %proj.getClassName() !$= "InteriorInstance") if(%proj.getDatablock().getName() $= "LogoProjector") { %flipflop.projector = %proj; %flipflop.projector.holo = 0; break; } } // may have been hidden %target = %flipFlop.getTarget(); if(%target != -1) { // set flipflop to base skin setTargetSkin(%target, $teamSkin[0]); // make this always visible in the commander map setTargetAlwaysVisMask(%target, 0xffffffff); // make this always visible in the commander list setTargetRenderMask(%target, getTargetRenderMask(%target) | $TargetInfo::CommanderListRender); } } function FlipFlop::playerTouch(%data, %flipflop, %player) { %client = %player.client; %flipTeam = %flipflop.team; if(%flipTeam == %client.team) return false; // Let the observers know: messageTeam( 0, 'MsgClaimFlipFlop', '\c2%1 claimed %2 for %3.~wfx/misc/flipflop_taken.wav', %client.name, Game.cleanWord( %flipflop.name ), $TeamName[%client.team] ); // Let the teammates know: messageTeam( %client.team, 'MsgClaimFlipFlop', '\c2%1 claimed %2 for %3.~wfx/misc/flipflop_taken.wav', %client.name, Game.cleanWord( %flipflop.name ), $TeamName[%client.team] ); // Let the other team know: %losers = %client.team == 1 ? 2 : 1; messageTeam( %losers, 'MsgClaimFlipFlop', '\c2%1 claimed %2 for %3.~wfx/misc/flipflop_lost.wav', %client.name, Game.cleanWord( %flipflop.name ), $TeamName[%client.team] ); logEcho(%client.nameBase@" (pl "@%player@"/cl "@%client@") claimed flipflop "@%flipflop@" for team "@%client.team); //change the skin on the switch to claiming team's logo setTargetSkin(%flipflop.getTarget(), $teamSkin[%player.team]); setTargetSensorGroup(%flipflop.getTarget(), %player.team); // if there is a "projector" associated with this flipflop, put the claiming team's logo there if(%flipflop.projector > 0) { %projector = %flipflop.projector; // axe the old projected holo, if one exists if(%projector.holo > 0) %projector.holo.delete(); %newHolo = $holoName[%client.team] @ "Logo"; %projTransform = %projector.getTransform(); // below two functions are from deployables.cs %projRot = rotFromTransform(%projTransform); %projPos = posFromTransform(%projTransform); // place the holo above the projector (default 10 meters) %hHeight = %projector.holoHeight; if(%hHeight $= "") %hHeight = 10; %holoZ = getWord(%projPos, 2) + %hHeight; %holoPos = firstWord(%projPos) SPC getWord(%projPos,1) SPC %holoZ; %holo = new StaticShape() { rotation = %projRot; position = %holoPos; dataBlock = %newHolo; }; // dump the hologram into MissionCleanup MissionCleanup.add(%holo); // associate the holo with the projector %projector.holo = %holo; } // convert the resources associated with the flipflop Game.claimFlipflopResources(%flipflop, %client.team); if(Game.countFlips()) for(%i = 1; %i <= Game.numTeams; %i++) { %teamHeld = Game.countFlipsHeld(%i); messageAll('MsgFlipFlopsHeld', "", %i, %teamHeld); } //call the ai function Game.AIplayerCaptureFlipFlop(%player, %flipflop); return true; } }; //--------- DEFAULT SCORING, SUPERCEDE IN GAMETYPE FILE ------------------ function DefaultGame::initGameVars(%game) { %game.SCORE_PER_SUICIDE = 0; %game.SCORE_PER_TEAMKILL = 0; %game.SCORE_PER_DEATH = 0; %game.SCORE_PER_KILL = 0; %game.SCORE_PER_TURRET_KILL = 0; } //-- tracking --- // .deaths .kills .suicides .teamKills .turretKills function DefaultGame::claimFlipflopResources(%game, %flipflop, %team) { %group = %flipflop.getGroup(); %group.setTeam(%team); // make this always visible in the commander map (gets reset when sensor group gets changed) setTargetAlwaysVisMask(%flipflop.getTarget(), 0xffffffff); } //------------------------------------------------------------------------------ function DefaultGame::selectSpawnSphere(%game, %team) { // - walks the objects in the 'teamdrops' group for this team // - find a random spawn point which has a running sum less more than // 0->total sphere weight %teamDropsGroup = "MissionCleanup/TeamDrops" @ %team; %group = nameToID(%teamDropsGroup); if (%group != -1) { %count = %group.getCount(); if (%count != 0) { // Get total weight of those spheres not filtered by mission types list- %overallWeight = 0; for (%i = 0; %i < %count; %i++) { %sphereObj = %group.getObject(%i); if ( ! %sphereObj.isHidden() ) %overallWeight += %sphereObj.sphereWeight; } if (%overallWeight > 0) { // Subtract a little from this as hedge against any rounding offness- %randSum = getRandom(%overallWeight) - 0.05; // echo("randSum = " @ %randSum); for (%i = 0; %i < %count; %i++) { %sphereObj = %group.getObject(%i); if (! %sphereObj.isHidden()) { %randSum -= %sphereObj.sphereWeight; if (%randSum <= 0) { // echo("Chose sphere " @ %i); return %group.getObject(%i); // Found our sphere } } } error("Random spawn sphere selection didn't work"); } else error("No non-hidden spawnspheres were found in " @ %teamDropsGroup); } else error("No spawnspheres found in " @ %teamDropsGroup); } else error(%teamDropsGroup @ " not found in selectSpawnSphere()."); return -1; } function DefaultGame::selectSpawnZone(%game, %sphere) { // determines if this should spawn inside or outside %overallWeight = %sphere.indoorWeight + %sphere.outdoorWeight; %index = mFloor(getRandom() * (%overallWeight - 0.1)) + 1; if ((%index - %sphere.indoorWeight) > 0) return false; //do not pick an indoor spawn else return true; //pick an indoor spawn } function DefaultGame::selectSpawnFacing(%game, %src, %target, %zone) { //this used only when spawn loc is not on an interior. This points spawning player to the ctr of spawnshpere %target = setWord(%target, 2, 0); %src = setWord(%src, 2, 0); if(VectorDist(%target, %src) == 0) return " 0 0 1 0 "; %vec = VectorNormalize(VectorSub(%target, %src)); %angle = mAcos(getWord(%vec, 1)); if(%src < %target) return(" 0 0 1 " @ %angle); else return(" 0 0 1 " @ -%angle); } function DefaultGame::pickTeamSpawn(%game, %team) { // early exit if no nav graph if (!navGraphExists()) { echo("No navigation graph is present. Build one."); return -1; } for (%attempt = 0; %attempt < 20; %attempt++) { // finds a random spawn sphere // selects inside/outside on this random sphere // if the navgraph exists, then uses it to grab a random node as spawn // location/rotation %sphere = %game.selectSpawnSphere(%team); if (%sphere == -1) { echo("No spawn spheres found for team " @ %team); return -1; } %zone = %game.selectSpawnZone(%sphere); %useIndoor = %zone; %useOutdoor = !%zone; if (%zone) %area = "indoor"; else %area = "outdoor"; %radius = %sphere.radius; %sphereTrans = %sphere.getTransform(); %sphereCtr = getWord(%sphereTrans, 0) @ " " @ getWord(%sphereTrans, 1) @ " " @ getWord(%sphereTrans, 2); //don't need full transform here, just x, y, z //echo("Selected Sphere is " @ %sphereCtr @ " with a radius of " @ %radius @ " meters. Selecting from " @ %area @ " zone."); %avoidThese = $TypeMasks::VehicleObjectType | $TypeMasks::MoveableObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::TurretObjectType; for (%tries = 0; %tries < 10; %tries++) { %nodeIndex = navGraph.randNode(%sphereCtr, %radius, %useIndoor, %useOutdoor); if (%nodeIndex >= 0) { %loc = navGraph.randNodeLoc(%nodeIndex); %adjUp = VectorAdd(%loc, "0 0 1.0"); // don't go much below if (ContainerBoxEmpty( %avoidThese, %adjUp, 2.0)) break; } } if (%nodeIndex >= 0) { %loc = navGraph.randNodeLoc(%nodeIndex); if (%zone) { %trns = %loc @ " 0 0 1 0"; %spawnLoc = whereToLook(%trns); } else { %rot = %game.selectSpawnFacing(%loc, %sphereCtr, %zone); %spawnLoc = %loc @ %rot; } return %spawnLoc; } } } //------------------------------------------------------------ function DefaultGame::pickObserverSpawn(%game, %client, %next) { %group = nameToID("MissionGroup/ObserverDropPoints"); %count = %group.getCount(); if(!%count || %group == -1) { echo("no observer spawn points found"); return -1; } if(%client.lastObserverSpawn == -1) { %client.lastObserverSpawn = 0; return(%group.getObject(%client.lastObserverSpawn)); } if(%next == true) %spawnIdx = %client.lastObserverSpawn + 1; else %spawnIdx = %client.lastObserverSpawn - 1; if(%spawnIdx < 0) %spawnIdx = %count - 1; else if(%spawnIdx >= %count) %spawnIdx = 0; %client.lastObserverSpawn = %spawnIdx; //echo("Observer spawn point found"); return %group.getObject(%spawnIdx); } //------------------------------------------------------------ function DefaultGame::spawnPlayer( %game, %client, %respawn ) { %client.lastSpawnPoint = %game.pickPlayerSpawn( %client, false ); %client.suicidePickRespawnTime = getSimTime() + 20000; %game.createPlayer( %client, %client.lastSpawnPoint, %respawn ); } //------------------------------------------------------------ function DefaultGame::playerSpawned(%game, %player) { if( %player.client.respawnTimer ) cancel(%player.client.respawnTimer); %player.client.observerStartTime = ""; %game.equip(%player); //set the spawn time (for use by the AI system) %player.client.spawnTime = getSimTime(); // jff: this should probably be checking the team of the client //update anyone observing this client %count = ClientGroup.getCount(); for (%i = 0; %i < %count; %i++) { %cl = ClientGroup.getObject(%i); if (%cl.camera.mode $= "observerFollow" && %cl.observeClient == %player.client) { %transform = %player.getTransform(); %cl.camera.setOrbitMode(%player, %transform, 0.5, 4.5, 4.5); %cl.camera.targetObj = %player; } } } function DefaultGame::equip(%game, %player) { for(%i =0; %i<$InventoryHudCount; %i++) %player.client.setInventoryHudItem($InventoryHudData[%i, itemDataName], 0, 1); //%player.setArmor("Light"); %player.setInventory(RepairKit,10); %player.setInventory(Grenade,6); %player.setInventory(Blaster,1); %player.setInventory(Disc,1); %player.setInventory(Chaingun, 1); %player.setInventory(ChaingunAmmo, 100); %player.setInventory(DiscAmmo, 100); %player.setInventory(Beacon, 3); %player.setInventory(TargetingLaser, 1); %player.weaponCount = 3; %player.use("Blaster"); } //------------------------------------------------------------ function DefaultGame::pickPlayerSpawn(%game, %client, %respawn) { // place this client on his own team, '%respawn' does not ever seem to be used //we no longer care whether it is a respawn since all spawns use same points. return %game.pickTeamSpawn(%client.team); } //------------------------------------------------------------ function DefaultGame::createPlayer(%game, %client, %spawnLoc, %respawn) { // do not allow a new player if there is one (not destroyed) on this client if(isObject(%client.player) && (%client.player.getState() !$= "Dead")) return; // clients and cameras can exist in team 0, but players should not if(%client.team == 0) error("Players should not be added to team0!"); // defaultplayerarmor is in 'players.cs' if(%spawnLoc == -1) %spawnLoc = "0 0 300 1 0 0 0"; //else // echo("Spawning player at " @ %spawnLoc); // copied from player.cs if (%client.race $= "Bioderm") // Only have male bioderms. %armor = $DefaultPlayerArmor @ "Male" @ %client.race @ Armor; else %armor = $DefaultPlayerArmor @ %client.sex @ %client.race @ Armor; %client.armor = $DefaultPlayerArmor; %player = new Player() { //dataBlock = $DefaultPlayerArmor; dataBlock = %armor; }; if(%respawn) { %player.setInvincible(true); %player.setCloaked(true); %player.setInvincibleMode($InvincibleTime,0.02); %player.respawnCloakThread = %player.schedule($InvincibleTime * 1000, "setRespawnCloakOff"); %player.schedule($InvincibleTime * 1000, "setInvincible", false); } %player.setTransform( %spawnLoc ); MissionCleanup.add(%player); // setup some info %player.setOwnerClient(%client); %player.team = %client.team; %client.outOfBounds = false; %player.setEnergyLevel(60); %client.player = %player; // updates client's target info for this player %player.setTarget(%client.target); setTargetDataBlock(%client.target, %player.getDatablock()); setTargetSensorData(%client.target, PlayerSensor); setTargetSensorGroup(%client.target, %client.team); %client.setSensorGroup(%client.team); //make sure the player has been added to the team rank array... %game.populateTeamRankArray(%client); %game.playerSpawned(%client.player); } function Player::setRespawnCloakOff(%player) { %player.setCloaked(false); %player.respawnCloakThread = ""; } //------------------------------------------------------------ function DefaultGame::startMatch(%game) { echo("START MATCH"); MessageAll('MsgMissionStart', "\c2Match started!"); //the match has been started, clear the team rank array, and repopulate it... for (%i = 0; %i < 32; %i++) %game.clearTeamRankArray(%i); //used in BountyGame, prolly in a few others as well... $matchStarted = true; %game.clearDeployableMaxes(); $missionStartTime = getSimTime(); %curTimeLeftMS = ($Host::TimeLimit * 60 * 1000); // schedule first timeLimit check for 20 seconds if(%game.class !$= "SiegeGame") { %game.timeCheck = %game.schedule(20000, "checkTimeLimit"); } //schedule the end of match countdown EndCountdown($Host::TimeLimit * 60 * 1000); //reset everyone's score and add them to the team rank array for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); %game.resetScore(%cl); %game.populateTeamRankArray(%cl); } // set all clients control to their player %count = ClientGroup.getCount(); for( %i = 0; %i < %count; %i++ ) { %cl = ClientGroup.getObject(%i); // Siege game will set the clock differently if(%game.class !$= "SiegeGame") messageClient(%cl, 'MsgSystemClock', "", $Host::TimeLimit, %curTimeLeftMS); if( !$Host::TournamentMode && %cl.matchStartReady && %cl.camera.mode $= "pre-game") { commandToClient(%cl, 'setHudMode', 'Standard'); %cl.setControlObject( %cl.player ); } else { if( %cl.matchStartReady ) { if(%cl.camera.mode $= "pre-game") { %cl.observerMode = ""; commandToClient(%cl, 'setHudMode', 'Standard'); if(isObject(%cl.player)) %cl.setControlObject( %cl.player ); else echo("can't set control for client: " @ %cl @ ", no player object found!"); } else %cl.observerMode = "observerFly"; } } } // on with the show this is it! AISystemEnabled( true ); } function DefaultGame::gameOver( %game ) { //set the bool $missionRunning = false; CancelCountdown(); CancelEndCountdown(); //loop through all the clients, and do any cleanup... %count = ClientGroup.getCount(); for (%i = 0; %i < %count; %i++) { %client = ClientGroup.getObject(%i); %player = %client.player; %client.lastTeam = %client.team; if ( !%client.isAiControlled() ) { %client.endMission(); messageClient( %client, 'MsgClearDebrief', "" ); %game.sendDebriefing( %client ); if(%client.player.isBomber) commandToClient(%client, 'endBomberSight'); //clear the score hud... messageClient( %client, 'SetScoreHudHeader', "", "" ); messageClient( %client, 'SetScoreHudSubheader', "", ""); messageClient( %client, 'ClearHud', "", 'scoreScreen', 0 ); } } // Default game does nothing... except lets the AI know the mission is over AIMissionEnd(); } //------------------------------------------------------------------------------ function DefaultGame::sendDebriefing( %game, %client ) { if ( %game.numTeams == 1 ) { // Mission result: %winner = $TeamRank[0, 0]; if ( %winner.score > 0 ) messageClient( %client, 'MsgDebriefResult', "", '%1 wins!', $TeamRank[0, 0].name ); else messageClient( %client, 'MsgDebriefResult', "", 'Nobody wins.' ); // Player scores: %count = $TeamRank[0, count]; messageClient( %client, 'MsgDebriefAddLine', "", 'PLAYERSCOREKILLS' ); for ( %i = 0; %i < %count; %i++ ) { %cl = $TeamRank[0, %i]; if ( %cl.score $= "" ) %score = 0; else %score = %cl.score; if ( %cl.kills $= "" ) %kills = 0; else %kills = %cl.kills; messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2 %3', %cl.name, %score, %kills ); } } else { %topScore = ""; %topCount = 0; for ( %team = 1; %team <= %game.numTeams; %team++ ) { if ( %topScore $= "" || $TeamScore[%team] > %topScore ) { %topScore = $TeamScore[%team]; %firstTeam = %team; %topCount = 1; } else if ( $TeamScore[%team] == %topScore ) { %secondTeam = %team; %topCount++; } } // Mission result: if ( %topCount == 1 ) messageClient( %client, 'MsgDebriefResult', "", 'Team %1 wins!', $TeamName[%firstTeam] ); else if ( %topCount == 2 ) messageClient( %client, 'MsgDebriefResult', "", 'Team %1 and Team %2 tie!', $TeamName[%firstTeam], $TeamName[%secondTeam] ); else messageClient( %client, 'MsgDebriefResult', "", 'The mission ended in a tie.' ); // Team scores: messageClient( %client, 'MsgDebriefAddLine', "", 'TEAMSCORE' ); for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) { if ( $TeamScore[%team] $= "" ) %score = 0; else %score = $TeamScore[%team]; messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2', $TeamName[%team], %score ); } // Player scores: messageClient( %client, 'MsgDebriefAddLine', "", '\nPLAYERTEAMSCOREKILLS' ); for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) %count[%team] = 0; %notDone = true; while ( %notDone ) { // Get the highest remaining score: %highScore = ""; for ( %team = 1; %team <= %game.numTeams; %team++ ) { if ( %count[%team] < $TeamRank[%team, count] && ( %highScore $= "" || $TeamRank[%team, %count[%team]].score > %highScore ) ) { %highScore = $TeamRank[%team, %count[%team]].score; %highTeam = %team; } } // Send the debrief line: %cl = $TeamRank[%highTeam, %count[%highTeam]]; %score = %cl.score $= "" ? 0 : %cl.score; %kills = %cl.kills $= "" ? 0 : %cl.kills; messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2 %3 %4', %cl.name, $TeamName[%cl.team], %score, %kills ); %count[%highTeam]++; %notDone = false; for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) { if ( %count[%team] < $TeamRank[%team, count] ) { %notDone = true; break; } } } } //now go through an list all the observers: %count = ClientGroup.getCount(); %printedHeader = false; for (%i = 0; %i < %count; %i++) { %cl = ClientGroup.getObject(%i); if (%cl.team <= 0) { //print the header only if we actually find an observer if (!%printedHeader) { %printedHeader = true; messageClient(%client, 'MsgDebriefAddLine', "", '\nOBSERVERSSCORE'); } //print out the client %score = %cl.score $= "" ? 0 : %cl.score; messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2', %cl.name, %score); } } } //------------------------------------------------------------ function DefaultGame::clearDeployableMaxes(%game) { for(%i = 0; %i <= %game.numTeams; %i++) { $TeamDeployedCount[%i, TurretIndoorDeployable] = 0; $TeamDeployedCount[%i, TurretOutdoorDeployable] = 0; $TeamDeployedCount[%i, PulseSensorDeployable] = 0; $TeamDeployedCount[%i, MotionSensorDeployable] = 0; $TeamDeployedCount[%i, InventoryDeployable] = 0; $TeamDeployedCount[%i, DeployedCamera] = 0; $TeamDeployedCount[%i, MineDeployed] = 0; $TeamDeployedCount[%i, TargetBeacon] = 0; $TeamDeployedCount[%i, MarkerBeacon] = 0; } } // called from player scripts function DefaultGame::onClientDamaged(%game, %clVictim, %clAttacker, %damageType, %sourceObject) { //set the vars if it was a turret if (isObject(%sourceObject)) { %sourceClassType = %sourceObject.getDataBlock().getClassName(); %sourceType = %sourceObject.getDataBlock().getName(); } if (%sourceClassType $= "TurretData") { // jff: are there special turret types which makes this needed? // tinman: yes, we don't want bots stopping to fire on the big outdoor turrets, which they // will just get mowed down. deployables only. if (%sourceType $= "TurretDeployedFloorIndoor" || %sourceType $= "TurretDeployedWallIndoor" || %sourceType $= "TurretDeployedCeilingIndoor" || %sourceType $= "TurretDeployedOutdoor") { %clVictim.lastDamageTurretTime = getSimTime(); %clVictim.lastDamageTurret = %sourceObject; } %turretAttacker = %sourceObject.getControllingClient(); // should get a damagae message from friendly fire turrets also if(%turretAttacker && %turretAttacker != %clVictim && %turretAttacker.team == %clVictim.team) { if (%game.numTeams > 1 && %turretAttacker.player.causedRecentDamage != %clVictim.player) //is a teamgame & player just damaged a teammate { %turretAttacker.player.causedRecentDamage = %clVictim.player; %turretAttacker.player.schedule(1000, "causedRecentDamage", ""); //allow friendly fire message every x ms %game.friendlyFireMessage(%clVictim, %turretAttacker); } } } else if (%sourceClassType $= "PlayerData") { //now see if both were on the same team if(%clAttacker && %clAttacker != %clVictim && %clVictim.team == %clAttacker.team) { if (%game.numTeams > 1 && %clAttacker.player.causedRecentDamage != %clVictim.player) //is a teamgame & player just damaged a teammate { %clAttacker.player.causedRecentDamage = %clVictim.player; %clAttacker.player.schedule(1000, "causedRecentDamage", ""); //allow friendly fire message every x ms %game.friendlyFireMessage(%clVictim, %clAttacker); } } if (%clAttacker && %clAttacker != %clVictim) { %clVictim.lastDamageTime = getSimTime(); %clVictim.lastDamageClient = %clAttacker; if (%clVictim.isAIControlled()) %clVictim.clientDetected(%clAttacker); } } //call the game specific AI routines... if (isObject(%clVictim) && %clVictim.isAIControlled()) %game.onAIDamaged(%clVictim, %clAttacker, %damageType, %sourceObject); if (isObject(%clAttacker) && %clAttacker.isAIControlled()) %game.onAIFriendlyFire(%clVictim, %clAttacker, %damageType, %sourceObject); } function DefaultGame::friendlyFireMessage(%game, %damaged, %damager) { messageClient(%damaged, 'MsgDamagedByTeam', '\c1You were harmed by teammate %1', %damager.name); messageClient(%damager, 'MsgDamagedTeam', '\c1You just harmed teammate %1.', %damaged.name); } function DefaultGame::clearWaitRespawn(%game, %client) { %client.waitRespawn = 0; } // called from player scripts function DefaultGame::onClientKilled(%game, %clVictim, %clKiller, %damageType, %implement, %damageLocation) { %plVictim = %clVictim.player; %plKiller = %clKiller.player; %clVictim.plyrPointOfDeath = %plVictim.position; %clVictim.plyrDiedHoldingFlag = %plVictim.holdingFlag; %clVictim.waitRespawn = 1; cancel( %plVictim.reCloak ); cancel(%clVictim.respawnTimer); %clVictim.respawnTimer = %game.schedule(($Host::PlayerRespawnTimeout * 1000), "forceObserver", %clVictim, "spawnTimeout" ); // reset the alarm for out of bounds if(%clVictim.outOfBounds) messageClient(%clVictim, 'EnterMissionArea', ""); if (%damageType == $DamageType::suicide) %respawnDelay = 10; else %respawnDelay = 2; %game.schedule(%respawnDelay*1000, "clearWaitRespawn", %clVictim); // if victim had an undetonated satchel charge pack, get rid of it if(%plVictim.thrownChargeId != 0) if(!%plVictim.thrownChargeId.kaboom) %plVictim.thrownChargeId.delete(); if(%plVictim.lastVehicle !$= "") { schedule(15000, %plVictim.lastVehicle,"vehicleAbandonTimeOut", %plVictim.lastVehicle); %plVictim.lastVehicle.lastPilot = ""; } // unmount pilot or remove sight from bomber if(%plVictim.isMounted()) { if(%plVictim.vehicleTurret) %plVictim.vehicleTurret.getDataBlock().playerDismount(%plVictim.vehicleTurret); else { %plVictim.getDataBlock().doDismount(%plVictim, true); %plVictim.mountVehicle = false; } } if(%plVictim.inStation) commandToClient(%plVictim.client,'setStationKeys', false); %clVictim.camera.mode = "playerDeath"; // reset who triggered this station and cancel outstanding armor switch thread if(%plVictim.station) { %plVictim.station.triggeredBy = ""; %plVictim.station.getDataBlock().stationTriggered(%plVictim.station,0); if(%plVictim.armorSwitchSchedule) cancel(%plVictim.armorSwitchSchedule); } //Close huds if player dies... messageClient(%clVictim, 'CloseHud', "", 'inventoryScreen'); messageClient(%clVictim, 'CloseHud', "", 'vehicleHud'); commandToClient(%clVictim, 'setHudMode', 'Standard', "", 0); // $weaponslot from item.cs %plVictim.setRepairRate(0); %plVictim.setImageTrigger($WeaponSlot, false); playDeathAnimation(%plVictim, %damageLocation, %damageType); playDeathCry(%plVictim); %victimName = %clVictim.name; %game.displayDeathMessages(%clVictim, %clKiller, %damageType, %implement); %game.updateKillScores(%clVictim, %clKiller, %damageType, %implement); // toss whatever is being carried, '$flagslot' from item.cs // MES - had to move this to after death message display because of Rabbit game type for(%index = 0 ; %index < 8; %index++) { %image = %plVictim.getMountedImage(%index); if(%image) { if(%index == $FlagSlot) %plVictim.throwObject(%plVictim.holdingFlag); else %plVictim.throw(%image.item); } } // target manager update setTargetDataBlock(%clVictim.target, 0); setTargetSensorData(%clVictim.target, 0); // clear the hud %clVictim.SetWeaponsHudClearAll(); %clVictim.SetInventoryHudClearAll(); %clVictim.setAmmoHudCount(-1); // clear out weapons, inventory and pack huds messageClient(%clVictim, 'msgDeploySensorOff', ""); //make sure the deploy hud gets shut off messageClient(%clVictim, 'msgPackIconOff', ""); // clear the pack icon //clear the deployable HUD %plVictim.client.deployPack = false; cancel(%plVictim.deployCheckThread); deactivateDeploySensor(%plVictim); //if the killer was an AI... if (isObject(%clKiller) && %clKiller.isAIControlled()) %game.onAIKilledClient(%clVictim, %clKiller, %damageType, %implement); // reset control object on this player: also sets 'playgui' as content serverCmdResetControlObject(%clVictim); // set control object to the camera %clVictim.player = 0; %transform = %plVictim.getTransform(); //note, AI's don't have a camera... if (isObject(%clVictim.camera)) { %clVictim.camera.setTransform(%transform); %clVictim.camera.setOrbitMode(%plVictim, %plVictim.getTransform(), 0.5, 4.5, 4.5); %clVictim.setControlObject(%clVictim.camera); } //hook in the AI specific code for when a client dies if (%clVictim.isAIControlled()) { aiReleaseHumanControl(%clVictim.controlByHuman, %clVictim); %game.onAIKilled(%clVictim, %clKiller, %damageType, %implement); } else aiReleaseHumanControl(%clVictim, %clVictim.controlAI); //used to track corpses so the AI can get ammo, etc... AICorpseAdded(%plVictim); //if the death was a suicide, prevent respawning for 5 seconds... %clVictim.lastDeathSuicide = false; if (%damageType == $DamageType::Suicide) { %clVictim.lastDeathSuicide = true; %clVictim.suicideRespawnTime = getSimTime() + 5000; } } function DefaultGame::forceObserver( %game, %client, %reason ) { //make sure we have a valid client... if (%client <= 0) return; // first kill this player if(%client.player) %client.player.scriptKill(0); if( %client.respawnTimer ) cancel(%client.respawnTimer); %client.respawnTimer = ""; // remove them from the team rank array %game.removeFromTeamRankArray(%client); // place them in observer mode %client.lastObserverSpawn = -1; %client.observerStartTime = getSimTime(); %adminForce = 0; switch$ ( %reason ) { case "playerChoose": %client.camera.getDataBlock().setMode( %client.camera, "observerFly" ); messageClient(%client, 'MsgClientJoinTeam', '\c2You have become an observer.', %client.name, $teamName[0], %client, 0 ); logEcho(%client.nameBase@" (cl "@%client@") entered observer mode"); %client.lastTeam = %client.team; case "AdminForce": %client.camera.getDataBlock().setMode( %client.camera, "observerFly" ); messageClient(%client, 'MsgClientJoinTeam', '\c2You have been forced into observer mode by the admin.', %client.name, $teamName[0], %client, 0 ); logEcho(%client.nameBase@" (cl "@%client@") was forced into observer mode by admin"); %client.lastTeam = %client.team; %adminForce = 1; if($Host::TournamentMode) { if(!$matchStarted) { if(%client.camera.Mode $= "pickingTeam") { commandToClient( %client, 'processPickTeam'); clearBottomPrint( %client ); } else { clearCenterPrint(%client); %client.notReady = true; } } } case "spawnTimeout": %client.camera.getDataBlock().setMode( %client.camera, "observerTimeout" ); messageClient(%client, 'MsgClientJoinTeam', '\c2You have been placed in observer mode due to delay in respawning.', %client.name, $teamName[0], %client, 0 ); logEcho(%client.nameBase@" (cl "@%client@") was placed in observer mode due to spawn delay"); // save the team the player was on - only if this was a delay in respawning %client.lastTeam = %client.team; } // switch client to team 0 (observer) %client.team = 0; %client.player.team = 0; setTargetSensorGroup( %client.target, %client.team ); %client.setSensorGroup( %client.team ); // set their control to the obs. cam %client.setControlObject( %client.camera ); commandToClient(%client, 'setHudMode', 'Observer'); // display the hud //displayObserverHud(%client, 0); updateObserverFlyHud(%client); // message everyone about this event if( !%adminForce ) messageAllExcept(%client, -1, 'MsgClientJoinTeam', '\c2%1 has become an observer.', %client.name, $teamName[0], %client, 0 ); else messageAllExcept(%client, -1, 'MsgClientJoinTeam', '\c2The admin has forced %1 to become an observer.', %client.name, $teamName[0], %client, 0 ); updateCanListenState( %client ); // call the onEvent for this game type %game.onClientEnterObserverMode(%client); //Bounty uses this to remove this client from others' hit lists } function DefaultGame::displayDeathMessages(%game, %clVictim, %clKiller, %damageType, %implement) { %victimGender = (%clVictim.sex $= "Male" ? 'him' : 'her'); %victimPoss = (%clVictim.sex $= "Male" ? 'his' : 'her'); %killerGender = (%clKiller.sex $= "Male" ? 'him' : 'her'); %killerPoss = (%clKiller.sex $= "Male" ? 'his' : 'her'); %victimName = %clVictim.name; %killerName = %clKiller.name; //error("DamageType = " @ %damageType @ ", implement = " @ %implement @ ", implement class = " @ %implement.getClassName() @ ", is controlled = " @ %implement.getControllingClient()); if(%damageType == $DamageType::Explosion) { messageAll('msgExplosionKill', $DeathMessageExplosion[mFloor(getRandom() * $DeathMessageExplosionCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a nearby explosion."); } else if(%damageType == $DamageType::Suicide) //player presses cntrl-k { messageAll('msgSuicide', $DeathMessageSuicide[mFloor(getRandom() * $DeathMessageSuicideCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") committed suicide (CTRL-K)"); } else if(%damageType == $DamageType::VehicleSpawn) { messageAll('msgVehicleSpawnKill', $DeathMessageVehPad[mFloor(getRandom() * $DeathMessageVehPadCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by vehicle spawn"); } else if(%damageType == $DamageType::ForceFieldPowerup) { messageAll('msgVehicleSpawnKill', $DeathMessageFFPowerup[mFloor(getRandom() * $DeathMessageFFPowerupCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by Force Field Powerup"); } else if(%damageType == $DamageType::Crash) { messageAll('msgVehicleCrash', $DeathMessageVehicleCrash[%damageType, mFloor(getRandom() * $DeathMessageVehicleCrashCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") crashes a vehicle."); } else if(%damageType == $DamageType::Impact) // run down by vehicle { if( ( %controller = %implement.getControllingClient() ) > 0) { %killerGender = (%controller.sex $= "Male" ? 'him' : 'her'); %killerPoss = (%controller.sex $= "Male" ? 'his' : 'her'); %killerName = %controller.name; messageAll('msgVehicleKill', $DeathMessageVehicle[mFloor(getRandom() * $DeathMessageVehicleCount)], %victimName, %victimGender, %victimPoss, %killerName ,%killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a vehicle controlled by "@%controller); } else { messageAll('msgVehicleKill', $DeathMessageVehicleUnmanned[mFloor(getRandom() * $DeathMessageVehicleUnmannedCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a vehicle (unmanned)"); } } else if (isObject(%implement) && (%implement.getClassName() $= "Turret" || %implement.getClassName() $= "VehicleTurret" || %implement.getClassName() $= "FlyingVehicle" )) //player killed by a turret { if (%implement.getControllingClient() != 0) //is turret being controlled? { %controller = %implement.getControllingClient(); %killerGender = (%controller.sex $= "Male" ? 'him' : 'her'); %killerPoss = (%controller.sex $= "Male" ? 'his' : 'her'); %killerName = %controller.name; if (%controller == %clVictim) messageAll('msgTurretSelfKill', $DeathMessageTurretSelfKill[mFloor(getRandom() * $DeathMessageTurretSelfKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); else if (%controller.team == %clVictim.team) //controller TK'd a friendly messageAll('msgCTurretKill', $DeathMessageCTurretTeamKill[%damageType, mFloor(getRandom() * $DeathMessageCTurretTeamKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); else //controller killed an enemy messageAll('msgCTurretKill', $DeathMessageCTurretKill[%damageType, mFloor(getRandom() * $DeathMessageCTurretKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a turret controlled by "@%controller); } // use the handle associated with the deployed object to verify valid owner else if (isObject(%implement.owner)) { %owner = %implement.owner; //error("Owner is " @ %owner @ " Handle is " @ %implement.ownerHandle); //error("Turret is still owned"); //turret is uncontrolled, but is owned - treat the same as controlled. %killerGender = (%owner.sex $= "Male" ? 'him' : 'her'); %killerPoss = (%owner.sex $= "Male" ? 'his' : 'her'); %killerName = %owner.name; if (%owner.team == %clVictim.team) //player got in the way of a teammates deployed but uncontrolled turret. messageAll('msgCTurretKill', $DeathMessageCTurretAccdtlKill[%damageType,mFloor(getRandom() * $DeathMessageCTurretAccdtlKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); else //deployed, uncontrolled turret killed an enemy messageAll('msgCTurretKill', $DeathMessageCTurretKill[%damageType,mFloor(getRandom() * $DeathMessageCTurretKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") was killed by turret (automated)"); } else //turret is not a placed (owned) turret (or owner is no longer on it's team), and is not being controlled { messageAll('msgTurretKill', $DeathMessageTurretKill[%damageType,mFloor(getRandom() * $DeathMessageTurretKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by turret"); } } else if((%clKiller == %clVictim) || (%damageType == $DamageType::Ground)) //player killed himself or fell to death { messageAll('msgSelfKill', $DeathMessageSelfKill[%damageType,mFloor(getRandom() * $DeathMessageSelfKillCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed self ("@$DamageTypeText[%damageType]@")"); } else if (%damageType == $DamageType::OutOfBounds) //killer died due to Out-of-Bounds damage { messageAll('msgOOBKill', $DeathMessageOOB[mFloor(getRandom() * $DeathMessageOOBCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by out-of-bounds damage"); } else if (%damageType == $DamageType::NexusCamping) //Victim died from camping near the nexus... { messageAll('msgCampKill', $DeathMessageCamping[mFloor(getRandom() * $DeathMessageCampingCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed for nexus camping"); } else if(%clKiller.team == %clVictim.team) //was a TK { messageAll('msgTeamKill', $DeathMessageTeamKill[%damageType, mFloor(getRandom() * $DeathMessageTeamKillCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") teamkilled by "@%clKiller.nameBase@" (pl "@%clKiller.player@"/cl "@%clKiller@")"); } else if (%damageType == $DamageType::Lava) //player died by falling in lava { messageAll('msgLavaKill', $DeathMessageLava[mFloor(getRandom() * $DeathMessageLavaCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by lava"); } else if ( %damageType == $DamageType::Lightning ) // player was struck by lightning { messageAll('msgLightningKill', $DeathMessageLightning[mFloor(getRandom() * $DeathMessageLightningCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by lightning"); } else if ( %damageType == $DamageType::Mine && !isObject(%clKiller) ) { error("Mine kill w/o source"); messageAll('MsgRogueMineKill', $DeathMessageRogueMine[%damageType, mFloor(getRandom() * $DeathMessageRogueMineCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); } else //was a legitimate enemy kill { if(%damageType == 6 && (%clVictim.headShot)) { // laser headshot just occurred messageAll('MsgHeadshotKill', $DeathMessageHeadshot[%damageType, mFloor(getRandom() * $DeathMessageHeadshotCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); } else messageAll('MsgLegitKill', $DeathMessage[%damageType, mFloor(getRandom() * $DeathMessageCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType); logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by "@%clKiller.nameBase@" (pl "@%clKiller.player@"/cl "@%clKiller@") using "@$DamageTypeText[%damageType]); } } function DefaultGame::assignClientTeam(%game, %client, %respawn ) { // this function is overwritten in non-team mission types (e.g. DM) // so these lines won't do anything //if(!%game.numTeams) //{ // setTargetSkin(%client.target, %client.skin); // return; //} // camera is responsible for creating a player // - counts the number of players per team // - puts this player on the least player count team // - sets the client's skin to the servers default %numPlayers = ClientGroup.getCount(); for(%i = 0; %i <= %game.numTeams; %i++) %numTeamPlayers[%i] = 0; for(%i = 0; %i < %numPlayers; %i = %i + 1) { %cl = ClientGroup.getObject(%i); if(%cl != %client) %numTeamPlayers[%cl.team]++; } %leastPlayers = %numTeamPlayers[1]; %leastTeam = 1; for(%i = 2; %i <= %game.numTeams; %i++) { if( (%numTeamPlayers[%i] < %leastPlayers) || ( (%numTeamPlayers[%i] == %leastPlayers) && ($teamScore[%i] < $teamScore[%leastTeam] ) )) { %leastTeam = %i; %leastPlayers = %numTeamPlayers[%i]; } } %client.team = %leastTeam; %client.lastTeam = %team; // Assign the team skin: if ( %client.isAIControlled() ) { if ( %leastTeam & 1 ) { %client.skin = addTaggedString( "basebot" ); setTargetSkin( %client.target, 'basebot' ); } else { %client.skin = addTaggedString( "basebbot" ); setTargetSkin( %client.target, 'basebbot' ); } } else setTargetSkin( %client.target, $teamSkin[%client.team] ); //setTargetSkin( %client.target, %client.skin ); // might as well standardize the messages //messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined %2.', %client.name, $teamName[%leastTeam], %client, %leastTeam ); //messageClient( %client, 'MsgClientJoinTeam', '\c1You joined the %2 team.', $client.name, $teamName[%client.team], %client, %client.team ); messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined %2.', %client.name, $teamName[%client.team], %client, %client.team ); messageClient( %client, 'MsgClientJoinTeam', '\c1You joined the %2 team.', %client.name, $teamName[%client.team], %client, %client.team ); updateCanListenState( %client ); logEcho(%client.nameBase@" (cl "@%client@") joined team "@%client.team); } function DefaultGame::clientJoinTeam( %game, %client, %team, %respawn ) { if ( %team < 1 || %team > %game.numTeams ) return; if( %respawn $= "" ) %respawn = 1; %client.team = %team; %client.lastTeam = %team; setTargetSkin( %client.target, $teamSkin[%team] ); setTargetSensorGroup( %client.target, %team ); %client.setSensorGroup( %team ); // Spawn the player: %game.spawnPlayer( %client, %respawn ); messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined %2.', %client.name, $teamName[%team], %client, %team ); messageClient( %client, 'MsgClientJoinTeam', '\c1You joined the %2 team.', $client.name, $teamName[%client.team], %client, %client.team ); updateCanListenState( %client ); logEcho(%client.nameBase@" (cl "@%client@") joined team "@%client.team); } function DefaultGame::AIHasJoined(%game, %client) { //defined to prevent console spam } function DefaultGame::AIChangeTeam(%game, %client, %newTeam) { //make sure we're trying to drop an AI if (!isObject(%client) || !%client.isAIControlled()) return; //clear the ai from any objectives, etc... AIUnassignClient(%client); %client.stop(); %client.clearTasks(); %client.clearStep(); %client.lastDamageClient = -1; %client.lastDamageTurret = -1; %client.shouldEngage = -1; %client.setEngageTarget(-1); %client.setTargetObject(-1); %client.pilotVehicle = false; %client.defaultTasksAdded = false; //kill the player, which should cause the Game object to perform whatever cleanup is required. if (isObject(%client.player)) %client.player.scriptKill(0); //clean up the team rank array %game.removeFromTeamRankArray(%client); //assign the new team %client.team = %newTeam; if (%newTeam < 0) Game.assignClientTeam(%client); else { if ( %client.team & 1 ) { %client.skin = addTaggedString( "basebot" ); setTargetSkin( %client.target, 'basebot' ); } else { %client.skin = addTaggedString( "basebbot" ); setTargetSkin( %client.target, 'basebbot' ); } } messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1bot %1 has switched to team %2.', %client.name, $teamName[%client.team], %client, %client.team ); } function DefaultGame::clientChangeTeam(%game, %client, %team, %fromObs) { //first, remove the client from the team rank array //the player will be added to the new team array as soon as he respawns... %game.removeFromTeamRankArray(%client); %pl = %client.player; if(isObject(%pl)) { if(%pl.isMounted()) %pl.getDataBlock().doDismount(%pl); %pl.scriptKill(0); } // reset the client's targets and tasks only clientResetTargets(%client, true); // give this client a new handle to disassociate ownership of deployed objects if( %team $= "" && (%team > 0 && %team <= %game.numTeams)) { if( %client.team == 1 ) %client.team = 2; else %client.team = 1; } else %client.team = %team; // Set the client's skin: if (!%client.isAIControlled()) setTargetSkin( %client.target, $teamSkin[%client.team] ); setTargetSensorGroup( %client.target, %client.team ); %client.setSensorGroup( %client.team ); // Spawn the player: %client.lastSpawnPoint = %game.pickPlayerSpawn( %client ); %game.createPlayer( %client, %client.lastSpawnPoint, $MatchStarted ); if($MatchStarted) %client.setControlObject(%client.player); else { %client.camera.getDataBlock().setMode(%client.camera, "pre-game", %client.player); %client.setControlObject(%client.camera); } // call the onEvent for this game type %game.onClientEnterObserverMode(%client); //Bounty uses this to remove this client from others' hit lists if(%fromObs $= "" || !%fromObs) { messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 switched to team %2.', %client.name, $teamName[%client.team], %client, %client.team ); messageClient( %client, 'MsgClientJoinTeam', '\c1You switched to team %2.', $client.name, $teamName[%client.team], %client, %client.team ); } else { messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined team %2.', %client.name, $teamName[%team], %client, %team ); messageClient( %client, 'MsgClientJoinTeam', '\c1You joined team %2.', $client.name, $teamName[%client.team], %client, %client.team ); } updateCanListenState( %client ); // MES - switch objective hud lines when client switches teams messageClient(%client, 'MsgCheckTeamLines', "", %client.team); logEcho(%client.nameBase@" (cl "@%client@") switched to team "@%client.team); } // missioncleanup and missiongroup are checked prior to entering game code function DefaultGame::missionLoadDone(%game) { // walks through the mission group and sets the power stuff up // - groups get initialized with power count 0 then iterated to // increment powercount if an object within is powered // - powers objects up/down //MissionGroup.objectiveInit(); MissionGroup.clearPower(); MissionGroup.powerInit(0); %game.initGameVars(); //set up scoring variables and other game specific globals // make team0 visible/friendly to all setSensorGroupAlwaysVisMask(0, 0xffffffff); setSensorGroupFriendlyMask(0, 0xffffffff); // update colors: // - enemy teams are red // - same team is green // - team 0 is white for(%i = 0; %i < 32; %i++) { %team = (1 << %i); setSensorGroupColor(%i, %team, "0 255 0 255"); setSensorGroupColor(%i, ~%team, "255 0 0 255"); setSensorGroupColor(%i, 1, "255 255 255 255"); // setup the team targets (alwyas friendly and visible to same team) setTargetAlwaysVisMask(%i, %team); setTargetFriendlyMask(%i, %team); } //set up the teams %game.setUpTeams(); //clear out the team rank array... for (%i = 0; %i < 32; %i++) $TeamRank[%i, count] = ""; // objectiveInit has to take place after setupTeams -- objective HUD relies on flags // having their team set MissionGroup.objectiveInit(); //initialize the AI system %game.aiInit(); //need to reset the teams if we switch from say, CTF to Bounty... // assign the bots team if ($currentMissionType !$= $previousMissionType) { $previousMissionType = $currentMissionType; for(%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); if (%cl.isAIControlled()) %game.assignClientTeam(%cl); } } //Save off respawn or Siege Team switch information... if(%game.class !$= "SiegeGame") MissionGroup.setupPositionMarkers(true); echo("Default game mission load done."); } function DefaultGame::onClientLeaveGame(%game, %client) { // if there is a player attached to this client, kill it if( isObject(%client.player)) %client.player.scriptKill(0); //cancel a scheduled call... cancel(%client.respawnTimer); %client.respawnTimer = ""; //remove them from the team rank arrays %game.removeFromTeamRankArray(%client); logEcho(%client.nameBase@" (cl "@%client@") dropped"); } function DefaultGame::clientMissionDropReady(%game, %client) { //synchronize the clock HUD messageClient(%client, 'MsgSystemClock', "", 0, 0); %game.sendClientTeamList( %client ); %game.setupClientHuds( %client ); if($CurrentMissionType $= "SinglePlayer") { //CommandToClient( %client, 'setPlayContent'); return; } %observer = false; if( !$Host::TournamentMode ) { if( %client.camera.mode $= "observerFly" || %client.camera.mode $= "justJoined") { %observer = true; %client.observerStartTime = getSimTime(); commandToClient(%client, 'setHudMode', 'Observer'); %client.setControlObject( %client.camera ); //displayObserverHud( %client, 0 ); updateObserverFlyHud(%client); } if( !%observer ) { if(!$MatchStarted && !$CountdownStarted) // server has not started anything yet { %client.setControlObject( %client.camera ); commandToClient(%client, 'setHudMode', 'Observer'); } else if(!$MatchStarted && $CountdownStarted) // server has started the countdown { commandToClient(%client, 'setHudMode', 'Observer'); %client.setControlObject( %client.camera ); } else { commandToClient(%client, 'setHudMode', 'Standard'); // the game has already started %client.setControlObject( %client.player ); } } } else { // set all players into obs mode. setting the control object will handle further procedures... %client.camera.getDataBlock().setMode( %client.camera, "ObserverFly" ); commandToClient(%client, 'setHudMode', 'Observer'); %client.setControlObject( %client.camera ); messageAll( 'MsgClientJoinTeam', "",%client.name, $teamName[0], %client, 0 ); %client.team = 0; if( !$MatchStarted && !$CountdownStarted) { if($TeamDamage) %damMess = "ENABLED"; else %damMess = "DISABLED"; if(%game.numTeams > 1) BottomPrint(%client, "Server is Running in Tournament Mode.\nPick a Team\nTeam Damage is " @ %damMess, 0, 3 ); } else { BottomPrint( %client, "\nServer is Running in Tournament Mode", 0, 3 ); } } //make sure the objective HUD indicates your team on top and in green... if (%client.team > 0) messageClient(%client, 'MsgCheckTeamLines', "", %client.team); // were ready to go. %client.matchStartReady = true; echo("Client" SPC %client SPC "is ready."); if ( isDemoServer() ) { if ( %client.demoJustJoined ) { %client.demoJustJoined = false; centerPrint( %client, "Welcome to the Tribes 2 Demo." NL "You have been assigned the name \"" @ %client.nameBase @ "\"." NL "Press FIRE to join the game.", 0, 3 ); } } } function DefaultGame::sendClientTeamList(%game, %client) { // Send the client the current team list: %teamCount = %game.numTeams; for ( %i = 0; %i < %teamCount; %i++ ) { if ( %i > 0 ) %teamList = %teamList @ "\n"; %teamList = %teamList @ detag( getTaggedString( $teamName[%i + 1] ) ); } messageClient( %client, 'MsgTeamList', "", %teamCount, %teamList ); } function DefaultGame::setupClientHuds(%game, %client) { // tell the client to setup the huds... for(%i =0; %i<$WeaponsHudCount; %i++) %client.setWeaponsHudBitmap(%i, $WeaponsHudData[%i, itemDataName], $WeaponsHudData[%i, bitmapName]); for(%i =0; %i<$InventoryHudCount; %i++) %client.setInventoryHudBitmap($InventoryHudData[%i, slot], $InventoryHudData[%i, itemDataName], $InventoryHudData[%i, bitmapName]); %client.setWeaponsHudBackGroundBmp("gui/hud_new_panel"); %client.setWeaponsHudHighLightBmp("gui/hud_new_weaponselect"); %client.setWeaponsHudInfiniteAmmoBmp("gui/hud_infinity"); %client.setInventoryHudBackGroundBmp("gui/hud_new_panel"); // tell the client if we are protecting statics (so no health bar will be displayed) commandToClient(%client, 'protectingStaticObjects', %game.allowsProtectedStatics()); commandToClient(%client, 'setPowerAudioProfiles', sPowerUp.getId(), sPowerDown.getId()); } function DefaultGame::testDrop( %game, %client ) { %game.clientJoinTeam( %client, 1, false ); %client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player ); %client.setControlObject( %client.camera ); CommandToClient( %client, 'setPlayContent' ); } function DefaultGame::onClientEnterObserverMode( %game, %client ) { // Default game doesn't care... } // from 'item.cs' function DefaultGame::playerTouchFlag(%game, %player, %flag) { messageAll('MsgPlayerTouchFlag', 'Player %1 touched flag %2', %player, %flag); } // from 'item.cs' function DefaultGame::playerDroppedFlag(%game, %player, %flag) { messageAll('MsgPlayerDroppedFlag', 'Player %1 dropped flag %2', %player, %flag); } // from 'staticShape.cs' function DefaultGame::flagStandCollision(%game, %dataBlock, %obj, %colObj) { // for retreiveGame } function DefaultGame::notifyMineDeployed(%game, %mine) { //do nothign in the default game... } // from 'staticshape.cs' function DefaultGame::findProjector(%game, %flipflop) { // search the flipflop's folder for a holo projector // if one exists, associate it with the flipflop %flipflop.projector = 0; %folder = %flipflop.getGroup(); for(%i = 0; %i < %folder.getCount(); %i++) { %proj = %folder.getObject(%i); if(%proj.getDatablock().getName() $= "LogoProjector") { %flipflop.projector = %proj; %flipflop.projector.holo = 0; break; } } } //****************************************************************************** //* DefaultGame Trigger - Functions * //****************************************************************************** /// -Trigger- ////////////////////////////////////////////////////////////////// //Function -- onEnterTrigger (%game, %name, %data, %obj, %colObj) // %game = Current game type object // %name = Trigger name - defined when trigger is created // %data = Trigger Data Block // %obj = Trigger Object // %colObj = Object that collided with the trigger //Decription -- Called when trigger has been triggered //////////////////////////////////////////////////////////////////////////////// // from 'trigger.cs' function DefaultGame::onEnterTrigger(%game, %triggerName, %data, %obj, %colobj) { //Do Nothing } /// -Trigger- ////////////////////////////////////////////////////////////////// //Function -- onLeaveTrigger (%game, %name, %data, %obj, %colObj) // %game = Current game type object // %name = Trigger name - defined when trigger is created // %data = Trigger Data Block // %obj = Trigger Object // %colObj = Object that collided with the trigger //Decription -- Called when trigger has been untriggered //////////////////////////////////////////////////////////////////////////////// // from 'trigger.cs' function DefaultGame::onLeaveTrigger(%game, %triggerName, %data, %obj, %colobj) { //Do Nothing } /// -Trigger- ////////////////////////////////////////////////////////////////// //Function -- onTickTrigger(%game, %name, %data, %obj) // %game = Current game type object // %name = Trigger name - defined when trigger is created // %data = Trigger Data Block // %obj = Trigger Object //Decription -- Called every tick if triggered //////////////////////////////////////////////////////////////////////////////// // from 'trigger.cs' function DefaultGame::onTickTrigger(%game, %triggerName, %data, %obj) { //Do Nothing } function DefaultGame::setUpTeams(%game) { %group = nameToID("MissionGroup/Teams"); if(%group == -1) return; // create a team0 if it does not exist %team = nameToID("MissionGroup/Teams/team0"); if(%team == -1) { %team = new SimGroup("team0"); %group.add(%team); } // 'team0' is not counted as a team here %game.numTeams = 0; while(%team != -1) { // create drop set and add all spawnsphere objects into it %dropSet = new SimSet("TeamDrops" @ %game.numTeams); MissionCleanup.add(%dropSet); %spawns = nameToID("MissionGroup/Teams/team" @ %game.numTeams @ "/SpawnSpheres"); if(%spawns != -1) { %count = %spawns.getCount(); for(%i = 0; %i < %count; %i++) %dropSet.add(%spawns.getObject(%i)); } // set the 'team' field for all the objects in this team %team.setTeam(%game.numTeams); clearVehicleCount(%team+1); // get next group %team = nameToID("MissionGroup/Teams/team" @ %game.numTeams + 1); if (%team != -1) %game.numTeams++; } // set the number of sensor groups (including team0) that are processed setSensorGroupCount(%game.numTeams + 1); } function SimGroup::setTeam(%this, %team) { for (%i = 0; %i < %this.getCount(); %i++) { %obj = %this.getObject(%i); switch$ (%obj.getClassName()) { case SpawnSphere : if($MatchStarted) { // find out what team the spawnsphere used to belong to %found = false; for(%l = 1; %l <= Game.numTeams; %l++) { %drops = nameToId("MissionCleanup/TeamDrops" @ %l); for(%j = 0; %j < %drops.getCount(); %j++) { %current = %drops.getObject(%j); if(%current == %obj) %found = %l; } } if(%team != %found) Game.claimSpawn(%obj, %team, %found); else error("spawn "@%obj@" is already on team "@%team@"!"); } else Game.claimSpawn(%obj, %team, ""); case SimGroup : %obj.setTeam(%team); default : %obj.team = %team; } if(%obj.getType() & $TypeMasks::GameBaseObjectType) { // eeck.. please go away when scripts get cleaned... if(%obj.getDataBlock().getName() $= "StationVehiclePad") %obj = %obj.station; %target = %obj.getTarget(); if(%target != -1) setTargetSensorGroup(%target, %team); } } } function DefaultGame::claimSpawn(%game, %obj, %newTeam, %oldTeam) { if(%newTeam == %oldTeam) return; %newSpawnGroup = nameToId("MissionCleanup/TeamDrops" @ %newTeam); if(%oldTeam !$= "") { %oldSpawnGroup = nameToId("MissionCleanup/TeamDrops" @ %oldTeam); %oldSpawnGroup.remove(%obj); } %newSpawnGroup.add(%obj); } // recursive function to assign teams to all mission objects function SimGroup::swapTeams(%this) { // used in Siege only Game.groupSwapTeams(%this); } function ShapeBase::swapTeams(%this) { // used in Siege only Game.objectSwapTeams(%this); } function GameBase::swapTeams(%this) { // used in Siege only Game.objectSwapTeams(%this); } function TSStatic::swapTeams(%this) { // used in Siege only // do nothing } function InteriorInstance::swapTeams(%this) { // used in Siege only // do nothing -- interiors don't switch teams } function SimGroup::swapVehiclePads(%this) { // used in Siege only Game.groupSwapVehiclePads(%this); } function ShapeBase::swapVehiclePads(%this) { // used in Siege only Game.objectSwapVehiclePads(%this); } function GameBase::swapVehiclePads(%this) { // used in Siege only // do nothing -- only searching for vehicle pads } function InteriorInstance::swapVehiclePads(%this) { // used in Siege only // do nothing -- only searching for vehicle pads } function SimSet::swapVehiclePads(%this) { // used in Siege only // do nothing -- only searching for vehicle pads } function PhysicalZone::swapVehiclePads(%this) { // used in Siege only // do nothing -- only searching for vehicle pads } function SimGroup::objectRestore(%this) { // used in Siege only Game.groupObjectRestore(%this); } function ShapeBase::objectRestore(%object) { // only used for Siege Game.shapeObjectRestore(%object); } function Turret::objectRestore(%object) { // only used for Siege Game.shapeObjectRestore(%object); } function AIObjective::objectRestore(%object) { // only used for Siege // don't do anything for AI Objectives } function DefaultGame::checkObjectives(%game) { //any special objectives that can be met by gametype //none for default game } //--------------------------------------------------- function DefaultGame::checkTimeLimit(%game, %forced) { // Don't add extra checks: if ( %forced ) cancel( %game.timeCheck ); // if there is no time limit, check back in a minute to see if it's been set if(($Host::TimeLimit $= "") || $Host::TimeLimit == 0) { %game.timeCheck = %game.schedule(20000, "checkTimeLimit"); return; } %curTimeLeftMS = ($Host::TimeLimit * 60 * 1000) + $missionStartTime - getSimTime(); if (%curTimeLeftMS <= 0) { // time's up, put down your pencils %game.timeLimitReached(); } else { if(%curTimeLeftMS >= 20000) %game.timeCheck = %game.schedule(20000, "checkTimeLimit"); else %game.timeCheck = %game.schedule(%curTimeLeftMS + 1, "checkTimeLimit"); //now synchronize everyone's clock messageAll('MsgSystemClock', "", $Host::TimeLimit, %curTimeLeftMS); } } function listplayers() { for(%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); %status = ""; if(%cl.isAiControlled()) %status = "Bot "; if(%cl.isSmurf) %status = "Alias "; if(%cl.isAdmin) %status = %status @ "Admin "; if(%cl.isSuperAdmin) %status = %status @ "SuperAdmin "; if(%status $= "") %status = ""; echo("client: " @ %cl @ " player: " @ %cl.player @ " name: " @ %cl.nameBase @ " team: " @ %cl.team @ " status: " @ %status); } } function logEcho(%msg) { if($LogEchoEnabled) echo("LOG: " @ %msg); } function DefaultGame::clearTeamRankArray(%game, %team) { %count = $TeamRank[%team, count]; for (%i = 0; %i < %count; %i++) $TeamRank[%team, %i] = ""; $TeamRank[%team, count] = 0; } function DefaultGame::populateTeamRankArray(%game, %client) { //this function should be called *after* the client has been added to a team... if (%client <= 0 || %client.team <= 0) return; //find the team if (%game.numTeams == 1) %team = 0; else %team = %client.team; //find the number of teammates already ranked... %count = $TeamRank[%team, count]; if (%count $= "") { $TeamRank[%team, count] = 0; %count = 0; } //make sure we're not already in the array for (%i = 0; %i < %count; %i++) { if ($TeamRank[%team, %i] == %client) return; } //add the client in at the bottom of the list, and increment the count $TeamRank[%team, %count] = %client; $TeamRank[%team, count] = $TeamRank[%team, count] + 1; //now recalculate the team rank for this player %game.recalcTeamRanks(%client); } function DefaultGame::removeFromTeamRankArray(%game, %client) { //note, this should be called *before* the client actually switches teams or drops... if (%client <= 0 || %client.team <= 0) return; //find the correct team if (%game.numTeams == 1) %team = 0; else %team = %client.team; //now search throught the team rank array, looking for this client %count = $TeamRank[%team, count]; for (%i = 0; %i < %count; %i++) { if ($TeamRank[%team, %i] == %client) { //we've found the client in the array, now loop through, and move everyone else up a rank for (%j = %i + 1; %j < %count; %j++) { %cl = $TeamRank[%team, %j]; $TeamRank[%team, %j - 1] = %cl; messageClient(%cl, 'MsgYourRankIs', "", %j); } //now decriment the team rank array count, and break $TeamRank[%team, count] = $TeamRank[%team, count] - 1; break; } } } function DefaultGame::recalcTeamRanks(%game, %client) { if (%client <= 0 || %client.team <= 0) return; // this is a little confusing -- someone's actual numerical rank is always // one number higher than his index in the $TeamRank array // (e.g. person ranked 1st has index of 0) // TINMAN: I'm going to remove the %client.teamRank field - the index in the // $TeamRank array already contains their rank - safer to search the array than // to maintiain the information in a separate variable... //find the team, the client in the team array if (%game.numTeams == 1) %team = 0; else %team = %client.team; %count = $TeamRank[%team, count]; %index = -1; for (%i = 0; %i < %count; %i++) { if ($TeamRank[%team, %i] == %client) { %index = %i; break; } } //if they weren't found in the array, return if (%index < 0) return; //make sure far down the array as they should be... %tempIndex = %index; %swapped = false; while (true) { if (%tempIndex <= 0) break; %tempIndex--; %tempClient = $TeamRank[%team, %tempIndex]; //see if we should swap the two if (%client.score > %tempClient.score) { %swapped = true; %index = %tempIndex; $TeamRank[%team, %tempIndex] = %client; $TeamRank[%team, %tempIndex + 1] = %tempClient; messageClient(%tempClient, 'MsgYourRankIs', "", %tempIndex + 2); } } //if we've swapped up at least once, we obviously won't need to swap down as well... if (%swapped) { messageClient(%client, 'MsgYourRankIs', "", %index + 1); return; } //since we didnt' swap up, see if we need to swap down... %tempIndex = %index; %swapped = false; while (true) { if (%tempIndex >= %count - 1) break; %tempIndex++; %tempClient = $TeamRank[%team, %tempIndex]; //see if we should swap the two if (%client.score < %tempClient.score) { %swapped = true; %index = %tempIndex; $TeamRank[%team, %tempIndex] = %client; $TeamRank[%team, %tempIndex - 1] = %tempClient; messageClient(%tempClient, 'MsgYourRankIs', "", %tempIndex); } } //send the message (regardless of whether a swap happened or not) messageClient(%client, 'MsgYourRankIs', "", %index + 1); } function DefaultGame::recalcScore(%game, %cl) { %game.recalcTeamRanks(%cl); } function DefaultGame::testKill(%game, %victimID, %killerID) { return ((%killerID !=0) && (%victimID.team != %killerID.team)); } function DefaultGame::testSuicide(%game, %victimID, %killerID, %damageType) { return ((%victimID == %killerID) || (%damageType == $DamageType::Ground) || (%damageType == $DamageType::Suicide)); } function DefaultGame::testTeamKill(%game, %victimID, %killerID) { return (%killerID.team == %victimID.team); } function DefaultGame::testTurretKill(%game, %implement) { if(%implement == 0) return false; else return (%implement.getClassName() $= "Turret"); } // function DefaultGame::awardScoreFlagCap(%game, %cl) // { // %cl.flagCaps++; // $TeamScore[%cl.team] += %game.SCORE_PER_TEAM_FLAG_CAP; // messageAll('MsgCTFTeamScore', "", %cl.team, $TeamScore[%cl.team]); // // if (%game.SCORE_PER_PLYR_FLAG_CAP > 1) // %plural = "s"; // else // %plural = ""; // // if (%game.SCORE_PER_PLYR_FLAG_CAP != 0) // messageClient(%cl, 'scoreFlaCapMsg', 'You received %1 point%2 for capturing the flag.', %game.SCORE_PER_PLYR_FLAG_CAP, %plural); // %game.recalcScore(%cl); // } function DefaultGame::testOOBDeath(%game, %damageType) { return (%damageType == $DamageType::OutOfBounds); } function DefaultGame::awardScoreTurretKill(%game, %victimID, %implement) { if ((%killer = %implement.getControllingClient()) != 0) //award whoever might be controlling the turret { if (%killer == %victimID) %game.awardScoreSuicide(%victimID); else if (%killer.team == %victimID.team) //player controlling a turret killed a teammate { %killer.teamKills++; %game.awardScoreTurretTeamKill(%victimID, %killer); %game.awardScoreDeath(%victimID); } else { %killer.turretKills++; %game.recalcScore(%killer); %game.awardScoreDeath(%victimID); } } else if ((%killer = %implement.owner) != 0) //if it isn't controlled, award score to whoever deployed it { if (%killer.team == %victimID.team) { %game.awardScoreDeath(%victimID); } else { %killer.turretKills++; %game.recalcScore(%killer); %game.awardScoreDeath(%victimID); } } //default is, no one was controlling it, no one owned it. No score given. } function DefaultGame::awardScoreDeath(%game, %victimID) { %victimID.deaths++; if ( %game.SCORE_PER_DEATH != 0 ) { // %plural = (abs(%game.SCORE_PER_DEATH) != 1 ? "s" : ""); // messageClient(%victimID, 'MsgScoreDeath', '\c0You have been penalized %1 point%2 for dying.', abs(%game.SCORE_PER_DEATH), %plural); %game.recalcScore(%victimID); } } function DefaultGame::awardScoreKill(%game, %killerID) { %killerID.kills++; %game.recalcScore(%killerID); } function DefaultGame::awardScoreSuicide(%game, %victimID) { %victimID.suicides++; // if (%game.SCORE_PER_SUICIDE != 0) // messageClient(%victimID, 'MsgScoreSuicide', '\c0You have been penalized for killing yourself.'); %game.recalcScore(%victimID); } function DefaultGame::awardScoreTeamkill(%game, %victimID, %killerID) { %killerID.teamKills++; if (%game.SCORE_PER_TEAMKILL != 0) messageClient(%killerID, 'MsgScoreTeamkill', '\c0You have been penalized for killing teammate %1.', %victimID.name); %game.recalcScore(%killerID); } function DefaultGame::awardScoreTurretTeamKill(%game, %victimID, %killerID) { %killerID.teamKills++; if (%game.SCORE_PER_TEAMKILL != 0) messageClient(%killerID, 'MsgScoreTeamkill', '\c0You have been penalized for killing your teammate %1, with a turret.', %victimID.name); %game.recalcScore(%killerID); } function DefaultGame::objectRepaired(%game, %obj, %objName) { %item = %obj.getDataBlock().getName(); //echo("Item repaired is a " @ %item); switch$ (%item) { case generatorLarge : %game.genOnRepaired(%obj, %objName); case stationInventory : %game.stationOnRepaired(%obj, %objName); case sensorMediumPulse : %game.sensorOnRepaired(%obj, %objName); case sensorLargePulse : %game.sensorOnRepaired(%obj, %objName); case turretBaseLarge : %game.turretOnRepaired(%obj, %objName); case stationVehicle : %game.vStationOnRepaired(%obj, %objName); default: //unused by current gametypes. Add more checks here if desired } } function DefaultGame::allowsProtectedStatics(%game) { return false; } // jff: why is game object doing this? //Return a simple string with no extras function DefaultGame::cleanWord(%game, %this) { %length = strlen(%this); for(%i = 0; %i < %length; %i++) { %char = getSubStr(%this, %i, 1); if(%char $= "_") { %next = getSubStr(%this, (%i+1), 1); if(%next $= "_") { %char = "'"; //apostrophe (2 chars) %i++; } else %char = " "; //space } %clean = (%clean @ %char); } } function DefaultGame::stationOnEnterTrigger(%game, %data, %obj, %colObj) { return true; } function DefaultGame::WeaponOnUse(%game, %data, %obj) { return true; } function DefaultGame::HandInvOnUse(%game, %data, %obj) { return true; } function DefaultGame::WeaponOnInventory(%game, %this, %obj, %amount) { return true; } function DefaultGame::ObserverOnTrigger(%game, %data, %obj, %trigger, %state) { return true; } // jff: why is the game being notified that a weapon is being thrown? hot potato gametype? function DefaultGame::ShapeThrowWeapon(%game, %this) { return true; } function DefaultGame::leaveMissionArea(%game, %playerData, %player) { if(%player.getState() $= "Dead") return; %player.client.outOfBounds = true; messageClient(%player.client, 'LeaveMissionArea', '\c1You left the mission area.~wfx/misc/warning_beep.wav'); } function DefaultGame::enterMissionArea(%game, %playerData, %player) { if(%player.getState() $= "Dead") return; %player.client.outOfBounds = false; messageClient(%player.client, 'EnterMissionArea', '\c1You are back in the mission area.'); } //------------------------------------------------------------------------------ // AI stubs: //------------------------------------------------------------------------------ function DefaultGame::onAIDamaged(%game, %clVictim, %clAttacker, %damageType, %sourceObject) { } function DefaultGame::onAIFriendlyFire(%game, %clVictim, %clAttacker, %damageType, %sourceObject) { } function DefaultGame::onAIKilled(%game, %clVictim, %clKiller, %damageType, %implement) { //unassign the client from any objectives AIUnassignClient(%clVictim); //break the link, if this ai is controlled aiReleaseHumanControl(%clVictim.controlByHuman, %clVictim); //and schedule the respawn %clVictim.respawnThread = schedule(5000, %clVictim, "onAIRespawn", %clVictim); } function DefaultGame::onAIKilledClient(%game, %clVictim, %clAttacker, %damageType, %implement) { %clAttacker.setVictim(%clVictim, %clVictim.player); } //------------------------------------------------------------------------------ // Voting stuff: //------------------------------------------------------------------------------ function DefaultGame::sendGamePlayerPopupMenu( %game, %client, %targetClient, %key ) { if( !%targetClient.matchStartReady ) return; %isAdmin = ( %client.isAdmin || %client.isSuperAdmin ); %isTargetSelf = ( %client == %targetClient ); %isTargetAdmin = ( %targetClient.isAdmin || %targetClient.isSuperAdmin ); %isTargetBot = %targetClient.isAIControlled(); %isTargetObserver = ( %targetClient.team == 0 ); %outrankTarget = false; if ( %client.isSuperAdmin ) %outrankTarget = !%targetClient.isSuperAdmin; else if ( %client.isAdmin ) %outrankTarget = !%targetClient.isAdmin; if( %client.isSuperAdmin && %targetClient.guid != 0 && !isDemo() && !isDemoServer()) { messageClient( %client, 'MsgPlayerPopupItem', "", %key, "addAdmin", "", 'Add to Server Admin List', 10); messageClient( %client, 'MsgPlayerPopupItem', "", %key, "addSuperAdmin", "", 'Add to Server SuperAdmin List', 11); } //mute options if ( !%isTargetSelf ) { if ( %client.muted[%targetClient] ) messageClient( %client, 'MsgPlayerPopupItem', "", %key, "MutePlayer", "", 'Unmute Text Chat', 1); else messageClient( %client, 'MsgPlayerPopupItem', "", %key, "MutePlayer", "", 'Mute Text Chat', 1); if ( !%isTargetBot && %client.canListenTo( %targetClient ) ) { if ( %client.getListenState( %targetClient ) ) messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ListenPlayer", "", 'Disable Voice Com', 9 ); else messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ListenPlayer", "", 'Enable Voice Com', 9 ); } } if( !%client.canVote && !%isAdmin ) return; // regular vote options on players if ( %game.scheduleVote $= "" && !%isAdmin && !%isTargetAdmin ) { if ( $Host::allowAdminPlayerVotes && !%isTargetBot && !isDemo() && !isDemoServer()) messageClient( %client, 'MsgPlayerPopupItem', "", %key, "AdminPlayer", "", 'Vote to Make Admin', 2 ); if ( !%isTargetSelf ) { messageClient( %client, 'MsgPlayerPopupItem', "", %key, "KickPlayer", "", 'Vote to Kick', 3 ); } } // Admin only options on players: else if ( %isAdmin && !isDemo() && !isDemoServer()) { if ( !%isTargetBot && !%isTargetAdmin ) messageClient( %client, 'MsgPlayerPopupItem', "", %key, "AdminPlayer", "", 'Make Admin', 2 ); if ( !%isTargetSelf && %outrankTarget ) { messageClient( %client, 'MsgPlayerPopupItem', "", %key, "KickPlayer", "", 'Kick', 3 ); if ( !%isTargetBot ) { if( %client.isSuperAdmin ) messageClient( %client, 'MsgPlayerPopupItem', "", %key, "BanPlayer", "", 'Ban', 4 ); if ( !%isTargetObserver ) messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ToObserver", "", 'Force observer', 5 ); } } if ( %isTargetSelf || %outrankTarget ) { if ( %game.numTeams > 1 ) { if ( %isTargetObserver ) { %action = %isTargetSelf ? "Join " : "Change to "; %str1 = %action @ getTaggedString( $TeamName[1] ); %str2 = %action @ getTaggedString( $TeamName[2] ); messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ChangeTeam", "", %str1, 6 ); messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ChangeTeam", "", %str2, 7 ); } else { %changeTo = %targetClient.team == 1 ? 2 : 1; %str = "Switch to " @ getTaggedString( $TeamName[%changeTo] ); %caseId = 5 + %changeTo; messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ChangeTeam", "", %str, %caseId ); } } else if ( %isTargetObserver ) { %str = %isTargetSelf ? 'Join the Game' : 'Add to Game'; messageClient( %client, 'MsgPlayerPopupItem', "", %key, "JoinGame", "", %str, 8 ); } } } } //------------------------------------------------------------------------------ function DefaultGame::sendGameVoteMenu( %game, %client, %key ) { %isAdmin = ( %client.isAdmin || %client.isSuperAdmin ); %multipleTeams = %game.numTeams > 1; // no one is going anywhere until this thing starts if($MatchStarted) { // Client options: if ( %client.team != 0 ) { if ( %multipleTeams ) if( !$Host::TournamentMode ) messageClient( %client, 'MsgVoteItem', "", %key, 'ChooseTeam', "", 'Change your Team' ); messageClient( %client, 'MsgVoteItem', "", %key, 'MakeObserver', "", 'Become an Observer' ); } else { if(!%multipleTeams && !$Host::TournamentMode) messageClient( %client, 'MsgVoteItem', "", %key, 'JoinGame', "", 'Join the Game' ); } //%totalSlots = $Host::maxPlayers - ($HostGamePlayerCount + $HostGameBotCount); // if( $HostGameBotCount > 0 && %totalSlots > 0 && %client.isAdmin) //messageClient( %client, 'MsgVoteItem', "", %key, 'Addbot', "", 'Add a Bot' ); } if( !%client.canVote && !%isAdmin ) return; if (isDemo() || isDemoServer()) return; if ( %game.scheduleVote $= "" ) { if(!%client.isAdmin) { // Actual vote options: messageClient( %client, 'MsgVoteItem', "", %key, 'VoteChangeMission', 'change the mission to', 'Vote to Change the Mission' ); if( $Host::TournamentMode ) { messageClient( %client, 'MsgVoteItem', "", %key, 'VoteFFAMode', 'Change server to Free For All.', 'Vote Free For All Mode' ); if(!$MatchStarted && !$CountdownStarted) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteMatchStart', 'Start Match', 'Vote to Start the Match' ); } else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTournamentMode', 'Change server to Tournament.', 'Vote Tournament Mode' ); if ( %multipleTeams ) { if(!$MatchStarted && !$Host::TournamentMode) messageClient( %client, 'MsgVoteItem', "", %key, 'ChooseTeam', "", 'Change your Team' ); if ( $teamDamage ) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'disable team damage', 'Vote to Disable Team Damage' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'enable team damage', 'Vote to Enable Team Damage' ); } } else { // Actual vote options: messageClient( %client, 'MsgVoteItem', "", %key, 'VoteChangeMission', 'change the mission to', 'Change the Mission' ); if( $Host::TournamentMode ) { messageClient( %client, 'MsgVoteItem', "", %key, 'VoteFFAMode', 'Change server to Free For All.', 'Free For All Mode' ); if(!$MatchStarted && !$CountdownStarted) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteMatchStart', 'Start Match', 'Start Match' ); } else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTournamentMode', 'Change server to Tournament.', 'Tournament Mode' ); if ( %multipleTeams ) { if(!$MatchStarted) messageClient( %client, 'MsgVoteItem', "", %key, 'ChooseTeam', "", 'Choose Team' ); if ( $teamDamage ) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'disable team damage', 'Disable Team Damage' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'enable team damage', 'Enable Team Damage' ); } } } // Admin only options: if ( %client.isAdmin ) { messageClient( %client, 'MsgVoteItem', "", %key, 'VoteChangeTimeLimit', 'change the time limit', 'Change the Time Limit' ); messageClient( %client, 'MsgVoteItem', "", %key, 'VoteResetServer', 'reset server defaults', 'Reset the Server' ); } } //------------------------------------------------------------------------------ function DefaultGame::sendGameTeamList( %game, %client, %key ) { %teamCount = %game.numTeams; if ( %teamCount < 2 ) { warn( "Team menu requested for one-team game!" ); return; } for ( %team = 1; %team - 1 < %teamCount; %team++ ) messageClient( %client, 'MsgVoteItem', "", %key, %team, "", detag( getTaggedString( $teamName[%team] ) ) ); } //------------------------------------------------------------------------------ function DefaultGame::sendTimeLimitList( %game, %client, %key ) { messageClient( %client, 'MsgVoteItem', "", %key, 10, "", '10 minutes' ); messageClient( %client, 'MsgVoteItem', "", %key, 15, "", '15 minutes' ); messageClient( %client, 'MsgVoteItem', "", %key, 20, "", '20 minutes' ); messageClient( %client, 'MsgVoteItem', "", %key, 25, "", '25 minutes' ); messageClient( %client, 'MsgVoteItem', "", %key, 30, "", '30 minutes' ); messageClient( %client, 'MsgVoteItem', "", %key, 45, "", '45 minutes' ); messageClient( %client, 'MsgVoteItem', "", %key, 60, "", '60 minutes' ); messageClient( %client, 'MsgVoteItem', "", %key, 999, "", 'No time limit' ); } //------------------------------------------------------------------------------ // all global votes here // this function was created to remove the call to "eval", which is non-functional in PURE servers... function DefaultGame::evalVote(%game, %typeName, %admin, %arg1, %arg2, %arg3, %arg4) { switch$ (%typeName) { case "voteChangeMission": %game.voteChangeMission(%admin, %arg1, %arg2, %arg3, %arg4); case "voteTeamDamage": %game.voteTeamDamage(%admin, %arg1, %arg2, %arg3, %arg4); case "voteTournamentMode": %game.voteTournamentMode(%admin, %arg1, %arg2, %arg3, %arg4); case "voteMatchStart": %game.voteMatchStart(%admin, %arg1, %arg2, %arg3, %arg4); case "voteFFAMode": %game.voteFFAMode(%admin, %arg1, %arg2, %arg3, %arg4); case "voteChangeTimeLimit": %game.voteChangeTimeLimit(%admin, %arg1, %arg2, %arg3, %arg4); case "voteResetServer": %game.voteResetServer(%admin, %arg1, %arg2, %arg3, %arg4); case "voteKickPlayer": %game.voteKickPlayer(%admin, %arg1, %arg2, %arg3, %arg4); case "voteAdminPlayer": %game.voteAdminPlayer(%admin, %arg1, %arg2, %arg3, %arg4); case "voteGreedMode": %game.voteGreedMode(%admin, %arg1, %arg2, %arg3, %arg4); case "voteHoardMode": %game.voteHoardMode(%admin, %arg1, %arg2, %arg3, %arg4); } } function DefaultGame::voteChangeMission(%game, %admin, %missionDisplayName, %typeDisplayName, %missionId, %missionTypeId) { %mission = $HostMissionFile[%missionId]; if ( %mission $= "" ) { error( "Invalid mission index passed to DefaultGame::voteChangeMission!" ); return; } %missionType = $HostTypeName[%missionTypeId]; if ( %missionType $= "" ) { error( "Invalid mission type id passed to DefaultGame::voteChangeMission!" ); return; } if(%admin) { messageAll('MsgAdminChangeMission', '\c2The Admin has changed the mission to %1 (%2).', %missionDisplayName, %typeDisplayName ); logEcho("mission changed to "@%missionDisplayName@"/"@%typeDisplayName@" (admin)"); %game.gameOver(); loadMission( %mission, %missionType, false ); } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { messageAll('MsgVotePassed', '\c2The mission was changed to %1 (%2) by vote.', %missionDisplayName, %typeDisplayName ); logEcho("mission changed to "@%missionDisplayName@"/"@%typeDisplayName@" (vote)"); %game.gameOver(); loadMission( %mission, %missionType, false ); } else messageAll('MsgVoteFailed', '\c2Change mission vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); } } //------------------------------------------------------------------------------ function DefaultGame::voteTeamDamage(%game, %admin) { %setto = ""; %cause = ""; if(%admin) { if($teamDamage) { messageAll('MsgAdminForce', '\c2The Admin has disabled team damage.'); $Host::TeamDamageOn = $TeamDamage = 0; %setto = "disabled"; } else { messageAll('MsgAdminForce', '\c2The Admin has enabled team damage.'); $Host::TeamDamageOn = $TeamDamage = 1; %setto = "enabled"; } %cause = "(admin)"; } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { if($teamDamage) { messageAll('MsgVotePassed', '\c2Team damage was disabled by vote.'); $Host::TeamDamageOn = $TeamDamage = 0; %setto = "disabled"; } else { messageAll('MsgVotePassed', '\c2Team damage was enabled by vote.'); $Host::TeamDamageOn = $TeamDamage = 1; %setto = "enabled"; } %cause = "(vote)"; } else { if($teamDamage) messageAll('MsgVoteFailed', '\c2Disable team damage vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); else messageAll('MsgVoteFailed', '\c2Enable team damage vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); } } if(%setto !$= "") logEcho("team damage "@%setto SPC %cause); } //------------------------------------------------------------------------------ function DefaultGame::voteTournamentMode( %game, %admin, %missionDisplayName, %typeDisplayName, %missionId, %missionTypeId ) { %mission = $HostMissionFile[%missionId]; if ( %mission $= "" ) { error( "Invalid mission index passed to DefaultGame::voteTournamentMode!" ); return; } %missionType = $HostTypeName[%missionTypeId]; if ( %missionType $= "" ) { error( "Invalid mission type id passed to DefaultGame::voteTournamentMode!" ); return; } %cause = ""; if (%admin) { messageAll( 'MsgAdminForce', '\c2The Admin has switched the server to Tournament mode (%1).', %missionDisplayName ); setModeTournament( %mission, %missionType ); %cause = "(admin)"; } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { messageAll('MsgVotePassed', '\c2Server switched to Tournament mode by vote (%1): %2 percent.', %missionDisplayName, mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); setModeTournament( %mission, %missionType ); %cause = "(vote)"; } else messageAll('MsgVoteFailed', '\c2Tournament mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); } if(%cause !$= "") logEcho("tournament mode set "@%cause); } //------------------------------------------------------------------------------ function DefaultGame::voteMatchStart( %game, %admin) { %cause = ""; %ready = forceTourneyMatchStart(); if(%admin) { if(!%ready) { messageClient( %client, 'msgClient', '\c2No players are ready yet.'); return; } else { messageAll('msgMissionStart', '\c2The admin has forced the match to start.'); %cause = "(admin)"; startTourneyCountdown(); } } else { if(!%ready) { messageAll( 'msgClient', '\c2Vote passed to start match, but no players are ready yet.'); return; } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { messageAll('MsgVotePassed', '\c2The match has been started by vote: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); startTourneyCountdown(); } else messageAll('MsgVoteFailed', '\c2Start Match vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); } } if(%cause !$= "") logEcho("start match "@%cause); } //------------------------------------------------------------------------------ function DefaultGame::voteFFAMode( %game, %admin, %client ) { %cause = ""; %name = getTaggedString(%client.name); if (%admin) { messageAll('MsgAdminForce', '\c2The Admin has switched the server to Free For All mode.', %client); setModeFFA($CurrentMission, $CurrentMissionType); %cause = "(admin)"; } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { messageAll('MsgVotePassed', '\c2Server switched to Free For All mode by vote.', %client); setModeFFA($CurrentMission, $CurrentMissionType); %cause = "(vote)"; } else messageAll('MsgVoteFailed', '\c2Free For All mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); } if(%cause !$= "") logEcho("free for all set "@%cause); } //------------------------------------------------------------------------------ function DefaultGame::voteChangeTimeLimit( %game, %admin, %newLimit ) { %cause = ""; if ( %admin ) { messageAll( 'MsgAdminForce', '\c2The Admin changed the mission time limit to %1 minutes.', %newLimit ); $Host::TimeLimit = %newLimit; %cause = "(admin)"; } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { messageAll('MsgVotePassed', '\c2The mission time limit was set to %1 minutes by vote.', %newLimit); $Host::TimeLimit = %newLimit; %cause = "(vote)"; } else messageAll('MsgVoteFailed', '\c2The vote to change the mission time limit did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); } //if the time limit was actually changed... if(%cause !$= "") { logEcho("time limit set to "@%newLimit SPC %cause); //if the match has been started, reset the end of match countdown if ($matchStarted) { //schedule the end of match countdown %elapsedTimeMS = getSimTime() - $missionStartTime; %curTimeLeftMS = ($Host::TimeLimit * 60 * 1000) - %elapsedTimeMS; //error("time limit="@$Host::TimeLimit@", elapsed="@(%elapsedTimeMS / 60000)@", curtimeleftms="@%curTimeLeftMS); CancelEndCountdown(); EndCountdown(%curTimeLeftMS); %game.checkTimeLimit(true); } } } //------------------------------------------------------------------------------ function DefaultGame::voteResetServer( %game, %admin, %client ) { %cause = ""; if ( %admin ) { messageAll( 'AdminResetServer', '\c2The Admin has reset the server.' ); resetServerDefaults(); %cause = "(admin)"; } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { messageAll('MsgVotePassed', '\c2The Server has been reset by vote.' ); resetServerDefaults(); %cause = "(vote)"; } else messageAll('MsgVoteFailed', '\c2The vote to reset Server to defaults did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); } if(%cause !$= "") logEcho("server reset "@%cause); } //------------------------------------------------------------------------------ // all team based votes here function DefaultGame::voteKickPlayer(%game, %admin, %client) { %cause = ""; if(%admin) { kick(%client, %admin, %client.guid ); %cause = "(admin)"; } else { //%team = %client.team; %totalVotes = %game.votesFor[%game.kickTeam] + %game.votesAgainst[%game.kickTeam]; if(%totalVotes > 0 && (%game.votesFor[%game.kickTeam] / %totalVotes) > ($Host::VotePasspercent / 100)) { kick(%client, %admin, %game.kickGuid); %cause = "(vote)"; } else messageAll('MsgVoteFailed', '\c2Kick player vote did not pass'); } %game.kickTeam = ""; %game.kickGuid = ""; %game.kickClientName = ""; if(%cause !$= "") logEcho(%name@" (cl " @ %game.kickClient @ ") kicked " @ %cause); } //------------------------------------------------------------------------------ function DefaultGame::banPlayer(%game, %admin, %client) { %cause = ""; %name = %client.nameBase; if( %admin ) { ban( %client, %admin ); %cause = "(admin)"; } if(%cause !$= "") logEcho(%name@" (cl "@%client@") banned "@%cause); } //------------------------------------------------------------------------------ function DefaultGame::voteAdminPlayer(%game, %admin, %client) { %cause = ""; if (%admin) { messageAll('MsgAdminAdminPlayer', '\c2The Admin made %2 an admin.', %client, %client.name); %client.isAdmin = 1; %cause = "(admin)"; } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { messageAll('MsgAdminPlayer', '\c2%2 was made an admin by vote.', %client, %client.name); %client.isAdmin = 1; %cause = "(vote)"; } else messageAll('MsgVoteFailed', '\c2Vote to make %1 an admin did not pass.', %client.name); } if(%cause !$= "") logEcho(%client.nameBase@" (cl "@%client@") made admin "@%cause); } //------------------------------------------------------------------------------ function DefaultGame::processGameLink(%game, %client, %arg1, %arg2, %arg3, %arg4, %arg5) { //the default behavior when clicking on a game link is to start observing that client %targetClient = %arg1; if ((%client.team == 0) && isObject(%targetClient) && (%targetClient.team != 0)) { %prevObsClient = %client.observeClient; serverCmdObserveClient(%client, %targetClient); displayObserverHud(%client, %targetClient); if (%targetClient != %prevObsClient) { messageClient(%targetClient, 'Observer', '\c1%1 is now observing you.', %client.name); messageClient(%prevObsClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); } } } //------------------------------------------------------------------------------ $ScoreHudMaxVisible = 19; function DefaultGame::updateScoreHud(%game, %client, %tag) { if (Game.numTeams > 1) { // Send header: messageClient( %client, 'SetScoreHudHeader', "", '\t%1%2\t%3%4', $TeamName[1], $TeamScore[1], $TeamName[2], $TeamScore[2] ); // Send subheader: messageClient( %client, 'SetScoreHudSubheader', "", '\tPLAYERS (%1)SCORE\tPLAYERS (%2)SCORE', $TeamRank[1, count], $TeamRank[2, count] ); %index = 0; while ( true ) { if ( %index >= $TeamRank[1, count] && %index >= $TeamRank[2, count] ) break; //get the team1 client info %team1Client = ""; %team1ClientScore = ""; if ( %index < $TeamRank[1, count] ) { %team1Client = $TeamRank[1, %index]; %team1ClientScore = %team1Client.score $= "" ? 0 : %team1Client.score; %col1Style = %team1Client == %client ? "" : ""; } //get the team2 client info %team2Client = ""; %team2ClientScore = ""; if ( %index < $TeamRank[2, count] ) { %team2Client = $TeamRank[2, %index]; %team2ClientScore = %team2Client.score $= "" ? 0 : %team2Client.score; %col2Style = %team2Client == %client ? "" : ""; } //if the client is not an observer, send the message if (%client.team != 0) { messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', %team1Client.name, %team1ClientScore, %team2Client.name, %team2ClientScore, %col1Style, %col2Style ); } //else for observers, create an anchor around the player name so they can be observed else { messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', %team1Client.name, %team1ClientScore, %team2Client.name, %team2ClientScore, %col1Style, %col2Style, %team1Client, %team2Client ); } %index++; } } else { //tricky stuff here... use two columns if we have more than 15 clients... %numClients = $TeamRank[0, count]; if ( %numClients > $ScoreHudMaxVisible ) %numColumns = 2; // Clear header: messageClient( %client, 'SetScoreHudHeader', "", "" ); // Send header: if (%numColumns == 2) messageClient(%client, 'SetScoreHudSubheader', "", '\tPLAYERSCORE\tPLAYERSCORE'); else messageClient(%client, 'SetScoreHudSubheader', "", '\tPLAYERSCORE'); %countMax = %numClients; if ( %countMax > ( 2 * $ScoreHudMaxVisible ) ) { if ( %countMax & 1 ) %countMax++; %countMax = %countMax / 2; } else if ( %countMax > $ScoreHudMaxVisible ) %countMax = $ScoreHudMaxVisible; for ( %index = 0; %index < %countMax; %index++ ) { //get the client info %col1Client = $TeamRank[0, %index]; %col1ClientScore = %col1Client.score $= "" ? 0 : %col1Client.score; %col1Style = %col1Client == %client ? "" : ""; //see if we have two columns if ( %numColumns == 2 ) { %col2Client = ""; %col2ClientScore = ""; %col2Style = ""; //get the column 2 client info %col2Index = %index + %countMax; if ( %col2Index < %numClients ) { %col2Client = $TeamRank[0, %col2Index]; %col2ClientScore = %col2Client.score $= "" ? 0 : %col2Client.score; %col2Style = %col2Client == %client ? "" : ""; } } //if the client is not an observer, send the message if (%client.team != 0) { if ( %numColumns == 2 ) messageClient(%client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', %col1Client.name, %col1ClientScore, %col2Client.name, %col2ClientScore, %col1Style, %col2Style ); else messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%3%1%2', %col1Client.name, %col1ClientScore, %col1Style ); } //else for observers, create an anchor around the player name so they can be observed else { if ( %numColumns == 2 ) messageClient(%client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', %col1Client.name, %col1ClientScore, %col2Client.name, %col2ClientScore, %col1Style, %col2Style, %col1Client, %col2Client ); else messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%3%1%2', %col1Client.name, %col1ClientScore, %col1Style, %col1Client ); } } } // Tack on the list of observers: %observerCount = 0; for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); if (%cl.team == 0) %observerCount++; } if (%observerCount > 0) { messageClient( %client, 'SetLineHud', "", %tag, %index, ""); %index++; messageClient(%client, 'SetLineHud', "", %tag, %index, '\tOBSERVERS (%1)TIME', %observerCount); %index++; for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); //if this is an observer if (%cl.team == 0) { %obsTime = getSimTime() - %cl.observerStartTime; %obsTimeStr = %game.formatTime(%obsTime, false); messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%1%2', %cl.name, %obsTimeStr ); %index++; } } } //clear the rest of Hud so we don't get old lines hanging around... messageClient( %client, 'ClearHud', "", %tag, %index ); } //------------------------------------------------------------------------------ function UpdateClientTimes(%time) { %secondsLeft = %time / 1000; messageAll('MsgSystemClock', "", (%secondsLeft / 60), %time); } //------------------------------------------------------------------------------ function notifyMatchStart(%time) { %seconds = mFloor(%time / 1000); if (%seconds > 2) MessageAll('MsgMissionStart', '\c2Match starts in %1 seconds.~wfx/misc/hunters_%1.wav', %seconds); else if (%seconds == 2) MessageAll('MsgMissionStart', '\c2Match starts in 2 seconds.~wvoice/announcer/ann.match_begins.wav'); else if (%seconds == 1) MessageAll('MsgMissionStart', '\c2Match starts in 1 second.'); UpdateClientTimes(%time); } //------------------------------------------------------------------------------ function notifyMatchEnd(%time) { %seconds = mFloor(%time / 1000); if (%seconds > 1) MessageAll('MsgMissionEnd', '\c2Match ends in %1 seconds.~wfx/misc/hunters_%1.wav', %seconds); else if (%seconds == 1) MessageAll('MsgMissionEnd', '\c2Match ends in 1 second.~wfx/misc/hunters_1.wav'); UpdateClientTimes(%time); } function DefaultGame::formatTime(%game, %tStr, %includeHundredths) { %timeInSeconds = %tStr / 1000; %mins = mFloor(%timeInSeconds / 60); if(%mins < 1) %timeString = "00:"; else if(%mins < 10) %timeString = "0" @ %mins @ ":"; else %timeString = %mins @ ":"; %timeInSeconds -= (%mins * 60); %secs = mFloor(%timeInSeconds); if(%secs < 1) %timeString = %timeString @ "00"; else if(%secs < 10) %timeString = %timeString @ "0" @ %secs; else %timeString = %timeString @ %secs; if (%includeHundredths) { %timeString = %timeString @ "."; %timeInSeconds -= %secs; %hSecs = mFloor(%timeInSeconds * 100); // will be between 0 and 999 if(%hSecs < 1) %timeString = %timeString @ "00"; else if(%hSecs < 10) %timeString = %timeString @ "0" @ %hSecs; else %timeString = %timeString @ %hSecs; } return %timeString; } //------------------------------------------------------------------------------ //AI FUNCTIONS function DefaultGame::AIChooseGameObjective(%game, %client) { AIChooseObjective(%client); } //------------------------------------------------------------------------------ function DefaultGame::getServerStatusString(%game) { %status = %game.numTeams; for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) { %score = isObject( $teamScore[%team] ) ? $teamScore[%team] : 0; %teamStr = getTaggedString( $teamName[%team] ) TAB %score; %status = %status NL %teamStr; } %status = %status NL ClientGroup.getCount(); for ( %i = 0; %i < ClientGroup.getCount(); %i++ ) { %cl = ClientGroup.getObject( %i ); %score = %cl.score $= "" ? 0 : %cl.score; %playerStr = getTaggedString( %cl.name ) TAB getTaggedString( $teamName[%cl.team] ) TAB %score; %status = %status NL %playerStr; } return( %status ); } //------------------------------------------------------------------------------ function DefaultGame::OptionsDlgSleep( %game ) { // ignore in the default game... }