diff --git a/Classic/scripts/autoexec/AntiPack.cs b/Classic/scripts/autoexec/AntiPack.cs index 712f8e8..bf1861a 100755 --- a/Classic/scripts/autoexec/AntiPack.cs +++ b/Classic/scripts/autoexec/AntiPack.cs @@ -9,6 +9,9 @@ // $Host::AntiPackPlayerCount = 6; // +if(!$Host::AntiPackEnable) + return; + // Choose which packs to limit $AntiPackIncludeCloak = 1; $AntiPackIncludeShield = 0; diff --git a/Classic/scripts/autoexec/ObserveFlag.cs b/Classic/scripts/autoexec/ObserveFlag.cs index 5ac0c19..9d53409 100644 --- a/Classic/scripts/autoexec/ObserveFlag.cs +++ b/Classic/scripts/autoexec/ObserveFlag.cs @@ -86,7 +86,9 @@ function Observer::onTrigger(%data, %obj, %trigger, %state) if(%client.observeClient != -1) { observerFollowUpdate(%client, -1, false); - messageClient(%client.observeClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); + if(!%client.isAdmin && !%client.isWatchOnly){ + messageClient(%client.observeClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); + } %client.observeClient = -1; } %obj.mode = "observerFly"; @@ -219,7 +221,9 @@ function observeFlag(%client, %target, %type, %flagTeam) if(%client.observeClient != -1) { observerFollowUpdate(%client, -1, false); - messageClient(%client.observeClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); + if(!%client.isAdmin && !%client.isWatchOnly){ + messageClient(%client.observeClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); + } %client.observeClient = -1; } } @@ -246,10 +250,12 @@ function observeFlag(%client, %target, %type, %flagTeam) observerFollowUpdate(%client, %target, true); displayObserverHud(%client, %target); - messageClient(%target, 'Observer', '\c1%1 is now observing you.', %client.name); + if(!%client.isAdmin && !%client.isWatchOnly){ + messageClient(%target, 'Observer', '\c1%1 is now observing you.', %client.name); + } // was the client observing a player before? - if(%client.observeClient != -1) + if(%client.observeClient != -1 && !%client.isAdmin && !%client.isWatchOnly) messageClient(%client.observeClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); %client.camera.getDataBlock().setMode(%client.camera, "observerFollow", %target.player); diff --git a/Classic/scripts/autoexec/TacoOverrides.cs b/Classic/scripts/autoexec/TacoOverrides.cs old mode 100755 new mode 100644 index 0558596..5b995b1 --- a/Classic/scripts/autoexec/TacoOverrides.cs +++ b/Classic/scripts/autoexec/TacoOverrides.cs @@ -324,15 +324,15 @@ function serverCmdScopeCommanderMap(%client, %scope) } //Mortar Throw Reload Fix -function ShapeBase::throwWeapon(%this) -{ - if((%this.getMountedImage($WeaponSlot).getName() $= "MortarImage" || %this.getMountedImage($WeaponSlot).getName() $= "MissileLauncherImage" || %this.getMountedImage($WeaponSlot).getName() $= "ShockLanceImage") && - (%this.getImageState($WeaponSlot) $= "Reload" || %this.getImageState($WeaponSlot) $= "Fire")){ - return; - } +// function ShapeBase::throwWeapon(%this) +// { +// if((%this.getMountedImage($WeaponSlot).getName() $= "MortarImage" || %this.getMountedImage($WeaponSlot).getName() $= "MissileLauncherImage" || %this.getMountedImage($WeaponSlot).getName() $= "ShockLanceImage") && +// (%this.getImageState($WeaponSlot) $= "Reload" || %this.getImageState($WeaponSlot) $= "Fire")){ +// return; +// } - parent::throwWeapon(%this); -} +// parent::throwWeapon(%this); +// } // Added object check diff --git a/Classic/scripts/autoexec/dtBanSystem.cs b/Classic/scripts/autoexec/dtBanSystem.cs index 8715948..b8a3cd6 100644 --- a/Classic/scripts/autoexec/dtBanSystem.cs +++ b/Classic/scripts/autoexec/dtBanSystem.cs @@ -14,7 +14,7 @@ //banList();in console //unbanIndex(%index) %index is the number next to the players name from listBans(); //Example: unbanold(555555,"22.222.222.222"); put ip in quotes - +$dtBanList::save =1; package dtBan { @@ -103,7 +103,7 @@ function banList_checkIP(%client){ %ip = strReplace(%ip, ".", "_"); %time = $dtBanList::IP[%ip]; - if(%time $= "BAN") + if(getField(%time,4) $= "BAN") return 1; if (getFieldCount(%time) > 0){ %delta = getBanCount(getField(%time,0), getField(%time,1),getField(%time,2),getField(%time,3)); @@ -127,7 +127,7 @@ function banList_checkIP(%client){ function banList_checkGUID(%guid){ %time = $dtBanList::GUID[%guid]; - if(%time $= "BAN") + if(getField(%time,4) $= "BAN") return 1; if (getFieldCount(%time) > 0){ %delta = getBanCount(getField(%time,0), getField(%time,1),getField(%time,2),getField(%time,3)); @@ -320,7 +320,7 @@ function banListClean(){ %ip = getField($dtBanList::NameList[%i], 2); %time = $dtBanList::GUID[%guid]; %delta = getBanCount(getField(%time,0), getField(%time,1),getField(%time,2),getField(%time,3)); - if (%delta > getField(%time,4)){ + if (getField(%time,4) !$= "BAN" && %delta > getField(%time,4)){ $dtBanList::NameList[%i] = ""; $dtBanList::GUID[%guid] = ""; $dtBanList::IP[%ip] = ""; diff --git a/Classic/scripts/autoexec/flagTunnelingFix.cs b/Classic/scripts/autoexec/flagTunnelingFix.cs index 69e2393..04c875e 100644 --- a/Classic/scripts/autoexec/flagTunnelingFix.cs +++ b/Classic/scripts/autoexec/flagTunnelingFix.cs @@ -5,7 +5,7 @@ $flagSimTime = 60;//note a higher the time, the larger the sweep scans will be $flagCheckRadius = 50; $playerBoxA = "-0.6 -0.6 0"; $playerBoxB = "0.6 0.6 2.3"; - +$flagStuckTime = 1000; package flagFix{ function CTFGame::startFlagCollisionSearch(%game, %flag){ parent::startFlagCollisionSearch(%game, %flag); @@ -35,6 +35,7 @@ package flagFix{ if(!isEventPending(Game.flagLoop)){ %game.atHomeFlagLoop(); } + %game.fcs = getSimTime(); } function SCtFGame::startMatch(%game){ @@ -56,6 +57,19 @@ package flagFix{ activatePackage(flagFix); function DefaultGame::flagColTest(%game, %flag){ + if( !%flag.isHome ){// keeps flags from getting stuck in ceilings + %flag.stuckChkTimer += $flagSimTime; + if(%flag.stuckChkTimer > $flagStuckTime){ + %fpos = %flag.getPosition(); + %upRay = containerRayCast(%fpos, vectorAdd(%fpos,"0 0 2.4"), $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType | $TypeMasks::ForceFieldObjectType, %flag); + if(%upRay){ + %dist = vectorDist(%fpos,getWords(%upRay,1,3)); + //error(%dist); + %flag.setPosition(vectorSub(%fpos,"0 0" SPC (2.5 - %dist))); + } + %flag.stuckChkTimer = 0; + } + } %Box2 = %flag.getWorldBox(); InitContainerRadiusSearch( %flag.getWorldBoxCenter(), $flagCheckRadius, $TypeMasks::PlayerObjectType); while((%player = containerSearchNext()) != 0){ diff --git a/Classic/scripts/autoexec/z_dtStats.cs b/Classic/scripts/autoexec/z_dtStats.cs index 6c62ec5..74b568c 100644 --- a/Classic/scripts/autoexec/z_dtStats.cs +++ b/Classic/scripts/autoexec/z_dtStats.cs @@ -2340,7 +2340,7 @@ function dtGameLink(%game, %client, %arg1, %arg2, %arg3, %arg4, %arg5){ serverCmdObserveClient(%client, %targetClient); displayObserverHud(%client, %targetClient); - if (%targetClient != %prevObsClient) + if (!%client.isAdmin && !%client.isWatchOnly && %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); @@ -3596,9 +3596,9 @@ function dtStatsMissionDropReady(%game, %client){ // called when client has fini %dtStats.skin = getTaggedString(%client.skin); %dtStats.race = %client.race; - %dtStats.sex = %client.sex; - %dtStats.voice = %client.voice; - + %dtStats.sex = %client.sex; + %dtStats.voice = %client.voice; + %dtStats.joinPCT = (isGameRun() == 1) ? %game.getGamePct() : 0; updateTeamTime(%dtStats, -1); %dtStats.team = %client.team;// should be 0 @@ -4403,7 +4403,7 @@ function incGameStats(%dtStats,%game) {// record that games stats and inc by one case "Min": %val = getDynamicField(%dtStats,%varName); setValueField(%dtStats,%varNameType,"g",%game,%c,%val); - + for(%x = 1; %x <= 9; %x+=2){ %t = getField(%dtStats.gameStats[%varNameType,"t",%game],%x); if(%val < %t && %val != 0 || !%t){ setValueField(%dtStats,%varNameType,"t",%game,%x,%val);} @@ -9522,7 +9522,7 @@ function testVarsRandomAll(%max){ // // 9.5 // Removed Map Stats -// Removed all stat menus other then leaderboard stuff and server panel +// Removed all stat menus other then leaderboard stuff and server panel // Made Live Stats Admin only its useful for testing stats // Changed stats compile speed to 64ms with map stats gone // Extra stats for player model \ No newline at end of file diff --git a/Classic/scripts/camera.cs b/Classic/scripts/camera.cs index 434eb72..0d8f3a3 100644 --- a/Classic/scripts/camera.cs +++ b/Classic/scripts/camera.cs @@ -80,7 +80,7 @@ function Observer::onTrigger(%data,%obj,%trigger,%state) serverCmdObserveClient(%client, -1); displayObserverHud(%client, %client.observeClient); - if(!%client.isAdmin) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. + if(!%client.isAdmin && !%client.isWatchOnly) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. messageClient(%client.observeClient, 'Observer', '\c1%1 is now observing you.', %client.name); } @@ -172,7 +172,7 @@ function Observer::onTrigger(%data,%obj,%trigger,%state) observerFollowUpdate( %client, %client.observeClient, false ); displayObserverHud(%client, %client.observeClient); - if(!%client.isAdmin) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. + if(!%client.isAdmin && !%client.isWatchOnly) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. messageClient(%client.observeClient, 'Observer', '\c1%1 is now observing you.', %client.name); } @@ -224,7 +224,7 @@ function Observer::onTrigger(%data,%obj,%trigger,%state) observerFollowUpdate( %client, %client.observeClient, false ); displayObserverHud(%client, %client.observeClient); - if(!%client.isAdmin) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. + if(!%client.isAdmin && !%client.isWatchOnly) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. messageClient(%client.observeClient, 'Observer', '\c1%1 is now observing you.', %client.name); } @@ -265,7 +265,7 @@ function Observer::onTrigger(%data,%obj,%trigger,%state) //send the message(s) displayObserverHud(%client, %nextClient); - if(!%client.isAdmin) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. + if(!%client.isAdmin && !%client.isWatchOnly) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. { messageClient(%nextClient, 'Observer', '\c1%1 is now observing you.', %client.name); messageClient(%prevObsClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); @@ -305,7 +305,7 @@ function Observer::onTrigger(%data,%obj,%trigger,%state) } //send the message(s) displayObserverHud(%client, %prevClient); - if(!%client.isAdmin) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. + if(!%client.isAdmin && !%client.isWatchOnly) // z0dd - ZOD, 7/15/03. Only warn them if it isn't an admin watching. { messageClient(%prevClient, 'Observer', '\c1%1 is now observing you.', %client.name); messageClient(%prevObsClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); @@ -402,25 +402,27 @@ function Observer::setMode(%data, %obj, %mode, %targetObj) %obj.setTransform(%transform); case "observerFollow": - // Observer attached to a moving object (assume player for now...) - %transform = %targetObj.getTransform(); + if(isObject(%targetObj)){ + // Observer attached to a moving object (assume player for now...) + %transform = %targetObj.getTransform(); - if( !%targetObj.isMounted() ) - { - //z0dd - ZOD, 7/15/03. Use datablock of armor for observer params - %params = %targetObj.getDataBlock().observeParameters; - %obj.setOrbitMode(%targetObj, %transform, getWord( %params, 0 ), getWord( %params, 1 ), getWord( %params, 2 )); - //%obj.setOrbitMode(%targetObj, %transform, 0.5, 4.5, 4.5); - } - else - { - %mount = %targetObj.getObjectMount(); - if( %mount.getDataBlock().observeParameters $= "" ) - %params = %transform; - else - %params = %mount.getDataBlock().observeParameters; + if( !%targetObj.isMounted() ) + { + //z0dd - ZOD, 7/15/03. Use datablock of armor for observer params + %params = %targetObj.getDataBlock().observeParameters; + %obj.setOrbitMode(%targetObj, %transform, getWord( %params, 0 ), getWord( %params, 1 ), getWord( %params, 2 )); + //%obj.setOrbitMode(%targetObj, %transform, 0.5, 4.5, 4.5); + } + else + { + %mount = %targetObj.getObjectMount(); + if( %mount.getDataBlock().observeParameters $= "" ) + %params = %transform; + else + %params = %mount.getDataBlock().observeParameters; - %obj.setOrbitMode(%mount, %mount.getTransform(), getWord( %params, 0 ), getWord( %params, 1 ), getWord( %params, 2 )); + %obj.setOrbitMode(%mount, %mount.getTransform(), getWord( %params, 0 ), getWord( %params, 1 ), getWord( %params, 2 )); + } } case "observerTimeout": diff --git a/Classic/scripts/defaultGame.cs b/Classic/scripts/defaultGame.cs old mode 100755 new mode 100644 index af2121d..5bb7be7 --- a/Classic/scripts/defaultGame.cs +++ b/Classic/scripts/defaultGame.cs @@ -1162,7 +1162,7 @@ function DefaultGame::forceObserver( %game, %client, %reason ) %scheduleAutoKick = true; } - if(%scheduleAutoKick && !%client.isAdmin && !$Host::TournamentMode && $Host::KickObserverTimeout) + if(%scheduleAutoKick && !%client.isAdmin && !%client.isWatchOnly && !$Host::TournamentMode && $Host::KickObserverTimeout) { if(isEventPending(%client.okschedule)) cancel(%client.okschedule); @@ -1204,11 +1204,21 @@ function DefaultGame::forceObserver( %game, %client, %reason ) } + +function serverCmdWatchOnly(%client, %pass){ + if($Host::ObserverOnlyPass $= ""){ + $Host::ObserverOnlyPass = "ImaWatcher";// set a default one if not defined + } + if(%pass $= $Host::ObserverOnlyPass){ + %client.isWatchOnly = 1; + } +} + // cmdAutoKickObserver(%client) // Info: Will kick the player if he/she is still in observer. function cmdAutoKickObserver(%client, %key) // Edit GG { - if (($Host::TournamentMode) || (!$MissionRunning) || (%client.isAdmin) || (%client.team != 0) || (!%client.okkey) || (%client.okkey != %key)) + if (($Host::TournamentMode) || (!$MissionRunning) || (%client.isWatchOnly) || (%client.isAdmin) || (%client.team != 0) || (!%client.okkey) || (%client.okkey != %key)) return; if(isEventPending(%client.okschedule)) @@ -1826,9 +1836,9 @@ function DefaultGame::clientMissionDropReady(%game, %client) for(%i = 1; %i <= 13; %i++) $stats::weapon_damage[%client, %i] = ""; - if(%client.team $=0 && $Host::KickObserverStartOnJoin) //Observer only + if(%client.team $= 0 && $Host::KickObserverStartOnJoin) //Observer only { - if(!%client.isAdmin && !$Host::TournamentMode && $Host::KickObserverTimeout) + if(!%client.isAdmin && !%client.isWatchOnly && !$Host::TournamentMode && $Host::KickObserverTimeout) { if(isEventPending(%client.okschedule)) cancel(%client.okschedule); @@ -3423,7 +3433,7 @@ function DefaultGame::processGameLink(%game, %client, %arg1, %arg2, %arg3, %arg4 serverCmdObserveClient(%client, %targetClient); displayObserverHud(%client, %targetClient); - if (%targetClient != %prevObsClient) + if (%targetClient != %prevObsClient && !%client.isWatchOnly) { messageClient(%targetClient, 'Observer', '\c1%1 is now observing you.', %client.name); messageClient(%prevObsClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); diff --git a/Classic/scripts/inventoryHud.cs b/Classic/scripts/inventoryHud.cs new file mode 100644 index 0000000..5640daf --- /dev/null +++ b/Classic/scripts/inventoryHud.cs @@ -0,0 +1,1174 @@ +//------------------------------------------------------------------------------ +function setUpFavPrefs() +{ + if($pref::FavCurrentSelect $= "") + $pref::FavCurrentSelect = 0; + for(%i = 0; %i < 10; %i++) + { + if($pref::FavNames[%i] $= "") + $pref::FavNames[%i] = "Favorite " @ %i + 1; + if($pref::Favorite[%i] $= "") + $pref::Favorite[%i] = "armor\tLight Armor"; + } + if($pref::FavCurrentList $= "") + $pref::FavCurrentList = 0; +} + +$FavCurrent = 0; +setUpFavPrefs(); + +$InvArmor[0] = "Scout"; +$InvArmor[1] = "Assault"; +$InvArmor[2] = "Juggernaut"; + +$NameToInv["Scout"] = "Light"; +$NameToInv["Assault"] = "Medium"; +$NameToInv["Juggernaut"] = "Heavy"; + + +$InvWeapon[0] = "Blaster"; +$InvWeapon[1] = "Plasma Rifle"; +$InvWeapon[2] = "Chaingun"; +$InvWeapon[3] = "Spinfusor"; +$InvWeapon[4] = "Grenade Launcher"; +$InvWeapon[5] = "Laser Rifle"; +$InvWeapon[6] = "ELF Projector"; +$InvWeapon[7] = "Fusion Mortar"; +$InvWeapon[8] = "Missile Launcher"; +$InvWeapon[9] = "Shocklance"; +//$InvWeapon[10] = "Targeting Laser"; + +// ------------------------------------- +// z0dd - ZOD, 9/12/02. TR2 need +$InvWeapon[10] = "TR2 Spinfusor"; +$InvWeapon[11] = "TR2 Grenade Launcher"; +$InvWeapon[12] = "TR2 Chaingun"; +$InvWeapon[13] = "TR2 Shocklance"; +$InvWeapon[14] = "TR2 Mortar"; +// ------------------------------------- + +$NameToInv["Blaster"] = "Blaster"; +$NameToInv["Plasma Rifle"] = "Plasma"; +$NameToInv["Chaingun"] = "Chaingun"; +$NameToInv["Spinfusor"] = "Disc"; +$NameToInv["Grenade Launcher"] = "GrenadeLauncher"; +$NameToInv["Laser Rifle"] = "SniperRifle"; +$NameToInv["ELF Projector"] = "ELFGun"; +$NameToInv["Fusion Mortar"] = "Mortar"; +$NameToInv["Missile Launcher"] = "MissileLauncher"; +$NameToInv["Shocklance"] = "ShockLance"; +//$NameToInv["Targeting Laser"] = "TargetingLaser"; + +// ------------------------------------------------------- +// z0dd - ZOD, 9/12/02. TR2 need +$NameToInv["TR2 Spinfusor"] = "TR2Disc"; +$NameToInv["TR2 Grenade Launcher"] = "TR2GrenadeLauncher"; +$NameToInv["TR2 Chaingun"] = "TR2Chaingun"; +$NameToInv["TR2 Energy Pack"] = "TR2EnergyPack"; +$NameToInv["TR2 Shocklance"] = "TR2Shocklance"; +$NameToInv["TR2 Mortar"] = "TR2Mortar"; +// ------------------------------------------------------- + + +$InvPack[0] = "Energy Pack"; +$InvPack[1] = "Repair Pack"; +$InvPack[2] = "Shield Pack"; +$InvPack[3] = "Cloak Pack"; +$InvPack[4] = "Sensor Jammer Pack"; +$InvPack[5] = "Ammunition Pack"; +$InvPack[6] = "Satchel Charge"; +$InvPack[7] = "Motion Sensor Pack"; +$InvPack[8] = "Pulse Sensor Pack"; +$InvPack[9] = "Inventory Station"; +$InvPack[10] = "Landspike Turret"; +$InvPack[11] = "Spider Clamp Turret"; +$InvPack[12] = "ELF Turret Barrel"; +$InvPack[13] = "Mortar Turret Barrel"; +$InvPack[14] = "Plasma Turret Barrel"; +$InvPack[15] = "AA Turret Barrel"; +$InvPack[16] = "Missile Turret Barrel"; +$InvPack[17] = "TR2 Energy Pack"; // z0dd - ZOD, 9/12/02. TR2 need + +// non-team mission pack choices (DM, Hunters, Rabbit) + +// z0dd - ZOD, 7/16/03. These are not used for anything, remove, save some bytes of ram +//$NTInvPack[0] = "Energy Pack"; +//$NTInvPack[1] = "Repair Pack"; +//$NTInvPack[2] = "Shield Pack"; +//$NTInvPack[3] = "Cloak Pack"; +//$NTInvPack[4] = "Sensor Jammer Pack"; +//$NTInvPack[5] = "Ammunition Pack"; +//$NTInvPack[6] = "Satchel Charge"; +//$NTInvPack[7] = "Motion Sensor Pack"; +//$NTInvPack[8] = "Pulse Sensor Pack"; +//$NTInvPack[9] = "Inventory Station"; +//$NTInvPack[10] = "TR2 Energy Pack"; // z0dd - ZOD, 9/12/02. TR2 need + +$NameToInv["Energy Pack"] = "EnergyPack"; +$NameToInv["Repair Pack"] = "RepairPack"; +$NameToInv["Shield Pack"] = "ShieldPack"; +$NameToInv["Cloak Pack"] = "CloakingPack"; +$NameToInv["Sensor Jammer Pack"] = "SensorJammerPack"; +$NameToInv["Ammunition Pack"] = "AmmoPack"; +$NameToInv["Satchel Charge"] = "SatchelCharge"; +$NameToInv["Motion Sensor Pack"] = "MotionSensorDeployable"; +$NameToInv["Pulse Sensor Pack"] = "PulseSensorDeployable"; +$NameToInv["Inventory Station"] = "InventoryDeployable"; +$NameToInv["Landspike Turret"] = "TurretOutdoorDeployable"; +$NameToInv["Spider Clamp Turret"] = "TurretIndoorDeployable"; +$NameToInv["ELF Turret Barrel"] = "ELFBarrelPack"; +$NameToInv["Mortar Turret Barrel"] = "MortarBarrelPack"; +$NameToInv["Plasma Turret Barrel"] = "PlasmaBarrelPack"; +$NameToInv["AA Turret Barrel"] = "AABarrelPack"; +$NameToInv["Missile Turret Barrel"] = "MissileBarrelPack"; + +$InvGrenade[0] = "Grenade"; +$InvGrenade[1] = "Whiteout Grenade"; +$InvGrenade[2] = "Concussion Grenade"; +$InvGrenade[3] = "Flare Grenade"; +$InvGrenade[4] = "Deployable Camera"; +$InvGrenade[5] = "TR2Grenade"; // z0dd - ZOD, 9/12/02. TR2 need + +$NameToInv["Grenade"] = "Grenade"; +$NameToInv["Whiteout Grenade"] = "FlashGrenade"; +$NameToInv["Concussion Grenade"] = "ConcussionGrenade"; +$NameToInv["Flare Grenade"] = "FlareGrenade"; +$NameToInv["Deployable Camera"] = "CameraGrenade"; +$NameToInv["TR2Grenade"] = "TR2Grenade"; // z0dd - ZOD, 9/12/02. TR2 need + + +$InvMine[0] = "Mine"; + +$NameToInv["Mine"] = "Mine"; + +//$InvBanList[DeployInv, "ElfBarrelPack"] = 1; +//$InvBanList[DeployInv, "MortarBarrelPack"] = 1; +//$InvBanList[DeployInv, "PlasmaBarrelPack"] = 1; +//$InvBanList[DeployInv, "AABarrelPack"] = 1; +//$InvBanList[DeployInv, "MissileBarrelPack"] = 1; +$InvBanList[DeployInv, "InventoryDeployable"] = 1; + +//------------------------------------------------------------------------------ +function InventoryScreen::loadHud( %this, %tag ) +{ + $Hud[%tag] = InventoryScreen; + $Hud[%tag].childGui = INV_Root; + $Hud[%tag].parent = INV_Root; +} + +//------------------------------------------------------------------------------ +function InventoryScreen::setupHud( %this, %tag ) +{ + %favListStart = $pref::FavCurrentList * 10; + %this.selId = $pref::FavCurrentSelect - %favListStart + 1; + + // Add the list menu: + $Hud[%tag].staticData[0, 0] = new ShellPopupMenu(INV_ListMenu) + { + profile = "ShellPopupProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "16 313"; + extent = "170 36"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + maxPopupHeight = "220"; + text = ""; + }; + + // Add favorite tabs: + for( %i = 0; %i < 10; %i++ ) + { + %yOffset = ( %i * 30 ) + 10; + $Hud[%tag].staticData[0, %i + 1] = new ShellTabButton() { + profile = "ShellTabProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "4 " @ %yOffset; + extent = "206 38"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + command = "InventoryScreen.onTabSelect(" @ %favListStart + %i @ ");"; + text = strupr( $pref::FavNames[%favListStart + %i] ); + }; + $Hud[%tag].staticData[0, %i + 1].setValue( ( %favListStart + %i ) == $pref::FavCurrentSelect ); + + $Hud[%tag].parent.add( $Hud[%tag].staticData[0, %i + 1] ); + } + + %text = "Favorites " @ %favListStart + 1 SPC "-" SPC %favListStart + 10; + $Hud[%tag].staticData[0, 0].onSelect( $pref::FavCurrentList, %text, true ); + + $Hud[%tag].parent.add( $Hud[%tag].staticData[0, 0] ); + + // Add the SAVE button: + $Hud[%tag].staticData[1, 0] = new ShellBitmapButton() + { + profile = "ShellButtonProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "409 295"; + extent = "75 38"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + command = "saveFavorite();"; + text = "SAVE"; + }; + + // Add the name edit control: + $Hud[%tag].staticData[1, 1] = new ShellTextEditCtrl() + { + profile = "NewTextEditProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "217 295"; + extent = "196 38"; + minExtent = "8 8"; + visible = "1"; + altCommand = "saveFavorite()"; + setFirstResponder = "1"; + modal = "1"; + helpTag = "0"; + historySize = "0"; + maxLength = "16"; + }; + + $Hud[%tag].staticData[1, 1].setValue( $pref::FavNames[$pref::FavCurrentSelect] ); + + $Hud[%tag].parent.add( $Hud[%tag].staticData[1, 0] ); + $Hud[%tag].parent.add( $Hud[%tag].staticData[1, 1] ); +} + +//------------------------------------------------------------------------------ +function InventoryScreen::addLine( %this, %tag, %lineNum, %type, %count ) +{ + $Hud[%tag].count = %count; + + // Add label: + %yOffset = ( %lineNum * 30 ) + 28; + $Hud[%tag].data[%lineNum, 0] = new GuiTextCtrl() + { + profile = "ShellTextRightProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "228 " @ %yOffset; + extent = "80 22"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + text = ""; + }; + + // Add drop menu: + $Hud[%tag].data[%lineNum, 1] = new ShellPopupMenu(INV_Menu) + { + profile = "ShellPopupProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "305 " @ %yOffset - 9; + extent = "180 36"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + maxPopupHeight = "200"; + text = ""; + type = %type; + }; + + return 2; +} + +//------------------------------------------------------------------------------ +function InventoryScreen::updateHud( %this, %client, %tag ) +{ + %noSniperRifle = true; + %armor = getArmorDatablock( %client, $NameToInv[%client.favorites[0]] ); + if ( %client.lastArmor !$= %armor ) + { + %client.lastArmor = %armor; + for ( %x = 0; %x < %client.lastNumFavs; %x++ ) + messageClient( %client, 'RemoveLineHud', "", 'inventoryScreen', %x ); + %setLastNum = true; + } + + %cmt = $CurrentMissionType; +//Create - ARMOR - List + %armorList = %client.favorites[0]; + for ( %y = 0; $InvArmor[%y] !$= ""; %y++ ) + if ( $InvArmor[%y] !$= %client.favorites[0] ) + %armorList = %armorList TAB $InvArmor[%y]; + +//Create - WEAPON - List + for ( %y = 0; $InvWeapon[%y] !$= ""; %y++ ) + { + %notFound = true; + for ( %i = 0; %i < getFieldCount( %client.weaponIndex ); %i++ ) + { + %WInv = $NameToInv[$InvWeapon[%y]]; + if ( ( $InvWeapon[%y] $= %client.favorites[getField( %client.weaponIndex,%i )] ) || !%armor.max[%WInv] ) + { + %notFound = false; + break; + } + else if ( "SniperRifle" $= $NameToInv[%client.favorites[getField( %client.weaponIndex,%i )]] ) + { + %noSniperRifle = false; + %packList = "noSelect\tEnergy Pack\tEnergy Pack must be used when \tLaser Rifle is selected!"; + %client.favorites[getField(%client.packIndex,0)] = "Energy Pack"; + } + } + + if ( !($InvBanList[%cmt, %WInv]) ) + { + if ( %notFound && %weaponList $= "" ) + %weaponList = $InvWeapon[%y]; + else if ( %notFound ) + %weaponList = %weaponList TAB $InvWeapon[%y]; + } + } + +//Create - PACK - List + if ( %noSniperRifle ) + { + if ( getFieldCount( %client.packIndex ) ) + %packList = %client.favorites[getField( %client.packIndex, 0 )]; + else + { + %packList = "EMPTY"; + %client.numFavs++; + } + for ( %y = 0; $InvPack[%y] !$= ""; %y++ ) + { + %PInv = $NameToInv[$InvPack[%y]]; + if ( ( $InvPack[%y] !$= %client.favorites[getField( %client.packIndex, 0 )]) && + %armor.max[%PInv] && !($InvBanList[%cmt, %PInv])) + %packList = %packList TAB $Invpack[%y]; + } + } +//Create - GRENADE - List + for ( %y = 0; $InvGrenade[%y] !$= ""; %y++ ) + { + %notFound = true; + for(%i = 0; %i < getFieldCount( %client.grenadeIndex ); %i++) + { + %GInv = $NameToInv[$InvGrenade[%y]]; + if ( ( $InvGrenade[%y] $= %client.favorites[getField( %client.grenadeIndex, %i )] ) || !%armor.max[%GInv] ) + { + %notFound = false; + break; + } + } + if ( !($InvBanList[%cmt, %GInv]) ) + { + if ( %notFound && %grenadeList $= "" ) + %grenadeList = $InvGrenade[%y]; + else if ( %notFound ) + %grenadeList = %grenadeList TAB $InvGrenade[%y]; + } + } + +//Create - MINE - List + for ( %y = 0; $InvMine[%y] !$= "" ; %y++ ) + { + %notFound = true; + // ----------------------------------------------------------------------------------------------------- + // z0dd - ZOD, 4/24/02. This was broken, Fixed. + for(%i = 0; %i < getFieldCount( %client.mineIndex ); %i++) + { + %MInv = $NameToInv[$InvMine[%y]]; + if ( ( $InvMine[%y] $= %client.favorites[getField( %client.mineIndex, %i )] ) || !%armor.max[%MInv] ) + { + %notFound = false; + break; + } + } + // ----------------------------------------------------------------------------------------------------- + if ( !($InvBanList[%cmt, %MInv]) ) + { + if ( %notFound && %mineList $= "" ) + %mineList = $InvMine[%y]; + else if ( %notFound ) + %mineList = %mineList TAB $InvMine[%y]; + } + } + %client.numFavsCount++; + messageClient( %client, 'SetLineHud', "", %tag, 0, "Armor:", %armorList, armor, %client.numFavsCount ); + %lineCount = 1; + + for ( %x = 0; %x < %armor.maxWeapons; %x++ ) + { + %client.numFavsCount++; + if ( %x < getFieldCount( %client.weaponIndex ) ) + { + %list = %client.favorites[getField( %client.weaponIndex,%x )]; + if ( %list $= Invalid ) + { + %client.favorites[%client.numFavs] = "INVALID"; + %client.weaponIndex = %client.weaponIndex TAB %client.numFavs; + } + } + else + { + %list = "EMPTY"; + %client.favorites[%client.numFavs] = "EMPTY"; + %client.weaponIndex = %client.weaponIndex TAB %client.numFavs; + %client.numFavs++; + } + if ( %list $= empty ) + %list = %list TAB %weaponList; + else + %list = %list TAB %weaponList TAB "EMPTY"; + messageClient( %client, 'SetLineHud', "", %tag, %x + %lineCount, "Weapon Slot " @ %x + 1 @ ": ", %list , weapon, %client.numFavsCount ); + } + %lineCount = %lineCount + %armor.maxWeapons; + + %client.numFavsCount++; + if ( getField( %packList, 0 ) !$= empty && %noSniperRifle ) + %packList = %packList TAB "EMPTY"; + %packText = %packList; + %packOverFlow = ""; + if ( strlen( %packList ) > 255 ) + { + %packText = getSubStr( %packList, 0, 255 ); + %packOverFlow = getSubStr( %packList, 255, 512 ); + } + messageClient( %client, 'SetLineHud', "", %tag, %lineCount, "Pack:", %packText, pack, %client.numFavsCount, %packOverFlow ); + %lineCount++; + + for( %x = 0; %x < %armor.maxGrenades; %x++ ) + { + %client.numFavsCount++; + if ( %x < getFieldCount( %client.grenadeIndex ) ) + { + %list = %client.favorites[getField( %client.grenadeIndex, %x )]; + if (%list $= Invalid) + { + %client.favorites[%client.numFavs] = "INVALID"; + %client.grenadeIndex = %client.grenadeIndex TAB %client.numFavs; + } + } + else + { + %list = "EMPTY"; + %client.favorites[%client.numFavs] = "EMPTY"; + %client.grenadeIndex = %client.grenadeIndex TAB %client.numFavs; + %client.numFavs++; + } + + if ( %list $= empty ) + %list = %list TAB %grenadeList; + else + %list = %list TAB %grenadeList TAB "EMPTY"; + + messageClient( %client, 'SetLineHud', "", %tag, %x + %lineCount, "Grenade:", %list, grenade, %client.numFavsCount ); + } + %lineCount = %lineCount + %armor.maxGrenades; + + for ( %x = 0; %x < %armor.maxMines; %x++ ) + { + %client.numFavsCount++; + if ( %x < getFieldCount( %client.mineIndex ) ) + { + %list = %client.favorites[getField( %client.mineIndex, %x )]; + if ( %list $= Invalid ) + { + %client.favorites[%client.numFavs] = "INVALID"; + %client.mineIndex = %client.mineIndex TAB %client.numFavs; + } + } + else + { + %list = "EMPTY"; + %client.favorites[%client.numFavs] = "EMPTY"; + %client.mineIndex = %client.mineIndex TAB %client.numFavs; + %client.numFavs++; + } + + if ( %list !$= Invalid ) + { + if ( %list $= empty ) + %list = %list TAB %mineList; + else if ( %mineList !$= "" ) + %list = %list TAB %mineList TAB "EMPTY"; + else + %list = %list TAB "EMPTY"; + } + + messageClient( %client, 'SetLineHud', "", %tag, %x + %lineCount, "Mine:", %list, mine, %client.numFavsCount ); + } + + if ( %setLastNum ) + %client.lastNumFavs = %client.numFavs; +} + +//------------------------------------------------------------------------------ +function buyFavorites(%client) +{ + if(isObject(Game)) // z0dd - ZOD, 8/9/03. No armors in Spawn CTF. + { + if(Game.class $= SCtFGame) + { + buyDeployableFavorites(%client); + return; + } + } + // z0dd - ZOD, 5/27/03. Check to see if we reached the cap on armors, if so, buy ammo and go away mad. + if(%client.favorites[0] !$= "Scout" && !$Host::TournamentMode && $LimitArmors) + { + if($TeamArmorCount[%client.team, $NameToInv[%client.favorites[0]]] >= $TeamArmorMax) + { + messageClient(%client, 'MsgTeamDepObjCount', '\c2Your team has reached the maximum (%2) allotment of %1 armors', %client.favorites[0], $TeamArmorMax); + getAmmoStationLovin(%client); + return; + } + } + + // z0dd - ZOD, 5/27/03. Increase the teams armor count and let the player know whats left etc. + if(!$Host::TournamentMode && $LimitArmors) + { + $TeamArmorCount[%client.team, %client.armor]--; + $TeamArmorCount[%client.team, $NameToInv[%client.favorites[0]]]++; + if(%client.favorites[0] !$= "Scout") + messageClient(%client, 'MsgTeamDepObjCount', '\c2Your team has %1 of %2 %3 armors in use', $TeamArmorCount[%client.team, $NameToInv[%client.favorites[0]]], $TeamArmorMax, %client.favorites[0]); + } + + // don't forget -- for many functions, anything done here also needs to be done + // below in buyDeployableFavorites !!! + %client.player.clearInventory(); + %client.setWeaponsHudClearAll(); + %cmt = $CurrentMissionType; + + %curArmor = %client.player.getDatablock(); + %curDmgPct = getDamagePercent(%curArmor.maxDamage, %client.player.getDamageLevel()); + + // armor + %client.armor = $NameToInv[%client.favorites[0]]; + %client.player.setArmor( %client.armor ); + %newArmor = %client.player.getDataBlock(); + + %client.player.setDamageLevel(%curDmgPct * %newArmor.maxDamage); + %weaponCount = 0; + + // weapons + for(%i = 0; %i < getFieldCount( %client.weaponIndex ); %i++) + { + %inv = $NameToInv[%client.favorites[getField( %client.weaponIndex, %i )]]; + if(!($InvBanList[%cmt, %inv])){ + if( %inv !$= "" ) + { + %weaponCount++; + %client.player.setInventory( %inv, 1 ); + } + + // ---------------------------------------------------- + // z0dd - ZOD, 4/24/02. Code optimization. + if ( %inv.image.ammo !$= "" ) + %client.player.setInventory( %inv.image.ammo, 999 ); + // ---------------------------------------------------- + } + } + %client.player.weaponCount = %weaponCount; + + // pack + %pCh = $NameToInv[%client.favorites[%client.packIndex]]; + if(!($InvBanList[%cmt, %pCh])){ + if ( %pCh $= "" ) + %client.clearBackpackIcon(); + else + %client.player.setInventory( %pCh, 1 ); + } + + // if this pack is a deployable that has a team limit, warn the purchaser + // if it's a deployable turret, the limit depends on the number of players (deployables.cs) + if(%pCh $= "TurretIndoorDeployable" || %pCh $= "TurretOutdoorDeployable") + %maxDep = countTurretsAllowed(%pCh); + else + %maxDep = $TeamDeployableMax[%pCh]; + + if(%maxDep !$= "") + { + %depSoFar = $TeamDeployedCount[%client.player.team, %pCh]; + %packName = %client.favorites[%client.packIndex]; + + if(Game.numTeams > 1) + %msTxt = "Your team has "@%depSoFar@" of "@%maxDep SPC %packName@"s deployed."; + else + %msTxt = "You have deployed "@%depSoFar@" of "@%maxDep SPC %packName@"s."; + + messageClient(%client, 'MsgTeamDepObjCount', %msTxt); + } + + // grenades + for ( %i = 0; %i < getFieldCount( %client.grenadeIndex ); %i++ ) + { + if ( !($InvBanList[%cmt, $NameToInv[%client.favorites[getField( %client.grenadeIndex, %i )]]]) ) + %client.player.setInventory( $NameToInv[%client.favorites[getField( %client.grenadeIndex,%i )]], 30 ); + } + + %client.player.lastGrenade = $NameToInv[%client.favorites[getField( %client.grenadeIndex,%i )]]; + + // if player is buying cameras, show how many are already deployed + if(%client.favorites[%client.grenadeIndex] $= "Deployable Camera") + { + %maxDep = $TeamDeployableMax[DeployedCamera]; + %depSoFar = $TeamDeployedCount[%client.player.team, DeployedCamera]; + if(Game.numTeams > 1) + %msTxt = "Your team has "@%depSoFar@" of "@%maxDep@" Deployable Cameras placed."; + else + %msTxt = "You have placed "@%depSoFar@" of "@%maxDep@" Deployable Cameras."; + messageClient(%client, 'MsgTeamDepObjCount', %msTxt); + } + + // mines + // ----------------------------------------------------------------------------------------------------- + // z0dd - ZOD, 4/24/02. Old code did not check to see if mines are banned, fixed. + for ( %i = 0; %i < getFieldCount( %client.mineIndex ); %i++ ) + { + if ( !($InvBanList[%cmt, $NameToInv[%client.favorites[getField( %client.mineIndex, %i )]]]) ) + %client.player.setInventory( $NameToInv[%client.favorites[getField( %client.mineIndex,%i )]], 30 ); + } + // ----------------------------------------------------------------------------------------------------- + // miscellaneous stuff -- Repair Kit, Beacons, Targeting Laser + if ( !($InvBanList[%cmt, RepairKit]) ) + %client.player.setInventory( RepairKit, 1 ); + if ( !($InvBanList[%cmt, Beacon]) ) + %client.player.setInventory( Beacon, 20 ); // z0dd - ZOD, 4/24/02. 400 was a bit much, changed to 20 + if ( !($InvBanList[%cmt, TargetingLaser]) ) + %client.player.setInventory( TargetingLaser, 1 ); + + // ammo pack pass -- hack! hack! + if( %pCh $= "AmmoPack" ) + invAmmoPackPass(%client); +} + +//------------------------------------------------------------------------------ +function buyDeployableFavorites(%client) +{ + %player = %client.player; + %prevPack = %player.getMountedImage($BackpackSlot); + %player.clearInventory(); + %client.setWeaponsHudClearAll(); + %cmt = $CurrentMissionType; + + // players cannot buy armor from deployable inventory stations + %weapCount = 0; + for ( %i = 0; %i < getFieldCount( %client.weaponIndex ); %i++ ) + { + %inv = $NameToInv[%client.favorites[getField( %client.weaponIndex, %i )]]; + if ( !($InvBanList[DeployInv, %inv]) && !$InvBanList[%cmt, %inv]) + { + %player.setInventory( %inv, 1 ); + // increment weapon count if current armor can hold this weapon + if(%player.getDatablock().max[%inv] > 0) + %weapCount++; + // --------------------------------------------- + // z0dd - ZOD, 4/24/02. Code streamlining. + if ( %inv.image.ammo !$= "" ) + %player.setInventory( %inv.image.ammo, 999 ); + // --------------------------------------------- + if(%weapCount >= %player.getDatablock().maxWeapons) + break; + } + } + %player.weaponCount = %weapCount; + // give player the grenades and mines they chose, beacons, and a repair kit + for ( %i = 0; %i < getFieldCount( %client.grenadeIndex ); %i++) + { + %GInv = $NameToInv[%client.favorites[getField( %client.grenadeIndex, %i )]]; + %client.player.lastGrenade = %GInv; + if ( !($InvBanList[DeployInv, %GInv]) && !$InvBanList[%cmt, %GInv]) + %player.setInventory( %GInv, 30 ); + } + + // if player is buying cameras, show how many are already deployed + if(%client.favorites[%client.grenadeIndex] $= "Deployable Camera") + { + %maxDep = $TeamDeployableMax[DeployedCamera]; + %depSoFar = $TeamDeployedCount[%client.player.team, DeployedCamera]; + if(Game.numTeams > 1) + %msTxt = "Your team has "@%depSoFar@" of "@%maxDep@" Deployable Cameras placed."; + else + %msTxt = "You have placed "@%depSoFar@" of "@%maxDep@" Deployable Cameras."; + messageClient(%client, 'MsgTeamDepObjCount', %msTxt); + } + + for ( %i = 0; %i < getFieldCount( %client.mineIndex ); %i++ ) + { + %MInv = $NameToInv[%client.favorites[getField( %client.mineIndex, %i )]]; + if ( !($InvBanList[DeployInv, %MInv]) && !$InvBanList[%cmt, %MInv]) + %player.setInventory( %MInv, 30 ); + } + if ( !($InvBanList[DeployInv, Beacon]) && !($InvBanList[%cmt, Beacon]) ) + %player.setInventory( Beacon, 20 ); // z0dd - ZOD, 4/24/02. 400 was a bit much, changed to 20. + if ( !($InvBanList[DeployInv, RepairKit]) && !($InvBanList[%cmt, RepairKit]) ) + %player.setInventory( RepairKit, 1 ); + if ( !($InvBanList[DeployInv, TargetingLaser]) && !($InvBanList[%cmt, TargetingLaser]) ) + %player.setInventory( TargetingLaser, 1 ); + + // players cannot buy deployable station packs from a deployable inventory station + %packChoice = $NameToInv[%client.favorites[%client.packIndex]]; + if ( !($InvBanList[DeployInv, %packChoice]) && !$InvBanList[%cmt, %packChoice]) + %player.setInventory( %packChoice, 1 ); + + // if this pack is a deployable that has a team limit, warn the purchaser + // if it's a deployable turret, the limit depends on the number of players (deployables.cs) + if(%packChoice $= "TurretIndoorDeployable" || %packChoice $= "TurretOutdoorDeployable") + %maxDep = countTurretsAllowed(%packChoice); + else + %maxDep = $TeamDeployableMax[%packChoice]; + if((%maxDep !$= "") && (%packChoice !$= "InventoryDeployable")) + { + %depSoFar = $TeamDeployedCount[%client.player.team, %packChoice]; + %packName = %client.favorites[%client.packIndex]; + + if(Game.numTeams > 1) + %msTxt = "Your team has "@%depSoFar@" of "@%maxDep SPC %packName@"s deployed."; + else + %msTxt = "You have deployed "@%depSoFar@" of "@%maxDep SPC %packName@"s."; + + messageClient(%client, 'MsgTeamDepObjCount', %msTxt); + } + + if(%prevPack > 0) + { + // if player had a "forbidden" pack (such as a deployable inventory station) + // BEFORE visiting a deployed inventory station AND still has that pack chosen + // as a favorite, give it back + if((%packChoice $= %prevPack.item) && ($InvBanList[DeployInv, %packChoice])) + %player.setInventory( %prevPack.item, 1 ); + } + + if(%packChoice $= "AmmoPack") + invAmmoPackPass(%client); +} + +//------------------------------------------------------------------------------------- +function getAmmoStationLovin(%client) +{ + // z0dd - ZOD, 4/24/02. This function was quite a mess, needed rewrite + %cmt = $CurrentMissionType; + + // weapons + for(%i = 0; %i < %client.player.weaponSlotCount; %i++) + { + %weapon = %client.player.weaponSlot[%i]; + if ( %weapon.image.ammo !$= "" ) + %client.player.setInventory( %weapon.image.ammo, 999 ); + } + + // grenades + for(%i = 0; $InvGrenade[%i] !$= ""; %i++) // z0dd - ZOD, 5/27/03. Clear them all in one pass + %player.setInventory($NameToInv[$InvGrenade[%i]], 0); + + for ( %i = 0; %i < getFieldCount( %client.grenadeIndex ); %i++ ) + { + %client.player.lastGrenade = $NameToInv[%client.favorites[getField( %client.grenadeIndex, %i )]]; + } + %grenType = %client.player.lastGrenade; + if(%grenType $= "") + { + %grenType = Grenade; + } + if ( !($InvBanList[%cmt, %grenType]) ) + %client.player.setInventory( %grenType, 30 ); + + if(%grenType $= "Deployable Camera") + { + %maxDep = $TeamDeployableMax[DeployedCamera]; + %depSoFar = $TeamDeployedCount[%client.player.team, DeployedCamera]; + if(Game.numTeams > 1) + %msTxt = "Your team has "@%depSoFar@" of "@%maxDep@" Deployable Cameras placed."; + else + %msTxt = "You have placed "@%depSoFar@" of "@%maxDep@" Deployable Cameras."; + messageClient(%client, 'MsgTeamDepObjCount', %msTxt); + } + + // Mines + for(%i = 0; $InvMine[%i] !$= ""; %i++) // z0dd - ZOD, 5/27/03. Clear them all in one pass + %player.setInventory($NameToInv[$InvMine[%i]], 0); + + for ( %i = 0; %i < getFieldCount( %client.mineIndex ); %i++ ) + { + %client.player.lastMine = $NameToInv[%client.favorites[getField( %client.mineIndex, %i )]]; + } + %mineType = %client.player.lastMine; + if(%mineType $= "") + { + %mineType = Mine; + } + if ( !($InvBanList[%cmt, %mineType]) ) + %client.player.setInventory( %mineType, 30 ); + + // miscellaneous stuff -- Repair Kit, Beacons, Targeting Laser + if ( !($InvBanList[%cmt, RepairKit]) ) + %client.player.setInventory( RepairKit, 1 ); + + if ( !($InvBanList[%cmt, Beacon]) ) + %client.player.setInventory( Beacon, 20 ); + + if ( !($InvBanList[%cmt, TargetingLaser]) ) + %client.player.setInventory( TargetingLaser, 1 ); + + if( %client.player.getMountedImage($BackpackSlot) $= "AmmoPack" ) + invAmmoPackPass(%client); +} + +function invAmmoPackPass(%client) +{ + // "normal" ammo stuff (everything but mines and grenades) + for ( %idx = 0; %idx < $numAmmoItems; %idx++ ) + { + %ammo = $AmmoItem[%idx]; + %client.player.incInventory(%ammo, AmmoPack.max[%ammo]); + } + //our good friends, the grenade family *SIGH* + // first find out what type of grenade the player has selected + %grenFav = %client.favorites[getField(%client.grenadeIndex, 0)]; + if((%grenFav !$= "EMPTY") && (%grenFav !$= "INVALID")) + %client.player.incInventory($NameToInv[%grenFav], AmmoPack.max[$NameToInv[%grenFav]]); + // now the same check for mines + %mineFav = %client.favorites[getField(%client.mineIndex, 0)]; + if((%mineFav !$= "EMPTY") && (%mineFav !$= "INVALID") && !($InvBanList[%cmt, Mine])) + %client.player.incInventory($NameToInv[%mineFav], AmmoPack.max[$NameToInv[%mineFav]]); +} + +//------------------------------------------------------------------------------ +function loadFavorite( %index, %echo ) +{ + $pref::FavCurrentSelect = %index; + %list = mFloor( %index / 10 ); + + if ( isObject( $Hud['inventoryScreen'] ) ) + { + // Deselect the old tab: + if ( InventoryScreen.selId !$= "" ) + $Hud['inventoryScreen'].staticData[0, InventoryScreen.selId].setValue( false ); + + // Make sure we are looking at the same list: + if ( $pref::FavCurrentList != %list ) + { + %favListStart = %list * 10; + %text = "Favorites " @ %favListStart + 1 SPC "-" SPC %favListStart + 10; + $Hud['inventoryScreen'].staticData[0, 0].onSelect( %list, %text, true ); + } + + // Select the new tab: + %tab = $pref::FavCurrentSelect - ( $pref::FavCurrentList * 10 ) + 1; + InventoryScreen.selId = %tab; + $Hud['inventoryScreen'].staticData[0, %tab].setValue( true ); + + // Update the Edit Name field: + $Hud['inventoryScreen'].staticData[1, 1].setValue( $pref::FavNames[%index] ); + } + + if ( %echo ) + addMessageHudLine( "Inventory set \"" @ $pref::FavNames[%index] @ "\" selected." ); + + commandToServer( 'setClientFav', $pref::Favorite[%index] ); +} + +//------------------------------------------------------------------------------ +function saveFavorite() +{ + if ( $pref::FavCurrentSelect !$= "" ) + { + %favName = $Hud['inventoryScreen'].staticData[1, 1].getValue(); + $pref::FavNames[$pref::FavCurrentSelect] = %favName; + $Hud['inventoryScreen'].staticData[0, $pref::FavCurrentSelect - ($pref::FavCurrentList * 10) + 1].setText( strupr( %favName ) ); + //$Hud[%tag].staticData[1, 1].setValue( %favName ); + %favList = $Hud['inventoryScreen'].data[0, 1].type TAB $Hud['inventoryScreen'].data[0, 1].getValue(); + for ( %i = 1; %i < $Hud['inventoryScreen'].count; %i++ ) + { + %name = $Hud['inventoryScreen'].data[%i, 1].getValue(); + if ( %name $= invalid ) + %name = "EMPTY"; + %favList = %favList TAB $Hud['inventoryScreen'].data[%i, 1].type TAB %name; + } + $pref::Favorite[$pref::FavCurrentSelect] = %favList; + echo("exporting pref::* to ClientPrefs.cs"); + export("$pref::*", "prefs/ClientPrefs.cs", False); + } +// else +// addMessageHudLine("Must First Select A Favorite Button."); +} + +//------------------------------------------------------------------------------ +function addQuickPackFavorite( %pack, %item ) +{ + // this has been such a success it has been changed to handle grenades + // and other equipment as well as packs so everything seems to be called 'pack' + // including the function itself. The default IS pack + + if(%item $= "") + %item = "Pack"; + %packFailMsg = "You cannot use that equipment with your selected loadout."; + if ( !isObject($Hud['inventoryScreen'].staticData[1, 1]) || $Hud['inventoryScreen'].staticData[1, 1].getValue() $= "" ) + { + //if the player hasnt brought up the inv screen we use his current fav + %currentFav = $pref::Favorite[$pref::FavCurrentSelect]; + //echo(%currentFav); + + for ( %i = 0; %i < getFieldCount( %currentFav ); %i++ ) + { + %type = getField( %currentFav, %i ); + %equipment = getField( %currentFav, %i++ ); + + %invalidPack = checkPackValidity(%pack, %equipment, %item ); + if(%invalidPack) + { + addMessageHudLine( %packFailMsg ); + return; + + } + // Success-------------------------------------------------- + if ( %type $= %item ) + %favList = %favList @ %type TAB %pack @ "\t"; + else + %favList = %favList @ %type TAB %equipment @ "\t"; + } + //echo(%favList); + } + else + { + //otherwise we go with whats on the invScreen (even if its asleep) + %armor = $Hud['inventoryScreen'].data[0, 1].getValue(); + + // check pack validity with armor + %invalidPack = checkPackValidity(%pack, %armor, %item ); + if(%invalidPack) + { + addMessageHudLine( %packFailMsg ); + return; + + } + %favList = $Hud['inventoryScreen'].data[0, 1].type TAB %armor; + for ( %i = 1; %i < $Hud['inventoryScreen'].count; %i++ ) + { + //echo( $Hud['inventoryScreen'].Data[%i, 1].type); + %type = $Hud['inventoryScreen'].data[%i, 1].type; + %equipment = $Hud['inventoryScreen'].data[%i, 1].getValue(); + + if(%type $= %item) + %equipment = %pack; + + // Special Cases again------------------------------------------------ + %invalidPack = checkPackValidity(%pack, %equipment, %item ); + if(%invalidPack) + { + addMessageHudLine( %packFailMsg ); + return; + + } + + %favList = %favList TAB %type TAB %equipment; + } + //echo(%favList); + } + commandToServer( 'setClientFav', %favList ); + + //we message the player real nice like + addMessageHudLine( "Inventory updated to " @ %pack @ "." ); +} + +function checkPackValidity(%pack, %equipment, %item) +{ + //echo("validityChecking:" SPC %pack SPC %equipment); + + // this is mostly for ease of mod makers + // this is the base restrictions stuff + // for your mod just overwrite this function and + // change the restrictions and onlyUses + + // you must have #1 to use #2 + //%restrict[#1, #2] = true; + + %restrict["Scout", "Inventory Station"] = true; + %restrict["Scout", "Landspike Turret"] = true; + %restrict["Scout", "Spider Clamp Turret"] = true; + %restrict["Scout", "ELF Turret Barrel"] = true; + %restrict["Scout", "Mortar Turret Barrel"] = true; + %restrict["Scout", "AA Turret Barrel"] = true; + %restrict["Scout", "Plasma Turret Barrel"] = true; + %restrict["Scout", "Missile Turret Barrel"] = true; + %restrict["Assault", "Cloak Pack"] = true; + %restrict["Juggernaut", "Cloak Pack"] = true; + + // you can only use #1 if you have a #2 of type #3 + //%require[#1] = #2 TAB #3; + + %require["Laser Rifle"] = "Pack" TAB "Energy Pack"; + + + if(%restrict[%equipment, %pack] ) + return true; + + else if(%require[%equipment] !$="" ) + { + if(%item $= getField(%require[%equipment], 0) ) + { + if(%pack !$= getField(%require[%equipment], 1) ) + return true; + } + } +} + + +//------------------------------------------------------------------------------ +function setDefaultInventory(%client) +{ + commandToClient(%client,'InitLoadClientFavorites'); +} + +//------------------------------------------------------------------------------ +function checkInventory( %client, %text ) +{ + %armor = getArmorDatablock( %client, $NameToInv[getField( %text, 1 )] ); + %list = getField( %text, 0 ) TAB getField( %text, 1 ); + %cmt = $CurrentMissionType; + for( %i = 3; %i < getFieldCount( %text ); %i = %i + 2 ) + { + %inv = $NameToInv[getField(%text,%i)]; + if ( (( %armor.max[%inv] && !($InvBanList[%cmt, %inv]) ) || + getField( %text, %i ) $= Empty || getField( %text, %i ) $= Invalid) + && (($InvTotalCount[getField( %text, %i - 1 )] - $BanCount[getField( %text, %i - 1 )]) > 0)) + %list = %list TAB getField( %text, %i - 1 ) TAB getField( %text, %i ); + else if( $InvBanList[%cmt, %inv] || %inv $= empty || %inv $= "") + %list = %list TAB getField( %text, %i - 1 ) TAB "INVALID"; + } + return %list; +} + +//------------------------------------------------------------------------------ +function getArmorDatablock(%client, %size) +{ + if ( %client.race $= "Bioderm" ) + %armor = %size @ "Male" @ %client.race @ Armor; + else + %armor = %size @ %client.sex @ %client.race @ Armor; + return %armor; +} + +//------------------------------------------------------------------------------ +function InventoryScreen::onWake(%this) +{ + if ( $HudHandle[inventoryScreen] !$= "" ) + alxStop( $HudHandle[inventoryScreen] ); + alxPlay(HudInventoryActivateSound, 0, 0, 0); + $HudHandle[inventoryScreen] = alxPlay(HudInventoryHumSound, 0, 0, 0); + + if ( isObject( hudMap ) ) + { + hudMap.pop(); + hudMap.delete(); + } + new ActionMap( hudMap ); + hudMap.blockBind( moveMap, toggleScoreScreen ); + hudMap.blockBind( moveMap, toggleCommanderMap ); + hudMap.bindCmd( keyboard, escape, "", "InventoryScreen.onDone();" ); + hudMap.push(); +} + +//------------------------------------------------------------------------------ +function InventoryScreen::onSleep() +{ + hudMap.pop(); + hudMap.delete(); + alxStop($HudHandle[inventoryScreen]); + alxPlay(HudInventoryDeactivateSound, 0, 0, 0); + $HudHandle[inventoryScreen] = ""; +} + +//------------------------------------------------------------------------------ +function InventoryScreen::onDone( %this ) +{ + toggleCursorHuds( 'inventoryScreen' ); +} + +//------------------------------------------------------------------------------ +function InventoryScreen::onTabSelect( %this, %favId ) +{ + loadFavorite( %favId, 0 ); +} + +function createInvBanCount() +{ + $BanCount["Armor"] = 0; + $BanCount["Weapon"] = 0; + $BanCount["Pack"] = 0; + $BanCount["Grenade"] = 0; + $BanCount["Mine"] = 0; + + for(%i = 0; $InvArmor[%i] !$= ""; %i++) + if($InvBanList[$CurrentMissionType, $NameToInv[$InvArmor[%i]]]) + $BanCount["Armor"]++; + $InvTotalCount["Armor"] = %i; + + for(%i = 0; $InvWeapon[%i] !$= ""; %i++) + if($InvBanList[$CurrentMissionType, $NameToInv[$InvWeapon[%i]]]) + $BanCount["Weapon"]++; + $InvTotalCount["Weapon"] = %i; + + for(%i = 0; $InvPack[%i] !$= ""; %i++) + if($InvBanList[$CurrentMissionType, $NameToInv[$InvPack[%i]]]) + $BanCount["Pack"]++; + $InvTotalCount["Pack"] = %i; + + for(%i = 0; $InvGrenade[%i] !$= ""; %i++) + if($InvBanList[$CurrentMissionType, $NameToInv[$InvGrenade[%i]]]) + $BanCount["Grenade"]++; + $InvTotalCount["Grenade"] = %i; + + for(%i = 0; $InvMine[%i] !$= ""; %i++) + if($InvBanList[$CurrentMissionType, $NameToInv[$InvMine[%i]]]) + $BanCount["Mine"]++; + $InvTotalCount["Mine"] = %i; +} + +// z0dd - ZOD, 5/17/03. New functions, limit armor types you can purchase +function countArmorAllowed() +{ + // This function is called from DefaultGame::assignClientTeam + // and loadMissionStage2, so its not run constantly. + + for(%j = 1; %j < Game.numTeams; %j++) + %teamPlayerCount[%j] = 0; + + %numClients = ClientGroup.getCount(); + for(%i = 0; %i < %numClients; %i++) + { + %cl = ClientGroup.getObject(%i); + if(%cl.team > 0) + %teamPlayerCount[%cl.team]++; + } + // the bigger team determines the number of armors allowed + %maxPlayers = %teamPlayerCount[1] > %teamPlayerCount[2] ? %teamPlayerCount[1] : %teamPlayerCount[2]; + if(%maxPlayers >= 16) + %teamArmorMax = mFloor(%maxPlayers * 0.38); + else + %teamArmorMax = 6; + + return $TeamArmorMax = %teamArmorMax; +} + +function resetArmorMaxes() +{ + for(%i = 0; %i <= Game.numTeams; %i++) + { + $TeamArmorCount[%i, Light] = 0; + $TeamArmorCount[%i, Medium] = 0; + $TeamArmorCount[%i, Heavy] = 0; + } +} diff --git a/Classic/scripts/projectiles.cs b/Classic/scripts/projectiles.cs index 9f24021..1ba0fd7 100644 --- a/Classic/scripts/projectiles.cs +++ b/Classic/scripts/projectiles.cs @@ -62,20 +62,21 @@ function ShapeBaseImageData::onFire(%data, %obj, %slot) { // --------------------------------------------------------------------------- // z0dd - ZOD, 9/3/02. Anti rapid fire mortar/missile fix. - if (%obj.cantFire !$= "") - { - return 0; - } + // if (%obj.cantFire !$= "") + // { + // return 0; + // } - %wpnName = %data.getName(); - if((%wpnName $= "MortarImage") || (%wpnName $= "MissileLauncherImage")) - { - %obj.cantFire = 1; - %preventTime = %data.stateTimeoutValue[4]; - //%preventTime = (%data.stateTimeoutValue[4] + %data.stateTimeoutValue[3]) - 0.032; - %obj.reloadSchedule = schedule(%preventTime * 1000, %obj, resetFire, %obj); - } + // %wpnName = %data.getName(); + // if((%wpnName $= "MortarImage") || (%wpnName $= "MissileLauncherImage")) + // { + // %obj.cantFire = 1; + // %preventTime = %data.stateTimeoutValue[4]; + // //%preventTime = (%data.stateTimeoutValue[4] + %data.stateTimeoutValue[3]) - 0.032; + // %obj.reloadSchedule = schedule(%preventTime * 1000, %obj, resetFire, %obj); + // } // --------------------------------------------------------------------------- + %obj.lfireTime[%data.getName()] = getSimTime(); %data.lightStart = getSimTime(); @@ -411,7 +412,6 @@ function ShockLanceImage::onFire(%this, %obj, %slot) %obj.cantfire = 1; %preventTime = %this.stateTimeoutValue[4]; - //%preventTime = (%data.stateTimeoutValue[4] + %data.stateTimeoutValue[3]) - 0.032; %obj.reloadSchedule = schedule(%preventTime * 1000, %obj, resetFire, %obj); if( %obj.getEnergyLevel() < %this.minEnergy ) // z0dd - ZOD, 5/22/03. Check energy level first diff --git a/Classic/scripts/server.cs b/Classic/scripts/server.cs index de7b8b5..46dfc28 100644 --- a/Classic/scripts/server.cs +++ b/Classic/scripts/server.cs @@ -890,7 +890,7 @@ function GameConnection::onConnect( %client, %name, %raceGender, %skin, %voice, //messageClient( %client, 'MsgClassic', 'Classic \c2V-Ramming Mod: \c3%1.', ($Host::ClassicLoadVRamChanges ? 'Enabled' : 'Disabled') ); // z0dd - ZOD, 9/29/02. Removed T2 demo code from here - messageClient(%client, 'MsgClientJoin', 'Welcome to Tribes2 %1.', + messageClient(%client, 'MsgClientJoin', '\c2Welcome to Tribes2 %1.', %client.name, %client, %client.target, diff --git a/Classic/scripts/supportClassic.cs b/Classic/scripts/supportClassic.cs index 384f65d..93f736f 100755 --- a/Classic/scripts/supportClassic.cs +++ b/Classic/scripts/supportClassic.cs @@ -319,3 +319,7 @@ function TSStatic::onTrigger(%this, %triggerId, %on){ function TSStatic::onTriggerTick(%this, %triggerId){ //anti console spam } + +function SimObject::setPosition(%obj, %pos){ + %obj.setTransform(%pos SPC getWords(%obj.getTransform(), 3, 6)); +} \ No newline at end of file diff --git a/Classic/scripts/weapons/missileLauncher.cs b/Classic/scripts/weapons/missileLauncher.cs new file mode 100644 index 0000000..abaec08 --- /dev/null +++ b/Classic/scripts/weapons/missileLauncher.cs @@ -0,0 +1,856 @@ +//-------------------------------------- +// Missile launcher +//-------------------------------------- + +//-------------------------------------------------------------------------- +// Sounds +//-------------------------------------- +datablock AudioProfile(MissileSwitchSound) +{ + filename = "fx/weapons/missile_launcher_activate.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(MissileFireSound) +{ + filename = "fx/weapons/missile_fire.WAV"; + description = AudioDefault3d; + preload = true; +}; + +datablock AudioProfile(MissileProjectileSound) +{ + filename = "fx/weapons/missile_projectile.wav"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock AudioProfile(MissileReloadSound) +{ + filename = "fx/weapons/weapon.missilereload.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(MissileLockSound) +{ + filename = "fx/weapons/missile_launcher_searching.WAV"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(MissileExplosionSound) +{ + filename = "fx/explosions/explosion.xpl23.wav"; + description = AudioBIGExplosion3d; + preload = true; +}; + +datablock AudioProfile(MissileDryFireSound) +{ + filename = "fx/weapons/missile_launcher_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + + +//---------------------------------------------------------------------------- +// Splash Debris +//---------------------------------------------------------------------------- +datablock ParticleData( MDebrisSmokeParticle ) +{ + dragCoeffiecient = 1.0; + gravityCoefficient = 0.10; + inheritedVelFactor = 0.1; + + lifetimeMS = 1000; + lifetimeVarianceMS = 100; + + textureName = "particleTest"; + +// useInvAlpha = true; + + spinRandomMin = -60.0; + spinRandomMax = 60.0; + + colors[0] = "0.7 0.8 1.0 1.0"; + colors[1] = "0.7 0.8 1.0 0.5"; + colors[2] = "0.7 0.8 1.0 0.0"; + sizes[0] = 0.0; + sizes[1] = 0.8; + sizes[2] = 0.8; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( MDebrisSmokeEmitter ) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 1; + + ejectionVelocity = 1.0; // A little oomph at the back end + velocityVariance = 0.2; + + thetaMin = 0.0; + thetaMax = 40.0; + + particles = "MDebrisSmokeParticle"; +}; + + +datablock DebrisData( MissileSplashDebris ) +{ + emitters[0] = MDebrisSmokeEmitter; + + explodeOnMaxBounce = true; + + elasticity = 0.4; + friction = 0.2; + + lifetime = 0.3; + lifetimeVariance = 0.1; + + numBounces = 1; +}; + + +//---------------------------------------------------------------------------- +// Missile smoke spike (for debris) +//---------------------------------------------------------------------------- +datablock ParticleData( MissileSmokeSpike ) +{ + dragCoeffiecient = 1.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + + lifetimeMS = 1000; + lifetimeVarianceMS = 100; + + textureName = "particleTest"; + + useInvAlpha = true; + + spinRandomMin = -60.0; + spinRandomMax = 60.0; + + colors[0] = "0.6 0.6 0.6 1.0"; + colors[1] = "0.4 0.4 0.4 0.5"; + colors[2] = "0.4 0.4 0.4 0.0"; + sizes[0] = 0.0; + sizes[1] = 1.0; + sizes[2] = 0.5; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( MissileSmokeSpikeEmitter ) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 1; + + ejectionVelocity = 1.0; // A little oomph at the back end + velocityVariance = 0.2; + + thetaMin = 0.0; + thetaMax = 40.0; + + particles = "MissileSmokeSpike"; +}; + + +//---------------------------------------------------------------------------- +// Explosion smoke particles +//---------------------------------------------------------------------------- + +datablock ParticleData(MissileExplosionSmoke) +{ + dragCoeffiecient = 0.3; + gravityCoefficient = -0.2; + inheritedVelFactor = 0.025; + + lifetimeMS = 1250; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -100.0; + spinRandomMax = 100.0; + + textureName = "special/Smoke/bigSmoke"; + + colors[0] = "1.0 0.7 0.0 1.0"; + colors[1] = "0.4 0.4 0.4 0.5"; + colors[2] = "0.4 0.4 0.4 0.0"; + sizes[0] = 1.0; + sizes[1] = 3.0; + sizes[2] = 1.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(MissileExplosionSmokeEMitter) +{ + ejectionOffset = 0.0; + ejectionPeriodMS = 5; + periodVarianceMS = 0; + + ejectionVelocity = 3.25; + velocityVariance = 0.25; + + thetaMin = 0.0; + thetaMax = 180.0; + + lifetimeMS = 250; + + particles = "MissileExplosionSmoke"; +}; + + + +datablock DebrisData( MissileSpikeDebris ) +{ + emitters[0] = MissileSmokeSpikeEmitter; + explodeOnMaxBounce = true; + elasticity = 0.4; + friction = 0.2; + lifetime = 0.3; + lifetimeVariance = 0.02; +}; + + +//--------------------------------------------------------------------------- +// Explosions +//--------------------------------------------------------------------------- +datablock ExplosionData(MissileExplosion) +{ + explosionShape = "effect_plasma_explosion.dts"; + playSpeed = 1.5; + soundProfile = MissileExplosionSound; + faceViewer = true; + + sizes[0] = "0.5 0.5 0.5"; + sizes[1] = "0.5 0.5 0.5"; + sizes[2] = "0.5 0.5 0.5"; + + emitter[0] = MissileExplosionSmokeEmitter; + + debris = MissileSpikeDebris; + debrisThetaMin = 10; + debrisThetaMax = 170; + debrisNum = 8; + debrisNumVariance = 6; + debrisVelocity = 15.0; + debrisVelocityVariance = 2.0; + + shakeCamera = true; + camShakeFreq = "6.0 7.0 7.0"; + camShakeAmp = "70.0 70.0 70.0"; + camShakeDuration = 1.0; + camShakeRadius = 7.0; +}; + +datablock ExplosionData(MissileSplashExplosion) +{ + explosionShape = "disc_explosion.dts"; + + faceViewer = true; + explosionScale = "1.0 1.0 1.0"; + + debris = MissileSplashDebris; + debrisThetaMin = 10; + debrisThetaMax = 80; + debrisNum = 10; + debrisVelocity = 10.0; + debrisVelocityVariance = 4.0; + + sizes[0] = "0.35 0.35 0.35"; + sizes[1] = "0.15 0.15 0.15"; + sizes[2] = "0.15 0.15 0.15"; + sizes[3] = "0.15 0.15 0.15"; + + times[0] = 0.0; + times[1] = 0.333; + times[2] = 0.666; + times[3] = 1.0; + +}; + +//-------------------------------------------------------------------------- +// Splash +//-------------------------------------------------------------------------- +datablock ParticleData(MissileMist) +{ + dragCoefficient = 2.0; + gravityCoefficient = -0.05; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 400; + lifetimeVarianceMS = 100; + useInvAlpha = false; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.7 0.8 1.0 1.0"; + colors[1] = "0.7 0.8 1.0 0.5"; + colors[2] = "0.7 0.8 1.0 0.0"; + sizes[0] = 0.5; + sizes[1] = 0.5; + sizes[2] = 0.8; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(MissileMistEmitter) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 0; + ejectionVelocity = 6.0; + velocityVariance = 4.0; + ejectionOffset = 0.0; + thetaMin = 85; + thetaMax = 85; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 250; + particles = "MissileMist"; +}; + +datablock ParticleData( MissileSplashParticle ) +{ + dragCoefficient = 1; + gravityCoefficient = 0.2; + inheritedVelFactor = 0.2; + constantAcceleration = -0.0; + lifetimeMS = 600; + lifetimeVarianceMS = 0; + textureName = "special/droplet"; + colors[0] = "0.7 0.8 1.0 1.0"; + colors[1] = "0.7 0.8 1.0 0.5"; + colors[2] = "0.7 0.8 1.0 0.0"; + sizes[0] = 0.5; + sizes[1] = 0.5; + sizes[2] = 0.5; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( MissileSplashEmitter ) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 6; + velocityVariance = 3.0; + ejectionOffset = 0.0; + thetaMin = 60; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 100; + particles = "MissileSplashParticle"; +}; + + +datablock SplashData(MissileSplash) +{ + numSegments = 15; + ejectionFreq = 0.0001; + ejectionAngle = 45; + ringLifetime = 0.5; + lifetimeMS = 400; + velocity = 5.0; + startRadius = 0.0; + acceleration = -3.0; + texWrap = 5.0; + + explosion = MissileSplashExplosion; + + texture = "special/water2"; + + emitter[0] = MissileSplashEmitter; + emitter[1] = MissileMistEmitter; + + colors[0] = "0.7 0.8 1.0 0.0"; + colors[1] = "0.7 0.8 1.0 1.0"; + colors[2] = "0.7 0.8 1.0 0.0"; + colors[3] = "0.7 0.8 1.0 0.0"; + times[0] = 0.0; + times[1] = 0.4; + times[2] = 0.8; + times[3] = 1.0; +}; + +//-------------------------------------------------------------------------- +// Particle effects +//-------------------------------------- +datablock ParticleData(MissileSmokeParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.02; + inheritedVelFactor = 0.1; + + lifetimeMS = 1200; + lifetimeVarianceMS = 100; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 90.0; + + colors[0] = "1.0 0.75 0.0 0.0"; + colors[1] = "0.5 0.5 0.5 1.0"; + colors[2] = "0.3 0.3 0.3 0.0"; + sizes[0] = 1; + sizes[1] = 2; + sizes[2] = 3; + times[0] = 0.0; + times[1] = 0.1; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(MissileSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 1.5; + velocityVariance = 0.3; + + thetaMin = 0.0; + thetaMax = 50.0; + + particles = "MissileSmokeParticle"; +}; + +datablock ParticleData(MissileFireParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 300; + lifetimeVarianceMS = 000; + + textureName = "particleTest"; + + spinRandomMin = -135; + spinRandomMax = 135; + + colors[0] = "1.0 0.75 0.2 1.0"; + colors[1] = "1.0 0.5 0.0 1.0"; + colors[2] = "1.0 0.40 0.0 0.0"; + sizes[0] = 0; + sizes[1] = 1; + sizes[2] = 1.5; + times[0] = 0.0; + times[1] = 0.3; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(MissileFireEmitter) +{ + ejectionPeriodMS = 15; + periodVarianceMS = 0; + + ejectionVelocity = 15.0; + velocityVariance = 0.0; + + thetaMin = 0.0; + thetaMax = 0.0; + + particles = "MissileFireParticle"; +}; + +datablock ParticleData(MissilePuffParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 500; + lifetimeVarianceMS = 300; + + textureName = "particleTest"; + + spinRandomMin = -135; + spinRandomMax = 135; + + colors[0] = "1.0 1.0 1.0 0.5"; + colors[1] = "0.7 0.7 0.7 0.0"; + sizes[0] = 0.25; + sizes[1] = 1.0; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ParticleEmitterData(MissilePuffEmitter) +{ + ejectionPeriodMS = 50; + periodVarianceMS = 3; + + ejectionVelocity = 0.5; + velocityVariance = 0.0; + + thetaMin = 0.0; + thetaMax = 90.0; + + particles = "MissilePuffParticle"; +}; + +datablock ParticleData(MissileLauncherExhaustParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.01; + inheritedVelFactor = 1.0; + + lifetimeMS = 500; + lifetimeVarianceMS = 300; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -135; + spinRandomMax = 135; + + colors[0] = "1.0 1.0 1.0 0.5"; + colors[1] = "0.7 0.7 0.7 0.0"; + sizes[0] = 0.25; + sizes[1] = 1.0; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ParticleEmitterData(MissileLauncherExhaustEmitter) +{ + ejectionPeriodMS = 15; + periodVarianceMS = 0; + + ejectionVelocity = 3.0; + velocityVariance = 0.0; + + thetaMin = 0.0; + thetaMax = 20.0; + + particles = "MissileLauncherExhaustParticle"; +}; + +//-------------------------------------------------------------------------- +// Debris +//-------------------------------------- +datablock DebrisData( FlechetteDebris ) +{ + shapeName = "weapon_missile_fleschette.dts"; + + lifetime = 5.0; + + minSpinSpeed = -320.0; + maxSpinSpeed = 320.0; + + elasticity = 0.2; + friction = 0.3; + + numBounces = 3; + + gravModifier = 0.40; + + staticOnMaxBounce = true; +}; + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- +datablock SeekerProjectileData(ShoulderMissile) +{ + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "weapon_missile_projectile.dts"; + hasDamageRadius = true; + indirectDamage = 0.8; + damageRadius = 8.0; + radiusDamageType = $DamageType::Missile; + kickBackStrength = 2000; + + explosion = "MissileExplosion"; + splash = MissileSplash; + velInheritFactor = 1.0; // to compensate for slow starting velocity, this value + // is cranked up to full so the missile doesn't start + // out behind the player when the player is moving + // very quickly - bramage + + baseEmitter = MissileSmokeEmitter; + delayEmitter = MissileFireEmitter; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = 7000; // z0dd - ZOD, 4/14/02. Was 6000 + muzzleVelocity = 10.0; + maxVelocity = 90.0; // z0dd - ZOD, 4/14/02. Was 80.0 + turningSpeed = 110.0; + acceleration = 200.0; + + proximityRadius = 3; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + flareDistance = 200; + flareAngle = 30; + + sound = MissileProjectileSound; + + hasLight = true; + lightRadius = 5.0; + lightColor = "0.2 0.05 0"; + + useFlechette = true; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = false; +}; + +datablock LinearProjectileData(Rocket) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + emitterDelay = -1; + baseEmitter = MissileSmokeEmitter; + delayEmitter = MissileFireEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.5; + damageRadius = 7.5; + radiusDamageType = $DamageType::Missile; + kickBackStrength = 2000; + sound = MissileProjectileSound; + explosion = "MissileExplosion"; + underwaterExplosion = "UnderwaterDiscExplosion"; + splash = MissileSplash; + dryVelocity = 90; + wetVelocity = 50; + velInheritFactor = 0.75; + fizzleTimeMS = 5000; + lifetimeMS = 5000; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = false; + deflectionOnWaterImpact = 20.0; + fizzleUnderwaterMS = 5000; +// activateDelayMS = 200; + hasLight = true; + lightRadius = 6.0; + lightColor = "0.175 0.175 0.5"; +}; + +//-------------------------------------------------------------------------- +// Ammo +//-------------------------------------- + +datablock ItemData(MissileLauncherAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "ammo_missile.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "some missiles"; + + computeCRC = true; + +}; + +//-------------------------------------------------------------------------- +// Weapon +//-------------------------------------- +datablock ItemData(MissileLauncher) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_missile.dts"; + image = MissileLauncherImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a missile launcher"; + + computeCRC = true; + emap = true; +}; + +datablock ShapeBaseImageData(MissileLauncherImage) +{ + className = WeaponImage; + shapeFile = "weapon_missile.dts"; + item = MissileLauncher; + ammo = MissileLauncherAmmo; + offset = "0 0 0"; + armThread = lookms; + emap = true; + + projectile = ShoulderMissile; + projectileType = SeekerProjectile; + + isSeeker = true; + seekRadius = 400; + maxSeekAngle = 8; + seekTime = 0.5; + minSeekHeat = $Host::ClassicLoadMissileChanges ? 1.0 : 0.6; // the heat that must be present on a target to lock it. // z0dd - ZOD, 8/22/02. Was 0.7 + + // only target objects outside this range + minTargetingDistance = 40; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = MissileSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnAmmo[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "FirstLoad"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "CheckWet"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.4; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateScript[3] = "onFire"; + stateSound[3] = MissileFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 2.5; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = MissileReloadSound; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateSound[6] = MissileDryFireSound; + stateTimeoutValue[6] = 1.0; + stateTransitionOnTimeout[6] = "ActivateReady"; + + stateName[7] = "CheckTarget"; + // z0dd - ZOD, 5/07/04. Shoot one off if gameplay changes are in affect. + //stateTransitionOnNoTarget[7] = "DryFire"; + stateTransitionOnNoTarget[7] = $Host::ClassicLoadMissileChanges ? "DumbFire" : "DryFire"; + stateTransitionOnTarget[7] = "Fire"; + + stateName[8] = "CheckWet"; + stateTransitionOnWet[8] = "WetFire"; + stateTransitionOnNotWet[8] = "CheckTarget"; + + stateName[9] = "WetFire"; + stateTransitionOnNoAmmo[9] = "NoAmmo"; + stateTransitionOnTimeout[9] = "Reload"; + stateSound[9] = MissileFireSound; + stateRecoil[3] = LightRecoil; + stateTimeoutValue[9] = 0.4; + stateSequence[3] = "Fire"; + stateScript[9] = "onWetFire"; + stateAllowImageChange[9] = false; + + stateName[10] = "DumbFire"; + stateTransitionOnTimeout[10] = "Reload"; + stateTimeoutValue[10] = 0.4; + stateFire[10] = true; + stateRecoil[10] = LightRecoil; + stateAllowImageChange[10] = false; + stateSequence[10] = "Fire"; + stateScript[10] = "onDumbFire"; + stateSound[10] = MissileFireSound; + + stateName[11] = "FirstLoad"; + stateTransitionOnAmmo[11] = "Ready"; +}; + +function MissileLauncherImage::onDumbFire(%data,%obj,%slot) +{ + %data.lightStart = getSimTime(); + %p = new (LinearProjectile)() { + dataBlock = Rocket; + initialDirection = MatrixMulVector("0 0 0 0 0 1 0", %obj.getMuzzleVector(%slot)); + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + sourceSlot = %slot; + }; + %obj.lastProjectile = %p; + MissionCleanup.add(%p); + if(%obj.client) + %obj.client.projectile = %p; + + %obj.decInventory(%data.ammo, 1); + return %p; +} +function MissileLauncherImage::onUnmount(%this,%obj,%slot){ + parent::onUnmount(%this,%obj,%slot); + if(isEventPending(%obj.reloadDelaySch)) + cancel(%obj.reloadDelaySch); +} +function MissileLauncherImage::onMount(%this,%obj,%slot){ + + if(%obj.getClassName() !$= "Player") + return; + + if (%this.armthread $= "") + %obj.setArmThread(look); + else + %obj.setArmThread(%this.armThread); + + if(%obj.getMountedImage($WeaponSlot).ammo !$= ""){ + if (%obj.getInventory(%this.ammo)){ + + %fireAndReloadTime = mFloor((%this.stateTimeoutValue[4] + %this.stateTimeoutValue[3]) * 1000); + + if(%obj.lfireTime[%this.getName()] && (getSimTime() - %obj.lfireTime[%this.getName()]) < %fireAndReloadTime){ + if(isEventPending(%obj.reloadDelaySch)){ + cancel(%obj.reloadDelaySch); + } + %time = mFloor(%fireAndReloadTime - (getSimTime() - %obj.lfireTime[%this.getName()])); + %obj.reloadDelaySch = schedule(%time, 0, "ammoStateDelay", %obj, %slot, true); + } + else{ + %obj.setImageAmmo(%slot,true); + } + } + } + + %obj.client.setWeaponsHudActive(%this.item); + if(%obj.getMountedImage($WeaponSlot).ammo !$= "") + %obj.client.setAmmoHudCount(%obj.getInventory(%this.ammo)); + else + %obj.client.setAmmoHudCount(-1); +} \ No newline at end of file diff --git a/Classic/scripts/weapons/mortar.cs b/Classic/scripts/weapons/mortar.cs new file mode 100644 index 0000000..876ee09 --- /dev/null +++ b/Classic/scripts/weapons/mortar.cs @@ -0,0 +1,824 @@ +//-------------------------------------- +// Mortar +//-------------------------------------- + +//-------------------------------------------------------------------------- +// Sounds +//-------------------------------------- +datablock AudioProfile(MortarSwitchSound) +{ + filename = "fx/weapons/mortar_activate.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(MortarReloadSound) +{ + filename = "fx/weapons/mortar_reload.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(MortarIdleSound) +{ + //filename = "fx/weapons/weapon.mortarIdle.wav"; + filename = "fx/weapons/plasma_rifle_idle.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(MortarFireSound) +{ + filename = "fx/weapons/mortar_fire.wav"; + description = AudioDefault3d; + preload = true; +}; + +datablock AudioProfile(MortarProjectileSound) +{ + filename = "fx/weapons/mortar_projectile.wav"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock AudioProfile(MortarExplosionSound) +{ + filename = "fx/weapons/mortar_explode.wav"; + description = AudioBIGExplosion3d; + preload = true; +}; + +datablock AudioProfile(UnderwaterMortarExplosionSound) +{ + filename = "fx/weapons/mortar_explode_UW.wav"; + description = AudioBIGExplosion3d; + preload = true; +}; + +datablock AudioProfile(MortarDryFireSound) +{ + filename = "fx/weapons/mortar_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +//---------------------------------------------------------------------------- +// Bubbles +//---------------------------------------------------------------------------- +datablock ParticleData(MortarBubbleParticle) +{ + dragCoefficient = 0.0; + gravityCoefficient = -0.25; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 1500; + lifetimeVarianceMS = 600; + useInvAlpha = false; + textureName = "special/bubbles"; + + spinRandomMin = -100.0; + spinRandomMax = 100.0; + + colors[0] = "0.7 0.8 1.0 0.4"; + colors[1] = "0.7 0.8 1.0 0.4"; + colors[2] = "0.7 0.8 1.0 0.0"; + sizes[0] = 0.8; + sizes[1] = 0.8; + sizes[2] = 0.8; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(MortarBubbleEmitter) +{ + ejectionPeriodMS = 9; + periodVarianceMS = 0; + ejectionVelocity = 1.0; + ejectionOffset = 0.1; + velocityVariance = 0.5; + thetaMin = 0; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "MortarBubbleParticle"; +}; + +//-------------------------------------------------------------------------- +// Splash +//-------------------------------------------------------------------------- +datablock ParticleData( MortarSplashParticle ) +{ + dragCoefficient = 1; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = -1.4; + lifetimeMS = 300; + lifetimeVarianceMS = 0; + textureName = "special/droplet"; + colors[0] = "0.7 0.8 1.0 1.0"; + colors[1] = "0.7 0.8 1.0 0.5"; + colors[2] = "0.7 0.8 1.0 0.0"; + sizes[0] = 0.05; + sizes[1] = 0.2; + sizes[2] = 0.2; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( MortarSplashEmitter ) +{ + ejectionPeriodMS = 4; + periodVarianceMS = 0; + ejectionVelocity = 3; + velocityVariance = 1.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 50; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 100; + particles = "MortarSplashParticle"; +}; + + +datablock SplashData(MortarSplash) +{ + numSegments = 10; + ejectionFreq = 10; + ejectionAngle = 20; + ringLifetime = 0.4; + lifetimeMS = 400; + velocity = 3.0; + startRadius = 0.0; + acceleration = -3.0; + texWrap = 5.0; + + texture = "special/water2"; + + emitter[0] = MortarSplashEmitter; + + colors[0] = "0.7 0.8 1.0 0.0"; + colors[1] = "0.7 0.8 1.0 1.0"; + colors[2] = "0.7 0.8 1.0 0.0"; + colors[3] = "0.7 0.8 1.0 0.0"; + times[0] = 0.0; + times[1] = 0.4; + times[2] = 0.8; + times[3] = 1.0; +}; + +//--------------------------------------------------------------------------- +// Mortar Shockwaves +//--------------------------------------------------------------------------- +datablock ShockwaveData(UnderwaterMortarShockwave) +{ + width = 6.0; + numSegments = 32; + numVertSegments = 6; + velocity = 10; + acceleration = 20.0; + lifetimeMS = 900; + height = 1.0; + verticalCurve = 0.5; + is2D = false; + + texture[0] = "special/shockwave4"; + texture[1] = "special/gradient"; + texWrap = 6.0; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + + colors[0] = "0.4 0.4 1.0 0.50"; + colors[1] = "0.4 0.4 1.0 0.25"; + colors[2] = "0.4 0.4 1.0 0.0"; + + mapToTerrain = true; + orientToNormal = false; + renderBottom = false; +}; + +datablock ShockwaveData(MortarShockwave) +{ + width = 6.0; + numSegments = 32; + numVertSegments = 6; + velocity = 15; + acceleration = 20.0; + lifetimeMS = 500; + height = 1.0; + verticalCurve = 0.5; + is2D = false; + + texture[0] = "special/shockwave4"; + texture[1] = "special/gradient"; + texWrap = 6.0; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + + colors[0] = "0.4 1.0 0.4 0.50"; + colors[1] = "0.4 1.0 0.4 0.25"; + colors[2] = "0.4 1.0 0.4 0.0"; + + mapToTerrain = true; + orientToNormal = false; + renderBottom = false; +}; + + +//-------------------------------------------------------------------------- +// Mortar Explosion Particle effects +//-------------------------------------- +datablock ParticleData( MortarCrescentParticle ) +{ + dragCoefficient = 2; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = -0.0; + lifetimeMS = 600; + lifetimeVarianceMS = 000; + textureName = "special/crescent3"; + colors[0] = "0.7 1.0 0.7 1.0"; + colors[1] = "0.7 1.0 0.7 0.5"; + colors[2] = "0.7 1.0 0.7 0.0"; + sizes[0] = 4.0; + sizes[1] = 8.0; + sizes[2] = 9.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( MortarCrescentEmitter ) +{ + ejectionPeriodMS = 25; + periodVarianceMS = 0; + ejectionVelocity = 40; + velocityVariance = 5.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 200; + particles = "MortarCrescentParticle"; +}; + + +datablock ParticleData(MortarExplosionSmoke) +{ + dragCoeffiecient = 0.4; + gravityCoefficient = -0.30; // rises slowly + inheritedVelFactor = 0.025; + + lifetimeMS = 1250; + lifetimeVarianceMS = 500; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -100.0; + spinRandomMax = 100.0; + + textureName = "special/Smoke/bigSmoke"; + + colors[0] = "0.7 0.7 0.7 0.0"; + colors[1] = "0.4 0.4 0.4 0.5"; + colors[2] = "0.4 0.4 0.4 0.5"; + colors[3] = "0.4 0.4 0.4 0.0"; + sizes[0] = 5.0; + sizes[1] = 6.0; + sizes[2] = 10.0; + sizes[3] = 12.0; + times[0] = 0.0; + times[1] = 0.333; + times[2] = 0.666; + times[3] = 1.0; + + + +}; + +datablock ParticleEmitterData(MortarExplosionSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionOffset = 8.0; + + + ejectionVelocity = 1.25; + velocityVariance = 1.2; + + thetaMin = 0.0; + thetaMax = 90.0; + + lifetimeMS = 500; + + particles = "MortarExplosionSmoke"; + +}; + +//--------------------------------------------------------------------------- +// Underwater Explosion +//--------------------------------------------------------------------------- +datablock ParticleData(UnderwaterExplosionSparks) +{ + dragCoefficient = 0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 350; + textureName = "special/crescent3"; + colors[0] = "0.4 0.4 1.0 1.0"; + colors[1] = "0.4 0.4 1.0 1.0"; + colors[2] = "0.4 0.4 1.0 0.0"; + sizes[0] = 3.5; + sizes[1] = 3.5; + sizes[2] = 3.5; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(UnderwaterExplosionSparksEmitter) +{ + ejectionPeriodMS = 2; + periodVarianceMS = 0; + ejectionVelocity = 17; + velocityVariance = 4; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 60; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 100; + particles = "UnderwaterExplosionSparks"; +}; + +datablock ParticleData(MortarExplosionBubbleParticle) +{ + dragCoefficient = 0.0; + gravityCoefficient = -0.25; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 1500; + lifetimeVarianceMS = 600; + useInvAlpha = false; + textureName = "special/bubbles"; + + spinRandomMin = -100.0; + spinRandomMax = 100.0; + + colors[0] = "0.7 0.8 1.0 0.0"; + colors[1] = "0.7 0.8 1.0 0.4"; + colors[2] = "0.7 0.8 1.0 0.0"; + sizes[0] = 2.0; + sizes[1] = 2.0; + sizes[2] = 2.0; + times[0] = 0.0; + times[1] = 0.8; + times[2] = 1.0; +}; +datablock ParticleEmitterData(MortarExplosionBubbleEmitter) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 0; + ejectionVelocity = 1.0; + ejectionOffset = 7.0; + velocityVariance = 0.5; + thetaMin = 0; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "MortarExplosionBubbleParticle"; +}; + +datablock DebrisData( UnderwaterMortarDebris ) +{ + emitters[0] = MortarExplosionBubbleEmitter; + + explodeOnMaxBounce = true; + + elasticity = 0.4; + friction = 0.2; + + lifetime = 1.5; + lifetimeVariance = 0.2; + + numBounces = 1; +}; + +datablock ExplosionData(UnderwaterMortarSubExplosion1) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + delayMS = 100; + offset = 3.0; + playSpeed = 1.5; + + sizes[0] = "0.75 0.75 0.75"; + sizes[1] = "1.0 1.0 1.0"; + sizes[2] = "0.5 0.5 0.5"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ExplosionData(UnderwaterMortarSubExplosion2) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + delayMS = 50; + offset = 3.0; + playSpeed = 0.75; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "1.5 1.5 1.5"; + sizes[2] = "1.0 1.0 1.0"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ExplosionData(UnderwaterMortarSubExplosion3) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + delayMS = 0; + offset = 0.0; + playSpeed = 0.5; + + sizes[0] = "1.0 1.0 1.0"; + sizes[1] = "2.0 2.0 2.0"; + sizes[2] = "1.5 1.5 1.5"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ExplosionData(UnderwaterMortarExplosion) +{ + soundProfile = UnderwaterMortarExplosionSound; + + shockwave = UnderwaterMortarShockwave; + shockwaveOnTerrain = true; + + subExplosion[0] = UnderwaterMortarSubExplosion1; + subExplosion[1] = UnderwaterMortarSubExplosion2; + subExplosion[2] = UnderwaterMortarSubExplosion3; + + emitter[0] = MortarExplosionBubbleEmitter; + emitter[1] = UnderwaterExplosionSparksEmitter; + + shakeCamera = true; + camShakeFreq = "8.0 9.0 7.0"; + camShakeAmp = "100.0 100.0 100.0"; + camShakeDuration = 1.3; + camShakeRadius = 25.0; +}; + + +//--------------------------------------------------------------------------- +// Explosion +//--------------------------------------------------------------------------- + +datablock ExplosionData(MortarSubExplosion1) +{ + explosionShape = "mortar_explosion.dts"; + faceViewer = true; + + delayMS = 100; + + offset = 5.0; + + playSpeed = 1.5; + + sizes[0] = "0.5 0.5 0.5"; + sizes[1] = "0.5 0.5 0.5"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(MortarSubExplosion2) +{ + explosionShape = "mortar_explosion.dts"; + faceViewer = true; + + delayMS = 50; + + offset = 5.0; + + playSpeed = 1.0; + + sizes[0] = "1.0 1.0 1.0"; + sizes[1] = "1.0 1.0 1.0"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(MortarSubExplosion3) +{ + explosionShape = "mortar_explosion.dts"; + faceViewer = true; + delayMS = 0; + offset = 0.0; + playSpeed = 0.7; + + sizes[0] = "1.0 1.0 1.0"; + sizes[1] = "2.0 2.0 2.0"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(MortarExplosion) +{ + soundProfile = MortarExplosionSound; + + shockwave = MortarShockwave; + shockwaveOnTerrain = true; + + subExplosion[0] = MortarSubExplosion1; + subExplosion[1] = MortarSubExplosion2; + subExplosion[2] = MortarSubExplosion3; + + emitter[0] = MortarExplosionSmokeEmitter; + emitter[1] = MortarCrescentEmitter; + + shakeCamera = true; + camShakeFreq = "8.0 9.0 7.0"; + camShakeAmp = "100.0 100.0 100.0"; + camShakeDuration = 1.3; + camShakeRadius = 25.0; +}; + +//--------------------------------------------------------------------------- +// Smoke particles +//--------------------------------------------------------------------------- +datablock ParticleData(MortarSmokeParticle) +{ + dragCoeffiecient = 0.4; + gravityCoefficient = -0.3; // rises slowly + inheritedVelFactor = 0.125; + + lifetimeMS = 1200; + lifetimeVarianceMS = 200; + useInvAlpha = true; + spinRandomMin = -100.0; + spinRandomMax = 100.0; + + animateTexture = false; + + textureName = "special/Smoke/bigSmoke"; + + colors[0] = "0.7 1.0 0.7 0.5"; + colors[1] = "0.3 0.7 0.3 0.8"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 1.0; + sizes[1] = 2.0; + sizes[2] = 4.5; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + + +datablock ParticleEmitterData(MortarSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 3; + + ejectionVelocity = 2.25; + velocityVariance = 0.55; + + thetaMin = 0.0; + thetaMax = 40.0; + + particles = "MortarSmokeParticle"; +}; + + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- +datablock GrenadeProjectileData(MortarShot) +{ + projectileShapeName = "mortar_projectile.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1.0; + damageRadius = 19.0; // z0dd - ZOD, 8/13/02. Was 20.0 + radiusDamageType = $DamageType::Mortar; + kickBackStrength = 2500; + + explosion = "MortarExplosion"; + underwaterExplosion = "UnderwaterMortarExplosion"; + velInheritFactor = 0.5; + splash = MortarSplash; + depthTolerance = 10.0; // depth at which it uses underwater explosion + + baseEmitter = MortarSmokeEmitter; + bubbleEmitter = MortarBubbleEmitter; + + grenadeElasticity = 0.15; + grenadeFriction = 0.4; + armingDelayMS = 1500; // z0dd - ZOD, 4/14/02. Was 2000 + + gravityMod = 1.1; // z0dd - ZOD, 5/18/02. Make mortar projectile heavier, less floaty + muzzleVelocity = 75.95; // z0dd - ZOD, 8/13/02. More velocity to compensate for higher gravity. Was 63.7 + drag = 0.1; + sound = MortarProjectileSound; + + hasLight = true; + lightRadius = 4; + lightColor = "0.05 0.2 0.05"; + + hasLightUnderwaterColor = true; + underWaterLightColor = "0.05 0.075 0.2"; + + // z0dd - ZOD, 5/22/03. Limit the mortars effective range to around 450 meters. + // Addresses long range mortar spam exploit. + explodeOnDeath = $Host::ClassicLoadMortarChanges ? true : false; + fizzleTimeMS = $Host::ClassicLoadMortarChanges ? 8000 : -1; + lifetimeMS = $Host::ClassicLoadMortarChanges ? 10000 : -1; + fizzleUnderwaterMS = $Host::ClassicLoadMortarChanges ? 8000 : -1; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = false; + deflectionOnWaterImpact = 0.0; +}; + +// z0dd - ZOD, 5/20/03. New block, spawn this at end of MortarShots lifetime. +datablock ItemData(MortarGrenadeThrown) +{ + className = Weapon; + shapeFile = "mortar_projectile.dts"; + mass = 0.7; + elasticity = 0.15; + friction = 1; + pickupRadius = 2; + maxDamage = 0.5; + explosion = "mortarExplosion"; + underwaterExplosion = UnderwaterMortarExplosion; + indirectDamage = 1.0; + damageRadius = 19.0; + radiusDamageType = $DamageType::Mortar; + kickBackStrength = 2500; +}; + +//-------------------------------------------------------------------------- +// Ammo +//-------------------------------------- + +datablock ItemData(MortarAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "ammo_mortar.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "some mortar ammo"; + computeCRC = true; +}; + +//-------------------------------------------------------------------------- +// Weapon +//-------------------------------------- +datablock ItemData(Mortar) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_mortar.dts"; + image = MortarImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a mortar gun"; + computeCRC = true; + emap = true; +}; + +datablock ShapeBaseImageData(MortarImage) +{ + className = WeaponImage; + shapeFile = "weapon_mortar.dts"; + item = Mortar; + ammo = MortarAmmo; + offset = "0 0 0"; + emap = true; + + projectile = MortarShot; + projectileType = GrenadeProjectile; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = MortarSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnAmmo[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "FirstLoad"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateSound[2] = MortarIdleSound; + + stateName[3] = "Fire"; + stateSequence[3] = "Recoil"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.8; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateScript[3] = "onFire"; + stateSound[3] = MortarFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 2.0; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = MortarReloadSound; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateSound[6] = MortarDryFireSound; + stateTimeoutValue[6] = 1.5; + stateTransitionOnTimeout[6] = "NoAmmo"; + + stateName[7] = "FirstLoad"; + stateTransitionOnAmmo[7] = "Ready"; +}; + +function MortarImage::onUnmount(%this,%obj,%slot){ + parent::onUnmount(%this,%obj,%slot); + if(isEventPending(%obj.reloadDelaySch)) + cancel(%obj.reloadDelaySch); +} +function MortarImage::onMount(%this,%obj,%slot){ + + if(%obj.getClassName() !$= "Player") + return; + + if (%this.armthread $= "") + %obj.setArmThread(look); + else + %obj.setArmThread(%this.armThread); + + if(%obj.getMountedImage($WeaponSlot).ammo !$= ""){ + if (%obj.getInventory(%this.ammo)){ + %fireAndReloadTime = mFloor((%this.stateTimeoutValue[4] + %this.stateTimeoutValue[3]) * 1000); + if(%obj.lfireTime[%this.getName()] && (getSimTime() - %obj.lfireTime[%this.getName()]) < %fireAndReloadTime){ + if(isEventPending(%obj.reloadDelaySch)){ + cancel(%obj.reloadDelaySch); + } + %time = mFloor(%fireAndReloadTime - (getSimTime() - %obj.lfireTime[%this.getName()])); + %obj.reloadDelaySch = schedule(%time, 0, "ammoStateDelay", %obj, %slot, true); + } + else{ + %obj.setImageAmmo(%slot,true); + } + } + } + + %obj.client.setWeaponsHudActive(%this.item); + if(%obj.getMountedImage($WeaponSlot).ammo !$= "") + %obj.client.setAmmoHudCount(%obj.getInventory(%this.ammo)); + else + %obj.client.setAmmoHudCount(-1); +} + +function ammoStateDelay(%obj, %slot, %state){ + if(isObject(%obj) && %obj.getState() !$= "Dead") + %obj.setImageAmmo(%slot, %state); +} \ No newline at end of file