//------------------------------------------------------------------- // Lak Rabbit script // ------------------------------------------------------------------- // DisplayName = LakRabbit //--- GAME RULES BEGIN --- //Spawn with your favorites and double ammunition //Rabbit is invincible for 2 seconds upon grab //No laser, no chain. Eat it Altimor. //Sounds for regular & special hits //Points based on difficulty, speed, and distance //Duel Mode forces rabbit to fight and rewards for killing //Stand and fight to get the most points. //--- GAME RULES END --- // Thanks for helping me test! // maradona, pip, phantom jaguar, hilikus, the_ham, pip, wiggle, dragon, pancho villa, w/o, nectar and many others.. // // v3.38 Nov 2020 // Added Observer GameOver (Mainly for switching to CTF) // // v3.37 Aug 2020 // Nerfed Blaster damage (Less spam) // Flag Transform 500 > 100 // Changed Duel Mode buzzer sound // Disabled disc jump restriction in duel mode & Pro Mode // // v3.36 Dec 2019 // Boundary bounce speed limit // Unified Lakrabbit Vars // // v3.35 April 2019 // Added Not enough players flag message delay // Shock in the back bonus 2 > 1.5 // // v3.34 Febuary 2019 // Armor::damageObject rework // Added SetNextMission support // Indoor Spawning support // // v3.33 January 2019 // Took out slap headshot. // Added footnotes for voting references with evo admin mod. // An improved Flag-Waypoint. // // v3.32 December 2018 // Fixed an issue with lak vote items in the Evo Admin Votemenu // // v3.31 October 2018 // Adjusted the flag updater code so its more like the way it was. A little harder to catch. Down from 10 times a second to 2. // Fixed a bug that broke weapons cycling. Players just run as if they have ammo packs now. // Cleaned up voting language. // Fixed a bug where the player would stay invisible when slapped. // Added disc headshot functionality to slap. // Fixed a bug where you would get multiple back in bounds messages even when you were dead after a slap. // // v3.3 - July 2018 // Nerfed Midair Flag grab points since its easier with the flag updater code. // Nerfed Shock height points just a tad. // // v3.2 - April 2018 // Made spawning closer to the Rabbit 200>150 // Made Debrief font slightly larger // Added flag updater code from CTF // Took out Snipe and Chain Stats. Replaced them with more relevant stats. // Added Unlimited DiscJump Variable. // // v3.1 9/11 Version // Fixed Boundary walls // Banned Certain types of weapons // // -2.17xxx points bug may be fixed. // Fixed the Resetting... spam while toggling duel mode. // Voting looks better (makes sense). // No mysterious 'hoorah' when you get 100% mine on ground. // Splash damage is based on how many are playing (more people less splash damage). Minimum 10% damage. No Splash is still votable. // Heavies are easier to kill. // Point adjustments. // Flag wont just drop to the ground in duel mode. Basically, if you don't have enough upward momentum, it will be added to the flag so it can fly up. // No 'duel kills' with missile special. // Rabbit cannot disk jump in duel mode. // DJ + Gren spam addressed again :) // Throwing a hand nade removes invincibility. // There is a minimum 'seconds per kill', to help with the 2 kills in 2 seconds scenario. // Point maximum raised to 2000. // Fixed No-Splash so you still take damage with direct hits on ground. // Extra duel time for rabbit with No-Splash enabled and when it's 1on1 in duel mode. // If you want to see the objective hud download LakRabbitObjHud.cs and put in /base/scripts/autoexec // // v3 // Code optimization and bug fixes. // Mortars are enabled, but only do half damage. Mortars can get long-distance or MA points. // Long-distance shots are a little easier to get. // You get one free disk-jump at spawn (DJ does no damage to you), but lose it if you get the flag. // 'Specials'. You'll know it when you see it ;) // No damage taken from mines if you aren't in the air, and mine damage in general is greatly reduced. // [Fix] You only get points with sniper if you have 50% energy. // Extra points for snipe headshot, and it is displayed with sound (regular snipe w/points has no sound). // Points show up as soon as you get them (don't have to respawn) // Distance and speed is now taken from where you shot, not where you are when the projectile hits. // Duel mode -- rabbit has to fight or blow up, and is awarded points for killing people quickly (votable on/off). // Grid is 'bouncy' like TR2 (code from TR2 as well -- thanks) for players and flags, and you can no longer spawn out of bounds. <-- may help with oob flag/ghost/sticky corpse bugs // Ground damage cut in half in duel mode, except for rabbit. // Messed with MA flag-grab points again, and it now shows your speed and height. // Points for hand grenades. // Hand nades don't detonate mines in duel mode (thx mista). // You can vote off splash damage. Mines and grenades may still damage you with splash, however, and you can still get long distance shot points. // You get points from chaingun every 5 hits (less spam, better looking points). Firing a different weapon resets your accuracy and hits same as before. // Shocklance points are based mostly on speed and height now, and your height is displayed. // Objective hud fixed. // Spawn a little closer to rabbit, and the rabbit waypoint is only shown if someone grabs flag and is far away from you. // Removed old AI Rabbit stuff (less console spam). // DJ + Gren spam abuse addressed. Good luck getting points this way... // New debriefing information at the end of a map: score, kills, MAs, avg speed and distance, overall chain accuracy, percent of snipe and shock hits. // Getting an MA with shocklance and sniper is now based on if -you- are in the air, not the opponent. // Point limit reduced to 1500. // // v2 // On CTF maps (or maps with two or more flags) you can capture the flag for points when 6 people are playing. Only one flag can be in play at a time. Once capped, your flag gets returned and you immediately take the new flag. // Mines are now available. // Flag gets 'tossed' when carrier dies, no longer drops like a rock. // Better messages, showing speed and distance. Distance bonuses are calculated into points; no multipliers. // Spawn with full energy. // MA flag-grab points are better calculated. // Spawning has been redone so you spawn within a radius of 250m from either the rabbit or flag. // Lots of new maps, all competition CTF maps, set up for LakRabbit (no generators, etc) // Rabbit doesn't suffer the CG or Laser damage subtraction based on players. // Point system revamped. // 2500 point limit. // Long-Distance disc and GL shots may give points (depending on difficulty of shot). // Flag-skipping bug fixed. // v1 - See game rules. // Vars: // $Host::LakRabbitShowFlagIcon // 0 - Don't show any // 1 - Show flag icon when flag dropped only // 2 - Show flag icon on rabbit // // $Host::LakRabbitPubPro // 0 - Disable LakPro features // 1 - Enable LakPro features // // $Host::LakRabbitDuelMode // 0 - Disable Duel Mode // 1 - Enable Duel Mode // // $Host::LakRabbitNoSplashDamage // 0 - Disable No Splash Damage // 1 - Enable No Splash Damage // // $Host::LakRabbitShowFlagTask // 0 - Do not show flag task // 1 - Show the flag when dropped as a task // // $Host::LakRabbitUnlimitedDJ // 0 - Players only get one DiscJump // 1 - Players get 999 or unlimited DiscJumps // package LakRabbitGame { function Flag::objectiveInit(%data, %flag) { $flagStatus = ""; %flag.carrier = ""; %flag.originalPosition = %flag.getTransform(); %flag.isHome = true; %flag.rotate = true; // ilys -- add the icon to the flag if( $Host::LakRabbitShowFlagIcon == 1 || $Host::LakRabbitShowFlagIcon == 2 ) { %flag.scopeWhenSensorVisible(true); setTargetSensorGroup(%flag.getTarget(), $NonRabbitTeam); setTargetRenderMask(%flag.getTarget(), getTargetRenderMask(%flag.getTarget()) | 0x2); setTargetAlwaysVisMask(%flag.getTarget(), 0x7); } // create a waypoint to the flag's starting place if( $Host::LakRabbitShowFlagIcon == 0 ) { %flagWaypoint = new WayPoint() { position = %flag.position; rotation = "1 0 0 0"; name = "Flag Home"; dataBlock = "WayPointMarker"; team = $NonRabbitTeam; }; } $AIRabbitFlag = %flag; MissionCleanup.add(%flagWaypoint); // ------------------------------------------------------------------------------------------- // z0dd - ZOD, 10/03/02. Use triggers for flags that are at home, hack for flag collision bug. %flag.trigger = new Trigger() { dataBlock = flagTrigger; polyhedron = "-0.6 0.6 0.1 1.2 0.0 0.0 0.0 -1.2 0.0 0.0 0.0 2.5"; position = %flag.position; rotation = %flag.rotation; }; MissionCleanup.add(%flag.trigger); %flag.trigger.flag = %flag; // ------------------------------------------------------------------------------------------- } // AI consoel spam function AIThrowObject(%object) { return; } function AIGrenadeThrown(%object) { return; } function AICorpseAdded(%corpse) { return; } // eat it ZP/Altimor function ChaingunImage::onFire(%data,%obj,%slot){} function SniperRifleImage::onFire(%data,%obj,%slot){} function ELFGunImage::onFire(%data,%obj,%slot){} function ShockLanceImage::onFire(%data, %obj, %slot) { %p = parent::onFire(%data,%obj,%slot); %obj.client.totalShocks++; %obj.setInvincible(false); return %p; } function ShapeBaseImageData::onFire(%data, %obj, %slot) { if(%data.projectile $= ChaingunBullet) $LakFired[%obj, ChaingunBullet, 0]++; else { $LakFired[%obj, ChaingunBullet, 0] = 0; $LakFired[%obj, ChaingunBullet, 1] = 0; } %p = parent::onFire(%data, %obj, %slot); %p.shotFrom = %obj.getWorldBoxCenter(); %p.shotSpeed = getSpeed(%obj); // borlak -- remove height from grenades to get rid of DJ + gren spam abuse switch$(%data.projectile) { case BasicGrenade: %p.shotFrom = setWord(%p.shotFrom, 2, getWord(%p.shotFrom,2) - getHeight(%obj)); } return %p; } // borlak -- this is going to be one ugly hack, but I can't find where a non radius damage // object calls damageObject on a -hit-, therefore cannot pass on the projectiles data to // damageObject and get it's true origin of fire function ProjectileData::onExplode(%data, %proj, %pos, %mod) { $lastObjExplode = %proj; parent::onExplode(%data, %proj, %pos, %mod); } // this too... function detonateGrenade(%obj) { %obj.shotSpeed = -1; %obj.isHandNade = 1; $lastObjExplode = %obj; parent::detonateGrenade(%obj); } function GrenadeThrown::onThrow(%this, %gren) { %gren.sourceObject.setInvincible(false); %gren.shotFrom = %gren.getWorldBoxCenter(); parent::onThrow(%this, %gren); } // borlak -- prevent getting hurt while knocked back (more fun) function Armor::onImpact(%data, %playerObject, %collidedObject, %vec, %vecLen) { if(%playerObject.knockback) return; parent::onImpact(%data, %playerObject, %collidedObject, %vec, %vecLen); } // borlak -- ma testing and points function Armor::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %mineSC) { %distance = 0; %energy = 0; %velBonus = 0; %sound = ""; %defaultSound = '~wfx/misc/bounty_bonus.wav'; %weapon = 0; %points = 0; %ma = 0; %special = ""; %long = 0; %accuracy = ""; %velstring = ""; %maxDamage = 0; %percentDam = 0; if(%targetObject.invincible || %targetObject.getState() $= "Dead") return; //rabbit can't DJ in duel mode // if(Game.duelMode && %targetObject.holdingFlag && %targetObject == %sourceObject // && %damageType == $DamageType::Disc // && getWord(%targetObject.getMuzzleVector(0),2) < -0.7 // && !TestForMA(%sourceObject, 5)) // { // %sound = '~wfx/misc/missed.wav'; // %amount = 2.0; // %targetObject.blowup(); // } //Zeph - PubPro no DJ // if(Game.PubPro && %targetObject == %sourceObject // && %damageType == $DamageType::Disc // && getWord(%targetObject.getMuzzleVector(0),2) < -0.7 // && !TestForMA(%sourceObject, 5)) // { // %sound = '~wfx/misc/missed.wav'; // %amount = 2.0; // %targetObject.blowup(); // %targetObject.scriptKill(); // } // hurting yourself, check for free DJ if( isObject(%sourceObject) && %sourceObject.getDataBlock().getClassName() $= "PlayerData" && %targetObject.client == %sourceObject.client) { if(%damageType == $DamageType::Disc && %sourceObject.freeDJ) { %amount = 0; %sourceObject.freeDJ--; } } %targetObject.lastDamageType = %damageType; // borlak -- MA, long distance, mine and grenade points if( isObject(%sourceObject) && %sourceObject.getDataBlock().getClassName() $= "PlayerData" && %targetObject.getDataBlock().getClassName() $= "PlayerData" && %targetObject.client.team != %sourceObject.client.team && %damageType) { $LakDamaged[%targetObject.client] = %sourceObject.client; %targetObject.lastDamagedBy = %sourceObject; %targetPosition = %targetObject.getWorldBoxCenter(); // borlak -- DJ + gren spam abuse, remove player height if(%damageType == $DamageType::Grenade && !$lastObjExplode.isHandNade) %targetPosition = setWord(%targetPosition, 2, getWord(%targetPosition,2) - getHeight(%targetObject)); if(%damageType == $DamageType::ShockLance || %damageType == $DamageType::Laser) { $lastObjExplode = 0; %distance = VectorDist(%targetPosition, %sourceObject.getWorldBoxCenter()); %vel = getSpeed(%sourceObject); } else { %maxDamage = $lastObjExplode.getDataBlock().directDamage ? $lastObjExplode.getDataBlock().directDamage : $lastObjExplode.getDataBlock().indirectDamage; %distance = VectorDist(%targetPosition, $lastObjExplode.shotFrom); if($lastObjExplode.shotSpeed < 0) %vel = getSpeed(%sourceObject); else %vel = $lastObjExplode.shotSpeed; } %percentDam = mFloor((%amount/%maxDamage)*100); %energy = %sourceObject.getEnergyLevel()/%sourceObject.getDataBlock().maxEnergy; %velTarget = getSpeed(%targetObject); %distanceBonus = (mPow(%distance,1.35)/10)+1; %longDistanceBonus = (mPow(%distance,1.10)/10)+1; %velBonus = (mPow(%vel,1.125)/10)+1; // for shock and laser, you get MA points if -you- are in the air not the opponent if(%damageType == $DamageType::ShockLance || %damageType == $DamageType::Laser) %ma = TestForMA(%sourceObject, 6); else %ma = TestForMA(%targetObject, 6); // lower splash damage depending on how many people are playing.. duel mode only if(Game.duelMode && %percentDam < 98 && $lastObjExplode && $lastObjExplode.getDataBlock().indirectDamage > 0) { %mult = 1-(ClientGroup.getCount()-1)/10; if(%mult < 0.10) %mult = 0.10; %amount *= %sourceObject.holdingFlag ? 1 : %mult; %maxDamage *= %sourceObject.holdingFlag ? 1 : %mult; } // no splash damage vote if(Game.noSplashDamage && %percentDam < 98 && $lastObjExplode && !$lastObjExplode.isHandNade && %damageType != $DamageType::Mine) %amount = 0.0; switch$(%damageType) { case $DamageType::Disc: if(%ma && %percentDam >= 98) { %points = %distanceBonus; %sound = %defaultSound; } if(%percentDam >= 25 && !%ma && %distance >= 80 && %velTarget > 20) { %points = %longDistanceBonus; %velBonus /= 2; %long = 1; %sound = %defaultSound; } // special knockback if you hit too close, max 15% chance (point blank).. 5% at 30meters, 1% chance for any MA // Slap based on a Disc headshot //%chance = mFloor(25 - %distance/3); //if(%ma && getRandom(1,50) <= %chance && %targetObject.client.headshot) //Normal Slap %chance = mFloor(15 - %distance/3); if(%chance <= 0) %chance = 1; if(%ma && getRandom(1,100) <= %chance) { if(%targetObject.holdingFlag) { Game.playerDroppedFlag(%targetObject); //Added so cloak is turned off when slapped. %targetObject.setCloaked(false); %targetObject.freeDJ = 1; } if(%sourceObject.holdingFlag && Game.duelMode) { duelBonus(%sourceObject.client); $LakDamaged[%targetObject.client] = 0; } // lower damage and make invincible to ground damage to make it a little more fun %amount = 0.01; %targetObject.setKnockback(true); %targetObject.schedule(15000, "setKnockback", false); %p = %targetObject.getWorldBoxCenter(); %muzzleVec = %sourceObject.getMuzzleVector(0); %impulseVec = VectorScale(%muzzleVec, 25000); %targetObject.applyImpulse(%p, %impulseVec); %sound = '~wfx/misc/slapshot.wav'; %slapmsg = getRandom(1,3); switch$(%slapmsg) { case 1: messageAll('msgSlapmessage','\c0%1 wonders what the five fingers said to the face.', %targetObject.client.name ); case 2: messageAll('msgSlapmessage','\c0%1 gets slapped the heck out!', %targetObject.client.name ); case 3: messageAll('msgSlapmessage','\c0%1 is taking a short tour around the map.', %targetObject.client.name ); } } %weapon = "Disc"; case $DamageType::Grenade: if($lastObjExplode.isHandNade) //Hand grenades { if(%percentDam > 20) { %accuracy = " [Accuracy:" @ %percentDam @ "%]"; %points = (%percentDam/10)+1; %velBonus = 0; %sound = '~wfx/misc/coin.wav'; } if(%percentDam >= 99) { %sound = '~wfx/misc/Cheer.wav'; %points *= 2.0; } if(%ma) %points *= 1.5; %weapon = "Hand-Nade"; } else { if(Game.PubPro) { if(%ma && %percentDam >= 98) { %points = %distanceBonus; %sound = %defaultSound; } if(%percentDam >= 25 && !%ma && %distance >= 80 && %velTarget > 20) { %points = %longDistanceBonus; %velBonus /= 2; %long = 1; %sound = %defaultSound; } } else { if(%ma && %percentDam >= 98) { %points = %distanceBonus/1.85; %sound = %defaultSound; } if(%percentDam >= 25 && !%ma && %distance >= 100 && %velTarget > 30) { %points = %longDistanceBonus/1.85; %velBonus /= 4; %long = 1; %sound = %defaultSound; } } %weapon = "Grenade-Launcher"; } case $DamageType::Mortar: if(%ma && %percentDam >= 98) { %points = %distanceBonus*2.66; %sound = %defaultSound; } if(%percentDam >= 25 && !%ma && %distance >= 100 && %velTarget > 30) { %points = %longDistanceBonus; %velBonus /= 2; %long = 1; %sound = %defaultSound; } if(!Game.duelMode) %amount /= 2; %weapon = "Mortar"; case $DamageType::Mine: %amount /= %amount > 0 ? 3 : 1; if(%ma) { %accuracy = " [Accuracy:" @ %percentDam @ "%]"; %points = (%percentDam/7)+2; %velBonus = 0; %sound = '~wfx/misc/coin.wav'; if(%percentDam >= 99) { %sound = '~wfx/misc/Cheer.wav'; %points *= 2.0; } } if(!%ma) %amount = 0; %weapon = "MINE"; case $DamageType::ShockLance: %height = getHeight(%sourceObject); %heightBonus = (mPow(%height,1.20)/14)+1; //was 10 %velBonus /= 2; %points = mFloor(%distance/2) + (%heightBonus); %accuracy = " [Height:" @ %height @"m]"; // borlak -- check rear shocklance hit %muzzlePos = %sourceObject.getMuzzlePoint(0); %forwardVec = %targetObject.getForwardVector(); %objDir2D = getWord(%forwardVec, 0) @ " " @ getWord(%forwardVec,1) @ " " @ "0.0"; %objPos = %targetObject.getPosition(); %dif = VectorSub(%objPos, %muzzlePos); %dif = getWord(%dif, 0) @ " " @ getWord(%dif, 1) @ " 0"; %dif = VectorNormalize(%dif); %dot = VectorDot(%dif, %objDir2D); if(%dot >= mCos(1.05)) { if(%sourceObject.holdingFlag && TestForMA(%targetObject, 6)) { %sourceObject.setCloaked(true); if($host::dontcloakflag) %sourceObject.holdingFlag.setCloaked(false); } %points *= 1.5; //was 2 %special = "-in-the-back"; } if(%ma) %points += 3; //not a bug. sl gets points ma or not %sound = %defaultSound; %sourceObject.client.totalShockHits++; %weapon = "ShockLance"; case $DamageType::Blaster: if(%ma) { %points = %distanceBonus/2.5; //was 2 %velBonus /= 2; %sound = %defaultSound; %amount *= 0.7; //Midair blaster damage reduction - particularly for blaster spamming } else %amount *= 0.5; //Ground blaster damage reduction - particularly for blaster spamming %weapon = "Blaster"; case $DamageType::Plasma: if(%ma && %percentDam >= 98) { %points = %distanceBonus/1.3+2; %sound = %defaultSound; } if(%percentDam >= 25 && !%ma && %distance >= 40 && %velTarget > 30) { %points = %longDistanceBonus*1.5; %velBonus /= 1.75; %long = 1; %sound = %defaultSound; } %weapon = "Plasma"; case $DamageType::Laser: if($InvBanList[LakRabbit, "SniperRifle"]) //banned return; if(%energy > 0.5 || %players > 7) { %players = (ClientGroup.getCount()-1)/1.5; %points = (%distance/75)+1; if(%ma) %points *= 1.75; if(%targetObject.client.headshot) { %sound = %defaultSound; %special = " Headshot"; %points *= 1.75; } %sourceObject.client.totalSnipeHits++; %weapon = "Snipe"; } case $DamageType::Bullet: // doesn't matter if it's MA %ma = 0; %players = (ClientGroup.getCount()-1)/1.75; $LakFired[%sourceObject, ChaingunBullet, 1]++; if($LakFired[%sourceObject, ChaingunBullet, 1] % 5 == 0) { %accamount = mFloor(($LakFired[%sourceObject, ChaingunBullet, 1] / $LakFired[%sourceObject, ChaingunBullet, 0])*100); %velBonus = 0; %points = (%accamount/3)+1; %accuracy = " [Accuracy:" @ %accamount @ "%]"; %sourceObject.client.totalChainAccuracy += %accamount; %sourceObject.client.totalChainHits++; } %weapon = "Chaingun"; case $DamageType::Missile: // doesn't matter if it's MA %ma = 0; if((getSimTime() - $LakRabbit::MissileHeistTime > 10000) || !$LakRabbit::MissileHeistTime) return; %weapon = "Missile"; } } // borlak -- recalc score for hits if( isObject(%sourceObject) && %sourceObject.getDataBlock().getClassName() $= "PlayerData" && %targetObject.getDataBlock().getClassName() $= "PlayerData" && %points) { %distance = mFloor(%distance); %points += %velBonus; %points = mFloor(%points); %sourceObject.client.morepoints += %points; if(%ma) { %sourceObject.client.mas++; %sourceObject.client.totalSpeed += %vel; %sourceObject.client.totalDistance += %distance; %hitType = "Mid-Air "; } else if(%long) %hitType = "Long-Distance "; else %hitType = ""; messageClient(%sourceObject.client,'msgPlrPointBonus', '\c4You receive %1 point%2! [%3%4%5] [Distance:%6m] [Speed:%7kph] %8', %points, %points == 1 ? "" : "s", %hitType, %weapon, %special !$= "" ? %special : "", %distance, %vel, %accuracy); messageAllExcept(%sourceObject.client, -1, 'msgRabbitPointBonus', '\c4%1 receives %2 point%3! [%4%5%6] [Distance:%7m] [Speed:%8kph] %9', %sourceObject.client.name, %points, %points == 1 ? "" : "s", %hitType, %weapon, %special !$= "" ? %special : "", %distance, %vel, %accuracy); if(%sourceObject.holdingFlag && %points >= 75) { missileEveryone(%sourceObject); %sound = '~wfx/Bonuses/horz_straipass2_heist.wav'; $LakRabbit::MissileHeistTime = getSimTime(); } else if(%points >= 100) { messageAll('', '~wfx/Misc/Flair.wav'); } Game.recalcScore(%sourceObject.client); //Code for DarkTigers discordBot if(discord.lastState $= "Connected") discordBotProcess("lakMApoints", %sourceObject, %points, %hitType, %weapon, %distance, %vel); } // borlak -- make a sound when you hit someone if(%sound $= "" && %sourceObject.client.team != %targetObject.client.team) messageClient(%sourceObject.client,'MsgHitSound','~wfx/misc/diagnostic_beep.wav'); else if(%sound !$= "") messageAll('msgSpecialHitSound', %sound); // borlak -- rabbit should be able to kill heavies/mediums fast(er) in duel mode if(%targetObject.client.armor $= "Heavy" || %targetObject.client.armor $= "Medium") { if(Game.duelMode && %targetObject != %sourceObject && %sourceObject.holdingFlag) %amount *= 2; else %amount *= 1.5; } %targetClient = %targetObject.getOwnerClient(); if(isObject(%mineSC)) %sourceClient = %mineSC; else %sourceClient = isObject(%sourceObject) ? %sourceObject.getOwnerClient() : 0; %targetTeam = %targetClient.team; // if the source object is a player object, player's don't have sensor groups // if it's a turret, get the sensor group of the target // if its a vehicle (of any type) use the sensor group if (%sourceClient) %sourceTeam = %sourceClient.getSensorGroup(); else if(%damageType == $DamageType::Suicide) %sourceTeam = 0; // if teamdamage is off, and both parties are on the same team // (but are not the same person), apply no damage if(!$teamDamage && (%targetClient != %sourceClient) && (%targetTeam == %sourceTeam)) return; if(%amount == 0) return; // Set the damage flash %damageScale = %data.damageScale[%damageType]; if(%damageScale !$= "") %amount *= %damageScale; %flash = %targetObject.getDamageFlash() + (%amount * 2); if (%flash > 0.75) %flash = 0.75; // Teratos: Originally from Eolk? Mine+Disc tracking/death message support. // No Schedules by DarkTiger Ver.2 %targetClient.mineDisc = false; switch$(%damageType) { case $DamageType::Disc: if((getSimTime() - %targetClient.mdcTime1) < 256) %targetClient.mineDisc = true; %targetClient.mdcTime2 = getSimTime(); case $DamageType::Mine: if((getSimTime() - %targetClient.mdcTime2) < 256) %targetClient.mineDisc = true; %targetClient.mdcTime1 = getSimTime(); } // -- End Mine+Disc insert. %previousDamage = %targetObject.getDamagePercent(); %targetObject.setDamageFlash(%flash); %targetObject.applyDamage(%amount); Game.onClientDamaged(%targetClient, %sourceClient, %damageType, %sourceObject); %targetClient.lastDamagedBy = %damagingClient; %targetClient.lastDamaged = getSimTime(); //now call the "onKilled" function if the client was... you know... if(%targetObject.getState() $= "Dead") { // where did this guy get it? %damLoc = %targetObject.getDamageLocation(%position); // should this guy be blown apart? if( %damageType == $DamageType::Explosion || %damageType == $DamageType::Mortar || %damageType == $DamageType::Missile ) { if( %previousDamage >= 0.35 ) // only if <= 35 percent damage remaining { %targetObject.setMomentumVector(%momVec); %targetObject.blowup(); } } // If we were killed, max out the flash %targetObject.setDamageFlash(0.75); %damLoc = %targetObject.getDamageLocation(%position); Game.onClientKilled(%targetClient, %sourceClient, %damageType, %sourceObject, %damLoc); } else if ( %amount > 0.1 ) { if( %targetObject.station $= "" && %targetObject.isCloaked() ) { %targetObject.setCloaked( false ); %targetObject.reCloak = %targetObject.schedule( 500, "setCloaked", true ); } playPain( %targetObject ); } } function deployMineCheck(%mineObj, %player) { // explode it vgc schedule(2000, %mineObj, "explodeMine", %mineObj, true); } // thanks mista function MineDeployed::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) { // NO NIFTY NADE/MINE SCRIPTS if (Game.duelMode && %damageType == $DamageType::Grenade && $lastObjExplode.isHandNade) return; parent:: damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType); } function MineDeployed::onThrow(%this, %mine, %thrower) { %mine.shotFrom = %mine.getWorldBoxCenter(); parent::onThrow(%this, %mine, %thrower); } function MineDeployed::onDestroyed(%data, %obj, %lastState) { %obj.shotFrom = %obj.getWorldBoxCenter(); %obj.shotSpeed = -1; $lastObjExplode = %obj; parent::onDestroyed(%data, %obj, %lastState); } function Player::maxInventory(%this, %data) { //chocotaco - just runs as an ammo pack cuz messing with the inv max messes up weapons cycling //%max = ShapeBase::maxInventory(%this,%data) * 2; %max = ShapeBase::maxInventory(%this,%data); //if (%this.getInventory(AmmoPack)) %max += AmmoPack.max[%data.getName()]; return %max; } function Player::setKnockback(%this, %val) { %this.knockback = %val; } //For slap headshot detection //Took out // //function ProjectileData::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal) //{ // %damLoc = firstWord(%targetObject.getDamageLocation(%position)); // if(%damLoc $= "head") // { // %targetObject.getOwnerClient().headShot = 1; // //%modifier = %data.rifleHeadMultiplier; // %targetObject.damage(%projectile.sourceObject, %position, %data.directDamage * %modifier, %data.directDamageType); // } // else // { // //%modifier = 1; // %targetObject.getOwnerClient().headShot = 0; // %targetObject.damage(%projectile.sourceObject, %position, %data.directDamage * %modifier, %data.directDamageType); // } //} //Put everyone on NonRabbit Team function DefaultGame::missionLoadDone(%game) { for(%i = 0; %i < ClientGroup.getCount(); %i++) { %client = ClientGroup.getObject(%i); if(%client.lakobs) %client.lakobs = ""; else { %client.team = $NonRabbitTeam; %client.lastTeam = $NonRabbitTeam; } } parent::missionLoadDone(%game); } }; // Added function LakRabbitGame::AIInit(%game) { //call the default AIInit() function AIInit(); } //exec the AI scripts //exec("scripts/aiRabbit.cs"); $InvBanList[LakRabbit, "TurretOutdoorDeployable"] = 1; $InvBanList[LakRabbit, "TurretIndoorDeployable"] = 1; $InvBanList[LakRabbit, "ElfBarrelPack"] = 1; $InvBanList[LakRabbit, "MortarBarrelPack"] = 1; $InvBanList[LakRabbit, "PlasmaBarrelPack"] = 1; $InvBanList[LakRabbit, "AABarrelPack"] = 1; $InvBanList[LakRabbit, "MissileBarrelPack"] = 1; $InvBanList[LakRabbit, "MissileLauncher"] = 1; $InvBanList[LakRabbit, "MotionSensorDeployable"] = 1; $InvBanList[LakRabbit, "PulseSensorDeployable"] = 1; $InvBanList[LakRabbit, "ELFGun"] = 1; $InvBanList[LakRabbit, "CameraGrenade"] = 1; $InvBanList[LakRabbit, "FlareGrenade"] = 1; $InvBanList[LakRabbit, "FlashGrenade"] = 1; $InvBanList[LakRabbit, "ConcussionGrenade"] = 1; // PubPro $InvBanList[LakRabbit, "AmmoPack"] = 1; $InvBanList[LakRabbit, "CloakingPack"] = 1; $InvBanList[LakRabbit, "RepairPack"] = 1; $InvBanList[LakRabbit, "SatchelCharge"] = 1; $InvBanList[LakRabbit, "SensorJammerPack"] = 1; $InvBanList[LakRabbit, "ShieldPack"] = 1; $InvBanList[LakRabbit, "SniperRifle"] = 1; $InvBanList[LakRabbit, "Chaingun"] = 1; $InvBanList[LakRabbit, "GrenadeLauncher"] = $Host::LakRabbitPubPro; $InvBanList[LakRabbit, "ShockLance"] = $Host::LakRabbitPubPro; $InvBanList[LakRabbit, "Mortar"] = $Host::LakRabbitPubPro; $InvBanList[LakRabbit, "Grenade"] = $Host::LakRabbitPubPro; $InvBanList[LakRabbit, "Disc"] = 0; $InvBanList[LakRabbit, "Plasma"] = 0; $InvBanList[LakRabbit, "Blaster"] = 0; $InvBanList[LakRabbit, "EnergyPack"] = 0; $InvBanList[LakRabbit, "Mine"] = 0; $InvBanList[LakRabbit, "TargetingLaser"] = 0; // borlak functions function TestForMA(%player, %distance) { %mask = $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType; %rayStart = %player.getWorldBoxCenter(); %rayEnd = getWord(%rayStart, 0) SPC getWord(%rayStart, 1) SPC getWord(%rayStart, 2) - %distance; %ground = ContainerRayCast(%rayStart, %rayEnd, %mask, 0); return !%ground; } function getSpeed(%obj) { return mFloor(VectorLen(%obj.getVelocity())*3.6); } function PlayingPlayers() { %players = 0; for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); if(isObject(%cl.player) && %cl.player.team > 0) %players++; } return %players; } function duelBonus(%client) { %client.duelSeconds += 12; if(Game.noSplashDamage) %client.duelSeconds += 5; %client.duelKills++; messageClient(%client, 'MsgDuelBonus', '\c4You now have %1 seconds to live.', %client.duelSeconds); } //for(%i = 0; %i < ClientGroup.getCount(); %i++){%target = ClientGroup.getObject(%i).player; if(%target.holdingFlag) missileEveryone(%target);} // awards/tricks/fun things function missileEveryone(%attacker) { for(%i = 0; %i < ClientGroup.getCount(); %i++) { %target = ClientGroup.getObject(%i); if(!%target.player || %target.player == %attacker) continue; %p = ShapeBaseImageData::onFire(MissileLauncherImage,%attacker,0); MissileSet.add(%p); %p.setObjectTarget(%target.player); %attacker.cantFire = ""; } // make him invincible so he doesn't get killed and ruin the effect! %attacker.setInvincible(true); %attacker.schedule(5000, "setInvincible", false); // give the rabbit some more duel seconds if it's duel mode.. if(Game.duelMode && %attacker.holdingFlag) %attacker.client.duelSeconds += 15; } function killEveryone(%ignore, %message) { if(!%message) messageAll('msgKillEveryone', 'Resetting...'); else messageAll('msgKillEveryone', %message); for(%i = 0; %i < ClientGroup.getCount(); %i++) { %target = ClientGroup.getObject(%i); if(!%target.player || %target.player == %ignore) continue; %target.player.blowup(); %target.player.scriptKill(); } } function checkDuelTimer(%client) { %client.duelTimer = schedule(1000, 0, checkDuelTimer, %client); if(PlayingPlayers() < 2) return; %client.duelSeconds--; %client.duelSecondsCounted++; if(%client.duelSeconds <= 0) { cancel(%client.duelTimer); messageAll('MsgDuelTimeout', '\c2%1 failed to kill within the alloted time!~wfx/misc/whistle.wav', %client.name); %client.player.blowup(); %client.player.scriptKill(); } else { if(%client.duelSeconds == 10 || %client.duelSeconds == 5 || %client.duelSeconds <= 3) { %plural = (%client.duelSeconds != 1 ? 's' : ""); messageClient(%client, 'MsgDuelTimer', '\c4You have %1 second%2 to kill someone, or die!~wgui/launchMenuOver.wav', %client.duelSeconds, %plural); } } } function setFlagDeny(%client, %value) { %client.flagDeny = %value; } // new "modes" and voting functions $VoteMessage["VoteDuelMode"] = "turn"; $VoteMessage["VoteSplashDamage"] = "turn"; $VoteMessage["VotePro"] = "turn"; function LakRabbitGame::sendGameVoteMenu( %game, %client, %key ) { parent::sendGameVoteMenu( %game, %client, %key ); %isAdmin = ( %client.isAdmin || %client.isSuperAdmin ); if(!%client.canVote && !%isAdmin) return; if( %game.scheduleVote $= "" ) { if(!%isAdmin) { if(!Game.duelMode) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteDuelMode', 'Enable Duel Mode', 'Vote to enable Duel Mode' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteDuelMode', 'Disable Duel Mode', 'Vote to disable Duel Mode' ); if(!Game.noSplashDamage) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSplashDamage', 'Disable Splash Damage', 'Vote to disable Splash Damage' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSplashDamage', 'Enable Splash Damage', 'Vote to enable Splash Damage' ); // DeVast - PubPro votes if(!Game.PubPro) messageClient( %client, 'MsgVoteItem', "", %key, 'VotePro', 'Enable Pro Mode', 'Vote to enable Pro Mode' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VotePro', 'Disable Pro Mode', 'Vote to disable Pro Mode' ); } //Added so lak vote items are properly displayed in evo adminvotemenu //A lot of changes were added to admin.ovl in evo //see footnotes below else if (%client.ForceVote > 0) { if(!Game.duelMode) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteDuelMode', 'Enable Duel Mode', 'Vote to enable Duel Mode' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteDuelMode', 'Disable Duel Mode', 'Vote to disable Duel Mode' ); if(!Game.noSplashDamage) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSplashDamage', 'Disable Splash Damage', 'Vote to disable Splash Damage' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSplashDamage', 'Enable Splash Damage', 'Vote to enable Splash Damage' ); // DeVast - PubPro votes if(!Game.PubPro) messageClient( %client, 'MsgVoteItem', "", %key, 'VotePro', 'Enable Pro Mode', 'Vote to enable Pro Mode' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VotePro', 'Disable Pro Mode', 'Vote to disable Pro Mode' ); } else { if(!Game.duelMode) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteDuelMode', 'Enable Duel Mode', 'Enable Duel Mode' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteDuelMode', 'Disable Duel Mode', 'Disable Duel Mode' ); if(!Game.noSplashDamage) messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSplashDamage', 'Disable Splash Damage', 'Disable Splash Damage' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSplashDamage', 'Enable Splash Damage', 'Enable Splash Damage' ); // DeVast - PubPro votes if(!Game.PubPro) messageClient( %client, 'MsgVoteItem', "", %key, 'VotePro', 'Enable Pro Mode', 'Enable Pro Mode' ); else messageClient( %client, 'MsgVoteItem', "", %key, 'VotePro', 'Disable Pro Mode', 'Disable Pro Mode' ); } } } function LakRabbitGame::evalVote(%game, %typeName, %admin, %arg1, %arg2, %arg3, %arg4) { switch$ (%typeName) { case "VoteDuelMode": %game.voteDuelMode(%admin, %arg1, %arg2, %arg3, %arg4); case "VoteSplashDamage": %game.voteSplashDamage(%admin, %arg1, %arg2, %arg3, %arg4); case "VotePro": %game.VotePro(%admin, %arg1, %arg2, %arg3, %arg4); } parent::evalVote(%game, %typeName, %admin, %arg1, %arg2, %arg3, %arg4); } // Zeph - PubPro voting function LakRabbitGame::VotePro(%game, %admin, %arg1, %arg2, %arg3, %arg4) { if(%admin) { killeveryone(); if(%game.PubPro) { messageAll('MsgAdminForce', '\c2The Admin has disabled Pro.'); $InvBanList[LakRabbit, "GrenadeLauncher"] = 0; $InvBanList[LakRabbit, "ShockLance"] = 0; $InvBanList[LakRabbit, "Mortar"] = 0; $InvBanList[LakRabbit, "Grenade"] = 0; %game.PubPro = false; } else { messageAll('MsgAdminForce', '\c2The Admin has enabled Pro.'); $InvBanList[LakRabbit, "GrenadeLauncher"] = 1; $InvBanList[LakRabbit, "ShockLance"] = 1; $InvBanList[LakRabbit, "Mortar"] = 1; $InvBanList[LakRabbit, "Grenade"] = 1; %game.PubPro = true; } } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / ClientGroup.getCount()) > ($Host::VotePasspercent / 100)) { killeveryone(); if(%game.PubPro) { messageAll('MsgVotePassed', '\c2PubPro Disabled.'); $InvBanList[LakRabbit, "GrenadeLauncher"] = 0; $InvBanList[LakRabbit, "ShockLance"] = 0; $InvBanList[LakRabbit, "Mortar"] = 0; $InvBanList[LakRabbit, "Grenade"] = 0; %game.PubPro = false; } else { messageAll('MsgVotePassed', '\c2PubPro Enabled.'); $InvBanList[LakRabbit, "GrenadeLauncher"] = 1; $InvBanList[LakRabbit, "ShockLance"] = 1; $InvBanList[LakRabbit, "Mortar"] = 1; $InvBanList[LakRabbit, "Grenade"] = 1; %game.PubPro = true; } } else messageAll('MsgVoteFailed', '\c2Mode change did not pass: %1 percent.', mFloor(%game.totalVotesFor/ClientGroup.getCount() * 100)); } $Host::LakRabbitPubPro = %game.PubPro; } function LakRabbitGame::voteDuelMode(%game, %admin, %arg1, %arg2, %arg3, %arg4) { if(%admin) { killEveryone(); if(%game.duelMode) { messageAll('MsgAdminForce', '\c2The Admin has disabled Duel Mode.'); %game.duelMode = false; } else { messageAll('MsgAdminForce', '\c2The Admin has enabled Duel Mode.'); %game.duelMode = true; } } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / ClientGroup.getCount()) > ($Host::VotePasspercent / 100)) { killEveryone(); if(%game.duelMode) { messageAll('MsgVotePassed', '\c2Duel Mode disabled.'); %game.duelMode = false; } else { messageAll('MsgVotePassed', '\c2Duel Mode enabled.'); %game.duelMode = true; } } else messageAll('MsgVoteFailed', '\c2Mode change did not pass: %1 percent.', mFloor(%game.totalVotesFor/ClientGroup.getCount() * 100)); } // save $Host::LakRabbitDuelMode = %game.duelMode; } function LakRabbitGame::voteSplashDamage(%game, %admin, %arg1, %arg2, %arg3, %arg4) { if(%admin) { if(%game.noSplashDamage) { messageAll('MsgAdminForce', '\c2The Admin has enabled Splash Damage.'); %game.noSplashDamage = false; } else { messageAll('MsgAdminForce', '\c2The Admin has disabled Splash Damage.'); %game.noSplashDamage = true; } } else { %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; if(%totalVotes > 0 && (%game.totalVotesFor / ClientGroup.getCount()) > ($Host::VotePasspercent / 100)) { if(%game.noSplashDamage) { messageAll('MsgVotePassed', '\c2Splash Damage enabled.'); %game.noSplashDamage = false; } else { messageAll('MsgVotePassed', '\c2Splash Damage disabled.'); %game.noSplashDamage = true; } } else messageAll('MsgVoteFailed', '\c2Mode change did not pass: %1 percent.', mFloor(%game.totalVotesFor/ClientGroup.getCount() * 100)); } // save $Host::LakRabbitNoSplashDamage = %game.noSplashDamage; } // new debriefing stuff function LakRabbitGame::sendDebriefing( %game, %client ) { messageClient( %client, 'MsgDebriefAddLine', "", 'PLAYERSCOREKILLSMASSPEEDDISTTOT DISTSHOCKSL HITS' ); // %cl.name, %score, %kills, %mas, %avgSpeed, %avgDistance, %alltotdistance, %shockPercent, %totshockhits // Scores: %totscore = 0; %totkills = 0; %totmas = 0; %totspeed = 0; %totdistance = 0; //%totchainacc = 0; //%totsnipepercent= 0; %totshockpercent= 0; %speeds = 0; %dists = 0; //%chains = 0; //%snipes = 0; %shocks = 0; %alltotdistance = 0; %totshockhits = 0; %count = $TeamRank[0, count]; for(%i = 0; %i < %count; %i++) { // Send the debrief line: %cl = $TeamRank[0, %i]; if(%cl.score == 0) %score = 0; else %score = %cl.score; if(%cl.kills == 0) %kills = 0; else %kills = %cl.kills; if(%cl.mas == 0) %mas = 0; else %mas = %cl.mas; //if(%cl.totalSnipes == 0) %cl.totalSnipes = 1; if(%cl.totalShocks == 0) %cl.totalShocks = 1; if(%cl.totalSpeed == 0) %avgSpeed = 0; else %avgSpeed = mFloor(%cl.totalSpeed/%cl.mas); if(%cl.totalDistance == 0) %avgDistance = 0; else %avgDistance = mFloor(%cl.totalDistance/%cl.mas); //if(%cl.totalChainAccuracy == 0) %avgChainAcc = 0; //else %avgChainAcc = mFloor(%cl.totalChainAccuracy/%cl.totalChainHits); //if(%cl.totalSnipeHits == 0) %snipePercent = 0; //else %snipePercent = mFloor(%cl.totalSnipeHits/%cl.totalSnipes*100); if(%cl.totalShockHits == 0) %shockPercent = 0; else %shockPercent = mFloor(%cl.totalShockHits/%cl.totalShocks*100); if(%cl.totalDistance == 0) %othertotdistance = 0; else %othertotdistance = mFloor(%cl.totalDistance); if(%cl.totalShockHits == 0) %shockhits = 0; else %shockhits = mFloor(%cl.totalShockHits); messageClient( %client, 'MsgDebriefAddLine', "", ' %1%2%3%4%5%6%7%8%%%9', %cl.name, %score, %kills, %mas, %avgSpeed, %avgDistance, %othertotdistance, %shockPercent, %shockhits); if(%score) %totscore += %score; if(%kills) %totkills += %kills; if(%mas) %totmas += %mas; if(%avgSpeed){ %totspeed += %avgSpeed; %speeds++; } if(%avgDistance){ %totdistance += %avgDistance; %dists++; } //if(%avgChainAcc){ %totchainacc += %avgChainAcc; %chains++; } //if(%snipePercent){ %totsnipepercent += %snipePercent; %snipes++; } if(%shockPercent){ %totshockpercent += %shockPercent; %shocks++; } if(%othertotdistance){ %alltotdistance += %othertotdistance; } if(%shockhits){ %totshockhits += %shockhits; } } messageClient( %client, 'MsgDebriefAddLine', "", '%1%2%3%4%5%6%7%8%%%9\n', " Totals:", %totscore, %totkills, %totmas, mFloor(%totspeed/%speeds), mFloor(%totdistance/%dists), %alltotdistance, mFloor(%totshockpercent/%shocks), %totshockhits); } // regular game functions function LakRabbitGame::setUpTeams(%game) { // Force the numTeams variable to one: DefaultGame::setUpTeams(%game); %game.numTeams = 1; setSensorGroupCount(3); //team damage should always be off for Rabbit $teamDamage = 0; //make all the sensor groups visible at all times if (!Game.teamMode) { setSensorGroupAlwaysVisMask($NonRabbitTeam, 0xffffffff); setSensorGroupAlwaysVisMask($RabbitTeam, 0xffffffff); // non-rabbits can listen to the rabbit: all others can only listen to self setSensorGroupListenMask($NonRabbitTeam, (1 << $RabbitTeam) | (1 << $NonRabbitTeam)); } } function LakRabbitGame::initGameVars(%game) { %game.playerBonusValue = 1; %game.playerBonusTime = 3 * 1000; %game.teamBonusValue = 3; %game.teamBonusTime = 5 * 1000; %game.flagReturnTime = 25 * 1000; %game.waypointFrequency = 24000; %game.waypointDuration = 6000; %game.duelMode = $Host::LakRabbitDuelMode; %game.PubPro = $Host::LakRabbitPubPro; %game.noSplashDamage = $Host::LakRabbitNoSplashDamage; } $RabbitTeam = 2; $NonRabbitTeam = 1; // ----- These functions supercede those in DefaultGame.cs function LakRabbitGame::allowsProtectedStatics(%game) { return true; } function LakRabbitGame::clientMissionDropReady(%game, %client) { messageClient(%client, 'MsgClientReady', "", %game.class); messageClient(%client, 'MsgYourScoreIs', "", 0); //messageClient(%client, 'MsgYourRankIs', "", -1); messageClient(%client, 'MsgRabbitFlagStatus', "", $flagStatus); messageClient(%client, 'MsgMissionDropInfo', '\c0You are in mission %1 (%2).', $MissionDisplayName, $MissionTypeDisplayName, $ServerName ); DefaultGame::clientMissionDropReady(%game,%client); } function LakRabbitGame::AIHasJoined(%game, %client) { //let everyone know the player has joined the game //messageAllExcept(%client, -1, 'MsgClientJoinTeam', '%1 has joined the hunt.', %client.name, "", %client, $NonRabbitTeam); } function LakRabbitGame::clientJoinTeam( %game, %client, %team, %respawn ) { %game.assignClientTeam( %client ); // Spawn the player: %game.spawnPlayer( %client, %respawn ); %game.recalcScore( %client ); } function LakRabbitGame::assignClientTeam(%game, %client) { // all players start on team 1 %client.team = $NonRabbitTeam; // set player's skin pref here setTargetSkin(%client.target, %client.skin); if(%client.kills $= "") %game.resetScore(%client); // Let everybody know you are no longer an observer: messageAll( 'MsgClientJoinTeam', '\c1%1 has joined the hunt.', %client.name, "", %client, %client.team ); updateCanListenState( %client ); } function LakRabbitGame::playerSpawned(%game, %player) { //call the default stuff first... DefaultGame::playerSpawned(%game, %player); //find the rabbit %clRabbit = -1; for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); if (isObject(%cl.player) && isObject(%cl.player.holdingFlag)) { %clRabbit = %cl; break; } } //now set a waypoint just for that client... // ilys -- show client waypoint if not showing flag icon if($Host::LakRabbitShowFlagIcon == 0 && $Host::LakRabbitShowFlagTask) { cancel(%player.client.waypointSchedule); if (isObject(%clRabbit) && !%player.client.isAIControlled()) %player.client.waypointSchedule = %game.showRabbitWaypointClient(%clRabbit, %player.client); } // borlak -- start with favorites if(!Game.PubPro) buyFavorites(%player.client); // Zeph - PubPro weapons else { %player.clearInventory(); %player.setInventory(Disc,1); %player.setInventory(Blaster,1); %player.setInventory(Plasma,1); %player.setInventory(DiscAmmo,30); %player.setInventory(PlasmaAmmo,40); %player.setInventory(Mine,6); %player.setInventory(RepairKit,1); %player.setInventory(EnergyPack,1); %player.use("Disc"); } %player.schedule(250,"selectWeaponSlot", 0); %player.setEnergyLevel(%player.getDatablock().maxEnergy); if($Host::LakRabbitUnlimitedDJ == 1) %player.freeDJ = 999; // free diskjump else %player.freeDJ = 1; // free diskjump } // modified to spawn you near rabbit or flag function LakRabbitGame::pickTeamSpawn(%game, %team) { //Use traditional spawnspheres for indoor maps if($CurrentMission $= "BoxLak") return parent::pickTeamSpawn(%game, %team); //find the rabbit %spawnNear = -1; for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); if (isObject(%cl.player) && isObject(%cl.player.holdingFlag)) { %spawnNear = %cl.player; break; } } if(!isObject(%spawnNear)) { for (%i = 0; %i < Team0.getCount(); %i++) { %obj = Team0.getObject(%i); if(%obj.dataBlock $= Flag) { %spawnNear = %obj; if(!%obj.isHome) break; } } } for(%i = 0; %i < 25; %i++) { %pos = %spawnNear.getWorldBoxCenter(); %randx = getWord(%pos,0)+getRandom(-150,150); %randy = getWord(%pos,1)+getRandom(-150,150); %mask = $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType; %rayStart = %randx SPC %randy SPC "1000"; %rayEnd = %randx SPC %randy SPC "-1000"; %ground = ContainerRayCast(%rayStart, %rayEnd, %mask, 0); if(%ground) { %loc = getWord(%ground,1) SPC getWord(%ground,2) SPC getWord(%ground,3); if(isOutOfBounds(%loc)) { %ground = 0; continue; } break; } } if(%ground) return %loc; return "0 0 500"; } function LakRabbitGame::pickPlayerSpawn(%game, %client, %respawn) { // borlak -- reset values at spawn $LakDamaged[%client] = 0; %client.duelSecondsCounted = 0; %client.duelSeconds = 0; %client.duelKills = 0; %client.player.lastDamageType = 0; %client.player.knockback = 0; cancel(%client.duelTimer); // all spawns come from team 1 return %game.pickTeamSpawn($NonRabbitTeam); } function LakRabbitGame::createPlayer(%game, %client, %spawnLoc, %respawn) { %client.team = $NonRabbitTeam; DefaultGame::createPlayer(%game, %client, %spawnLoc, %respawn); } function LakRabbitGame::recalcScore(%game, %client) { //score is grabs + kills + (totalTime / 15 seconds); %timeHoldingFlagMS = %client.flagTimeMS; if (isObject(%client.player.holdingFlag)) %timeHoldingFlagMS += getSimTime() - %client.startTime; if(Game.PubPro) %client.score = %client.flagGrabs + (%client.kills*5) + %client.morepoints + mFloor(%timeHoldingFlagMS / 3000); else %client.score = %client.flagGrabs + %client.kills + %client.morepoints + mFloor(%timeHoldingFlagMS / 3000); messageClient(%client, 'MsgYourScoreIs', "", %client.score); %game.recalcTeamRanks(%client); %game.checkScoreLimit(%client); } function LakRabbitGame::onClientDamaged(%game, %clVictim, %clAttacker, %damageType, %sourceObject) { //if the victim is the rabbit, and the attacker is not the rabbit, set the damage time... if (isObject(%clAttacker) && %clAttacker != %clVictim) { if (%clVictim.team == $RabbitTeam) %game.rabbitDamageTime = getSimTime(); } //call the default DefaultGame::onClientDamaged(%game, %clVictim, %clAttacker, %damageType, %sourceObject); } function LakRabbitGame::onClientKilled(%game, %clVictim, %clKiller, %damageType, %implement, %damageLoc) { // borlak - make sure victim isn't killer if(%clKiller != %clVictim) { %clKiller.kills++; %game.recalcScore(%clKiller); if($LakDamaged[%clVictim]) %killer = $LakDamaged[%clVictim]; else %killer = %clKiller; if(Game.duelMode && %killer.player.holdingFlag && %damageType != $DamageType::Missile) duelBonus(%killer); } // borlak -- flag bug fix %clVictim.flagDeny = schedule(2500, 0, setFlagDeny, %clVictim, 0); DefaultGame::onClientKilled(%game, %clVictim, %clKiller, %damageType, %implement, %damageLoc); } // z0dd - ZOD, 8/4/02: KineticPoet's flag updater code function LakRabbitGame::updateFlagTransform(%game, %flag) { %flag.setTransform(%flag.getTransform()); %game.updateFlagThread[%flag] = %game.schedule(100, "updateFlagTransform", %flag); } function LakRabbitGame::playerDroppedFlag(%game, %player) { //set the flag status %flag = %player.holdingFlag; %player.holdingFlag = ""; %flag.carrier = ""; $flagStatus = ""; %player.unmountImage($FlagSlot); %flag.hide(false); // ilys -- remove flag icon from player if($Host::LakRabbitShowFlagIcon == 1 || $Host::LakRabbitShowFlagIcon == 2) { setTargetSensorGroup(%flag.getTarget(), $Observer); %player.scopeWhenSensorVisible(true); %target = %player.getTarget(); setTargetRenderMask(%target, getTargetRenderMask(%target) & ~0x2); setTargetAlwaysVisMask(%target, (1 << getTargetSensorGroup(%target))); } //just always true //if( $Host::LakRabbitShowFlagIcon == 1 ) //%flag.scopeWhenSensorVisible(true); //else if($Host::LakRabbitShowFlagIcon == 2) //%flag.scopeWhenSensorVisible(false); // borlak -- throw the flag, don't just drop it like dead weight // v3.1 -- in duel mode, make flag bounce up always, even if player isn't moving.. more midair grabs %flag.static = false; %vec = (-1.0 + getRandom() * 2.0) SPC (-1.0 + getRandom() * 2.0) SPC getRandom(); %vec = vectorScale(%vec, 10); %dot = vectorDot("0 0 1",%eye); if (%dot < 0) %dot = -%dot; %vec = vectorAdd(%vec,vectorScale("0 0 12",1 - %dot)); %vec = vectorAdd(%vec,%player.getVelocity()); if(%game.duelMode && getWord(%vec,2) < 35) %vec = getWord(%vec, 0) @ " " @ getWord(%vec, 1) @ " 35"; %pos = getBoxCenter(%player.getWorldBox()); %vec = vectorScale(%vec, 75); %flag.setTransform(%pos); %flag.applyImpulse(%pos,%vec); %flag.setCollisionTimeout(%player); // ilys -- hide waypoint if not showing flag icon if($Host::LakRabbitShowFlagIcon == 0 && $Host::LakRabbitShowFlagTask) { cancel(%game.waypointSchedule); %game.hideRabbitWaypoint(%player.client); } //set the client status %player.client.flagTimeMS += getSimTime() - %player.client.startTime; %player.client.team = $NonRabbitTeam; %player.client.setSensorGroup($NonRabbitTeam); setTargetSensorGroup(%player.getTarget(), $NonRabbitTeam); messageAllExcept(%player.client, -1, 'MsgRabbitFlagDropped', '\c2%1 dropped the flag!~wfx/misc/flag_drop.wav', %player.client.name); // if the player left the mission area, he's already been notified if(!%player.outArea) messageClient(%player.client, 'MsgRabbitFlagDropped', '\c2You dropped the flag!~wfx/misc/flag_drop.wav'); logEcho(%player.client.nameBase@" (pl "@%player@"/cl "@%player.client@") dropped flag"); %flag.returnThread = %game.schedule(%game.flagReturnTime, "returnFlag", %flag); // z0dd - ZOD - SquirrelOfDeath, 10/02/02. Hack for flag collision bug. %flag.searchSchedule = Game.schedule(10, "startFlagCollisionSearch", %flag); %game.updateFlagTransform(%flag); // z0dd - ZOD, 8/4/02, Call to KineticPoet's flag updater // borlak -- timer fix and re-catch fix %player.client.flagDeny = schedule(2500, 0, setFlagDeny, %player.client, 0); cancel(%player.client.duelTimer); // borlak -- give bonus for duel mode if(%game.duelMode) { if(%player.lastDamageType == $DamageType::Suicide) { messageAll('MsgDuelBonus', '\c2%1 suicides and gets no points!', %player.client.name); return; } %points = 0; for(%i = 1; %i <= %player.client.duelKills; %i++) %points += (%i*4); %kills = (%player.client.duelKills*12)+12; if(%kills <= 0) %kills = 1; %seconds = %player.client.duelSecondsCounted; if(%seconds < %player.duelKills*4) %seconds = %player.duelKills*4; %points *= %kills / %seconds; %points = mFloor(%points); %plural = (%points != 1 ? 's' : ""); %pluralP = (%player.client.duelKills != 1 ? 'people' : 'person'); %pluralSec = (%player.client.duelSecondsCounted != 1 ? 's' : ""); if(%player.client.duelKills == 0) messageAll('MsgDuelBonus', '\c2%1 kills nobody and gets nothing! Better luck next time....', %player.client.name, %points, %plural, %player.client.duelKills, %player.client.duelSecondsCounted); else messageAll('MsgDuelBonus', '\c2%1 gets %2 bonus point%3 for killing %4 %5 in %6 second%7.', %player.client.name, %points, %plural, %player.client.duelKills, %pluralP, %player.client.duelSecondsCounted, %pluralSec); %player.client.morepoints += %points; %game.recalcScore(%player.client); } } function LakRabbitGame::playerTouchFlag(%game, %player, %flag) { if(%player.getState() $= "Dead" || %player.client.flagDeny) return; // borlak - can't pick up flag until 2 ppl are on if(PlayingPlayers() < 2) { %timeDif = getSimTime() - %player.client.pickUpTime; if(%timeDif > 5000 || !%player.client.pickUpTime) { messageClient(%player.client, 'msgNoFlagWarning', "\c2You can't pick up the flag until another person joins." ); %player.client.pickUpTime = getSimTime(); } return; } // borlak -- flag capturing in CTF maps.. extra points.. rabbit mode only if ((%flag.carrier $= "") && %player.holdingFlag && !%game.duelMode) { if(PlayingPlayers() < 6) { messageClient(%player.client, 'msgNoFlagWarning', "\c2You can't start capping until there are 6 players." ); return; } %points = mFloor((getSimTime() - %player.client.startTime)/2000); if(%points < 10) %points = 10; // minimum 10 points messageAll('MsgRabbitFlagTaken', '\c4%1 gets %2 points for a capturing the flag!~wfx/misc/flipflop_lost.wav', %player.client.name, %points); %player.client.flagTimeMS += getSimTime() - %player.client.startTime; %game.resetFlag(%player.holdingFlag); } // check if someone already has other flag.. only one flag can be in play.. also make sure you can only pick up flag that IS in play %flagInPlay = 0; for (%i = 0; %i < Team0.getCount(); %i++) { %obj = Team0.getObject(%i); if(%obj.dataBlock $= Flag) { if(!%obj.isHome) %flagInPlay = %obj; if(!%obj.isHome && %obj.carrier) { messageClient(%player.client, 'msgNoFlagWarning', "\c2Only one flag may be in play."); return; } } } if(%flagInPlay && %flag != %flagInPlay) { messageClient(%player.client, 'msgNoFlagWarning', "\c2You can only pick up the flag in play."); return; } if(%flag.carrier $= "") { // borlak cancel flag search and remove free diskjump cancel(%flag.searchSchedule); cancel(%game.updateFlagThread[%flag]); // z0dd - ZOD, 8/4/02. Cancel this flag's thread to KineticPoet's flag updater %player.freeDJ = 0; %flag.bounced = 0; %player.client.startTime = getSimTime(); %player.holdingFlag = %flag; %flag.carrier = %player; %player.mountImage(FlagImage, $FlagSlot, true); //, $teamSkin[$RabbitTeam]); cancel(%flag.returnThread); %flag.hide(true); // ilys -- add flag icon to player if( $Host::LakRabbitShowFlagIcon == 2 ) { setTargetSensorGroup(%flag.getTarget(), $RabbitTeam); %player.scopeWhenSensorVisible(true); %target = %player.getTarget(); setTargetRenderMask(%target, getTargetRenderMask(%target) | 0x2); setTargetAlwaysVisMask(%target, 0x7); } %flag.isHome = false; $flagStatus = %client.name; // borlak -- points for MA flag grabs %mask = $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType; %rayStart = %player.getWorldBoxCenter(); %rayEnd = getWord(%rayStart, 0) SPC getWord(%rayStart, 1) SPC getWord(%rayStart, 2) - 5; %ground = ContainerRayCast(%rayStart, %rayEnd, %mask, 0); if(!%ground) { %points = mFloor((getSpeed(%player)/7.3) + (getHeight(%player)/3.3)); //was 5.3 - 2.3 %points = %points > 5 ? %points : 5; messageAll('MsgRabbitFlagTaken', '\c4%1 gets %2 points for a Mid-Air flag grab! [Speed:%3] [Height:%4]~wfx/misc/hunters_horde.wav', %player.client.name, %points, getSpeed(%player), getHeight(%player)); %player.client.morepoints += %points; %player.client.MidairflagGrabs++; //for stats %player.client.MidairflagGrabPoints += %points; //for stats } else messageAll('MsgRabbitFlagTaken', '\c2%1 has taken the flag!~wfx/misc/flag_snatch.wav', %player.client.name); logEcho(%player.client.nameBase@" (pl "@%player@"/cl "@%player.client@") took flag"); %player.client.team = $RabbitTeam; %player.client.setSensorGroup($RabbitTeam); setTargetSensorGroup(%player.getTarget(), $RabbitTeam); //increase the score %player.client.flagGrabs++; %game.recalcScore(%player.client); %game.schedule(5000, "RabbitFlagCheck", %player); //show the rabbit waypoint %game.rabbitDamageTime = 0; // ilys -- waypoint if not showing flag icon if($Host::LakRabbitShowFlagIcon == 0 && $Host::LakRabbitShowFlagTask) { cancel(%game.waypointSchedule); %game.showRabbitWaypoint(%player.client); } // borlak - make rabbit invincible for 2 seconds .. %player.setInvincible(true); %player.schedule(2000, "setInvincible", false); // duel mode if(%game.duelMode) { %player.client.duelTimer = schedule(1000, 0, checkDuelTimer, %player.client); %player.client.duelSeconds = 36 - (PlayingPlayers()*4); if(PlayingPlayers() == 2 || %game.noSplashDamage) %player.client.duelSeconds += 10; if(%player.client.duelSeconds < 20) %player.client.duelSeconds = 20; %player.client.duelKills = 0; } } } function LakRabbitGame::rabbitFlagCheck(%game, %player) { // this function calculates the score for the rabbit. It must be done periodically // since the rabbit's score is based on how long the flag has been in possession. if((%player.holdingFlag != 0) && (%player.getState() !$= "Dead")) { %game.recalcScore(%player.client); //reschedule this flagcheck for 5 seconds %game.schedule(5000, "RabbitFlagCheck", %player); } } function LakRabbitGame::returnFlag(%game, %flag) { messageAll('MsgRabbitFlagReturned', '\c2The flag was returned to its starting point.~wfx/misc/flag_return.wav'); logEcho("flag return (timeout)"); %game.resetFlag(%flag); } function LakRabbitGame::resetFlag(%game, %flag) { %flag.setVelocity("0 0 0"); %flag.setTransform(%flag.originalPosition); %flag.isHome = true; %flag.carrier = ""; $flagStatus = ""; %flag.hide(false); //so flag turns back green if($Host::LakRabbitShowFlagIcon == 1 || $Host::LakRabbitShowFlagIcon == 2) { setTargetSensorGroup(%flag.getTarget(), $NonRabbitTeam); } cancel(%flag.searchSchedule); cancel(%game.updateFlagThread[%flag]); // z0dd - ZOD, 8/4/02. Cancel this flag's thread to KineticPoet's flag updater } // ----- These functions are native to Rabbit function LakRabbitGame::timeLimitReached(%game) { logEcho("game over (timelimit)"); %game.gameOver(); cycleMissions(); } function LakRabbitGame::scoreLimitReached(%game) { logEcho("game over (scorelimit)"); %game.gameOver(); cycleMissions(); } function LakRabbitGame::checkScoreLimit(%game, %client) { %scoreLimit = MissionGroup.Rabbit_scoreLimit; // default of 1200 if scoreLimit not defined (that's 1200 seconds worth - 20 minutes) if(%scoreLimit $= "") %scoreLimit = 2000; if(%client.score >= %scoreLimit) %game.scoreLimitReached(); } function LakRabbitGame::gameOver(%game) { // z0dd - ZOD, 9/28/02. Hack for flag collision bug. for(%f = 1; %f <= %game.numTeams; %f++) { cancel($TeamFlag[%f].searchSchedule); } //call the default DefaultGame::gameOver(%game); //send the message messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.gameover.wav" ); cancel(%game.rabbitWaypointThread); messageAll('MsgClearObjHud', ""); for(%i = 0; %i < ClientGroup.getCount(); %i++) { %client = ClientGroup.getObject(%i); %game.resetScore(%client); // ilys -- cancel waypoint if not showing flag icon if($Host::LakRabbitShowFlagIcon == 0 && $Host::LakRabbitShowFlagTask) cancel(%client.waypointSchedule); cancel(%client.duelTimer); if(%client.team $=0) %client.lakobs = 1; //Put everyone in observer //Mainly for switching to CTF %client.team = 0; %client.lastTeam = 0; } // ilys -- cancel waypoint if not showing flag icon if($Host::LakRabbitShowFlagIcon == 0 && $Host::LakRabbitShowFlagTask) cancel(%game.waypointSchedule); // borlak -- delete variables deleteVariables("$LakFired*"); deleteVariables("$LakDamaged*"); } function LakRabbitGame::resetScore(%game, %client) { %client.score = 0; %client.kills = 0; %client.deaths = 0; %client.suicides = 0; %client.flagGrabs = 0; %client.flagTimeMS = 0; %client.morepoints = 0; // new debriefing stuff %client.mas = 0; %client.totalSpeed = 0; %client.totalDistance = 0; %client.totalChainAccuracy = 0; %client.totalChainHits = 0; %client.totalSnipeHits = 0; %client.totalSnipes = 0; %client.totalShockHits = 0; %client.totalShocks = 0; } function LakRabbitGame::enterMissionArea(%game, %playerData, %player) { if(%player.getState() $= "Dead") return; %player.client.outOfBounds = false; messageClient(%player.client, 'EnterMissionArea', '\c1You are back in the mission area.'); logEcho(%player.client.nameBase@" (pl "@%player@"/cl "@%player.client@") entered mission area"); cancel(%player.alertThread); } // borlak -- TAKEN FROM TR2 -- thanks! :D function plzBounceOffGrid(%obj, %bounceForce, %count) { %bounds = MissionArea.area; %boundsWest = firstWord(%bounds); %boundsNorth = getWord(%bounds, 1); %boundsEast = %boundsWest + getWord(%bounds, 2); %boundsSouth = %boundsNorth + getWord(%bounds, 3); %shapePos = %obj.getPosition(); %shapex = firstWord(%shapePos); %shapey = getWord(%shapePos, 1); if( %shapex >= %boundsWest && %shapex <= %boundsEast && %shapey >= %boundsNorth && %shapey <= %boundsSouth) { // we don't need to bounce at all return; } if( %count == 8 ) { // just kill this retard %obj.scriptKill($DamageType::OutOfBounds); return; } if (%bounceForce $= "") %bounceForce = 65; %oldVel = %obj.getVelocity(); %obj.setVelocity("0 0 0"); %vecx = firstWord(%oldVel); %vecy = getWord(%oldVel, 1); %vecz = getWord(%oldVel, 2); // four cases, not two cases you fucktard kineticpoet // no wonder the trives of vengrances failed if(%shapex <= %boundsWest) { %vecx = mAbs(%vecx); } else if(%shapex >= %boundsEast) { %vecx = -mAbs(%vecx); } if(%shapey <= %boundsNorth) { %vecy = mAbs(%vecy); } else if(%shapey >= %boundsSouth) { %vecy = -mAbs(%vecy); } %vec = %vecx SPC %vecy SPC %vecz; // If the object's speed was pretty slow, give it a boost %oldSpeed = VectorLen(%oldVel); if (%oldSpeed < 25) { %vec = VectorNormalize(%vec); %vec = VectorScale(%vec, 25); } else if (%oldSpeed < 60) //Max speed a boost gets applied to a bounce: Added so runners cant abuse %vec = VectorScale(%vec, 1.15); // apply the impulse to the object //%obj.applyImpulse(%obj.getWorldBoxCenter(), %vec); %obj.setVelocity(%vec); // repeat this bounce 4 times per second. if we're oob for 2 seconds, take action // don't do this with the flag because that has its own thread if( %obj.dataBlock !$= "Flag" ) { schedule(250, 0, plzBounceOffGrid, %obj, %bounceForce, %count + 1); } } function isOutOfBounds(%position) { %shapePos = %position; %shapex = firstWord(%shapePos); %shapey = getWord(%shapePos, 1); %bounds = MissionArea.area; %boundsWest = firstWord(%bounds); %boundsNorth = getWord(%bounds, 1); %boundsEast = %boundsWest + getWord(%bounds, 2); %boundsSouth = %boundsNorth + getWord(%bounds, 3); return (%shapex < %boundsWest || %shapex > %boundsEast || %shapey < %boundsNorth || %shapey > %boundsSouth); } function getHeight(%this) { %z = getWord(%this.getPosition(), 2); return mFloor((%z - getTerrainHeight(%this.getPosition()))); } function LakRabbitGame::leaveMissionArea(%game, %playerData, %player) { plzBounceOffGrid(%player, 65); } // z0dd - ZOD, 10/02/02. Hack for flag collision bug. // borlak -- stolen from classic function LakRabbitGame::startFlagCollisionSearch(%game, %flag) { if(isOutOfBounds(%flag.getPosition())) { plzBounceOffGrid(%flag, 15); %flag.bounced++; if(%flag.bounced >= 25) { cancel(%flag.returnThread); %game.returnFlag(%flag); } } %flag.searchSchedule = %game.schedule(10, "startFlagCollisionSearch", %flag); // SquirrelOfDeath, 10/02/02. Moved from after the while loop %pos = %flag.getWorldBoxCenter(); InitContainerRadiusSearch( %pos, 1.0, $TypeMasks::VehicleObjectType | $TypeMasks::CorpseObjectType | $TypeMasks::PlayerObjectType ); while((%found = containerSearchNext()) != 0) { %flag.getDataBlock().onCollision(%flag, %found); // SquirrelOfDeath, 10/02/02. Removed break to catch all players possibly intersecting with flag } } function LakRabbitGame::dropFlag(%game, %player) { //you can no longer throw the flag in Rabbit... } function LakRabbitGame::updateScoreHud(%game, %client, %tag) { //tricky stuff here... use two columns if we have more than 15 clients... %numClients = $TeamRank[0, count]; if ( %numClients > $ScoreHudMaxVisible ) %numColumns = 2; // Clear the header: messageClient( %client, 'SetScoreHudHeader', "", "" ); // Send subheader: if (%numColumns == 2) messageClient(%client, 'SetScoreHudSubheader', "", '\tPLAYER\tSCORE\tTIME\tPLAYER\tSCORE\tTIME'); else messageClient(%client, 'SetScoreHudSubheader', "", '\tPLAYER\tSCORE\tTIME'); //recalc the score for whoever is holding the flag if (isObject($AIRabbitFlag.carrier)) %game.recalcScore($AIRabbitFlag.carrier.client); %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 = ""; if (isObject(%col1Client.player.holdingFlag)) { %col1ClientTimeMS = %col1Client.flagTimeMS + getSimTime() - %col1Client.startTime; %col1Style = ""; } else { %col1ClientTimeMS = %col1Client.flagTimeMS; if ( %col1Client == %client ) %col1Style = ""; } if (%col1ClientTimeMS <= 0) %col1ClientTime = ""; else { %minutes = mFloor(%col1ClientTimeMS / (60 * 1000)); if (%minutes <= 0) %minutes = "0"; %seconds = mFloor(%col1ClientTimeMS / 1000) % 60; if (%seconds < 10) %seconds = "0" @ %seconds; %col1ClientTime = %minutes @ ":" @ %seconds; } //see if we have two columns if (%numColumns == 2) { %col2Client = ""; %col2ClientScore = ""; %col2ClientTime = ""; %col2Style = ""; //get the column 2 client info %col2Index = %index + %countMax; if (%col2Index < %numClients) { %col2Client = $TeamRank[0, %col2Index]; %col2ClientScore = %col2Client.score $= "" ? 0 : %col2Client.score; if (isObject(%col2Client.player.holdingFlag)) { %col2ClientTimeMS = %col2Client.flagTimeMS + getSimTime() - %col2Client.startTime; %col2Style = ""; } else { %col2ClientTimeMS = %col2Client.flagTimeMS; if ( %col2Client == %client ) %col2Style = ""; } if (%col2ClientTimeMS <= 0) %col2ClientTime = ""; else { %minutes = mFloor(%col2ClientTimeMS / (60 * 1000)); if (%minutes <= 0) %minutes = "0"; %seconds = mFloor(%col2ClientTimeMS / 1000) % 60; if (%seconds < 10) %seconds = "0" @ %seconds; %col2ClientTime = %minutes @ ":" @ %seconds; } } } //if the client is not an observer, send the message if (%client.team != 0) { if ( %numColumns == 2 ) messageClient( %client, 'SetLineHud', "", %tag, %index, '%7\t%1%2%3%8%4%5%6', %col1Client.name, %col1ClientScore, %col1ClientTime, %col2Client.name, %col2ClientScore, %col2ClientTime, %col1Style, %col2Style ); else messageClient( %client, 'SetLineHud', "", %tag, %index, '%4\t%1%2%3', %col1Client.name, %col1ClientScore, %col1ClientTime, %col1Style ); } //else for observers, create an anchor around the player name so they can be observed else { if ( %numColumns == 2 ) { //this is really crappy, but I need to save 1 tag - can only pass in up to %9, %10 doesn't work... if (%col2Style $= "") { messageClient( %client, 'SetLineHud', "", %tag, %index, '%7\t%1%2%3%4%5%6', %col1Client.name, %col1ClientScore, %col1ClientTime, %col2Client.name, %col2ClientScore, %col2ClientTime, %col1Style, %col1Client, %col2Client ); } else if (%col2Style $= "") { messageClient( %client, 'SetLineHud', "", %tag, %index, '%7\t%1%2%3%4%5%6', %col1Client.name, %col1ClientScore, %col1ClientTime, %col2Client.name, %col2ClientScore, %col2ClientTime, %col1Style, %col1Client, %col2Client ); } else { messageClient( %client, 'SetLineHud', "", %tag, %index, '%7\t%1%2%3%4%5%6', %col1Client.name, %col1ClientScore, %col1ClientTime, %col2Client.name, %col2ClientScore, %col2ClientTime, %col1Style, %col1Client, %col2Client ); } } else messageClient( %client, 'SetLineHud', "", %tag, %index, '%4\t%1%2%3', %col1Client.name, %col1ClientScore, %col1ClientTime, %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 LakRabbitGame::showRabbitWaypointClient(%game, %clRabbit, %client) { //make sure we have a rabbit if (!isObject(%clRabbit) || !isObject(%clRabbit.player) || !isObject(%clRabbit.player.holdingFlag)) return; //no waypoints for bots if (%client.isAIControlled()) return; //scope the client, then set the always vis mask... %clRabbit.player.scopeToClient(%client); %visMask = getSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup()); %visMask |= (1 << %client.getSensorGroup()); setSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup(), %visMask); //now issue a command to kill the target %client.setTargetId(%clRabbit.target); commandToClient(%client, 'TaskInfo', %client, -1, false, "Kill the Rabbit!"); %client.sendTargetTo(%client, true); //send the "waypoint is here sound" messageClient(%client, 'MsgRabbitWaypoint', '~wfx/misc/target_waypoint.wav'); //and hide the waypoint %client.waypointSchedule = %game.schedule(%game.waypointDuration, "hideRabbitWaypointClient", %clRabbit, %client); } function LakRabbitGame::hideRabbitWaypointClient(%game, %clRabbit, %client) { //no waypoints for bots if (%client.isAIControlled()) return; //unset the always vis mask... %visMask = getSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup()); %visMask &= ~(1 << %client.getSensorGroup()); setSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup(), %visMask); //kill the actually task... removeClientTargetType(%client, "AssignedTask"); } function LakRabbitGame::showRabbitWaypoint(%game, %clRabbit) { //make sure we have a rabbit if (!isObject(%clRabbit) || !isObject(%clRabbit.player) || !isObject(%clRabbit.player.holdingFlag)) return; //only show the rabbit waypoint if the rabbit hasn't been damaged within the frequency period if (getSimTime() - %game.rabbitDamageTime < %game.waypointFrequency) { %game.waypointSchedule = %game.schedule(%game.waypointFrequency, "showRabbitWaypoint", %clRabbit); return; } //loop through all the clients and flash a waypoint at the rabbits position for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); if (%cl.isAIControlled() || %cl == %clRabbit || !%cl.player) continue; // borlak -- don't make waypoing if client is nearby (mess up aim) %distance = VectorDist(%clRabbit.player.getWorldBoxCenter(), %cl.player.getWorldBoxCenter()); if(%distance < 100) continue; //scope the client, then set the always vis mask... %clRabbit.player.scopeToClient(%cl); %visMask = getSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup()); %visMask |= (1 << %cl.getSensorGroup()); setSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup(), %visMask); //now issue a command to kill the target %cl.setTargetId(%clRabbit.target); commandToClient(%cl, 'TaskInfo', %cl, -1, false, "Kill the Rabbit!"); %cl.sendTargetTo(%cl, true); //send the "waypoint is here sound" messageClient(%cl, 'MsgRabbitWaypoint', '~wfx/misc/target_waypoint.wav'); } //schedule the time to hide the waypoint %game.waypointSchedule = %game.schedule(%game.waypointDuration, "hideRabbitWaypoint", %clRabbit); } function LakRabbitGame::hideRabbitWaypoint(%game, %clRabbit) { //make sure we have a valid client if (!isObject(%clRabbit)) return; //loop through all the clients and hide the waypoint for (%i = 0; %i < ClientGroup.getCount(); %i++) { %cl = ClientGroup.getObject(%i); if (%cl.isAIControlled()) continue; //unset the always vis mask... %visMask = getSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup()); %visMask &= ~(1 << %cl.getSensorGroup()); setSensorGroupAlwaysVisMask(%clRabbit.getSensorGroup(), %visMask); //kill the actually task... removeClientTargetType(%cl, "AssignedTask"); } //make sure we have a rabbit before scheduling the next showRabbitWaypoint... if (isObject(%clRabbit.player) && isObject(%clRabbit.player.holdingFlag)) %game.waypointSchedule = %game.schedule(%game.waypointFrequency, "showRabbitWaypoint", %clRabbit); } function LakRabbitGame::updateKillScores(%game, %clVictim, %clKiller, %damageType, %implement) { if(%game.testTurretKill(%implement)) //check for turretkill before awarded a non client points for a kill %game.awardScoreTurretKill(%clVictim, %implement); else if (%game.testKill(%clVictim, %clKiller)) //verify victim was an enemy { %game.awardScoreKill(%clKiller); %game.awardScoreDeath(%clVictim); } else { if (%game.testSuicide(%clVictim, %clKiller, %damageType)) //otherwise test for suicide { %game.awardScoreSuicide(%clVictim); } else { if (%game.testTeamKill(%clVictim, %clKiller)) //otherwise test for a teamkill %game.awardScoreTeamKill(%clVictim, %clKiller); } } } function LakRabbitGame::applyConcussion(%game, %player) { // MES -- this won't do anything, the function LakRabbitGame::dropFlag is empty %game.dropFlag( %player ); } //--------------------------------Footnotes--------------------------------------- // // //To make vote options work in evo admin mod, demonstration only below // //function serverCmdStartNewVote(%client, %typeName, %arg1, %arg2, %arg3, %arg4, %playerVote) //{ // parent::serverCmdStartNewVote(%client, %typeName, %arg1, %arg2, %arg3, %arg4, %playerVote); // // // sonic9k 11/6/2003 - Added support for LakRabbit DuelMode option // // // case "VoteDuelMode": // if( %isAdmin && !%client.ForceVote ) // { // adminStartNewVote(%client, %typename, %arg1, %arg2, %arg3, %arg4); // adminLog(%client, " has toggled " @ %arg1 @ " (" @ %arg2 @ ")"); // } // else // { // if(Game.scheduleVote !$= "") // { // messageClient(%client, 'voteAlreadyRunning', '\c2A vote is already in progress.'); // return; // } // %actionMsg = ($Host::LakRabbitDuelMode ? "disable Duel mode" : "enable Duel mode"); // for(%idx = 0; %idx < ClientGroup.getCount(); %idx++) // { // %cl = ClientGroup.getObject(%idx); // if(!%cl.isAIControlled()) // { // messageClient(%cl, 'VoteStarted', '\c2%1 initiated a vote to %2.', %client.name, %actionMsg); // %clientsVoting++; // } // } // playerStartNewVote(%client, %typename, %arg1, %arg2, %arg3, %arg4, %clientsVoting); // } // // // // sonic9k 11/6/2003 - Added support for LakRabbit SplashDamage option // // // case "VoteSplashDamage": // if( %isAdmin && !%client.ForceVote ) // { // adminStartNewVote(%client, %typename, %arg1, %arg2, %arg3, %arg4); // adminLog(%client, " has toggled " @ %arg1 @ " (" @ %arg2 @ ")"); // } // else // { // if(Game.scheduleVote !$= "") // { // messageClient(%client, 'voteAlreadyRunning', '\c2A vote is already in progress.'); // return; // } // %actionMsg = ($Host::LakRabbitNoSplashDamage ? "enable SplashDamage" : "disable SplashDamage"); // for(%idx = 0; %idx < ClientGroup.getCount(); %idx++) // { // %cl = ClientGroup.getObject(%idx); // if(!%cl.isAIControlled()) // { // messageClient(%cl, 'VoteStarted', '\c2%1 initiated a vote to %2.', %client.name, %actionMsg); // %clientsVoting++; // } // } // playerStartNewVote(%client, %typename, %arg1, %arg2, %arg3, %arg4, %clientsVoting); // } // // // // chocotaco 8/7/2018 - Added support for LakRabbit Pro option // // // case "VotePro": // if( %isAdmin && !%client.ForceVote ) // { // adminStartNewVote(%client, %typename, %arg1, %arg2, %arg3, %arg4); // adminLog(%client, " has toggled " @ %arg1 @ " (" @ %arg2 @ ")"); // } // else // { // if(Game.scheduleVote !$= "") // { // messageClient(%client, 'voteAlreadyRunning', '\c2A vote is already in progress.'); // return; // } // %actionMsg = ($Host::LakRabbitPubPro ? "disable Pro mode" : "enable Pro mode"); // for(%idx = 0; %idx < ClientGroup.getCount(); %idx++) // { // %cl = ClientGroup.getObject(%idx); // if(!%cl.isAIControlled()) // { // messageClient(%cl, 'VoteStarted', '\c2%1 initiated a vote to %2.', %client.name, %actionMsg); // %clientsVoting++; // } // } // playerStartNewVote(%client, %typename, %arg1, %arg2, %arg3, %arg4, %clientsVoting); // } //}